]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/utilLib/common.c
Security-57740.31.2.tar.gz
[apple/security.git] / SecurityTests / cspxutils / utilLib / common.c
1 /* Copyright (c) 1997,2003-2005,2008 Apple Inc.
2 *
3 * common.c - Common CSP test code
4 *
5 * Revision History
6 * ----------------
7 * 4 May 2000 Doug Mitchell
8 * Ported to X/CDSA2.
9 * 6 Jul 1998 Doug Mitchell at Apple
10 * Added clStartup().
11 * 12 Aug 1997 Doug Mitchell at Apple
12 * Created.
13 */
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <Security/cssm.h>
19 #include "common.h"
20 #include <Security/cssmapple.h> /* apple, not intel */
21 #include <time.h>
22
23 static CSSM_VERSION vers = {2, 0};
24 //const static uint32 guidPrefix = 0xFADE;
25 const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }};
26
27 /*
28 * We can't enable this until all of these are fixed and integrated:
29 * 2890978 CSP
30 * 2927474 CSPDL
31 * 2928357 TP
32 */
33 #define DETECT_MALLOC_ABUSE 1
34
35 #if DETECT_MALLOC_ABUSE
36
37 /*
38 * This set of allocator functions detects when we free something
39 * which was mallocd by CDSA or a plugin using something other than
40 * our callback malloc/realloc/calloc. With proper runtime support
41 * (which is present in Jaguar 6C35), the reverse is also detected
42 * by malloc (i.e., we malloc something and CDSA or a plugin frees
43 * it).
44 */
45 #define APP_MALLOC_MAGIC 'Util'
46
47 void * appMalloc (CSSM_SIZE size, void *allocRef) {
48 void *ptr;
49
50 /* scribble magic number in first four bytes */
51 ptr = malloc(size + 4);
52 *(uint32 *)ptr = APP_MALLOC_MAGIC;
53 ptr = (char *)ptr + 4;
54
55 return ptr;
56 }
57
58 void appFree (void *ptr, void *allocRef) {
59 if(ptr == NULL) {
60 return;
61 }
62 ptr = (char *)ptr - 4;
63 if(*(uint32 *)ptr != APP_MALLOC_MAGIC) {
64 printf("ERROR: appFree() freeing a block that we didn't allocate!\n");
65 return; // this free is not safe
66 }
67 *(uint32 *)ptr = 0;
68 free(ptr);
69 }
70
71 /* Realloc - adjust both original pointer and size */
72 void * appRealloc (void *ptr, CSSM_SIZE size, void *allocRef) {
73 if(ptr == NULL) {
74 /* no ptr, no existing magic number */
75 return appMalloc(size, allocRef);
76 }
77 ptr = (char *)ptr - 4;
78 if(*(uint32 *)ptr != APP_MALLOC_MAGIC) {
79 printf("ERROR: appRealloc() on a block that we didn't allocate!\n");
80 }
81 *(uint32 *)ptr = 0;
82 ptr = realloc(ptr, size + 4);
83 *(uint32 *)ptr = APP_MALLOC_MAGIC;
84 ptr = (char *)ptr + 4;
85 return ptr;
86 }
87
88 /* Have to do this manually */
89 void * appCalloc (uint32 num, CSSM_SIZE size, void *allocRef) {
90 uint32 memSize = num * size;
91
92 void *ptr = appMalloc(memSize, allocRef);
93 memset(ptr, 0, memSize);
94 return ptr;
95 }
96
97 #else /* DETECT_MALLOC_ABUSE */
98 /*
99 * Standard app-level memory functions required by CDSA.
100 */
101 void * appMalloc (CSSM_SIZE size, void *allocRef) {
102 return( malloc(size) );
103 }
104 void appFree (void *mem_ptr, void *allocRef) {
105 free(mem_ptr);
106 return;
107 }
108 void * appRealloc (void *ptr, CSSM_SIZE size, void *allocRef) {
109 return( realloc( ptr, size ) );
110 }
111 void * appCalloc (uint32 num, CSSM_SIZE size, void *allocRef) {
112 return( calloc( num, size ) );
113 }
114 #endif /* DETECT_MALLOC_ABUSE */
115
116 static CSSM_API_MEMORY_FUNCS memFuncs = {
117 appMalloc,
118 appFree,
119 appRealloc,
120 appCalloc,
121 NULL
122 };
123
124 /*
125 * Init CSSM; returns CSSM_FALSE on error. Reusable.
126 */
127 static CSSM_BOOL cssmInitd = CSSM_FALSE;
128 CSSM_BOOL cssmStartup()
129 {
130 CSSM_RETURN crtn;
131 CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE;
132
133 if(cssmInitd) {
134 return CSSM_TRUE;
135 }
136 crtn = CSSM_Init (&vers,
137 CSSM_PRIVILEGE_SCOPE_NONE,
138 &testGuid,
139 CSSM_KEY_HIERARCHY_NONE,
140 &pvcPolicy,
141 NULL /* reserved */);
142 if(crtn != CSSM_OK)
143 {
144 printError("CSSM_Init", crtn);
145 return CSSM_FALSE;
146 }
147 else {
148 cssmInitd = CSSM_TRUE;
149 return CSSM_TRUE;
150 }
151 }
152
153 /*
154 * Init CSSM and establish a session with the Apple CSP.
155 */
156 CSSM_CSP_HANDLE cspStartup()
157 {
158 return cspDlDbStartup(CSSM_TRUE, NULL);
159 }
160
161 /* like cspStartup, but also returns DB handle. If incoming dbHandPtr
162 * is NULL, no DB startup. */
163 CSSM_CSP_HANDLE cspDbStartup(
164 CSSM_DB_HANDLE *dbHandPtr)
165 {
166 return cspDlDbStartup(CSSM_TRUE, NULL);
167 }
168
169 CSSM_CSP_HANDLE cspDlDbStartup(
170 CSSM_BOOL bareCsp, // true ==> CSP, false ==> CSP/DL
171 CSSM_DB_HANDLE *dbHandPtr) // optional - TO BE DELETED
172 {
173 CSSM_CSP_HANDLE cspHand;
174 CSSM_RETURN crtn;
175 const CSSM_GUID *guid;
176 char *modName;
177
178 if(dbHandPtr) {
179 *dbHandPtr = 0;
180 }
181 if(cssmStartup() == CSSM_FALSE) {
182 return 0;
183 }
184 if(bareCsp) {
185 guid = &gGuidAppleCSP;
186 modName = (char*) "AppleCSP";
187 }
188 else {
189 guid = &gGuidAppleCSPDL;
190 modName = (char *) "AppleCSPDL";
191 }
192 crtn = CSSM_ModuleLoad(guid,
193 CSSM_KEY_HIERARCHY_NONE,
194 NULL, // eventHandler
195 NULL); // AppNotifyCallbackCtx
196 if(crtn) {
197 char outStr[100];
198 sprintf(outStr, "CSSM_ModuleLoad(%s)", modName);
199 printError(outStr, crtn);
200 return 0;
201 }
202 crtn = CSSM_ModuleAttach (guid,
203 &vers,
204 &memFuncs, // memFuncs
205 0, // SubserviceID
206 CSSM_SERVICE_CSP,
207 0, // AttachFlags
208 CSSM_KEY_HIERARCHY_NONE,
209 NULL, // FunctionTable
210 0, // NumFuncTable
211 NULL, // reserved
212 &cspHand);
213 if(crtn) {
214 char outStr[100];
215 sprintf(outStr, "CSSM_ModuleAttach(%s)", modName);
216 printError(outStr, crtn);
217 return 0;
218 }
219 return cspHand;
220 }
221
222 /*
223 * Detach and unload from a CSP.
224 */
225 CSSM_RETURN cspShutdown(
226 CSSM_CSP_HANDLE cspHand,
227 CSSM_BOOL bareCsp) // true ==> CSP, false ==> CSP/DL
228 {
229 CSSM_RETURN crtn;
230 const CSSM_GUID *guid;
231 char *modName;
232
233 if(bareCsp) {
234 guid = &gGuidAppleCSP;
235 modName = (char *) "AppleCSP";
236 }
237 else {
238 guid = &gGuidAppleCSPDL;
239 modName = (char *) "AppleCSPDL";
240 }
241 crtn = CSSM_ModuleDetach(cspHand);
242 if(crtn) {
243 printf("Error detaching from %s\n", modName);
244 printError("CSSM_ModuleDetach", crtn);
245 return crtn;
246 }
247 crtn = CSSM_ModuleUnload(guid, NULL, NULL);
248 if(crtn) {
249 printf("Error unloading %s\n", modName);
250 printError("CSSM_ModuleUnload", crtn);
251 }
252 return crtn;
253 }
254
255 /* Attach to DL side of CSPDL */
256 CSSM_DL_HANDLE dlStartup()
257 {
258 CSSM_DL_HANDLE dlHand = 0;
259 CSSM_RETURN crtn;
260
261 if(cssmStartup() == CSSM_FALSE) {
262 return 0;
263 }
264 crtn = CSSM_ModuleLoad(&gGuidAppleCSPDL,
265 CSSM_KEY_HIERARCHY_NONE,
266 NULL, // eventHandler
267 NULL); // AppNotifyCallbackCtx
268 if(crtn) {
269 printError("CSSM_ModuleLoad(Apple CSPDL)", crtn);
270 return 0;
271 }
272 crtn = CSSM_ModuleAttach (&gGuidAppleCSPDL,
273 &vers,
274 &memFuncs, // memFuncs
275 0, // SubserviceID
276 CSSM_SERVICE_DL,
277 0, // AttachFlags
278 CSSM_KEY_HIERARCHY_NONE,
279 NULL, // FunctionTable
280 0, // NumFuncTable
281 NULL, // reserved
282 &dlHand);
283 if(crtn) {
284 printError("CSSM_ModuleAttach(Apple CSPDL)", crtn);
285 return 0;
286 }
287 return dlHand;
288 }
289
290 /*
291 * Delete a DB.
292 */
293 #define DELETE_WITH_AUTHENT 0
294 CSSM_RETURN dbDelete(
295 CSSM_DL_HANDLE dlHand, // from dlStartup()
296 const char *dbName)
297 {
298 return CSSM_DL_DbDelete(dlHand, dbName, NULL, NULL);
299 }
300
301 /*
302 * open a DB, ensure it's empty.
303 */
304 CSSM_DB_HANDLE dbStartup(
305 CSSM_DL_HANDLE dlHand, // from dlStartup()
306 const char *dbName)
307 {
308 CSSM_DB_HANDLE dbHand = 0;
309
310 CSSM_RETURN crtn = dbCreateOpen(dlHand, dbName,
311 CSSM_TRUE, // create
312 CSSM_TRUE, // delete
313 NULL, // pwd
314 &dbHand);
315 if(crtn == CSSM_OK) {
316 return dbHand;
317 }
318 else {
319 return 0;
320 }
321 }
322
323 #if 0
324 /*
325 * Attach to existing DB or create an empty new one.
326 */
327 CSSM_DB_HANDLE dbStartupByName(CSSM_DL_HANDLE dlHand,
328 char *dbName,
329 CSSM_BOOL doCreate)
330 {
331 CSSM_RETURN crtn;
332 CSSM_DB_HANDLE dbHand;
333
334 /* try to open existing DB in either case */
335
336 crtn = CSSM_DL_DbOpen(dlHand,
337 dbName,
338 NULL, // DbLocation
339 CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE,
340 NULL, // CSSM_ACCESS_CREDENTIALS *AccessCred
341 NULL, // void *OpenParameters
342 &dbHand);
343 if(dbHand != 0) {
344 return dbHand;
345 }
346 if(!doCreate) {
347 printf("***no such data base (%s)\n", dbName);
348 printError("CSSM_DL_DbOpen", crtn);
349 return 0;
350 }
351 /* have to create one */
352 return dbStartup(dlHand, dbName);
353 }
354 #endif
355
356 /*
357 * routines which convert various types to untyped byte arrays.
358 */
359 void intToBytes(unsigned i, unsigned char *buf)
360 {
361 *buf++ = (unsigned char)((i >> 24) & 0xff);
362 *buf++ = (unsigned char)((i >> 16) & 0xff);
363 *buf++ = (unsigned char)((i >> 8) & 0xff);
364 *buf = (unsigned char)(i & 0xff);
365 }
366 void shortToBytes(unsigned short s, unsigned char *buf)
367 {
368 *buf++ = (unsigned char)((s >> 8) & 0xff);
369 *buf = (unsigned char)(s & 0xff);
370 }
371 unsigned bytesToInt(const unsigned char *buf) {
372 unsigned result;
373 result = (((unsigned)buf[0] << 24) & 0xff000000) |
374 (((unsigned)buf[1] << 16) & 0x00ff0000) |
375 (((unsigned)buf[2] << 8) & 0xff00) |
376 (((unsigned)buf[3]) & 0xff);
377 return result;
378 }
379 unsigned short bytesToShort(const unsigned char *buf) {
380 unsigned short result;
381 result = (((unsigned short)buf[0] << 8) & 0xff00) |
382 (((unsigned short)buf[1]) & 0xff);
383 return result;
384 }
385
386 /*
387 * Given a context specified via a CSSM_CC_HANDLE, add a new
388 * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType,
389 * AttributeLength, and an untyped pointer.
390 *
391 * This is currently used to add a second CSSM_KEY attribute when performing
392 * ops with algorithm CSSM_ALGID_FEED and CSSM_ALGID_FEECFILE.
393 */
394 CSSM_RETURN AddContextAttribute(CSSM_CC_HANDLE CCHandle,
395 uint32 AttributeType,
396 uint32 AttributeLength,
397 ContextAttrType attrType,
398 /* specify exactly one of these */
399 const void *AttributePtr,
400 uint32 attributeInt)
401 {
402 CSSM_CONTEXT_ATTRIBUTE newAttr;
403 CSSM_RETURN crtn;
404
405 newAttr.AttributeType = AttributeType;
406 newAttr.AttributeLength = AttributeLength;
407 if(attrType == CAT_Uint32) {
408 newAttr.Attribute.Uint32 = attributeInt;
409 }
410 else {
411 newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr;
412 }
413 crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr);
414 if(crtn) {
415 printError("CSSM_UpdateContextAttributes", crtn);
416 }
417 return crtn;
418 }
419
420 /*
421 * Set up a CSSM data.
422 */
423 CSSM_RETURN appSetupCssmData(
424 CSSM_DATA_PTR data,
425 uint32 numBytes)
426 {
427 if(data == NULL) {
428 printf("Hey! appSetupCssmData with NULL Data!\n");
429 return CSSMERR_CSSM_INTERNAL_ERROR;
430 }
431 data->Data = (uint8 *)CSSM_MALLOC(numBytes);
432 if(data->Data == NULL) {
433 return CSSMERR_CSSM_MEMORY_ERROR;
434 }
435 data->Length = numBytes;
436 return CSSM_OK;
437 }
438
439 /*
440 * Free the data referenced by a CSSM data, and optionally, the struct itself.
441 */
442 void appFreeCssmData(CSSM_DATA_PTR data,
443 CSSM_BOOL freeStruct)
444 {
445 if(data == NULL) {
446 return;
447 }
448 if(data->Length != 0) {
449 CSSM_FREE(data->Data);
450 }
451 if(freeStruct) {
452 CSSM_FREE(data);
453 }
454 else {
455 data->Length = 0;
456 data->Data = NULL;
457 }
458 }
459
460 /*
461 * Copy src to dst, mallocing dst.
462 */
463 CSSM_RETURN appCopyCssmData(const CSSM_DATA *src,
464 CSSM_DATA_PTR dst)
465 {
466 return appCopyData(src->Data, src->Length, dst);
467 }
468
469 /* copy raw data to a CSSM_DATA, mallocing dst. */
470 CSSM_RETURN appCopyData(const void *src,
471 uint32 len,
472 CSSM_DATA_PTR dst)
473 {
474 dst->Length = 0;
475 if(len == 0) {
476 dst->Data = NULL;
477 return CSSM_OK;
478 }
479 dst->Data = (uint8 *)CSSM_MALLOC(len);
480 if(dst->Data == NULL) {
481 return CSSM_ERRCODE_MEMORY_ERROR;
482 }
483 dst->Length = len;
484 memcpy(dst->Data, src, len);
485 return CSSM_OK;
486 }
487
488 CSSM_BOOL appCompareCssmData(const CSSM_DATA *d1,
489 const CSSM_DATA *d2)
490 {
491 if(d1->Length != d2->Length) {
492 return CSSM_FALSE;
493 }
494 if(memcmp(d1->Data, d2->Data, d1->Length)) {
495 return CSSM_FALSE;
496 }
497 return CSSM_TRUE;
498 }
499
500 /* min <= return <= max */
501 unsigned genRand(unsigned min, unsigned max)
502 {
503 unsigned i;
504 if(min == max) {
505 return min;
506 }
507 appGetRandomBytes(&i, 4);
508 return (min + (i % (max - min + 1)));
509 }
510
511 void simpleGenData(CSSM_DATA_PTR dbuf, unsigned minBufSize, unsigned maxBufSize)
512 {
513 unsigned len = genRand(minBufSize, maxBufSize);
514 appGetRandomBytes(dbuf->Data, len);
515 dbuf->Length = len;
516 }
517
518 #define MIN_OFFSET 0
519 #define MAX_OFFSET 99
520 #define MIN_ASCII 'a'
521 #define MAX_ASCII 'z'
522
523 /*
524 * Calculate random data size, fill dataPool with that many random bytes.
525 *
526 * (10**minExp + MIN_OFFSET) <= size <= (10**maxExp + MAX_OFFSET)
527 */
528 unsigned genData(unsigned char *dataPool,
529 unsigned minExp,
530 unsigned maxExp,
531 dataType type)
532 {
533 int exp;
534 int offset;
535 int size;
536 char *cp;
537 int i;
538 char ac;
539
540 /*
541 * Calculate "random" size : (10 ** (random exponent)) + random offset
542 */
543 exp = genRand(minExp, maxExp);
544 offset = genRand(MIN_OFFSET, MAX_OFFSET);
545 size = 1;
546 while(exp--) { // size = 10 ** exp
547 size *= 10;
548 }
549 size += offset;
550 switch(type) {
551 case DT_Zero:
552 bzero(dataPool, size);
553 break;
554 case DT_Increment:
555 {
556 int i;
557 for(i=0; i<size; i++) {
558 dataPool[i] = i;
559 }
560 }
561 break;
562 case DT_ASCII:
563 ac = MIN_ASCII;
564 cp = (char *)dataPool;
565 for(i=0; i<size; i++) {
566 *cp++ = ac++;
567 if(ac > MAX_ASCII) {
568 ac = MIN_ASCII;
569 }
570 }
571 break;
572 case DT_Random:
573 appGetRandomBytes(dataPool, size);
574 break;
575 }
576 return size;
577 }
578
579 void dumpBuffer(
580 const char *bufName, // optional
581 unsigned char *buf,
582 unsigned len)
583 {
584 unsigned i;
585
586 if(bufName) {
587 printf("%s\n", bufName);
588 }
589 printf(" ");
590 for(i=0; i<len; i++) {
591 printf("%02X ", buf[i]);
592 if((i % 24) == 23) {
593 printf("\n ");
594 }
595 }
596 printf("\n");
597 }
598
599 int testError(CSSM_BOOL quiet)
600 {
601 char resp;
602
603 if(quiet) {
604 printf("\n***Test aborting.\n");
605 exit(1);
606 }
607 fpurge(stdin);
608 printf("a to abort, c to continue: ");
609 resp = getchar();
610 return (resp == 'a');
611 }
612
613 void testStartBanner(
614 const char *testName,
615 int argc,
616 char **argv)
617 {
618 printf("Starting %s; args: ", testName);
619 for(int i=1; i<argc; i++) {
620 printf("%s ", argv[i]);
621 }
622 printf("\n");
623 }
624