]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/ccOneShot/ccOneShot.cpp
Security-57031.10.10.tar.gz
[apple/security.git] / SecurityTests / cspxutils / ccOneShot / ccOneShot.cpp
1 /*
2 * ccOneShot.c - Ensure that one-shot CommonDigest routines behave correctly.
3 *
4 * Written 3/31/06 by Doug Mitchell.
5 */
6
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <time.h>
10 #include "common.h"
11 #include <string.h>
12 #include <CommonCrypto/CommonDigest.h>
13 #include <openssl/hmac.h>
14
15 /*
16 * Defaults.
17 */
18 #define LOOPS_DEF 200
19 #define MIN_DATA_SIZE 1
20 #define MAX_DATA_SIZE 10000 /* bytes */
21 #define LOOP_NOTIFY 20
22
23 /*
24 * Enumerate algs our own way to allow iteration.
25 */
26 typedef enum {
27 ALG_MD2 = 1,
28 ALG_MD4,
29 ALG_MD5,
30 ALG_SHA1,
31 ALG_SHA224,
32 ALG_SHA256,
33 ALG_SHA384,
34 ALG_SHA512
35 } HashAlg;
36 #define ALG_FIRST ALG_MD2
37 #define ALG_LAST ALG_SHA512
38
39 static void usage(char **argv)
40 {
41 printf("usage: %s [options]\n", argv[0]);
42 printf(" Options:\n");
43 printf(" l=loops (default %d)\n", LOOPS_DEF);
44 printf(" q(uiet)\n");
45 printf(" h(elp)\n");
46 exit(1);
47 }
48
49 /* the context pointers are void * here for polymorphism later on */
50 typedef int (*initFcn)(void *ctx);
51 typedef int (*updateFcn)(void *ctx, const void *data, CC_LONG len);
52 typedef int (*finalFcn)(unsigned char *md, void *ctx);
53 typedef unsigned char (*oneShotFcn)(const void *data, CC_LONG len, unsigned char *md);
54
55 typedef struct {
56 HashAlg alg;
57 const char *algName;
58 size_t digestSize;
59 initFcn init;
60 updateFcn update;
61 finalFcn final;
62 oneShotFcn oneShot;
63 } CommonDigestInfo;
64
65 /* casts are necessary to cover the void* context args */
66 static const CommonDigestInfo digests[] =
67 {
68 { ALG_MD2, "MD2", CC_MD2_DIGEST_LENGTH,
69 (initFcn)CC_MD2_Init, (updateFcn)CC_MD2_Update,
70 (finalFcn)CC_MD2_Final, (oneShotFcn)CC_MD2
71 },
72 { ALG_MD4, "MD4", CC_MD4_DIGEST_LENGTH,
73 (initFcn)CC_MD4_Init, (updateFcn)CC_MD4_Update,
74 (finalFcn)CC_MD4_Final, (oneShotFcn)CC_MD4
75 },
76 { ALG_MD5, "MD5", CC_MD5_DIGEST_LENGTH,
77 (initFcn)CC_MD5_Init, (updateFcn)CC_MD5_Update,
78 (finalFcn)CC_MD5_Final, (oneShotFcn)CC_MD5
79 },
80 { ALG_SHA1, "SHA1", CC_SHA1_DIGEST_LENGTH,
81 (initFcn)CC_SHA1_Init, (updateFcn)CC_SHA1_Update,
82 (finalFcn)CC_SHA1_Final, (oneShotFcn)CC_SHA1
83 },
84 { ALG_SHA224, "SHA224", CC_SHA224_DIGEST_LENGTH,
85 (initFcn)CC_SHA224_Init, (updateFcn)CC_SHA224_Update,
86 (finalFcn)CC_SHA224_Final, (oneShotFcn)CC_SHA224
87 },
88 { ALG_SHA256, "SHA256", CC_SHA256_DIGEST_LENGTH,
89 (initFcn)CC_SHA256_Init, (updateFcn)CC_SHA256_Update,
90 (finalFcn)CC_SHA256_Final, (oneShotFcn)CC_SHA256
91 },
92 { ALG_SHA384, "SHA384", CC_SHA384_DIGEST_LENGTH,
93 (initFcn)CC_SHA384_Init, (updateFcn)CC_SHA384_Update,
94 (finalFcn)CC_SHA384_Final, (oneShotFcn)CC_SHA384
95 },
96 { ALG_SHA512, "SHA512", CC_SHA512_DIGEST_LENGTH,
97 (initFcn)CC_SHA512_Init, (updateFcn)CC_SHA512_Update,
98 (finalFcn)CC_SHA512_Final, (oneShotFcn)CC_SHA512
99 },
100 };
101 #define NUM_DIGESTS (sizeof(digests) / sizeof(digests[0]))
102
103 static const CommonDigestInfo *findDigestInfo(unsigned alg)
104 {
105 unsigned dex;
106 for(dex=0; dex<NUM_DIGESTS; dex++) {
107 if((unsigned)(digests[dex].alg) == alg) {
108 return &digests[dex];
109 }
110 }
111 return NULL;
112 }
113
114
115 /*
116 * These consts let us allocate context and digest buffers for
117 * any arbitrary algorithm.
118 */
119 #define MAX_DIGEST_SIZE 64
120 #define MAX_CONTEXT_SIZE sizeof(CC_SHA512_CTX)
121
122 /* staged digest with random updates */
123 static void doStaged(
124 const CommonDigestInfo *digestInfo,
125 const unsigned char *ptext,
126 unsigned ptextLen,
127 unsigned char *md)
128 {
129 char ctx[MAX_CONTEXT_SIZE];
130 unsigned thisMove;
131
132 digestInfo->init(ctx);
133 while(ptextLen) {
134 thisMove = genRand(1, ptextLen);
135 digestInfo->update(ctx, ptext, thisMove);
136 ptext += thisMove;
137 ptextLen -= thisMove;
138 }
139 digestInfo->final(md, ctx);
140 }
141
142 static int doTest(
143 const CommonDigestInfo *digestInfo,
144 const unsigned char *ptext,
145 unsigned ptextLen,
146 bool quiet)
147 {
148 unsigned char mdStaged[MAX_DIGEST_SIZE];
149 unsigned char mdOneShot[MAX_DIGEST_SIZE];
150
151 digestInfo->oneShot(ptext, ptextLen, mdOneShot);
152 doStaged(digestInfo, ptext, ptextLen, mdStaged);
153 if(memcmp(mdStaged, mdOneShot, digestInfo->digestSize)) {
154 printf("***Digest miscompare for %s\n", digestInfo->algName);
155 if(testError(quiet)) {
156 return 1;
157 }
158 }
159 return 0;
160 }
161
162 int main(int argc, char **argv)
163 {
164 int arg;
165 char *argp;
166 unsigned loop;
167 uint8 *ptext;
168 size_t ptextLen;
169 unsigned currAlg;
170 const CommonDigestInfo *digestInfo;
171 int rtn = 0;
172 int i;
173
174 /*
175 * User-spec'd params
176 */
177 unsigned loops = LOOPS_DEF;
178 bool quiet = false;
179
180 for(arg=1; arg<argc; arg++) {
181 argp = argv[arg];
182 switch(argp[0]) {
183 case 'l':
184 loops = atoi(&argp[2]);
185 break;
186 case 'q':
187 quiet = true;
188 break;
189 case 'h':
190 default:
191 usage(argv);
192 }
193 }
194 ptext = (uint8 *)malloc(MAX_DATA_SIZE);
195 if(ptext == NULL) {
196 printf("Insufficient heap space\n");
197 exit(1);
198 }
199 /* ptext length set in test loop */
200
201 printf("Starting ccOneShot; args: ");
202 for(i=1; i<argc; i++) {
203 printf("%s ", argv[i]);
204 }
205 printf("\n");
206
207 for(currAlg=ALG_FIRST; currAlg<=ALG_LAST; currAlg++) {
208 digestInfo = findDigestInfo(currAlg);
209 if(!quiet) {
210 printf("Testing alg %s\n", digestInfo->algName);
211 }
212 for(loop=1; ; loop++) {
213 ptextLen = genRand(MIN_DATA_SIZE, MAX_DATA_SIZE);
214 appGetRandomBytes(ptext, ptextLen);
215 if(!quiet) {
216 if((loop % LOOP_NOTIFY) == 0) {
217 printf("..loop %d ptextLen %lu\n",
218 loop, (unsigned long)ptextLen);
219 }
220 }
221
222 if(doTest(digestInfo, ptext, ptextLen, quiet)) {
223 rtn = 1;
224 break;
225 }
226 if(loops && (loop == loops)) {
227 break;
228 }
229 } /* main loop */
230 if(rtn) {
231 break;
232 }
233
234 } /* for algs */
235
236 if((rtn == 0) && !quiet) {
237 printf("%s test complete\n", argv[0]);
238 }
239 free(ptext);
240 return rtn;
241 }
242
243