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 23static CSSM_VERSION vers = {2, 0}; 24//const static uint32 guidPrefix = 0xFADE; 25const 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 47void * 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 58void 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 */ 72void * 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 */ 89void * 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 */ 101void * appMalloc (CSSM_SIZE size, void *allocRef) { 102 return( malloc(size) ); 103} 104void appFree (void *mem_ptr, void *allocRef) { 105 free(mem_ptr); 106 return; 107} 108void * appRealloc (void *ptr, CSSM_SIZE size, void *allocRef) { 109 return( realloc( ptr, size ) ); 110} 111void * appCalloc (uint32 num, CSSM_SIZE size, void *allocRef) { 112 return( calloc( num, size ) ); 113} 114#endif /* DETECT_MALLOC_ABUSE */ 115 116static 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 */ 127static CSSM_BOOL cssmInitd = CSSM_FALSE; 128CSSM_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 */ 156CSSM_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. */ 163CSSM_CSP_HANDLE cspDbStartup( 164 CSSM_DB_HANDLE *dbHandPtr) 165{ 166 return cspDlDbStartup(CSSM_TRUE, NULL); 167} 168 169CSSM_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 */ 225CSSM_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 */ 256CSSM_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 294CSSM_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 */ 304CSSM_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 */ 327CSSM_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 */ 359void 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} 366void shortToBytes(unsigned short s, unsigned char *buf) 367{ 368 *buf++ = (unsigned char)((s >> 8) & 0xff); 369 *buf = (unsigned char)(s & 0xff); 370} 371unsigned 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} 379unsigned 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 */ 394CSSM_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 */ 423CSSM_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 */ 442void 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 */ 463CSSM_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. */ 470CSSM_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 488CSSM_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 */ 501unsigned 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 511void 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 */ 528unsigned 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 579void 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 599int 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 613void 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 625