1/* 2 * hashClone.c - test CSSM_DigestDataClone function 3 */ 4 5#include <stdlib.h> 6#include <stdio.h> 7#include <time.h> 8#include <Security/cssm.h> 9#include <Security/cssmapple.h> 10#include "cspwrap.h" 11#include "common.h" 12 13/* 14 * Defaults 15 */ 16#define LOOPS_DEF 50 17#define MAX_PTEXT (8 * 1024) 18#define MIN_PTEXT 16 19#define LOOP_NOTIFY 20 20 21/* 22 * Enumerated algs 23 */ 24typedef unsigned privAlg; 25enum { 26 ALG_MD5 = 1, 27 ALG_SHA1, 28 ALG_MD2, 29 ALG_SHA224, 30 ALG_SHA256, 31 ALG_SHA384, 32 ALG_SHA512 33}; 34 35#define ALG_FIRST ALG_MD5 36#define ALG_LAST ALG_SHA512 37 38static void usage(char **argv) 39{ 40 printf("usage: %s [options]\n", argv[0]); 41 printf(" Options:\n"); 42 printf(" a=algorithm (s=SHA1; m=MD5; M=MD2; 4=SHA224; 2=SHA256; 3=SHA384; 5=SHA512; " 43 "default=all\n"); 44 printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); 45 printf(" p=pauseInterval (default=0, no pause)\n"); 46 printf(" D (CSP/DL; default = bare CSP)\n"); 47 printf(" v(erbose)\n"); 48 printf(" q(uiet)\n"); 49 printf(" h(elp)\n"); 50 exit(1); 51} 52 53static int doTest(CSSM_CSP_HANDLE cspHand, 54 CSSM_ALGORITHMS alg, 55 const char *algStr, 56 CSSM_DATA_PTR ptext, 57 CSSM_BOOL verbose, 58 CSSM_BOOL quiet) 59{ 60 CSSM_CC_HANDLE digHand1 = 0; // reference 61 CSSM_CC_HANDLE digHand2 = 0; // to be cloned 62 CSSM_CC_HANDLE digHand3 = 0; // cloned from digHand2 63 CSSM_DATA dig1 = {0, NULL}; 64 CSSM_DATA dig2 = {0, NULL}; 65 CSSM_DATA dig3 = {0, NULL}; 66 CSSM_RETURN crtn; 67 unsigned thisMove; // this update 68 unsigned toMove; // total to go 69 unsigned totalRequest; // originally requested 70 CSSM_DATA thisText; // actually passed to update 71 72 /* cook up two digest contexts */ 73 crtn = CSSM_CSP_CreateDigestContext(cspHand, 74 alg, 75 &digHand1); 76 if(crtn) { 77 printError("CSSM_CSP_CreateDigestContext (1)", crtn); 78 return testError(quiet); 79 } 80 crtn = CSSM_CSP_CreateDigestContext(cspHand, 81 alg, 82 &digHand2); 83 if(crtn) { 84 printError("CSSM_CSP_CreateDigestContext (2)", crtn); 85 return testError(quiet); 86 } 87 crtn = CSSM_DigestDataInit(digHand1); 88 if(crtn) { 89 printError("CSSM_DigestDataInit (1)", crtn); 90 return testError(quiet); 91 } 92 crtn = CSSM_DigestDataInit(digHand2); 93 if(crtn) { 94 printError("CSSM_DigestDataInit (2)", crtn); 95 return testError(quiet); 96 } 97 98 /* do some random updates to first two digests, until we've digested 99 * at least half of the requested data */ 100 totalRequest = ptext->Length; 101 toMove = ptext->Length; 102 thisText.Data = ptext->Data; 103 while(toMove > (totalRequest / 2)) { 104 thisMove = genRand((MIN_PTEXT / 2), toMove); 105 thisText.Length = thisMove; 106 if(verbose) { 107 printf(" ..updating digest1, digest2 with %d bytes\n", thisMove); 108 } 109 crtn = CSSM_DigestDataUpdate(digHand1, &thisText, 1); 110 if(crtn) { 111 printError("CSSM_DigestDataUpdate (1)", crtn); 112 return testError(quiet); 113 } 114 crtn = CSSM_DigestDataUpdate(digHand2, &thisText, 1); 115 if(crtn) { 116 printError("CSSM_DigestDataUpdate (2)", crtn); 117 return testError(quiet); 118 } 119 thisText.Data += thisMove; 120 toMove -= thisMove; 121 } 122 123 /* digest3 := clone(digest2) */ 124 crtn = CSSM_DigestDataClone(digHand2, &digHand3); 125 if(crtn) { 126 printError("CSSM_DigestDataClone", crtn); 127 return testError(quiet); 128 } 129 130 /* finish off remaining ptext, updating all 3 digests identically */ 131 while(toMove) { 132 thisMove = genRand(1, toMove); 133 thisText.Length = thisMove; 134 if(verbose) { 135 printf(" ..updating all three digests with %d bytes\n", thisMove); 136 } 137 crtn = CSSM_DigestDataUpdate(digHand1, &thisText, 1); 138 if(crtn) { 139 printError("CSSM_DigestDataUpdate (3)", crtn); 140 return testError(quiet); 141 } 142 crtn = CSSM_DigestDataUpdate(digHand2, &thisText, 1); 143 if(crtn) { 144 printError("CSSM_DigestDataUpdate (4)", crtn); 145 return testError(quiet); 146 } 147 crtn = CSSM_DigestDataUpdate(digHand3, &thisText, 1); 148 if(crtn) { 149 printError("CSSM_DigestDataUpdate (5)", crtn); 150 return testError(quiet); 151 } 152 thisText.Data += thisMove; 153 toMove -= thisMove; 154 } 155 156 /* obtain all three digests */ 157 crtn = CSSM_DigestDataFinal(digHand1, &dig1); 158 if(crtn) { 159 printError("CSSM_DigestDataFinal (1)", crtn); 160 return testError(quiet); 161 } 162 crtn = CSSM_DigestDataFinal(digHand2, &dig2); 163 if(crtn) { 164 printError("CSSM_DigestDataFinal (2)", crtn); 165 return testError(quiet); 166 } 167 crtn = CSSM_DigestDataFinal(digHand3, &dig3); 168 if(crtn) { 169 printError("CSSM_DigestDataFinal (3)", crtn); 170 return testError(quiet); 171 } 172 173 /* ensure all three digests identical */ 174 if(!appCompareCssmData(&dig1, &dig2)) { 175 printf("***Digest miscompare(dig1, dig2)***\n"); 176 if(testError(quiet)) { 177 return 1; 178 } 179 } 180 if(!appCompareCssmData(&dig2, &dig3)) { 181 printf("***Digest miscompare(dig2, dig3)***\n"); 182 if(testError(quiet)) { 183 return 1; 184 } 185 } 186 187 /* free resources */ 188 appFreeCssmData(&dig1, CSSM_FALSE); 189 appFreeCssmData(&dig2, CSSM_FALSE); 190 appFreeCssmData(&dig3, CSSM_FALSE); 191 CSSM_DeleteContext(digHand1); 192 CSSM_DeleteContext(digHand2); 193 CSSM_DeleteContext(digHand3); 194 return 0; 195} 196 197int main(int argc, char **argv) 198{ 199 int arg; 200 char *argp; 201 unsigned loop; 202 CSSM_DATA ptext; 203 CSSM_CSP_HANDLE cspHand; 204 const char *algStr; 205 privAlg alg; // ALG_MD5, etc. 206 CSSM_ALGORITHMS cssmAlg; // CSSM_ALGID_MD5, etc. 207 int j; 208 209 /* 210 * User-spec'd params 211 */ 212 unsigned loops = LOOPS_DEF; 213 CSSM_BOOL verbose = CSSM_FALSE; 214 CSSM_BOOL quiet = CSSM_FALSE; 215 unsigned minAlg = ALG_FIRST; 216 unsigned maxAlg = ALG_LAST; 217 unsigned pauseInterval = 0; 218 CSSM_BOOL bareCsp = CSSM_TRUE; 219 220 for(arg=1; arg<argc; arg++) { 221 argp = argv[arg]; 222 switch(argp[0]) { 223 case 'a': 224 if(argp[1] != '=') { 225 usage(argv); 226 } 227 switch(argp[2]) { 228 case 's': 229 minAlg = maxAlg = ALG_SHA1; 230 break; 231 case 'm': 232 minAlg = maxAlg = ALG_MD5; 233 break; 234 case 'M': 235 minAlg = maxAlg = ALG_MD2; 236 break; 237 case '4': 238 minAlg = maxAlg = ALG_SHA224; 239 break; 240 case '2': 241 minAlg = maxAlg = ALG_SHA256; 242 break; 243 case '3': 244 minAlg = maxAlg = ALG_SHA384; 245 break; 246 case '5': 247 minAlg = maxAlg = ALG_SHA512; 248 break; 249 default: 250 usage(argv); 251 } 252 break; 253 case 'l': 254 loops = atoi(&argp[2]); 255 break; 256 case 'p': 257 pauseInterval = atoi(&argp[2]);; 258 break; 259 case 'v': 260 verbose = CSSM_TRUE; 261 break; 262 case 'q': 263 quiet = CSSM_TRUE; 264 break; 265 case 'D': 266 bareCsp = CSSM_FALSE; 267 break; 268 case 'h': 269 default: 270 usage(argv); 271 } 272 } 273 ptext.Data = (uint8 *)CSSM_MALLOC(MAX_PTEXT); 274 /* length set in test loop */ 275 if(ptext.Data == NULL) { 276 printf("Insufficient heap\n"); 277 exit(1); 278 } 279 280 printf("Starting hashClone; args: "); 281 for(j=1; j<argc; j++) { 282 printf("%s ", argv[j]); 283 } 284 printf("\n"); 285 cspHand = cspDlDbStartup(bareCsp, NULL); 286 if(cspHand == 0) { 287 exit(1); 288 } 289 290 for(alg=minAlg; alg<=maxAlg; alg++) { 291 switch(alg) { 292 case ALG_MD5: 293 algStr = "MD5"; 294 cssmAlg = CSSM_ALGID_MD5; 295 break; 296 case ALG_MD2: 297 algStr = "MD2"; 298 cssmAlg = CSSM_ALGID_MD2; 299 break; 300 case ALG_SHA1: 301 algStr = "SHA1"; 302 cssmAlg = CSSM_ALGID_SHA1; 303 break; 304 case ALG_SHA224: 305 algStr = "SHA224"; 306 cssmAlg = CSSM_ALGID_SHA224; 307 break; 308 case ALG_SHA256: 309 algStr = "SHA256"; 310 cssmAlg = CSSM_ALGID_SHA256; 311 break; 312 case ALG_SHA384: 313 algStr = "SHA384"; 314 cssmAlg = CSSM_ALGID_SHA384; 315 break; 316 case ALG_SHA512: 317 algStr = "SHA512"; 318 cssmAlg = CSSM_ALGID_SHA512; 319 break; 320 } 321 if(!quiet) { 322 printf("Testing alg %s\n", algStr); 323 } 324 for(loop=1; ; loop++) { 325 simpleGenData(&ptext, MIN_PTEXT, MAX_PTEXT); 326 if(!quiet) { 327 if(verbose || ((loop % LOOP_NOTIFY) == 0)) { 328 printf("..loop %d text size %lu\n", loop, ptext.Length); 329 } 330 } 331 if(doTest(cspHand, 332 cssmAlg, 333 algStr, 334 &ptext, 335 verbose, 336 quiet)) { 337 exit(1); 338 } 339 if(loops && (loop == loops)) { 340 break; 341 } 342 if(pauseInterval && ((loop % pauseInterval) == 0)) { 343 fpurge(stdin); 344 printf("Hit CR to proceed: "); 345 getchar(); 346 } 347 } 348 } 349 cspShutdown(cspHand, bareCsp); 350 if(!quiet) { 351 printf("%s test complete\n", argv[0]); 352 } 353 return 0; 354} 355