+++ /dev/null
-/*
- * ccOneShot.c - Ensure that one-shot CommonDigest routines behave correctly.
- *
- * Written 3/31/06 by Doug Mitchell.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include "common.h"
-#include <string.h>
-#include <CommonCrypto/CommonDigest.h>
-#include <openssl/hmac.h>
-
-/*
- * Defaults.
- */
-#define LOOPS_DEF 200
-#define MIN_DATA_SIZE 1
-#define MAX_DATA_SIZE 10000 /* bytes */
-#define LOOP_NOTIFY 20
-
-/*
- * Enumerate algs our own way to allow iteration.
- */
-typedef enum {
- ALG_MD2 = 1,
- ALG_MD4,
- ALG_MD5,
- ALG_SHA1,
- ALG_SHA224,
- ALG_SHA256,
- ALG_SHA384,
- ALG_SHA512
-} HashAlg;
-#define ALG_FIRST ALG_MD2
-#define ALG_LAST ALG_SHA512
-
-static void usage(char **argv)
-{
- printf("usage: %s [options]\n", argv[0]);
- printf(" Options:\n");
- printf(" l=loops (default %d)\n", LOOPS_DEF);
- printf(" q(uiet)\n");
- printf(" h(elp)\n");
- exit(1);
-}
-
-/* the context pointers are void * here for polymorphism later on */
-typedef int (*initFcn)(void *ctx);
-typedef int (*updateFcn)(void *ctx, const void *data, CC_LONG len);
-typedef int (*finalFcn)(unsigned char *md, void *ctx);
-typedef unsigned char (*oneShotFcn)(const void *data, CC_LONG len, unsigned char *md);
-
-typedef struct {
- HashAlg alg;
- const char *algName;
- size_t digestSize;
- initFcn init;
- updateFcn update;
- finalFcn final;
- oneShotFcn oneShot;
-} CommonDigestInfo;
-
-/* casts are necessary to cover the void* context args */
-static const CommonDigestInfo digests[] =
-{
- { ALG_MD2, "MD2", CC_MD2_DIGEST_LENGTH,
- (initFcn)CC_MD2_Init, (updateFcn)CC_MD2_Update,
- (finalFcn)CC_MD2_Final, (oneShotFcn)CC_MD2
- },
- { ALG_MD4, "MD4", CC_MD4_DIGEST_LENGTH,
- (initFcn)CC_MD4_Init, (updateFcn)CC_MD4_Update,
- (finalFcn)CC_MD4_Final, (oneShotFcn)CC_MD4
- },
- { ALG_MD5, "MD5", CC_MD5_DIGEST_LENGTH,
- (initFcn)CC_MD5_Init, (updateFcn)CC_MD5_Update,
- (finalFcn)CC_MD5_Final, (oneShotFcn)CC_MD5
- },
- { ALG_SHA1, "SHA1", CC_SHA1_DIGEST_LENGTH,
- (initFcn)CC_SHA1_Init, (updateFcn)CC_SHA1_Update,
- (finalFcn)CC_SHA1_Final, (oneShotFcn)CC_SHA1
- },
- { ALG_SHA224, "SHA224", CC_SHA224_DIGEST_LENGTH,
- (initFcn)CC_SHA224_Init, (updateFcn)CC_SHA224_Update,
- (finalFcn)CC_SHA224_Final, (oneShotFcn)CC_SHA224
- },
- { ALG_SHA256, "SHA256", CC_SHA256_DIGEST_LENGTH,
- (initFcn)CC_SHA256_Init, (updateFcn)CC_SHA256_Update,
- (finalFcn)CC_SHA256_Final, (oneShotFcn)CC_SHA256
- },
- { ALG_SHA384, "SHA384", CC_SHA384_DIGEST_LENGTH,
- (initFcn)CC_SHA384_Init, (updateFcn)CC_SHA384_Update,
- (finalFcn)CC_SHA384_Final, (oneShotFcn)CC_SHA384
- },
- { ALG_SHA512, "SHA512", CC_SHA512_DIGEST_LENGTH,
- (initFcn)CC_SHA512_Init, (updateFcn)CC_SHA512_Update,
- (finalFcn)CC_SHA512_Final, (oneShotFcn)CC_SHA512
- },
-};
-#define NUM_DIGESTS (sizeof(digests) / sizeof(digests[0]))
-
-static const CommonDigestInfo *findDigestInfo(unsigned alg)
-{
- unsigned dex;
- for(dex=0; dex<NUM_DIGESTS; dex++) {
- if((unsigned)(digests[dex].alg) == alg) {
- return &digests[dex];
- }
- }
- return NULL;
-}
-
-
-/*
- * These consts let us allocate context and digest buffers for
- * any arbitrary algorithm.
- */
-#define MAX_DIGEST_SIZE 64
-#define MAX_CONTEXT_SIZE sizeof(CC_SHA512_CTX)
-
-/* staged digest with random updates */
-static void doStaged(
- const CommonDigestInfo *digestInfo,
- const unsigned char *ptext,
- unsigned ptextLen,
- unsigned char *md)
-{
- char ctx[MAX_CONTEXT_SIZE];
- unsigned thisMove;
-
- digestInfo->init(ctx);
- while(ptextLen) {
- thisMove = genRand(1, ptextLen);
- digestInfo->update(ctx, ptext, thisMove);
- ptext += thisMove;
- ptextLen -= thisMove;
- }
- digestInfo->final(md, ctx);
-}
-
-static int doTest(
- const CommonDigestInfo *digestInfo,
- const unsigned char *ptext,
- unsigned ptextLen,
- bool quiet)
-{
- unsigned char mdStaged[MAX_DIGEST_SIZE];
- unsigned char mdOneShot[MAX_DIGEST_SIZE];
-
- digestInfo->oneShot(ptext, ptextLen, mdOneShot);
- doStaged(digestInfo, ptext, ptextLen, mdStaged);
- if(memcmp(mdStaged, mdOneShot, digestInfo->digestSize)) {
- printf("***Digest miscompare for %s\n", digestInfo->algName);
- if(testError(quiet)) {
- return 1;
- }
- }
- return 0;
-}
-
-int main(int argc, char **argv)
-{
- int arg;
- char *argp;
- unsigned loop;
- uint8 *ptext;
- size_t ptextLen;
- unsigned currAlg;
- const CommonDigestInfo *digestInfo;
- int rtn = 0;
- int i;
-
- /*
- * User-spec'd params
- */
- unsigned loops = LOOPS_DEF;
- bool quiet = false;
-
- for(arg=1; arg<argc; arg++) {
- argp = argv[arg];
- switch(argp[0]) {
- case 'l':
- loops = atoi(&argp[2]);
- break;
- case 'q':
- quiet = true;
- break;
- case 'h':
- default:
- usage(argv);
- }
- }
- ptext = (uint8 *)malloc(MAX_DATA_SIZE);
- if(ptext == NULL) {
- printf("Insufficient heap space\n");
- exit(1);
- }
- /* ptext length set in test loop */
-
- printf("Starting ccOneShot; args: ");
- for(i=1; i<argc; i++) {
- printf("%s ", argv[i]);
- }
- printf("\n");
-
- for(currAlg=ALG_FIRST; currAlg<=ALG_LAST; currAlg++) {
- digestInfo = findDigestInfo(currAlg);
- if(!quiet) {
- printf("Testing alg %s\n", digestInfo->algName);
- }
- for(loop=1; ; loop++) {
- ptextLen = genRand(MIN_DATA_SIZE, MAX_DATA_SIZE);
- appGetRandomBytes(ptext, ptextLen);
- if(!quiet) {
- if((loop % LOOP_NOTIFY) == 0) {
- printf("..loop %d ptextLen %lu\n",
- loop, (unsigned long)ptextLen);
- }
- }
-
- if(doTest(digestInfo, ptext, ptextLen, quiet)) {
- rtn = 1;
- break;
- }
- if(loops && (loop == loops)) {
- break;
- }
- } /* main loop */
- if(rtn) {
- break;
- }
-
- } /* for algs */
-
- if((rtn == 0) && !quiet) {
- printf("%s test complete\n", argv[0]);
- }
- free(ptext);
- return rtn;
-}
-
-