--- /dev/null
+/*
+ * Simple interactive CSP RNG exerciser.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <Security/cssm.h>
+#include <Security/cssmapple.h>
+#include "cspwrap.h"
+#include "common.h"
+
+#define RAND_ALG CSSM_ALGID_APPLE_YARROW
+#define BUFSIZE 32
+
+static void usage(char **argv)
+{
+ printf("usage: %s [options]\n", argv[0]);
+ printf("Options:\n");
+ printf(" D (CSP/DL; default = bare CSP)\n");
+ exit(1);
+}
+
+static void dumpBuf(uint8 *buf,
+ unsigned len)
+{
+ unsigned i;
+
+ printf(" ");
+ for(i=0; i<len; i++) {
+ printf("%02X ", buf[i]);
+ if((i % 8) == 7) {
+ printf("\n ");
+ }
+ }
+ printf("\n");
+}
+
+void doGenRand(
+ CSSM_CSP_HANDLE cspHand,
+ CSSM_CC_HANDLE ccHand, // 0 ==> gen a new one
+ // else use this
+ CSSM_CRYPTO_DATA_PTR seed, // optional
+ unsigned len,
+ CSSM_BOOL weMalloc)
+{
+ CSSM_RETURN crtn;
+ CSSM_DATA data = {0, NULL};
+
+ /* optional existing context */
+ if(ccHand == 0) {
+ crtn = CSSM_CSP_CreateRandomGenContext(
+ cspHand,
+ RAND_ALG,
+ seed,
+ len,
+ &ccHand);
+ if(crtn) {
+ printError("CSSM_CSP_CreateRandomGenContext", crtn);
+ return;
+ }
+ }
+
+ /* who mallocs the data? */
+ if(weMalloc) {
+ data.Data = (uint8 *)appMalloc(len, NULL);
+ if(data.Data == NULL) {
+ printf("***malloc failure\n");
+ return;
+ }
+ data.Length = len;
+ }
+
+ /* go for it */
+ crtn = CSSM_GenerateRandom(ccHand, &data);
+ if(crtn) {
+ printError("CSSM_GenerateRandom", crtn);
+ return;
+ }
+
+ dumpBuf(data.Data, data.Length);
+ appFree(data.Data, NULL);
+ return;
+}
+
+#define SEED_SIZE 32
+
+/*
+ * CryptoData callback for optional random seed.
+ */
+CSSM_RETURN seedCallback(
+ CSSM_DATA_PTR OutData,
+ void *CallerCtx)
+{
+ int i, j;
+ static unsigned char seed[SEED_SIZE];
+
+ OutData->Length = SEED_SIZE;
+ OutData->Data = seed;
+ for(i=SEED_SIZE, j=0; i>0; i--, j++) {
+ seed[j] = i;
+ }
+ return CSSM_OK;
+}
+
+int main(int argc, char **argv)
+{
+ int arg;
+ char *argp;
+ CSSM_CSP_HANDLE cspHand;
+ CSSM_CC_HANDLE ccHand = 0;
+ CSSM_RETURN crtn;
+ CSSM_BOOL bareCsp = CSSM_TRUE;
+ char resp = 'n';
+ // initial op = get random data
+ CSSM_BOOL weMalloc = CSSM_FALSE;
+ unsigned char seed[SEED_SIZE];
+ CSSM_CRYPTO_DATA cseed;
+ int i;
+ unsigned reqLen = 16;
+ CSSM_BOOL explicitSeed;
+
+ for(arg=1; arg<argc; arg++) {
+ argp = argv[arg];
+ switch(argv[arg][0]) {
+ case 'D':
+ bareCsp = CSSM_FALSE;
+ break;
+ default:
+ usage(argv);
+ }
+ }
+ cspHand = cspDlDbStartup(bareCsp, NULL);
+ if(cspHand == 0) {
+ exit(1);
+ }
+
+ /* set up for explicit seed */
+ cseed.Param.Length = SEED_SIZE;
+ cseed.Param.Data = seed;
+ for(i=0; i<SEED_SIZE; i++) {
+ seed[i] = i;
+ }
+ cseed.Callback = NULL;
+ cseed.CallerCtx = NULL;
+ explicitSeed = CSSM_TRUE;
+
+ while(1) {
+ printf(" g Get random data w/seed\n");
+ printf(" n Get random data w/o seed\n");
+ printf(" c Get random data using current context\n");
+ printf(" m we malloc (current: %s)\n",
+ weMalloc ? "True" : "False");
+ printf(" M CSP mallocs\n");
+ printf(" s seed via explicit data (current: %d)\n", (int)explicitSeed);
+ printf(" S seed via callback\n");
+ printf(" q quit\n");
+ fpurge(stdin);
+ printf("\ncommand me: ");
+ nextChar:
+ resp = getchar();
+ if(resp == 'q') {
+ break;
+ }
+ switch(resp) {
+ case 'g':
+ if(ccHand != 0) {
+ crtn = CSSM_DeleteContext(ccHand);
+ if(crtn) {
+ printError("CSSM_DeleteContext", crtn);
+ }
+ ccHand = 0;
+ }
+ doGenRand(cspHand, ccHand, &cseed, reqLen, weMalloc);
+ break;
+ case 'n':
+ if(ccHand != 0) {
+ crtn = CSSM_DeleteContext(ccHand);
+ if(crtn) {
+ printError("CSSM_DeleteContext", crtn);
+ }
+ ccHand = 0;
+ }
+ doGenRand(cspHand, ccHand, NULL, reqLen, weMalloc);
+ break;
+ case 'c':
+ doGenRand(cspHand, ccHand, NULL, reqLen, weMalloc);
+ break;
+ case 'm':
+ weMalloc = CSSM_TRUE;
+ break;
+ case 'M':
+ weMalloc = CSSM_FALSE;
+ break;
+ case 'l':
+ printf("New length: ");
+ scanf("%d", &reqLen);
+ break;
+ case 's':
+ /* explicit seed - presence of callback is the determinant */
+ cseed.Callback = NULL;
+ explicitSeed = CSSM_TRUE;
+ break;
+ case 'S':
+ /* seed by calllback */
+ cseed.Callback = seedCallback;
+ explicitSeed = CSSM_FALSE;
+ break;
+ case '\n':
+ goto nextChar;
+ default:
+ printf("Huh?\n");
+ }
+ }
+ if((crtn = CSSM_ModuleDetach(cspHand))) {
+ printError("CSSM_ModuleDetach", crtn);
+ exit(1);
+ }
+ return 0;
+}