1/* Copyright (c) 1997,2003-2006,2008,2010,2013 Apple Inc. 2 * 3 * cspwrap.c - wrappers to simplify access to CDSA 4 * 5 * Revision History 6 * ---------------- 7 * 3 May 2000 Doug Mitchell 8 * Ported to X/CDSA2. 9 * 12 Aug 1997 Doug Mitchell at Apple 10 * Created. 11 */ 12 13#include <Security/cssmapple.h> 14#include <Security/cssm.h> 15#include "cspwrap.h" 16#include "common.h" 17#include <stdio.h> 18#include <stdlib.h> 19#include <string.h> 20/* MCF hack */ 21// #include <CarbonCore/MacTypes.h> 22#include <MacTypes.h> 23/* end MCF */ 24 25#ifndef NULL 26#define NULL ((void *)0) 27#endif /* NULL */ 28#ifndef MAX 29#define MAX(a,b) ((a > b) ? a : b) 30#define MIN(a,b) ((a < b) ? a : b) 31#endif 32 33#pragma mark --------- Key Generation --------- 34 35/* 36 * Key generation 37 */ 38#define FEE_PRIV_DATA_SIZE 20 39/* 40 * Debug/test only. BsafeCSP only (long since disabled, in Puma). 41 * This results in quicker but less secure RSA key generation. 42 */ 43#define RSA_WEAK_KEYS 0 44 45/* 46 * Force bad data in KeyData prior to generating, deriving, or 47 * wrapping key to ensure that the CSP ignores incoming 48 * KeyData. 49 */ 50static void setBadKeyData( 51 CSSM_KEY_PTR key) 52{ 53 key->KeyData.Data = (uint8 *)0xeaaaeaaa; // bad ptr 54 key->KeyData.Length = 1; // no key can fit here 55} 56 57/* 58 * Generate key pair of arbitrary algorithm. 59 * FEE keys will have random private data. 60 */ 61CSSM_RETURN cspGenKeyPair(CSSM_CSP_HANDLE cspHand, 62 uint32 algorithm, 63 const char *keyLabel, 64 unsigned keyLabelLen, 65 uint32 keySize, // in bits 66 CSSM_KEY_PTR pubKey, // mallocd by caller 67 CSSM_BOOL pubIsRef, // true - reference key, false - data 68 uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. 69 CSSM_KEYBLOB_FORMAT pubFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE 70 // to get the default format. 71 CSSM_KEY_PTR privKey, // mallocd by caller 72 CSSM_BOOL privIsRef, // true - reference key, false - data 73 uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. 74 CSSM_KEYBLOB_FORMAT privFormat, // optional 0 ==> default 75 CSSM_BOOL genSeed) // FEE only. True: we generate seed and CSP 76 // will hash it. False: CSP generates random 77 // seed. 78{ 79 CSSM_RETURN crtn; 80 CSSM_CC_HANDLE ccHand; 81 CSSM_DATA privData = {0, NULL}; // mallocd for FEE 82 CSSM_CRYPTO_DATA privCData; 83 CSSM_CRYPTO_DATA_PTR privCDataPtr = NULL; 84 CSSM_DATA keyLabelData; 85 uint32 pubAttr; 86 uint32 privAttr; 87 CSSM_RETURN ocrtn = CSSM_OK; 88 89 if(keySize == CSP_KEY_SIZE_DEFAULT) { 90 keySize = cspDefaultKeySize(algorithm); 91 } 92 93 /* pre-context-create algorithm-specific stuff */ 94 switch(algorithm) { 95 case CSSM_ALGID_FEE: 96 if(genSeed) { 97 /* cook up random privData */ 98 privData.Data = (uint8 *)CSSM_MALLOC(FEE_PRIV_DATA_SIZE); 99 privData.Length = FEE_PRIV_DATA_SIZE; 100 appGetRandomBytes(privData.Data, FEE_PRIV_DATA_SIZE); 101 privCData.Param = privData; 102 privCData.Callback = NULL; 103 privCDataPtr = &privCData; 104 } 105 /* else CSP generates random seed/key */ 106 break; 107 case CSSM_ALGID_RSA: 108 break; 109 case CSSM_ALGID_DSA: 110 break; 111 case CSSM_ALGID_ECDSA: 112 break; 113 default: 114 printf("cspGenKeyPair: Unknown algorithm\n"); 115 /* but what the hey */ 116 privCDataPtr = NULL; 117 break; 118 } 119 keyLabelData.Data = (uint8 *)keyLabel, 120 keyLabelData.Length = keyLabelLen; 121 memset(pubKey, 0, sizeof(CSSM_KEY)); 122 memset(privKey, 0, sizeof(CSSM_KEY)); 123 setBadKeyData(pubKey); 124 setBadKeyData(privKey); 125 126 crtn = CSSM_CSP_CreateKeyGenContext(cspHand, 127 algorithm, 128 keySize, 129 privCDataPtr, // Seed 130 NULL, // Salt 131 NULL, // StartDate 132 NULL, // EndDate 133 NULL, // Params 134 &ccHand); 135 if(crtn) { 136 printError("CSSM_CSP_CreateKeyGenContext", crtn); 137 ocrtn = crtn; 138 goto abort; 139 } 140 /* cook up attribute bits */ 141 if(pubIsRef) { 142 pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; 143 } 144 else { 145 pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; 146 } 147 if(privIsRef) { 148 privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; 149 } 150 else { 151 privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; 152 } 153 154 /* post-context-create algorithm-specific stuff */ 155 switch(algorithm) { 156 case CSSM_ALGID_RSA: 157 158 #if RSA_WEAK_KEYS 159 { 160 /* for testing, speed up key gen by using the 161 * undocumented "CUSTOM" key gen mode. This 162 * results in the CSP using AI_RsaKeyGen instead of 163 * AI_RSAStrongKeyGen. 164 */ 165 crtn = AddContextAttribute(ccHand, 166 CSSM_ATTRIBUTE_MODE, 167 sizeof(uint32), 168 CAT_Uint32, 169 NULL, 170 CSSM_ALGMODE_CUSTOM); 171 if(crtn) { 172 printError("CSSM_UpdateContextAttributes", crtn); 173 return crtn; 174 } 175 } 176 #endif // RSA_WEAK_KEYS 177 break; 178 179 case CSSM_ALGID_DSA: 180 /* 181 * extra step - generate params - this just adds some 182 * info to the context 183 */ 184 { 185 CSSM_DATA dummy = {0, NULL}; 186 crtn = CSSM_GenerateAlgorithmParams(ccHand, 187 keySize, &dummy); 188 if(crtn) { 189 printError("CSSM_GenerateAlgorithmParams", crtn); 190 return crtn; 191 } 192 appFreeCssmData(&dummy, CSSM_FALSE); 193 } 194 break; 195 default: 196 break; 197 } 198 199 /* optional format specifiers */ 200 if(!pubIsRef && (pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE)) { 201 crtn = AddContextAttribute(ccHand, 202 CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, 203 sizeof(uint32), 204 CAT_Uint32, 205 NULL, 206 pubFormat); 207 if(crtn) { 208 printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn); 209 return crtn; 210 } 211 } 212 if(!privIsRef && (privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE)) { 213 crtn = AddContextAttribute(ccHand, 214 CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT, 215 sizeof(uint32), // currently sizeof CSSM_DATA 216 CAT_Uint32, 217 NULL, 218 privFormat); 219 if(crtn) { 220 printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn); 221 return crtn; 222 } 223 } 224 crtn = CSSM_GenerateKeyPair(ccHand, 225 pubKeyUsage, 226 pubAttr, 227 &keyLabelData, 228 pubKey, 229 privKeyUsage, 230 privAttr, 231 &keyLabelData, // same labels 232 NULL, // CredAndAclEntry 233 privKey); 234 if(crtn) { 235 printError("CSSM_GenerateKeyPair", crtn); 236 ocrtn = crtn; 237 goto abort; 238 } 239 /* basic checks...*/ 240 if(privIsRef) { 241 if(privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { 242 printf("privKey blob type: exp %u got %u\n", 243 CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType); 244 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 245 goto abort; 246 } 247 } 248 else { 249 switch(privKey->KeyHeader.BlobType) { 250 case CSSM_KEYBLOB_RAW: 251 break; 252 default: 253 printf("privKey blob type: exp raw, got %u\n", 254 (unsigned)privKey->KeyHeader.BlobType); 255 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 256 goto abort; 257 } 258 } 259 if(pubIsRef) { 260 if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { 261 printf("pubKey blob type: exp %u got %u\n", 262 CSSM_KEYBLOB_REFERENCE, (unsigned)pubKey->KeyHeader.BlobType); 263 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 264 goto abort; 265 } 266 } 267 else { 268 switch(pubKey->KeyHeader.BlobType) { 269 case CSSM_KEYBLOB_RAW: 270 break; 271 default: 272 printf("pubKey blob type: exp raw or raw_berder, got %u\n", 273 (unsigned)pubKey->KeyHeader.BlobType); 274 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 275 goto abort; 276 } 277 } 278abort: 279 if(ccHand != 0) { 280 crtn = CSSM_DeleteContext(ccHand); 281 if(crtn) { 282 printError("CSSM_DeleteContext", crtn); 283 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 284 } 285 } 286 if(privData.Data != NULL) { 287 CSSM_FREE(privData.Data); 288 } 289 return ocrtn; 290} 291 292/* 293 * Generate FEE key pair with optional primeType, curveType, and seed (password) data. 294 */ 295CSSM_RETURN cspGenFEEKeyPair(CSSM_CSP_HANDLE cspHand, 296 const char *keyLabel, 297 unsigned keyLabelLen, 298 uint32 keySize, // in bits 299 uint32 primeType, // CSSM_FEE_PRIME_TYPE_MERSENNE, etc. 300 uint32 curveType, // CSSM_FEE_CURVE_TYPE_MONTGOMERY, etc. 301 CSSM_KEY_PTR pubKey, // mallocd by caller 302 CSSM_BOOL pubIsRef, // true - reference key, false - data 303 uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. 304 CSSM_KEYBLOB_FORMAT pubFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE 305 // to get the default format. 306 CSSM_KEY_PTR privKey, // mallocd by caller 307 CSSM_BOOL privIsRef, // true - reference key, false - data 308 uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. 309 CSSM_KEYBLOB_FORMAT privFormat, // optional 0 ==> default 310 const CSSM_DATA *seedData) // Present: CSP will hash this for private data. 311 // NULL: CSP generates random seed. 312{ 313 CSSM_RETURN crtn; 314 CSSM_CC_HANDLE ccHand; 315 CSSM_CRYPTO_DATA privCData; 316 CSSM_CRYPTO_DATA_PTR privCDataPtr = NULL; 317 CSSM_DATA keyLabelData; 318 uint32 pubAttr; 319 uint32 privAttr; 320 CSSM_RETURN ocrtn = CSSM_OK; 321 322 /* pre-context-create algorithm-specific stuff */ 323 if(seedData) { 324 privCData.Param = *((CSSM_DATA_PTR)seedData); 325 privCData.Callback = NULL; 326 privCDataPtr = &privCData; 327 } 328 /* else CSP generates random seed/key */ 329 330 if(keySize == CSP_KEY_SIZE_DEFAULT) { 331 keySize = CSP_FEE_KEY_SIZE_DEFAULT; 332 } 333 334 keyLabelData.Data = (uint8 *)keyLabel, 335 keyLabelData.Length = keyLabelLen; 336 memset(pubKey, 0, sizeof(CSSM_KEY)); 337 memset(privKey, 0, sizeof(CSSM_KEY)); 338 setBadKeyData(pubKey); 339 setBadKeyData(privKey); 340 341 crtn = CSSM_CSP_CreateKeyGenContext(cspHand, 342 CSSM_ALGID_FEE, 343 keySize, 344 privCDataPtr, // Seed 345 NULL, // Salt 346 NULL, // StartDate 347 NULL, // EndDate 348 NULL, // Params 349 &ccHand); 350 if(crtn) { 351 printError("CSSM_CSP_CreateKeyGenContext", crtn); 352 ocrtn = crtn; 353 goto abort; 354 } 355 /* cook up attribute bits */ 356 if(pubIsRef) { 357 pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; 358 } 359 else { 360 pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; 361 } 362 if(privIsRef) { 363 privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; 364 } 365 else { 366 privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; 367 } 368 369 /* optional post-context-create stuff */ 370 if(primeType != CSSM_FEE_PRIME_TYPE_DEFAULT) { 371 crtn = AddContextAttribute(ccHand, 372 CSSM_ATTRIBUTE_FEE_PRIME_TYPE, 373 sizeof(uint32), 374 CAT_Uint32, 375 NULL, 376 primeType); 377 if(crtn) { 378 printError("AddContextAttribute(CSSM_ATTRIBUTE_FEE_PRIME_TYPE)", crtn); 379 return crtn; 380 } 381 } 382 if(curveType != CSSM_FEE_CURVE_TYPE_DEFAULT) { 383 crtn = AddContextAttribute(ccHand, 384 CSSM_ATTRIBUTE_FEE_CURVE_TYPE, 385 sizeof(uint32), 386 CAT_Uint32, 387 NULL, 388 curveType); 389 if(crtn) { 390 printError("AddContextAttribute(CSSM_ATTRIBUTE_FEE_CURVE_TYPE)", crtn); 391 return crtn; 392 } 393 } 394 395 if(pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) { 396 crtn = AddContextAttribute(ccHand, 397 CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, 398 sizeof(uint32), 399 CAT_Uint32, 400 NULL, 401 pubFormat); 402 if(crtn) { 403 printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn); 404 return crtn; 405 } 406 } 407 if(privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) { 408 crtn = AddContextAttribute(ccHand, 409 CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT, 410 sizeof(uint32), // currently sizeof CSSM_DATA 411 CAT_Uint32, 412 NULL, 413 pubFormat); 414 if(crtn) { 415 printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn); 416 return crtn; 417 } 418 } 419 crtn = CSSM_GenerateKeyPair(ccHand, 420 pubKeyUsage, 421 pubAttr, 422 &keyLabelData, 423 pubKey, 424 privKeyUsage, 425 privAttr, 426 &keyLabelData, // same labels 427 NULL, // CredAndAclEntry 428 privKey); 429 if(crtn) { 430 printError("CSSM_GenerateKeyPair", crtn); 431 ocrtn = crtn; 432 goto abort; 433 } 434 /* basic checks...*/ 435 if(privIsRef) { 436 if(privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { 437 printf("privKey blob type: exp %u got %u\n", 438 CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType); 439 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 440 goto abort; 441 } 442 } 443 else { 444 switch(privKey->KeyHeader.BlobType) { 445 case CSSM_KEYBLOB_RAW: 446 break; 447 default: 448 printf("privKey blob type: exp raw, got %u\n", 449 (unsigned)privKey->KeyHeader.BlobType); 450 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 451 goto abort; 452 } 453 } 454 if(pubIsRef) { 455 if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { 456 printf("pubKey blob type: exp %u got %u\n", 457 CSSM_KEYBLOB_REFERENCE, (unsigned)pubKey->KeyHeader.BlobType); 458 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 459 goto abort; 460 } 461 } 462 else { 463 switch(pubKey->KeyHeader.BlobType) { 464 case CSSM_KEYBLOB_RAW: 465 break; 466 default: 467 printf("pubKey blob type: exp raw or raw_berder, got %u\n", 468 (unsigned)pubKey->KeyHeader.BlobType); 469 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 470 goto abort; 471 } 472 } 473abort: 474 if(ccHand != 0) { 475 crtn = CSSM_DeleteContext(ccHand); 476 if(crtn) { 477 printError("CSSM_DeleteContext", crtn); 478 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 479 } 480 } 481 return ocrtn; 482} 483 484/* 485 * Generate DSA key pair with optional generateAlgParams and optional 486 * incoming parameters. 487 */ 488CSSM_RETURN cspGenDSAKeyPair(CSSM_CSP_HANDLE cspHand, 489 const char *keyLabel, 490 unsigned keyLabelLen, 491 uint32 keySize, // in bits 492 CSSM_KEY_PTR pubKey, // mallocd by caller 493 CSSM_BOOL pubIsRef, // true - reference key, false - data 494 uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. 495 CSSM_KEYBLOB_FORMAT pubFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE 496 // to get the default format. 497 CSSM_KEY_PTR privKey, // mallocd by caller 498 CSSM_BOOL privIsRef, // true - reference key, false - data 499 uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. 500 CSSM_KEYBLOB_FORMAT privFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE 501 // to get the default format. 502 CSSM_BOOL genParams, 503 CSSM_DATA_PTR paramData) // optional 504{ 505 CSSM_RETURN crtn; 506 CSSM_CC_HANDLE ccHand; 507 CSSM_DATA keyLabelData; 508 uint32 pubAttr; 509 uint32 privAttr; 510 CSSM_RETURN ocrtn = CSSM_OK; 511 512 if(keySize == CSP_KEY_SIZE_DEFAULT) { 513 keySize = CSP_DSA_KEY_SIZE_DEFAULT; 514 } 515 keyLabelData.Data = (uint8 *)keyLabel, 516 keyLabelData.Length = keyLabelLen; 517 memset(pubKey, 0, sizeof(CSSM_KEY)); 518 memset(privKey, 0, sizeof(CSSM_KEY)); 519 setBadKeyData(pubKey); 520 setBadKeyData(privKey); 521 522 crtn = CSSM_CSP_CreateKeyGenContext(cspHand, 523 CSSM_ALGID_DSA, 524 keySize, 525 NULL, // Seed 526 NULL, // Salt 527 NULL, // StartDate 528 NULL, // EndDate 529 paramData, 530 &ccHand); 531 if(crtn) { 532 printError("CSSM_CSP_CreateKeyGenContext", crtn); 533 ocrtn = crtn; 534 goto abort; 535 } 536 537 /* cook up attribute bits */ 538 if(pubIsRef) { 539 pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; 540 } 541 else { 542 pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; 543 } 544 if(privIsRef) { 545 privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; 546 } 547 else { 548 privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; 549 } 550 551 if(genParams) { 552 /* 553 * extra step - generate params - this just adds some 554 * info to the context 555 */ 556 CSSM_DATA dummy = {0, NULL}; 557 crtn = CSSM_GenerateAlgorithmParams(ccHand, 558 keySize, &dummy); 559 if(crtn) { 560 printError("CSSM_GenerateAlgorithmParams", crtn); 561 return crtn; 562 } 563 appFreeCssmData(&dummy, CSSM_FALSE); 564 } 565 566 /* optional format specifiers */ 567 if(!pubIsRef && (pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE)) { 568 crtn = AddContextAttribute(ccHand, 569 CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, 570 sizeof(uint32), 571 CAT_Uint32, 572 NULL, 573 pubFormat); 574 if(crtn) { 575 printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn); 576 return crtn; 577 } 578 } 579 if(!privIsRef && (privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE)) { 580 crtn = AddContextAttribute(ccHand, 581 CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT, 582 sizeof(uint32), // currently sizeof CSSM_DATA 583 CAT_Uint32, 584 NULL, 585 privFormat); 586 if(crtn) { 587 printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn); 588 return crtn; 589 } 590 } 591 592 crtn = CSSM_GenerateKeyPair(ccHand, 593 pubKeyUsage, 594 pubAttr, 595 &keyLabelData, 596 pubKey, 597 privKeyUsage, 598 privAttr, 599 &keyLabelData, // same labels 600 NULL, // CredAndAclEntry 601 privKey); 602 if(crtn) { 603 printError("CSSM_GenerateKeyPair", crtn); 604 ocrtn = crtn; 605 goto abort; 606 } 607 /* basic checks...*/ 608 if(privIsRef) { 609 if(privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { 610 printf("privKey blob type: exp %u got %u\n", 611 CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType); 612 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 613 goto abort; 614 } 615 } 616 else { 617 switch(privKey->KeyHeader.BlobType) { 618 case CSSM_KEYBLOB_RAW: 619 break; 620 default: 621 printf("privKey blob type: exp raw, got %u\n", 622 (unsigned)privKey->KeyHeader.BlobType); 623 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 624 goto abort; 625 } 626 } 627 if(pubIsRef) { 628 if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { 629 printf("pubKey blob type: exp %u got %u\n", 630 CSSM_KEYBLOB_REFERENCE, (unsigned)pubKey->KeyHeader.BlobType); 631 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 632 goto abort; 633 } 634 } 635 else { 636 switch(pubKey->KeyHeader.BlobType) { 637 case CSSM_KEYBLOB_RAW: 638 break; 639 default: 640 printf("pubKey blob type: exp raw or raw_berder, got %u\n", 641 (unsigned)pubKey->KeyHeader.BlobType); 642 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 643 goto abort; 644 } 645 } 646abort: 647 if(ccHand != 0) { 648 crtn = CSSM_DeleteContext(ccHand); 649 if(crtn) { 650 printError("CSSM_DeleteContext", crtn); 651 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 652 } 653 } 654 return ocrtn; 655} 656 657 658uint32 cspDefaultKeySize(uint32 alg) 659{ 660 uint32 keySizeInBits; 661 switch(alg) { 662 case CSSM_ALGID_DES: 663 keySizeInBits = CSP_DES_KEY_SIZE_DEFAULT; 664 break; 665 case CSSM_ALGID_3DES_3KEY: 666 case CSSM_ALGID_DESX: 667 keySizeInBits = CSP_DES3_KEY_SIZE_DEFAULT; 668 break; 669 case CSSM_ALGID_RC2: 670 keySizeInBits = CSP_RC2_KEY_SIZE_DEFAULT; 671 break; 672 case CSSM_ALGID_RC4: 673 keySizeInBits = CSP_RC4_KEY_SIZE_DEFAULT; 674 break; 675 case CSSM_ALGID_RC5: 676 keySizeInBits = CSP_RC5_KEY_SIZE_DEFAULT; 677 break; 678 case CSSM_ALGID_ASC: 679 keySizeInBits = CSP_ASC_KEY_SIZE_DEFAULT; 680 break; 681 case CSSM_ALGID_BLOWFISH: 682 keySizeInBits = CSP_BFISH_KEY_SIZE_DEFAULT; 683 break; 684 case CSSM_ALGID_CAST: 685 keySizeInBits = CSP_CAST_KEY_SIZE_DEFAULT; 686 break; 687 case CSSM_ALGID_IDEA: 688 keySizeInBits = CSP_IDEA_KEY_SIZE_DEFAULT; 689 break; 690 case CSSM_ALGID_AES: 691 keySizeInBits = CSP_AES_KEY_SIZE_DEFAULT; 692 break; 693 case CSSM_ALGID_SHA1HMAC: 694 keySizeInBits = CSP_HMAC_SHA_KEY_SIZE_DEFAULT; 695 break; 696 case CSSM_ALGID_MD5HMAC: 697 keySizeInBits = CSP_HMAC_MD5_KEY_SIZE_DEFAULT; 698 break; 699 case CSSM_ALGID_FEE: 700 keySizeInBits = CSP_FEE_KEY_SIZE_DEFAULT; 701 break; 702 case CSSM_ALGID_RSA: 703 keySizeInBits = CSP_RSA_KEY_SIZE_DEFAULT; 704 break; 705 case CSSM_ALGID_DSA: 706 keySizeInBits = CSP_DSA_KEY_SIZE_DEFAULT; 707 break; 708 case CSSM_ALGID_ECDSA: 709 keySizeInBits = CSP_ECDSA_KEY_SIZE_DEFAULT; 710 break; 711 case CSSM_ALGID_NONE: 712 keySizeInBits = CSP_NULL_CRYPT_KEY_SIZE_DEF; 713 break; 714 default: 715 printf("***cspDefaultKeySize: Unknown symmetric algorithm\n"); 716 keySizeInBits = 0; 717 break; 718 } 719 return keySizeInBits; 720} 721 722/* 723 * Create a random symmetric key. 724 */ 725CSSM_KEY_PTR cspGenSymKey(CSSM_CSP_HANDLE cspHand, 726 uint32 alg, 727 const char *keyLabel, 728 unsigned keyLabelLen, 729 uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. 730 uint32 keySizeInBits, 731 CSSM_BOOL refKey) 732{ 733 CSSM_KEY_PTR symKey = (CSSM_KEY_PTR)CSSM_MALLOC(sizeof(CSSM_KEY)); 734 CSSM_RETURN crtn; 735 CSSM_CC_HANDLE ccHand; 736 uint32 keyAttr; 737 CSSM_DATA dummyLabel; 738 739 if(symKey == NULL) { 740 printf("Insufficient heap space\n"); 741 return NULL; 742 } 743 memset(symKey, 0, sizeof(CSSM_KEY)); 744 setBadKeyData(symKey); 745 if(keySizeInBits == CSP_KEY_SIZE_DEFAULT) { 746 keySizeInBits = cspDefaultKeySize(alg); 747 } 748 crtn = CSSM_CSP_CreateKeyGenContext(cspHand, 749 alg, 750 keySizeInBits, // keySizeInBits 751 NULL, // Seed 752 NULL, // Salt 753 NULL, // StartDate 754 NULL, // EndDate 755 NULL, // Params 756 &ccHand); 757 if(crtn) { 758 printError("CSSM_CSP_CreateKeyGenContext", crtn); 759 goto errorOut; 760 } 761 if(refKey) { 762 keyAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; 763 } 764 else { 765 keyAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; 766 } 767 dummyLabel.Length = keyLabelLen; 768 dummyLabel.Data = (uint8 *)keyLabel; 769 770 crtn = CSSM_GenerateKey(ccHand, 771 keyUsage, 772 keyAttr, 773 &dummyLabel, 774 NULL, // ACL 775 symKey); 776 if(crtn) { 777 printError("CSSM_GenerateKey", crtn); 778 goto errorOut; 779 } 780 crtn = CSSM_DeleteContext(ccHand); 781 if(crtn) { 782 printError("CSSM_DeleteContext", crtn); 783 goto errorOut; 784 } 785 return symKey; 786errorOut: 787 CSSM_FREE(symKey); 788 return NULL; 789} 790 791/* 792 * Derive symmetric key. 793 * Note in the X CSP, we never return an IV. 794 */ 795CSSM_KEY_PTR cspDeriveKey(CSSM_CSP_HANDLE cspHand, 796 uint32 deriveAlg, // CSSM_ALGID_PKCS5_PBKDF2, etc. 797 uint32 keyAlg, // CSSM_ALGID_RC5, etc. 798 const char *keyLabel, 799 unsigned keyLabelLen, 800 uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. 801 uint32 keySizeInBits, 802 CSSM_BOOL isRefKey, 803 CSSM_DATA_PTR password, // in PKCS-5 lingo 804 CSSM_DATA_PTR salt, // ditto 805 uint32 iterationCnt, // ditto 806 CSSM_DATA_PTR initVector) // mallocd & RETURNED 807{ 808 CSSM_KEY_PTR symKey = (CSSM_KEY_PTR) 809 CSSM_MALLOC(sizeof(CSSM_KEY)); 810 CSSM_RETURN crtn; 811 CSSM_CC_HANDLE ccHand; 812 uint32 keyAttr; 813 CSSM_DATA dummyLabel; 814 CSSM_PKCS5_PBKDF2_PARAMS pbeParams; 815 CSSM_DATA pbeData; 816 CSSM_ACCESS_CREDENTIALS creds; 817 818 if(symKey == NULL) { 819 printf("Insufficient heap space\n"); 820 return NULL; 821 } 822 memset(symKey, 0, sizeof(CSSM_KEY)); 823 setBadKeyData(symKey); 824 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); 825 if(keySizeInBits == CSP_KEY_SIZE_DEFAULT) { 826 keySizeInBits = cspDefaultKeySize(keyAlg); 827 } 828 crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, 829 deriveAlg, 830 keyAlg, 831 keySizeInBits, 832 &creds, 833 NULL, // BaseKey 834 iterationCnt, 835 salt, 836 NULL, // seed 837 &ccHand); 838 if(crtn) { 839 printError("CSSM_CSP_CreateDeriveKeyContext", crtn); 840 goto errorOut; 841 } 842 keyAttr = CSSM_KEYATTR_EXTRACTABLE; 843 if(isRefKey) { 844 keyAttr |= (CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE); 845 } 846 else { 847 keyAttr |= CSSM_KEYATTR_RETURN_DATA; 848 } 849 dummyLabel.Length = keyLabelLen; 850 dummyLabel.Data = (uint8 *)keyLabel; 851 852 /* passing in password is pretty strange....*/ 853 pbeParams.Passphrase = *password; 854 pbeParams.PseudoRandomFunction = 855 CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1; 856 pbeData.Data = (uint8 *)&pbeParams; 857 pbeData.Length = sizeof(pbeParams); 858 crtn = CSSM_DeriveKey(ccHand, 859 &pbeData, 860 keyUsage, 861 keyAttr, 862 &dummyLabel, 863 NULL, // cred and acl 864 symKey); 865 if(crtn) { 866 printError("CSSM_DeriveKey", crtn); 867 goto errorOut; 868 } 869 /* copy IV back to caller */ 870 /* Nope, not supported */ 871 #if 0 872 if(pbeParams.InitVector.Data != NULL) { 873 if(initVector->Data != NULL) { 874 if(initVector->Length < pbeParams.InitVector.Length) { 875 printf("***Insufficient InitVector\n"); 876 goto errorOut; 877 } 878 } 879 else { 880 initVector->Data = 881 (uint8 *)CSSM_MALLOC(pbeParams.InitVector.Length); 882 } 883 memmove(initVector->Data, pbeParams.InitVector.Data, 884 pbeParams.InitVector.Length); 885 initVector->Length = pbeParams.InitVector.Length; 886 CSSM_FREE(pbeParams.InitVector.Data); 887 } 888 else { 889 printf("***Warning: CSSM_DeriveKey, no InitVector\n"); 890 } 891 #endif 892 crtn = CSSM_DeleteContext(ccHand); 893 if(crtn) { 894 printError("CSSM_DeleteContext", crtn); 895 goto errorOut; 896 } 897 return symKey; 898errorOut: 899 CSSM_FREE(symKey); 900 return NULL; 901} 902 903/* 904 * Cook up a symmetric key with specified key bits and other 905 * params. Currently the CSPDL can only deal with reference keys except when 906 * doing wrap/unwrap, so we manually cook up a raw key, then we null-unwrap it. 907 */ 908CSSM_RETURN cspGenSymKeyWithBits( 909 CSSM_CSP_HANDLE cspHand, 910 CSSM_ALGORITHMS keyAlg, 911 CSSM_KEYUSE keyUsage, 912 const CSSM_DATA *keyBits, 913 unsigned keySizeInBytes, 914 CSSM_KEY_PTR refKey) // init'd and RETURNED 915{ 916 CSSM_KEY rawKey; 917 CSSM_KEYHEADER_PTR hdr = &rawKey.KeyHeader; 918 CSSM_RETURN crtn; 919 920 /* set up a raw key the CSP will accept */ 921 memset(&rawKey, 0, sizeof(CSSM_KEY)); 922 hdr->HeaderVersion = CSSM_KEYHEADER_VERSION; 923 hdr->BlobType = CSSM_KEYBLOB_RAW; 924 hdr->Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; 925 hdr->AlgorithmId = keyAlg; 926 hdr->KeyClass = CSSM_KEYCLASS_SESSION_KEY; 927 hdr->LogicalKeySizeInBits = keySizeInBytes * 8; 928 hdr->KeyAttr = CSSM_KEYATTR_EXTRACTABLE; 929 hdr->KeyUsage = keyUsage; 930 appSetupCssmData(&rawKey.KeyData, keySizeInBytes); 931 memmove(rawKey.KeyData.Data, keyBits->Data, keySizeInBytes); 932 933 /* convert to a ref key */ 934 crtn = cspRawKeyToRef(cspHand, &rawKey, refKey); 935 appFreeCssmData(&rawKey.KeyData, CSSM_FALSE); 936 return crtn; 937} 938 939/* 940 * Free a key. This frees a CSP's resources associated with the key if 941 * the key is a reference key. It also frees key->KeyData. The CSSM_KEY 942 * struct itself is not freed. 943 * Note this has no effect on the CSP or DL cached keys unless the incoming 944 * key is a reference key. 945 */ 946CSSM_RETURN cspFreeKey(CSSM_CSP_HANDLE cspHand, 947 CSSM_KEY_PTR key) 948{ 949 CSSM_RETURN crtn; 950 crtn = CSSM_FreeKey(cspHand, 951 NULL, // access cred 952 key, 953 CSSM_FALSE); // delete - OK? maybe should parameterize? 954 if(crtn) { 955 printError("CSSM_FreeKey", crtn); 956 } 957 return crtn; 958} 959 960/* generate a random and reasonable key size in bits for specified CSSM algorithm */ 961uint32 randKeySizeBits(uint32 alg, 962 opType op) // OT_Encrypt, etc. 963{ 964 uint32 minSize; 965 uint32 maxSize; 966 uint32 size; 967 968 switch(alg) { 969 case CSSM_ALGID_DES: 970 return CSP_DES_KEY_SIZE_DEFAULT; 971 case CSSM_ALGID_3DES_3KEY: 972 case CSSM_ALGID_DESX: 973 return CSP_DES3_KEY_SIZE_DEFAULT; 974 case CSSM_ALGID_ASC: 975 case CSSM_ALGID_RC2: 976 case CSSM_ALGID_RC4: 977 case CSSM_ALGID_RC5: 978 minSize = 5 * 8; 979 maxSize = MAX_KEY_SIZE_RC245_BYTES * 8 ; // somewhat arbitrary 980 break; 981 case CSSM_ALGID_BLOWFISH: 982 minSize = 32; 983 maxSize = 448; 984 break; 985 case CSSM_ALGID_CAST: 986 minSize = 40; 987 maxSize = 128; 988 break; 989 case CSSM_ALGID_IDEA: 990 return CSP_IDEA_KEY_SIZE_DEFAULT; 991 case CSSM_ALGID_RSA: 992 minSize = CSP_RSA_KEY_SIZE_DEFAULT; 993 maxSize = 1024; 994 break; 995 case CSSM_ALGID_DSA: 996 /* signature only, no export restriction */ 997 minSize = 512; 998 maxSize = 1024; 999 break; 1000 case CSSM_ALGID_SHA1HMAC: 1001 minSize = 20 * 8; 1002 maxSize = 256 * 8; 1003 break; 1004 case CSSM_ALGID_MD5HMAC: 1005 minSize = 16 * 8; 1006 maxSize = 256 * 8; 1007 break; 1008 case CSSM_ALGID_FEE: 1009 /* FEE requires discrete sizes */ 1010 size = genRand(1,4); 1011 switch(size) { 1012 case 1: 1013 return 31; 1014 case 2: 1015 if(alg == CSSM_ALGID_FEE) { 1016 return 127; 1017 } 1018 else { 1019 return 128; 1020 } 1021 case 3: 1022 return 161; 1023 case 4: 1024 return 192; 1025 default: 1026 printf("randKeySizeBits: internal error\n"); 1027 return 0; 1028 } 1029 case CSSM_ALGID_ECDSA: 1030 case CSSM_ALGID_SHA1WithECDSA: 1031 /* ECDSA require discrete sizes */ 1032 size = genRand(1,4); 1033 switch(size) { 1034 case 1: 1035 return 192; 1036 case 2: 1037 return 256; 1038 case 3: 1039 return 384; 1040 case 4: 1041 default: 1042 return 521; 1043 } 1044 case CSSM_ALGID_AES: 1045 size = genRand(1, 3); 1046 switch(size) { 1047 case 1: 1048 return 128; 1049 case 2: 1050 return 192; 1051 case 3: 1052 return 256; 1053 } 1054 case CSSM_ALGID_NONE: 1055 return CSP_NULL_CRYPT_KEY_SIZE_DEF; 1056 default: 1057 printf("randKeySizeBits: unknown alg\n"); 1058 return CSP_KEY_SIZE_DEFAULT; 1059 } 1060 size = genRand(minSize, maxSize); 1061 1062 /* per-alg postprocessing.... */ 1063 if(alg != CSSM_ALGID_RC2) { 1064 size &= ~0x7; 1065 } 1066 switch(alg) { 1067 case CSSM_ALGID_RSA: 1068 // new for X - strong keys */ 1069 size &= ~(16 - 1); 1070 break; 1071 case CSSM_ALGID_DSA: 1072 /* size mod 64 == 0 */ 1073 size &= ~(64 - 1); 1074 break; 1075 default: 1076 break; 1077 } 1078 return size; 1079} 1080 1081#pragma mark --------- Encrypt/Decrypt --------- 1082 1083/* 1084 * Encrypt/Decrypt 1085 */ 1086/* 1087 * Common routine for encrypt/decrypt - cook up an appropriate context handle 1088 */ 1089/* 1090 * When true, effectiveKeySizeInBits is passed down via the Params argument. 1091 * Otherwise, we add a customized context attribute. 1092 * Setting this true works with the stock Intel CSSM; this may well change. 1093 * Note this overloading prevent us from specifying RC5 rounds.... 1094 */ 1095#define EFFECTIVE_SIZE_VIA_PARAMS 0 1096CSSM_CC_HANDLE genCryptHandle(CSSM_CSP_HANDLE cspHand, 1097 uint32 algorithm, // CSSM_ALGID_FEED, etc. 1098 uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs 1099 CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. 1100 const CSSM_KEY *key0, 1101 const CSSM_KEY *key1, // for CSSM_ALGID_FEED only - must be the 1102 // public key 1103 const CSSM_DATA *iv, // optional 1104 uint32 effectiveKeySizeInBits, // 0 means skip this attribute 1105 uint32 rounds) // ditto 1106{ 1107 CSSM_CC_HANDLE cryptHand = 0; 1108 uint32 params; 1109 CSSM_RETURN crtn; 1110 CSSM_ACCESS_CREDENTIALS creds; 1111 1112 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); 1113 #if EFFECTIVE_SIZE_VIA_PARAMS 1114 params = effectiveKeySizeInBits; 1115 #else 1116 params = 0; 1117 #endif 1118 switch(algorithm) { 1119 case CSSM_ALGID_DES: 1120 case CSSM_ALGID_3DES_3KEY_EDE: 1121 case CSSM_ALGID_DESX: 1122 case CSSM_ALGID_ASC: 1123 case CSSM_ALGID_RC2: 1124 case CSSM_ALGID_RC4: 1125 case CSSM_ALGID_RC5: 1126 case CSSM_ALGID_AES: 1127 case CSSM_ALGID_BLOWFISH: 1128 case CSSM_ALGID_CAST: 1129 case CSSM_ALGID_IDEA: 1130 case CSSM_ALGID_NONE: // used for wrapKey() 1131 crtn = CSSM_CSP_CreateSymmetricContext(cspHand, 1132 algorithm, 1133 mode, 1134 NULL, // access cred 1135 key0, 1136 iv, // InitVector 1137 padding, 1138 NULL, // Params 1139 &cryptHand); 1140 if(crtn) { 1141 printError("CSSM_CSP_CreateSymmetricContext", crtn); 1142 return 0; 1143 } 1144 break; 1145 case CSSM_ALGID_FEED: 1146 case CSSM_ALGID_FEEDEXP: 1147 case CSSM_ALGID_FEECFILE: 1148 case CSSM_ALGID_RSA: 1149 crtn = CSSM_CSP_CreateAsymmetricContext(cspHand, 1150 algorithm, 1151 &creds, // access 1152 key0, 1153 padding, 1154 &cryptHand); 1155 if(crtn) { 1156 printError("CSSM_CSP_CreateAsymmetricContext", crtn); 1157 return 0; 1158 } 1159 if(key1 != NULL) { 1160 /* 1161 * FEED, some CFILE. Add (non-standard) second key attribute. 1162 */ 1163 crtn = AddContextAttribute(cryptHand, 1164 CSSM_ATTRIBUTE_PUBLIC_KEY, 1165 sizeof(CSSM_KEY), // currently sizeof CSSM_DATA 1166 CAT_Ptr, 1167 key1, 1168 0); 1169 if(crtn) { 1170 printError("AddContextAttribute", crtn); 1171 return 0; 1172 } 1173 } 1174 if(mode != CSSM_ALGMODE_NONE) { 1175 /* special case, e.g., CSSM_ALGMODE_PUBLIC_KEY */ 1176 crtn = AddContextAttribute(cryptHand, 1177 CSSM_ATTRIBUTE_MODE, 1178 sizeof(uint32), 1179 CAT_Uint32, 1180 NULL, 1181 mode); 1182 if(crtn) { 1183 printError("AddContextAttribute", crtn); 1184 return 0; 1185 } 1186 } 1187 break; 1188 default: 1189 printf("genCryptHandle: bogus algorithm\n"); 1190 return 0; 1191 } 1192 #if !EFFECTIVE_SIZE_VIA_PARAMS 1193 /* add optional EffectiveKeySizeInBits and rounds attributes */ 1194 if(effectiveKeySizeInBits != 0) { 1195 CSSM_CONTEXT_ATTRIBUTE attr; 1196 attr.AttributeType = CSSM_ATTRIBUTE_EFFECTIVE_BITS; 1197 attr.AttributeLength = sizeof(uint32); 1198 attr.Attribute.Uint32 = effectiveKeySizeInBits; 1199 crtn = CSSM_UpdateContextAttributes( 1200 cryptHand, 1201 1, 1202 &attr); 1203 if(crtn) { 1204 printError("CSSM_UpdateContextAttributes", crtn); 1205 return crtn; 1206 } 1207 } 1208 #endif 1209 1210 if(rounds != 0) { 1211 CSSM_CONTEXT_ATTRIBUTE attr; 1212 attr.AttributeType = CSSM_ATTRIBUTE_ROUNDS; 1213 attr.AttributeLength = sizeof(uint32); 1214 attr.Attribute.Uint32 = rounds; 1215 crtn = CSSM_UpdateContextAttributes( 1216 cryptHand, 1217 1, 1218 &attr); 1219 if(crtn) { 1220 printError("CSSM_UpdateContextAttributes", crtn); 1221 return crtn; 1222 } 1223 } 1224 1225 return cryptHand; 1226} 1227 1228CSSM_RETURN cspEncrypt(CSSM_CSP_HANDLE cspHand, 1229 uint32 algorithm, // CSSM_ALGID_FEED, etc. 1230 uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs 1231 CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. 1232 const CSSM_KEY *key, // public or session key 1233 const CSSM_KEY *pubKey, // for CSSM_ALGID_FEED, CSSM_ALGID_FEECFILE only 1234 uint32 effectiveKeySizeInBits, // 0 means skip this attribute 1235 uint32 rounds, // ditto 1236 const CSSM_DATA *iv, // init vector, optional 1237 const CSSM_DATA *ptext, 1238 CSSM_DATA_PTR ctext, // RETURNED 1239 CSSM_BOOL mallocCtext) // if true, and ctext empty, malloc 1240 // by getting size from CSP 1241{ 1242 CSSM_CC_HANDLE cryptHand; 1243 CSSM_RETURN crtn; 1244 CSSM_SIZE bytesEncrypted; 1245 CSSM_DATA remData = {0, NULL}; 1246 CSSM_RETURN ocrtn = CSSM_OK; 1247 unsigned origCtextLen; // the amount we malloc, if any 1248 CSSM_RETURN savedErr = CSSM_OK; 1249 CSSM_BOOL restoreErr = CSSM_FALSE; 1250 1251 cryptHand = genCryptHandle(cspHand, 1252 algorithm, 1253 mode, 1254 padding, 1255 key, 1256 pubKey, 1257 iv, 1258 effectiveKeySizeInBits, 1259 rounds); 1260 if(cryptHand == 0) { 1261 return CSSMERR_CSSM_INTERNAL_ERROR; 1262 } 1263 if(mallocCtext && (ctext->Length == 0)) { 1264 CSSM_QUERY_SIZE_DATA querySize; 1265 querySize.SizeInputBlock = ptext->Length; 1266 crtn = CSSM_QuerySize(cryptHand, 1267 CSSM_TRUE, // encrypt 1268 1, 1269 &querySize); 1270 if(crtn) { 1271 printError("CSSM_QuerySize", crtn); 1272 ocrtn = crtn; 1273 goto abort; 1274 } 1275 if(querySize.SizeOutputBlock == 0) { 1276 /* CSP couldn't figure this out; skip our malloc */ 1277 printf("***cspEncrypt: warning: cipherTextSize unknown; " 1278 "skipping malloc\n"); 1279 origCtextLen = 0; 1280 } 1281 else { 1282 ctext->Data = (uint8 *) 1283 appMalloc(querySize.SizeOutputBlock, NULL); 1284 if(ctext->Data == NULL) { 1285 printf("Insufficient heap space\n"); 1286 ocrtn = CSSM_ERRCODE_MEMORY_ERROR; 1287 goto abort; 1288 } 1289 ctext->Length = origCtextLen = querySize.SizeOutputBlock; 1290 memset(ctext->Data, 0, ctext->Length); 1291 } 1292 } 1293 else { 1294 origCtextLen = ctext->Length; 1295 } 1296 crtn = CSSM_EncryptData(cryptHand, 1297 ptext, 1298 1, 1299 ctext, 1300 1, 1301 &bytesEncrypted, 1302 &remData); 1303 if(crtn == CSSM_OK) { 1304 /* 1305 * Deal with remData - its contents are included in bytesEncrypted. 1306 */ 1307 if((remData.Length != 0) && mallocCtext) { 1308 /* shouldn't happen - right? */ 1309 if(bytesEncrypted > origCtextLen) { 1310 /* malloc and copy a new one */ 1311 uint8 *newCdata = (uint8 *)appMalloc(bytesEncrypted, NULL); 1312 printf("**Warning: app malloced cipherBuf, but got nonzero " 1313 "remData!\n"); 1314 if(newCdata == NULL) { 1315 printf("Insufficient heap space\n"); 1316 ocrtn = CSSM_ERRCODE_MEMORY_ERROR; 1317 goto abort; 1318 } 1319 memmove(newCdata, ctext->Data, ctext->Length); 1320 memmove(newCdata+ctext->Length, remData.Data, remData.Length); 1321 CSSM_FREE(ctext->Data); 1322 ctext->Data = newCdata; 1323 } 1324 else { 1325 /* there's room left over */ 1326 memmove(ctext->Data+ctext->Length, remData.Data, remData.Length); 1327 } 1328 ctext->Length = bytesEncrypted; 1329 } 1330 // NOTE: We return the proper length in ctext.... 1331 ctext->Length = bytesEncrypted; 1332 } 1333 else { 1334 savedErr = crtn; 1335 restoreErr = CSSM_TRUE; 1336 printError("CSSM_EncryptData", crtn); 1337 } 1338abort: 1339 crtn = CSSM_DeleteContext(cryptHand); 1340 if(crtn) { 1341 printError("CSSM_DeleteContext", crtn); 1342 ocrtn = crtn; 1343 } 1344 if(restoreErr) { 1345 ocrtn = savedErr; 1346 } 1347 return ocrtn; 1348} 1349 1350#define PAD_IMPLIES_RAND_PTEXTSIZE 1 1351#define LOG_STAGED_OPS 0 1352#if LOG_STAGED_OPS 1353#define soprintf(s) printf s 1354#else 1355#define soprintf(s) 1356#endif 1357 1358CSSM_RETURN cspStagedEncrypt(CSSM_CSP_HANDLE cspHand, 1359 uint32 algorithm, // CSSM_ALGID_FEED, etc. 1360 uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs 1361 CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. 1362 const CSSM_KEY *key, // public or session key 1363 const CSSM_KEY *pubKey, // for CSSM_ALGID_FEED, CSSM_ALGID_FEECFILE only 1364 uint32 effectiveKeySizeInBits, // 0 means skip this attribute 1365 uint32 cipherBlockSize, // ditto 1366 uint32 rounds, // ditto 1367 const CSSM_DATA *iv, // init vector, optional 1368 const CSSM_DATA *ptext, 1369 CSSM_DATA_PTR ctext, // RETURNED, we malloc 1370 CSSM_BOOL multiUpdates) // false:single update, true:multi updates 1371{ 1372 CSSM_CC_HANDLE cryptHand; 1373 CSSM_RETURN crtn; 1374 CSSM_SIZE bytesEncrypted; // per update 1375 CSSM_SIZE bytesEncryptedTotal = 0; 1376 CSSM_RETURN ocrtn = CSSM_OK; // 'our' crtn 1377 unsigned toMove; // remaining 1378 unsigned thisMove; // bytes to encrypt on this update 1379 CSSM_DATA thisPtext; // running ptr into ptext 1380 CSSM_DATA ctextWork; // per update, mallocd by CSP 1381 CSSM_QUERY_SIZE_DATA querySize; 1382 uint8 *origCtext; // initial ctext->Data 1383 unsigned origCtextLen; // amount we mallocd 1384 CSSM_BOOL restoreErr = CSSM_FALSE; 1385 CSSM_RETURN savedErr = CSSM_OK; 1386 1387 1388 cryptHand = genCryptHandle(cspHand, 1389 algorithm, 1390 mode, 1391 padding, 1392 key, 1393 pubKey, 1394 iv, 1395 effectiveKeySizeInBits, 1396 rounds); 1397 if(cryptHand == 0) { 1398 return CSSMERR_CSP_INTERNAL_ERROR; 1399 } 1400 if(cipherBlockSize) { 1401 crtn = AddContextAttribute(cryptHand, 1402 CSSM_ATTRIBUTE_BLOCK_SIZE, 1403 sizeof(uint32), 1404 CAT_Uint32, 1405 NULL, 1406 cipherBlockSize); 1407 if(crtn) { 1408 printError("CSSM_UpdateContextAttributes", crtn); 1409 goto abort; 1410 } 1411 } 1412 1413 /* obtain total required ciphertext size and block size */ 1414 querySize.SizeInputBlock = ptext->Length; 1415 crtn = CSSM_QuerySize(cryptHand, 1416 CSSM_TRUE, // encrypt 1417 1, 1418 &querySize); 1419 if(crtn) { 1420 printError("CSSM_QuerySize(1)", crtn); 1421 ocrtn = CSSMERR_CSP_INTERNAL_ERROR; 1422 goto abort; 1423 } 1424 if(querySize.SizeOutputBlock == 0) { 1425 /* CSP couldn't figure this out; skip our malloc - caller is taking its 1426 * chances */ 1427 printf("***cspStagedEncrypt: warning: cipherTextSize unknown; aborting\n"); 1428 ocrtn = CSSMERR_CSP_INTERNAL_ERROR; 1429 goto abort; 1430 } 1431 else { 1432 origCtextLen = querySize.SizeOutputBlock; 1433 if(algorithm == CSSM_ALGID_ASC) { 1434 /* ASC is weird - the more chunks we do, the bigger the 1435 * resulting ctext...*/ 1436 origCtextLen *= 2; 1437 } 1438 ctext->Length = origCtextLen; 1439 ctext->Data = origCtext = (uint8 *)appMalloc(origCtextLen, NULL); 1440 if(ctext->Data == NULL) { 1441 printf("Insufficient heap space\n"); 1442 ocrtn = CSSMERR_CSP_MEMORY_ERROR; 1443 goto abort; 1444 } 1445 memset(ctext->Data, 0, ctext->Length); 1446 } 1447 1448 crtn = CSSM_EncryptDataInit(cryptHand); 1449 if(crtn) { 1450 printError("CSSM_EncryptDataInit", crtn); 1451 ocrtn = crtn; 1452 goto abort; 1453 } 1454 1455 toMove = ptext->Length; 1456 thisPtext.Data = ptext->Data; 1457 while(toMove) { 1458 if(multiUpdates) { 1459 thisMove = genRand(1, toMove); 1460 } 1461 else { 1462 /* just do one pass thru this loop */ 1463 thisMove = toMove; 1464 } 1465 thisPtext.Length = thisMove; 1466 /* let CSP do the individual mallocs */ 1467 ctextWork.Data = NULL; 1468 ctextWork.Length = 0; 1469 soprintf(("*** EncryptDataUpdate: ptextLen 0x%x\n", thisMove)); 1470 crtn = CSSM_EncryptDataUpdate(cryptHand, 1471 &thisPtext, 1472 1, 1473 &ctextWork, 1474 1, 1475 &bytesEncrypted); 1476 if(crtn) { 1477 printError("CSSM_EncryptDataUpdate", crtn); 1478 ocrtn = crtn; 1479 goto abort; 1480 } 1481 // NOTE: We return the proper length in ctext.... 1482 ctextWork.Length = bytesEncrypted; 1483 soprintf(("*** EncryptDataUpdate: ptextLen 0x%x bytesEncrypted 0x%x\n", 1484 thisMove, bytesEncrypted)); 1485 thisPtext.Data += thisMove; 1486 toMove -= thisMove; 1487 if(bytesEncrypted > ctext->Length) { 1488 printf("cspStagedEncrypt: ctext overflow!\n"); 1489 ocrtn = crtn; 1490 goto abort; 1491 } 1492 if(bytesEncrypted != 0) { 1493 memmove(ctext->Data, ctextWork.Data, bytesEncrypted); 1494 bytesEncryptedTotal += bytesEncrypted; 1495 ctext->Data += bytesEncrypted; 1496 ctext->Length -= bytesEncrypted; 1497 } 1498 if(ctextWork.Data != NULL) { 1499 CSSM_FREE(ctextWork.Data); 1500 } 1501 } 1502 /* OK, one more */ 1503 ctextWork.Data = NULL; 1504 ctextWork.Length = 0; 1505 crtn = CSSM_EncryptDataFinal(cryptHand, &ctextWork); 1506 if(crtn) { 1507 printError("CSSM_EncryptDataFinal", crtn); 1508 savedErr = crtn; 1509 restoreErr = CSSM_TRUE; 1510 goto abort; 1511 } 1512 if(ctextWork.Length != 0) { 1513 bytesEncryptedTotal += ctextWork.Length; 1514 if(ctextWork.Length > ctext->Length) { 1515 printf("cspStagedEncrypt: ctext overflow (2)!\n"); 1516 ocrtn = CSSMERR_CSP_INTERNAL_ERROR; 1517 goto abort; 1518 } 1519 memmove(ctext->Data, ctextWork.Data, ctextWork.Length); 1520 } 1521 if(ctextWork.Data) { 1522 /* this could have gotten mallocd and Length still be zero */ 1523 CSSM_FREE(ctextWork.Data); 1524 } 1525 1526 /* retweeze ctext */ 1527 ctext->Data = origCtext; 1528 ctext->Length = bytesEncryptedTotal; 1529abort: 1530 crtn = CSSM_DeleteContext(cryptHand); 1531 if(crtn) { 1532 printError("CSSM_DeleteContext", crtn); 1533 ocrtn = crtn; 1534 } 1535 if(restoreErr) { 1536 /* give caller the error from the encrypt */ 1537 ocrtn = savedErr; 1538 } 1539 return ocrtn; 1540} 1541 1542CSSM_RETURN cspDecrypt(CSSM_CSP_HANDLE cspHand, 1543 uint32 algorithm, // CSSM_ALGID_FEED, etc. 1544 uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs 1545 CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. 1546 const CSSM_KEY *key, // public or session key 1547 const CSSM_KEY *pubKey, // for CSSM_ALGID_FEED, CSSM_ALGID_FEECFILE only 1548 uint32 effectiveKeySizeInBits, // 0 means skip this attribute 1549 uint32 rounds, // ditto 1550 const CSSM_DATA *iv, // init vector, optional 1551 const CSSM_DATA *ctext, 1552 CSSM_DATA_PTR ptext, // RETURNED 1553 CSSM_BOOL mallocPtext) // if true and ptext->Length = 0, 1554 // we'll malloc 1555{ 1556 CSSM_CC_HANDLE cryptHand; 1557 CSSM_RETURN crtn; 1558 CSSM_RETURN ocrtn = CSSM_OK; 1559 CSSM_SIZE bytesDecrypted; 1560 CSSM_DATA remData = {0, NULL}; 1561 unsigned origPtextLen; // the amount we malloc, if any 1562 1563 cryptHand = genCryptHandle(cspHand, 1564 algorithm, 1565 mode, 1566 padding, 1567 key, 1568 pubKey, 1569 iv, 1570 effectiveKeySizeInBits, 1571 rounds); 1572 if(cryptHand == 0) { 1573 return CSSMERR_CSP_INTERNAL_ERROR; 1574 } 1575 if(mallocPtext && (ptext->Length == 0)) { 1576 CSSM_QUERY_SIZE_DATA querySize; 1577 querySize.SizeInputBlock = ctext->Length; 1578 crtn = CSSM_QuerySize(cryptHand, 1579 CSSM_FALSE, // encrypt 1580 1, 1581 &querySize); 1582 if(crtn) { 1583 printError("CSSM_QuerySize", crtn); 1584 ocrtn = crtn; 1585 goto abort; 1586 } 1587 if(querySize.SizeOutputBlock == 0) { 1588 /* CSP couldn't figure this one out; skip our malloc */ 1589 printf("***cspDecrypt: warning: plainTextSize unknown; " 1590 "skipping malloc\n"); 1591 origPtextLen = 0; 1592 } 1593 else { 1594 ptext->Data = 1595 (uint8 *)appMalloc(querySize.SizeOutputBlock, NULL); 1596 if(ptext->Data == NULL) { 1597 printf("Insufficient heap space\n"); 1598 ocrtn = CSSMERR_CSP_MEMORY_ERROR; 1599 goto abort; 1600 } 1601 ptext->Length = origPtextLen = querySize.SizeOutputBlock; 1602 memset(ptext->Data, 0, ptext->Length); 1603 } 1604 } 1605 else { 1606 origPtextLen = ptext->Length; 1607 } 1608 crtn = CSSM_DecryptData(cryptHand, 1609 ctext, 1610 1, 1611 ptext, 1612 1, 1613 &bytesDecrypted, 1614 &remData); 1615 if(crtn == CSSM_OK) { 1616 /* 1617 * Deal with remData - its contents are included in bytesDecrypted. 1618 */ 1619 if((remData.Length != 0) && mallocPtext) { 1620 /* shouldn't happen - right? */ 1621 if(bytesDecrypted > origPtextLen) { 1622 /* malloc and copy a new one */ 1623 uint8 *newPdata = (uint8 *)appMalloc(bytesDecrypted, NULL); 1624 printf("**Warning: app malloced ClearBuf, but got nonzero " 1625 "remData!\n"); 1626 if(newPdata == NULL) { 1627 printf("Insufficient heap space\n"); 1628 ocrtn = CSSMERR_CSP_MEMORY_ERROR; 1629 goto abort; 1630 } 1631 memmove(newPdata, ptext->Data, ptext->Length); 1632 memmove(newPdata + ptext->Length, 1633 remData.Data, remData.Length); 1634 CSSM_FREE(ptext->Data); 1635 ptext->Data = newPdata; 1636 } 1637 else { 1638 /* there's room left over */ 1639 memmove(ptext->Data + ptext->Length, 1640 remData.Data, remData.Length); 1641 } 1642 ptext->Length = bytesDecrypted; 1643 } 1644 // NOTE: We return the proper length in ptext.... 1645 ptext->Length = bytesDecrypted; 1646 1647 // FIXME - sometimes get mallocd RemData here, but never any valid data 1648 // there...side effect of CSPFullPluginSession's buffer handling logic; 1649 // but will we ever actually see valid data in RemData? So far we never 1650 // have.... 1651 if(remData.Data != NULL) { 1652 appFree(remData.Data, NULL); 1653 } 1654 } 1655 else { 1656 printError("CSSM_DecryptData", crtn); 1657 ocrtn = crtn; 1658 } 1659abort: 1660 crtn = CSSM_DeleteContext(cryptHand); 1661 if(crtn) { 1662 printError("CSSM_DeleteContext", crtn); 1663 ocrtn = crtn; 1664 } 1665 return ocrtn; 1666} 1667 1668CSSM_RETURN cspStagedDecrypt(CSSM_CSP_HANDLE cspHand, 1669 uint32 algorithm, // CSSM_ALGID_FEED, etc. 1670 uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs 1671 CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. 1672 const CSSM_KEY *key, // public or session key 1673 const CSSM_KEY *pubKey, // for CSSM_ALGID_FEED, CSSM_ALGID_FEECFILE only 1674 uint32 effectiveKeySizeInBits, // 0 means skip this attribute 1675 uint32 cipherBlockSize, // ditto 1676 uint32 rounds, // ditto 1677 const CSSM_DATA *iv, // init vector, optional 1678 const CSSM_DATA *ctext, 1679 CSSM_DATA_PTR ptext, // RETURNED, we malloc 1680 CSSM_BOOL multiUpdates) // false:single update, true:multi updates 1681{ 1682 CSSM_CC_HANDLE cryptHand; 1683 CSSM_RETURN crtn; 1684 CSSM_SIZE bytesDecrypted; // per update 1685 CSSM_SIZE bytesDecryptedTotal = 0; 1686 CSSM_RETURN ocrtn = CSSM_OK; // 'our' crtn 1687 unsigned toMove; // remaining 1688 unsigned thisMove; // bytes to encrypt on this update 1689 CSSM_DATA thisCtext; // running ptr into ptext 1690 CSSM_DATA ptextWork; // per update, mallocd by CSP 1691 CSSM_QUERY_SIZE_DATA querySize; 1692 uint8 *origPtext; // initial ptext->Data 1693 unsigned origPtextLen; // amount we mallocd 1694 1695 cryptHand = genCryptHandle(cspHand, 1696 algorithm, 1697 mode, 1698 padding, 1699 key, 1700 pubKey, 1701 iv, 1702 effectiveKeySizeInBits, 1703 rounds); 1704 if(cryptHand == 0) { 1705 return CSSMERR_CSP_INTERNAL_ERROR; 1706 } 1707 if(cipherBlockSize) { 1708 crtn = AddContextAttribute(cryptHand, 1709 CSSM_ATTRIBUTE_BLOCK_SIZE, 1710 sizeof(uint32), 1711 CAT_Uint32, 1712 NULL, 1713 cipherBlockSize); 1714 if(crtn) { 1715 printError("CSSM_UpdateContextAttributes", crtn); 1716 goto abort; 1717 } 1718 } 1719 1720 /* obtain total required ciphertext size and block size */ 1721 querySize.SizeInputBlock = ctext->Length; 1722 crtn = CSSM_QuerySize(cryptHand, 1723 CSSM_FALSE, // encrypt 1724 1, 1725 &querySize); 1726 if(crtn) { 1727 printError("CSSM_QuerySize(1)", crtn); 1728 ocrtn = crtn; 1729 goto abort; 1730 } 1731 1732 /* required ptext size should be independent of number of chunks */ 1733 if(querySize.SizeOutputBlock == 0) { 1734 printf("***warning: cspStagedDecrypt: plainTextSize unknown; aborting\n"); 1735 ocrtn = CSSMERR_CSP_INTERNAL_ERROR; 1736 goto abort; 1737 } 1738 else { 1739 // until exit, ptext->Length indicates remaining bytes of usable data in 1740 // ptext->Data 1741 ptext->Length = origPtextLen = querySize.SizeOutputBlock; 1742 ptext->Data = origPtext = 1743 (uint8 *)appMalloc(origPtextLen, NULL); 1744 if(ptext->Data == NULL) { 1745 printf("Insufficient heap space\n"); 1746 ocrtn = CSSMERR_CSP_INTERNAL_ERROR; 1747 goto abort; 1748 } 1749 memset(ptext->Data, 0, ptext->Length); 1750 } 1751 1752 crtn = CSSM_DecryptDataInit(cryptHand); 1753 if(crtn) { 1754 printError("CSSM_DecryptDataInit", crtn); 1755 ocrtn = crtn; 1756 goto abort; 1757 } 1758 toMove = ctext->Length; 1759 thisCtext.Data = ctext->Data; 1760 while(toMove) { 1761 if(multiUpdates) { 1762 thisMove = genRand(1, toMove); 1763 } 1764 else { 1765 /* just do one pass thru this loop */ 1766 thisMove = toMove; 1767 } 1768 thisCtext.Length = thisMove; 1769 /* let CSP do the individual mallocs */ 1770 ptextWork.Data = NULL; 1771 ptextWork.Length = 0; 1772 soprintf(("*** DecryptDataUpdate: ctextLen 0x%x\n", thisMove)); 1773 crtn = CSSM_DecryptDataUpdate(cryptHand, 1774 &thisCtext, 1775 1, 1776 &ptextWork, 1777 1, 1778 &bytesDecrypted); 1779 if(crtn) { 1780 printError("CSSM_DecryptDataUpdate", crtn); 1781 ocrtn = crtn; 1782 goto abort; 1783 } 1784 // 1785 // NOTE: We return the proper length in ptext.... 1786 ptextWork.Length = bytesDecrypted; 1787 thisCtext.Data += thisMove; 1788 toMove -= thisMove; 1789 if(bytesDecrypted > ptext->Length) { 1790 printf("cspStagedDecrypt: ptext overflow!\n"); 1791 ocrtn = CSSMERR_CSP_INTERNAL_ERROR; 1792 goto abort; 1793 } 1794 if(bytesDecrypted != 0) { 1795 memmove(ptext->Data, ptextWork.Data, bytesDecrypted); 1796 bytesDecryptedTotal += bytesDecrypted; 1797 ptext->Data += bytesDecrypted; 1798 ptext->Length -= bytesDecrypted; 1799 } 1800 if(ptextWork.Data != NULL) { 1801 CSSM_FREE(ptextWork.Data); 1802 } 1803 } 1804 /* OK, one more */ 1805 ptextWork.Data = NULL; 1806 ptextWork.Length = 0; 1807 crtn = CSSM_DecryptDataFinal(cryptHand, &ptextWork); 1808 if(crtn) { 1809 printError("CSSM_DecryptDataFinal", crtn); 1810 ocrtn = crtn; 1811 goto abort; 1812 } 1813 if(ptextWork.Length != 0) { 1814 bytesDecryptedTotal += ptextWork.Length; 1815 if(ptextWork.Length > ptext->Length) { 1816 printf("cspStagedDecrypt: ptext overflow (2)!\n"); 1817 ocrtn = CSSMERR_CSP_INTERNAL_ERROR; 1818 goto abort; 1819 } 1820 memmove(ptext->Data, ptextWork.Data, ptextWork.Length); 1821 } 1822 if(ptextWork.Data) { 1823 /* this could have gotten mallocd and Length still be zero */ 1824 CSSM_FREE(ptextWork.Data); 1825 } 1826 1827 /* retweeze ptext */ 1828 ptext->Data = origPtext; 1829 ptext->Length = bytesDecryptedTotal; 1830abort: 1831 crtn = CSSM_DeleteContext(cryptHand); 1832 if(crtn) { 1833 printError("CSSM_DeleteContext", crtn); 1834 ocrtn = crtn; 1835 } 1836 return ocrtn; 1837} 1838 1839#pragma mark --------- sign/verify/MAC --------- 1840 1841/* 1842 * Signature routines 1843 * This all-in-one sign op has a special case for RSA keys. If the requested 1844 * alg is MD5 or SHA1, we'll do a manual digest op followed by raw RSA sign. 1845 * Likewise, if it's CSSM_ALGID_DSA, we'll do manual SHA1 digest followed by 1846 * raw DSA sign. 1847 */ 1848 1849CSSM_RETURN cspSign(CSSM_CSP_HANDLE cspHand, 1850 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. 1851 CSSM_KEY_PTR key, // private key 1852 const CSSM_DATA *text, 1853 CSSM_DATA_PTR sig) // RETURNED 1854{ 1855 CSSM_CC_HANDLE sigHand; 1856 CSSM_RETURN crtn; 1857 CSSM_RETURN ocrtn = CSSM_OK; 1858 const CSSM_DATA *ptext; 1859 CSSM_DATA digest = {0, NULL}; 1860 CSSM_ALGORITHMS digestAlg = CSSM_ALGID_NONE; 1861 1862 /* handle special cases for raw sign */ 1863 switch(algorithm) { 1864 case CSSM_ALGID_SHA1: 1865 digestAlg = CSSM_ALGID_SHA1; 1866 algorithm = CSSM_ALGID_RSA; 1867 break; 1868 case CSSM_ALGID_MD5: 1869 digestAlg = CSSM_ALGID_MD5; 1870 algorithm = CSSM_ALGID_RSA; 1871 break; 1872 case CSSM_ALGID_DSA: 1873 digestAlg = CSSM_ALGID_SHA1; 1874 algorithm = CSSM_ALGID_DSA; 1875 break; 1876 default: 1877 break; 1878 } 1879 if(digestAlg != CSSM_ALGID_NONE) { 1880 crtn = cspDigest(cspHand, 1881 digestAlg, 1882 CSSM_FALSE, // mallocDigest 1883 text, 1884 &digest); 1885 if(crtn) { 1886 return crtn; 1887 } 1888 /* sign digest with raw RSA/DSA */ 1889 ptext = &digest; 1890 } 1891 else { 1892 ptext = text; 1893 } 1894 crtn = CSSM_CSP_CreateSignatureContext(cspHand, 1895 algorithm, 1896 NULL, // passPhrase 1897 key, 1898 &sigHand); 1899 if(crtn) { 1900 printError("CSSM_CSP_CreateSignatureContext (1)", crtn); 1901 return crtn; 1902 } 1903 crtn = CSSM_SignData(sigHand, 1904 ptext, 1905 1, 1906 digestAlg, 1907 sig); 1908 if(crtn) { 1909 printError("CSSM_SignData", crtn); 1910 ocrtn = crtn; 1911 } 1912 crtn = CSSM_DeleteContext(sigHand); 1913 if(crtn) { 1914 printError("CSSM_DeleteContext", crtn); 1915 ocrtn = crtn; 1916 } 1917 if(digest.Data != NULL) { 1918 CSSM_FREE(digest.Data); 1919 } 1920 return ocrtn; 1921} 1922 1923/* 1924 * Staged sign. Each update does a random number of bytes 'till through. 1925 */ 1926CSSM_RETURN cspStagedSign(CSSM_CSP_HANDLE cspHand, 1927 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. 1928 CSSM_KEY_PTR key, // private key 1929 const CSSM_DATA *text, 1930 CSSM_BOOL multiUpdates, // false:single update, true:multi updates 1931 CSSM_DATA_PTR sig) // RETURNED 1932{ 1933 CSSM_CC_HANDLE sigHand; 1934 CSSM_RETURN crtn; 1935 CSSM_RETURN ocrtn = CSSM_OK; 1936 unsigned thisMove; // this update 1937 unsigned toMove; // total to go 1938 CSSM_DATA thisText; // actaully passed to update 1939 crtn = CSSM_CSP_CreateSignatureContext(cspHand, 1940 algorithm, 1941 NULL, // passPhrase 1942 key, 1943 &sigHand); 1944 if(crtn) { 1945 printError("CSSM_CSP_CreateSignatureContext (1)", crtn); 1946 return crtn; 1947 } 1948 crtn = CSSM_SignDataInit(sigHand); 1949 if(crtn) { 1950 printError("CSSM_SignDataInit", crtn); 1951 ocrtn = crtn; 1952 goto abort; 1953 } 1954 toMove = text->Length; 1955 thisText.Data = text->Data; 1956 while(toMove) { 1957 if(multiUpdates) { 1958 thisMove = genRand(1, toMove); 1959 } 1960 else { 1961 thisMove = toMove; 1962 } 1963 thisText.Length = thisMove; 1964 crtn = CSSM_SignDataUpdate(sigHand, 1965 &thisText, 1966 1); 1967 if(crtn) { 1968 printError("CSSM_SignDataUpdate", crtn); 1969 ocrtn = crtn; 1970 goto abort; 1971 } 1972 thisText.Data += thisMove; 1973 toMove -= thisMove; 1974 } 1975 crtn = CSSM_SignDataFinal(sigHand, sig); 1976 if(crtn) { 1977 printError("CSSM_SignDataFinal", crtn); 1978 ocrtn = crtn; 1979 goto abort; 1980 } 1981abort: 1982 crtn = CSSM_DeleteContext(sigHand); 1983 if(crtn) { 1984 printError("CSSM_DeleteContext", crtn); 1985 ocrtn = crtn; 1986 } 1987 return ocrtn; 1988} 1989 1990/* 1991 * This all-in-one verify op has a special case for RSA keys. If the requested 1992 * alg is MD5 or SHA1, we'll do a manual digest op followed by raw RSA verify. 1993 * Likewise, if it's CSSM_ALGID_DSA, we'll do manual SHA1 digest followed by 1994 * raw DSA sign. 1995 */ 1996 1997CSSM_RETURN cspSigVerify(CSSM_CSP_HANDLE cspHand, 1998 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. 1999 CSSM_KEY_PTR key, // public key 2000 const CSSM_DATA *text, 2001 const CSSM_DATA *sig, 2002 CSSM_RETURN expectResult) // expected result is verify failure 2003 // CSSM_OK - expect success 2004{ 2005 CSSM_CC_HANDLE sigHand; 2006 CSSM_RETURN ocrtn = CSSM_OK; 2007 CSSM_RETURN crtn; 2008 const CSSM_DATA *ptext; 2009 CSSM_DATA digest = {0, NULL}; 2010 CSSM_ALGORITHMS digestAlg = CSSM_ALGID_NONE; 2011 2012 /* handle special cases for raw sign */ 2013 switch(algorithm) { 2014 case CSSM_ALGID_SHA1: 2015 digestAlg = CSSM_ALGID_SHA1; 2016 algorithm = CSSM_ALGID_RSA; 2017 break; 2018 case CSSM_ALGID_MD5: 2019 digestAlg = CSSM_ALGID_MD5; 2020 algorithm = CSSM_ALGID_RSA; 2021 break; 2022 case CSSM_ALGID_DSA: 2023 digestAlg = CSSM_ALGID_SHA1; 2024 algorithm = CSSM_ALGID_DSA; 2025 break; 2026 default: 2027 break; 2028 } 2029 if(digestAlg != CSSM_ALGID_NONE) { 2030 crtn = cspDigest(cspHand, 2031 digestAlg, 2032 CSSM_FALSE, // mallocDigest 2033 text, 2034 &digest); 2035 if(crtn) { 2036 return crtn; 2037 } 2038 /* sign digest with raw RSA/DSA */ 2039 ptext = &digest; 2040 } 2041 else { 2042 ptext = text; 2043 } 2044 crtn = CSSM_CSP_CreateSignatureContext(cspHand, 2045 algorithm, 2046 NULL, // passPhrase 2047 key, 2048 &sigHand); 2049 if(crtn) { 2050 printError("CSSM_CSP_CreateSignatureContext (3)", crtn); 2051 return crtn; 2052 } 2053 2054 crtn = CSSM_VerifyData(sigHand, 2055 ptext, 2056 1, 2057 digestAlg, 2058 sig); 2059 if(crtn != expectResult) { 2060 if(!crtn) { 2061 printf("Unexpected good Sig Verify\n"); 2062 } 2063 else { 2064 printError("CSSM_VerifyData", crtn); 2065 } 2066 ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; 2067 } 2068 crtn = CSSM_DeleteContext(sigHand); 2069 if(crtn) { 2070 printError("CSSM_DeleteContext", crtn); 2071 ocrtn = crtn; 2072 } 2073 if(digest.Data != NULL) { 2074 CSSM_FREE(digest.Data); 2075 } 2076 return ocrtn; 2077} 2078 2079/* 2080 * Staged verify. Each update does a random number of bytes 'till through. 2081 */ 2082CSSM_RETURN cspStagedSigVerify(CSSM_CSP_HANDLE cspHand, 2083 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. 2084 CSSM_KEY_PTR key, // private key 2085 const CSSM_DATA *text, 2086 const CSSM_DATA *sig, 2087 CSSM_BOOL multiUpdates, // false:single update, true:multi updates 2088 CSSM_RETURN expectResult) // expected result is verify failure 2089 // CSSM_TRUE - expect success 2090{ 2091 CSSM_CC_HANDLE sigHand; 2092 CSSM_RETURN crtn; 2093 CSSM_RETURN ocrtn = CSSM_OK; 2094 unsigned thisMove; // this update 2095 unsigned toMove; // total to go 2096 CSSM_DATA thisText; // actaully passed to update 2097 crtn = CSSM_CSP_CreateSignatureContext(cspHand, 2098 algorithm, 2099 NULL, // passPhrase 2100 key, 2101 &sigHand); 2102 if(crtn) { 2103 printError("CSSM_CSP_CreateSignatureContext (4)", crtn); 2104 return crtn; 2105 } 2106 crtn = CSSM_VerifyDataInit(sigHand); 2107 if(crtn) { 2108 printError("CSSM_VerifyDataInit", crtn); 2109 ocrtn = crtn; 2110 goto abort; 2111 } 2112 toMove = text->Length; 2113 thisText.Data = text->Data; 2114 while(toMove) { 2115 if(multiUpdates) { 2116 thisMove = genRand(1, toMove); 2117 } 2118 else { 2119 thisMove = toMove; 2120 } 2121 thisText.Length = thisMove; 2122 crtn = CSSM_VerifyDataUpdate(sigHand, 2123 &thisText, 2124 1); 2125 if(crtn) { 2126 printError("CSSM_VerifyDataUpdate", crtn); 2127 ocrtn = crtn; 2128 goto abort; 2129 } 2130 thisText.Data += thisMove; 2131 toMove -= thisMove; 2132 } 2133 crtn = CSSM_VerifyDataFinal(sigHand, sig); 2134 if(crtn != expectResult) { 2135 if(crtn) { 2136 printError("CSSM_VerifyDataFinal", crtn); 2137 } 2138 else { 2139 printf("Unexpected good Staged Sig Verify\n"); 2140 } 2141 ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; 2142 } 2143abort: 2144 crtn = CSSM_DeleteContext(sigHand); 2145 if(crtn) { 2146 printError("CSSM_DeleteContext", crtn); 2147 ocrtn = crtn; 2148 } 2149 return ocrtn; 2150} 2151 2152/* 2153 * MAC routines 2154 */ 2155CSSM_RETURN cspGenMac(CSSM_CSP_HANDLE cspHand, 2156 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. 2157 CSSM_KEY_PTR key, // session key 2158 const CSSM_DATA *text, 2159 CSSM_DATA_PTR mac) // RETURNED 2160{ 2161 CSSM_CC_HANDLE macHand; 2162 CSSM_RETURN crtn; 2163 CSSM_RETURN ocrtn = CSSM_OK; 2164 crtn = CSSM_CSP_CreateMacContext(cspHand, 2165 algorithm, 2166 key, 2167 &macHand); 2168 if(crtn) { 2169 printError("CSSM_CSP_CreateMacContext (1)", crtn); 2170 return crtn; 2171 } 2172 crtn = CSSM_GenerateMac(macHand, 2173 text, 2174 1, 2175 mac); 2176 if(crtn) { 2177 printError("CSSM_GenerateMac", crtn); 2178 ocrtn = crtn; 2179 } 2180 crtn = CSSM_DeleteContext(macHand); 2181 if(crtn) { 2182 printError("CSSM_DeleteContext", crtn); 2183 ocrtn = crtn; 2184 } 2185 return ocrtn; 2186} 2187 2188/* 2189 * Staged generate mac. 2190 */ 2191CSSM_RETURN cspStagedGenMac(CSSM_CSP_HANDLE cspHand, 2192 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. 2193 CSSM_KEY_PTR key, // private key 2194 const CSSM_DATA *text, 2195 CSSM_BOOL mallocMac, // if true and digest->Length = 0, we'll 2196 // malloc 2197 CSSM_BOOL multiUpdates, // false:single update, true:multi updates 2198 CSSM_DATA_PTR mac) // RETURNED 2199{ 2200 CSSM_CC_HANDLE macHand; 2201 CSSM_RETURN crtn; 2202 CSSM_RETURN ocrtn = CSSM_OK; 2203 unsigned thisMove; // this update 2204 unsigned toMove; // total to go 2205 CSSM_DATA thisText; // actaully passed to update 2206 2207 crtn = CSSM_CSP_CreateMacContext(cspHand, 2208 algorithm, 2209 key, 2210 &macHand); 2211 if(crtn) { 2212 printError("CSSM_CSP_CreateMacContext (2)", crtn); 2213 return crtn; 2214 } 2215 2216 if(mallocMac && (mac->Length == 0)) { 2217 /* malloc mac - ask CSP for size */ 2218 CSSM_QUERY_SIZE_DATA querySize = {0, 0}; 2219 crtn = CSSM_QuerySize(macHand, 2220 CSSM_TRUE, // encrypt 2221 1, 2222 &querySize); 2223 if(crtn) { 2224 printError("CSSM_QuerySize(mac)", crtn); 2225 ocrtn = crtn; 2226 goto abort; 2227 } 2228 if(querySize.SizeOutputBlock == 0) { 2229 printf("Unknown mac size\n"); 2230 ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; 2231 goto abort; 2232 } 2233 mac->Data = (uint8 *)appMalloc(querySize.SizeOutputBlock, NULL); 2234 if(mac->Data == NULL) { 2235 printf("malloc failure\n"); 2236 ocrtn = CSSMERR_CSSM_MEMORY_ERROR; 2237 goto abort; 2238 } 2239 mac->Length = querySize.SizeOutputBlock; 2240 } 2241 2242 crtn = CSSM_GenerateMacInit(macHand); 2243 if(crtn) { 2244 printError("CSSM_GenerateMacInit", crtn); 2245 ocrtn = crtn; 2246 goto abort; 2247 } 2248 toMove = text->Length; 2249 thisText.Data = text->Data; 2250 2251 while(toMove) { 2252 if(multiUpdates) { 2253 thisMove = genRand(1, toMove); 2254 } 2255 else { 2256 thisMove = toMove; 2257 } 2258 thisText.Length = thisMove; 2259 crtn = CSSM_GenerateMacUpdate(macHand, 2260 &thisText, 2261 1); 2262 if(crtn) { 2263 printError("CSSM_GenerateMacUpdate", crtn); 2264 ocrtn = crtn; 2265 goto abort; 2266 } 2267 thisText.Data += thisMove; 2268 toMove -= thisMove; 2269 } 2270 crtn = CSSM_GenerateMacFinal(macHand, mac); 2271 if(crtn) { 2272 printError("CSSM_GenerateMacFinal", crtn); 2273 ocrtn = crtn; 2274 goto abort; 2275 } 2276abort: 2277 crtn = CSSM_DeleteContext(macHand); 2278 if(crtn) { 2279 printError("CSSM_DeleteContext", crtn); 2280 ocrtn = crtn; 2281 } 2282 return ocrtn; 2283} 2284 2285CSSM_RETURN cspMacVerify(CSSM_CSP_HANDLE cspHand, 2286 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. 2287 CSSM_KEY_PTR key, // public key 2288 const CSSM_DATA *text, 2289 const CSSM_DATA_PTR mac, 2290 CSSM_RETURN expectResult) // expected result 2291 // CSSM_OK - expect success 2292{ 2293 CSSM_CC_HANDLE macHand; 2294 CSSM_RETURN ocrtn = CSSM_OK; 2295 CSSM_RETURN crtn; 2296 crtn = CSSM_CSP_CreateMacContext(cspHand, 2297 algorithm, 2298 key, 2299 &macHand); 2300 if(crtn) { 2301 printError("CSSM_CSP_CreateMacContext (3)", crtn); 2302 return crtn; 2303 } 2304 crtn = CSSM_VerifyMac(macHand, 2305 text, 2306 1, 2307 mac); 2308 if(crtn != expectResult) { 2309 if(crtn) { 2310 printError("CSSM_VerifyMac", crtn); 2311 } 2312 else { 2313 printf("Unexpected good Mac Verify\n"); 2314 } 2315 ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; 2316 } 2317 crtn = CSSM_DeleteContext(macHand); 2318 if(crtn) { 2319 printError("CSSM_DeleteContext", crtn); 2320 ocrtn = crtn; 2321 } 2322 return ocrtn; 2323} 2324 2325/* 2326 * Staged mac verify. Each update does a random number of bytes 'till through. 2327 */ 2328CSSM_RETURN cspStagedMacVerify(CSSM_CSP_HANDLE cspHand, 2329 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. 2330 CSSM_KEY_PTR key, // private key 2331 const CSSM_DATA *text, 2332 const CSSM_DATA_PTR mac, 2333 CSSM_BOOL multiUpdates, // false:single update, true:multi updates 2334 CSSM_RETURN expectResult) // expected result is verify failure 2335 // CSSM_OK - expect success 2336{ 2337 CSSM_CC_HANDLE macHand; 2338 CSSM_RETURN crtn; 2339 CSSM_RETURN ocrtn = CSSM_OK; 2340 unsigned thisMove; // this update 2341 unsigned toMove; // total to go 2342 CSSM_DATA thisText; // actaully passed to update 2343 2344 crtn = CSSM_CSP_CreateMacContext(cspHand, 2345 algorithm, 2346 key, 2347 &macHand); 2348 if(crtn) { 2349 printError("CSSM_CSP_CreateMacContext (4)", crtn); 2350 return crtn; 2351 } 2352 crtn = CSSM_VerifyMacInit(macHand); 2353 if(crtn) { 2354 printError("CSSM_VerifyMacInit", crtn); 2355 ocrtn = crtn; 2356 goto abort; 2357 } 2358 toMove = text->Length; 2359 thisText.Data = text->Data; 2360 2361 while(toMove) { 2362 if(multiUpdates) { 2363 thisMove = genRand(1, toMove); 2364 } 2365 else { 2366 thisMove = toMove; 2367 } 2368 thisText.Length = thisMove; 2369 crtn = CSSM_VerifyMacUpdate(macHand, 2370 &thisText, 2371 1); 2372 if(crtn) { 2373 printError("CSSM_VerifyMacUpdate", crtn); 2374 ocrtn = crtn; 2375 goto abort; 2376 } 2377 thisText.Data += thisMove; 2378 toMove -= thisMove; 2379 } 2380 crtn = CSSM_VerifyMacFinal(macHand, mac); 2381 if(crtn != expectResult) { 2382 if(crtn) { 2383 printError("CSSM_VerifyMacFinal", crtn); 2384 } 2385 else { 2386 printf("Unexpected good Staged Mac Verify\n"); 2387 } 2388 ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; 2389 } 2390abort: 2391 crtn = CSSM_DeleteContext(macHand); 2392 if(crtn) { 2393 printError("CSSM_DeleteContext", crtn); 2394 ocrtn = crtn; 2395 } 2396 return ocrtn; 2397} 2398 2399#pragma mark --------- Digest --------- 2400 2401/* 2402 * Digest functions 2403 */ 2404CSSM_RETURN cspDigest(CSSM_CSP_HANDLE cspHand, 2405 uint32 algorithm, // CSSM_ALGID_MD5, etc. 2406 CSSM_BOOL mallocDigest, // if true and digest->Length = 0, we'll malloc 2407 const CSSM_DATA *text, 2408 CSSM_DATA_PTR digest) 2409{ 2410 CSSM_CC_HANDLE digestHand; 2411 CSSM_RETURN crtn; 2412 CSSM_RETURN ocrtn = CSSM_OK; 2413 2414 crtn = CSSM_CSP_CreateDigestContext(cspHand, 2415 algorithm, 2416 &digestHand); 2417 if(crtn) { 2418 printError("CSSM_CSP_CreateDIgestContext (1)", crtn); 2419 return crtn; 2420 } 2421 if(mallocDigest && (digest->Length == 0)) { 2422 /* malloc digest - ask CSP for size */ 2423 CSSM_QUERY_SIZE_DATA querySize = {0, 0}; 2424 crtn = CSSM_QuerySize(digestHand, 2425 CSSM_FALSE, // encrypt 2426 1, 2427 &querySize); 2428 if(crtn) { 2429 printError("CSSM_QuerySize(3)", crtn); 2430 ocrtn = crtn; 2431 goto abort; 2432 } 2433 if(querySize.SizeOutputBlock == 0) { 2434 printf("Unknown digest size\n"); 2435 ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; 2436 goto abort; 2437 } 2438 digest->Data = (uint8 *)appMalloc(querySize.SizeOutputBlock, NULL); 2439 if(digest->Data == NULL) { 2440 printf("malloc failure\n"); 2441 ocrtn = CSSMERR_CSSM_MEMORY_ERROR; 2442 goto abort; 2443 } 2444 digest->Length = querySize.SizeOutputBlock; 2445 } 2446 crtn = CSSM_DigestData(digestHand, 2447 text, 2448 1, 2449 digest); 2450 if(crtn) { 2451 printError("CSSM_DigestData", crtn); 2452 ocrtn = crtn; 2453 } 2454abort: 2455 crtn = CSSM_DeleteContext(digestHand); 2456 if(crtn) { 2457 printError("CSSM_DeleteContext", crtn); 2458 ocrtn = crtn; 2459 } 2460 return ocrtn; 2461} 2462 2463CSSM_RETURN cspStagedDigest(CSSM_CSP_HANDLE cspHand, 2464 uint32 algorithm, // CSSM_ALGID_MD5, etc. 2465 CSSM_BOOL mallocDigest, // if true and digest->Length = 0, we'll 2466 // malloc 2467 CSSM_BOOL multiUpdates, // false:single update, true:multi updates 2468 const CSSM_DATA *text, 2469 CSSM_DATA_PTR digest) 2470{ 2471 CSSM_CC_HANDLE digestHand; 2472 CSSM_RETURN crtn; 2473 CSSM_RETURN ocrtn = CSSM_OK; 2474 unsigned thisMove; // this update 2475 unsigned toMove; // total to go 2476 CSSM_DATA thisText; // actually passed to update 2477 2478 crtn = CSSM_CSP_CreateDigestContext(cspHand, 2479 algorithm, 2480 &digestHand); 2481 if(crtn) { 2482 printError("CSSM_CSP_CreateDigestContext (2)", crtn); 2483 return crtn; 2484 } 2485 if(mallocDigest && (digest->Length == 0)) { 2486 /* malloc digest - ask CSP for size */ 2487 CSSM_QUERY_SIZE_DATA querySize = {0, 0}; 2488 crtn = CSSM_QuerySize(digestHand, 2489 CSSM_FALSE, // encrypt 2490 1, 2491 &querySize); 2492 if(crtn) { 2493 printError("CSSM_QuerySize(4)", crtn); 2494 ocrtn = crtn; 2495 goto abort; 2496 } 2497 if(querySize.SizeOutputBlock == 0) { 2498 printf("Unknown digest size\n"); 2499 ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; 2500 goto abort; 2501 } 2502 digest->Data = (uint8 *)appMalloc(querySize.SizeOutputBlock, NULL); 2503 if(digest->Data == NULL) { 2504 printf("malloc failure\n"); 2505 ocrtn = CSSMERR_CSSM_MEMORY_ERROR; 2506 goto abort; 2507 } 2508 digest->Length = querySize.SizeOutputBlock; 2509 } 2510 crtn = CSSM_DigestDataInit(digestHand); 2511 if(crtn) { 2512 printError("CSSM_DigestDataInit", crtn); 2513 ocrtn = crtn; 2514 goto abort; 2515 } 2516 toMove = text->Length; 2517 thisText.Data = text->Data; 2518 while(toMove) { 2519 if(multiUpdates) { 2520 thisMove = genRand(1, toMove); 2521 } 2522 else { 2523 thisMove = toMove; 2524 } 2525 thisText.Length = thisMove; 2526 crtn = CSSM_DigestDataUpdate(digestHand, 2527 &thisText, 2528 1); 2529 if(crtn) { 2530 printError("CSSM_DigestDataUpdate", crtn); 2531 ocrtn = crtn; 2532 goto abort; 2533 } 2534 thisText.Data += thisMove; 2535 toMove -= thisMove; 2536 } 2537 crtn = CSSM_DigestDataFinal(digestHand, digest); 2538 if(crtn) { 2539 printError("CSSM_DigestDataFinal", crtn); 2540 ocrtn = crtn; 2541 goto abort; 2542 } 2543abort: 2544 crtn = CSSM_DeleteContext(digestHand); 2545 if(crtn) { 2546 printError("CSSM_DeleteContext", crtn); 2547 ocrtn = crtn; 2548 } 2549 return ocrtn; 2550} 2551 2552#pragma mark --------- wrap/unwrap --------- 2553 2554/* wrap key function. */ 2555CSSM_RETURN cspWrapKey(CSSM_CSP_HANDLE cspHand, 2556 const CSSM_KEY *unwrappedKey, 2557 const CSSM_KEY *wrappingKey, 2558 CSSM_ALGORITHMS wrapAlg, 2559 CSSM_ENCRYPT_MODE wrapMode, 2560 CSSM_KEYBLOB_FORMAT wrapFormat, // NONE, PKCS7, PKCS8 2561 CSSM_PADDING wrapPad, 2562 CSSM_DATA_PTR initVector, // for some wrapping algs 2563 CSSM_DATA_PTR descrData, // optional 2564 CSSM_KEY_PTR wrappedKey) // RETURNED 2565{ 2566 CSSM_CC_HANDLE ccHand; 2567 CSSM_RETURN crtn; 2568 CSSM_ACCESS_CREDENTIALS creds; 2569 2570 memset(wrappedKey, 0, sizeof(CSSM_KEY)); 2571 setBadKeyData(wrappedKey); 2572 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); 2573 /* special case for NULL wrap - no wrapping key */ 2574 if((wrappingKey == NULL) || 2575 (wrappingKey->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY)) { 2576 crtn = CSSM_CSP_CreateSymmetricContext(cspHand, 2577 wrapAlg, 2578 wrapMode, 2579 &creds, // passPhrase, 2580 wrappingKey, 2581 initVector, 2582 wrapPad, // Padding 2583 0, // Params 2584 &ccHand); 2585 } 2586 else { 2587 crtn = CSSM_CSP_CreateAsymmetricContext(cspHand, 2588 wrapAlg, 2589 &creds, 2590 wrappingKey, 2591 wrapPad, // padding 2592 &ccHand); 2593 if(crtn) { 2594 printError("cspWrapKey/CreateContext", crtn); 2595 return crtn; 2596 } 2597 if(initVector) { 2598 /* manually add IV for CMS. The actual low-level encrypt doesn't 2599 * use it (and must ignore it). */ 2600 crtn = AddContextAttribute(ccHand, 2601 CSSM_ATTRIBUTE_INIT_VECTOR, 2602 sizeof(CSSM_DATA), 2603 CAT_Ptr, 2604 initVector, 2605 0); 2606 if(crtn) { 2607 printError("CSSM_UpdateContextAttributes", crtn); 2608 return crtn; 2609 } 2610 } 2611 } 2612 if(crtn) { 2613 printError("cspWrapKey/CreateContext", crtn); 2614 return crtn; 2615 } 2616 if(wrapFormat != CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) { 2617 /* only add this attribute if it's not the default */ 2618 CSSM_CONTEXT_ATTRIBUTE attr; 2619 attr.AttributeType = CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT; 2620 attr.AttributeLength = sizeof(uint32); 2621 attr.Attribute.Uint32 = wrapFormat; 2622 crtn = CSSM_UpdateContextAttributes( 2623 ccHand, 2624 1, 2625 &attr); 2626 if(crtn) { 2627 printError("CSSM_UpdateContextAttributes", crtn); 2628 return crtn; 2629 } 2630 } 2631 crtn = CSSM_WrapKey(ccHand, 2632 &creds, 2633 unwrappedKey, 2634 descrData, // DescriptiveData 2635 wrappedKey); 2636 if(crtn != CSSM_OK) { 2637 printError("CSSM_WrapKey", crtn); 2638 } 2639 if(CSSM_DeleteContext(ccHand)) { 2640 printf("CSSM_DeleteContext failure\n"); 2641 } 2642 return crtn; 2643} 2644 2645/* unwrap key function. */ 2646CSSM_RETURN cspUnwrapKey(CSSM_CSP_HANDLE cspHand, 2647 const CSSM_KEY *wrappedKey, 2648 const CSSM_KEY *unwrappingKey, 2649 CSSM_ALGORITHMS unwrapAlg, 2650 CSSM_ENCRYPT_MODE unwrapMode, 2651 CSSM_PADDING unwrapPad, 2652 CSSM_DATA_PTR initVector, // for some wrapping algs 2653 CSSM_KEY_PTR unwrappedKey, // RETURNED 2654 CSSM_DATA_PTR descrData, // required 2655 const char *keyLabel, 2656 unsigned keyLabelLen) 2657{ 2658 CSSM_CC_HANDLE ccHand; 2659 CSSM_RETURN crtn; 2660 CSSM_DATA labelData; 2661 uint32 keyAttr; 2662 CSSM_ACCESS_CREDENTIALS creds; 2663 2664 memset(unwrappedKey, 0, sizeof(CSSM_KEY)); 2665 setBadKeyData(unwrappedKey); 2666 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); 2667 if((unwrappingKey == NULL) || 2668 (unwrappingKey->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY)) { 2669 crtn = CSSM_CSP_CreateSymmetricContext(cspHand, 2670 unwrapAlg, 2671 unwrapMode, 2672 &creds, 2673 unwrappingKey, 2674 initVector, 2675 unwrapPad, 2676 0, // Params 2677 &ccHand); 2678 } 2679 else { 2680 crtn = CSSM_CSP_CreateAsymmetricContext(cspHand, 2681 unwrapAlg, 2682 &creds, // passPhrase, 2683 unwrappingKey, 2684 unwrapPad, // Padding 2685 &ccHand); 2686 if(crtn) { 2687 printError("cspUnwrapKey/CreateContext", crtn); 2688 return crtn; 2689 } 2690 if(initVector) { 2691 /* manually add IV for CMS. The actual low-level encrypt doesn't 2692 * use it (and must ignore it). */ 2693 crtn = AddContextAttribute(ccHand, 2694 CSSM_ATTRIBUTE_INIT_VECTOR, 2695 sizeof(CSSM_DATA), 2696 CAT_Ptr, 2697 initVector, 2698 0); 2699 if(crtn) { 2700 printError("CSSM_UpdateContextAttributes", crtn); 2701 return crtn; 2702 } 2703 } 2704 } 2705 if(crtn) { 2706 printError("cspUnwrapKey/CreateContext", crtn); 2707 return crtn; 2708 } 2709 labelData.Data = (uint8 *)keyLabel; 2710 labelData.Length = keyLabelLen; 2711 2712 /* 2713 * New keyAttr - clear some old bits, make sure we ask for ref key 2714 */ 2715 keyAttr = wrappedKey->KeyHeader.KeyAttr; 2716 keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE); 2717 keyAttr |= CSSM_KEYATTR_RETURN_REF; 2718 crtn = CSSM_UnwrapKey(ccHand, 2719 NULL, // PublicKey 2720 wrappedKey, 2721 wrappedKey->KeyHeader.KeyUsage, 2722 keyAttr, 2723 &labelData, 2724 NULL, // CredAndAclEntry 2725 unwrappedKey, 2726 descrData); // required 2727 if(crtn != CSSM_OK) { 2728 printError("CSSM_UnwrapKey", crtn); 2729 } 2730 if(CSSM_DeleteContext(ccHand)) { 2731 printf("CSSM_DeleteContext failure\n"); 2732 } 2733 return crtn; 2734} 2735 2736/* 2737 * Simple NULL wrap to convert a reference key to a raw key. 2738 */ 2739CSSM_RETURN cspRefKeyToRaw( 2740 CSSM_CSP_HANDLE cspHand, 2741 const CSSM_KEY *refKey, 2742 CSSM_KEY_PTR rawKey) // init'd and RETURNED 2743{ 2744 CSSM_DATA descData = {0, 0}; 2745 2746 memset(rawKey, 0, sizeof(CSSM_KEY)); 2747 return cspWrapKey(cspHand, 2748 refKey, 2749 NULL, // unwrappingKey 2750 CSSM_ALGID_NONE, 2751 CSSM_ALGMODE_NONE, 2752 CSSM_KEYBLOB_WRAPPED_FORMAT_NONE, 2753 CSSM_PADDING_NONE, 2754 NULL, // IV 2755 &descData, 2756 rawKey); 2757} 2758 2759/* 2760 * Convert ref key to raw key with specified format. 2761 */ 2762CSSM_RETURN cspRefKeyToRawWithFormat( 2763 CSSM_CSP_HANDLE cspHand, 2764 const CSSM_KEY *refKey, 2765 CSSM_KEYBLOB_FORMAT format, 2766 CSSM_KEY_PTR rawKey) // init'd and RETURNED 2767{ 2768 memset(rawKey, 0, sizeof(CSSM_KEY)); 2769 CSSM_ATTRIBUTE_TYPE attrType; 2770 2771 switch(refKey->KeyHeader.KeyClass) { 2772 case CSSM_KEYCLASS_PUBLIC_KEY: 2773 attrType = CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT; 2774 break; 2775 case CSSM_KEYCLASS_PRIVATE_KEY: 2776 attrType = CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT; 2777 break; 2778 case CSSM_KEYCLASS_SESSION_KEY: 2779 attrType = CSSM_ATTRIBUTE_SYMMETRIC_KEY_FORMAT; 2780 break; 2781 default: 2782 printf("***Unknown key class\n"); 2783 return CSSMERR_CSP_INVALID_KEY; 2784 } 2785 2786 CSSM_DATA descData = {0, 0}; 2787 CSSM_CC_HANDLE ccHand; 2788 CSSM_RETURN crtn; 2789// uint32 keyAttr; 2790 CSSM_ACCESS_CREDENTIALS creds; 2791 2792 memset(rawKey, 0, sizeof(CSSM_KEY)); 2793 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); 2794 crtn = CSSM_CSP_CreateSymmetricContext(cspHand, 2795 CSSM_ALGID_NONE, 2796 CSSM_ALGMODE_NONE, 2797 &creds, 2798 NULL, // unwrappingKey 2799 NULL, // initVector 2800 CSSM_PADDING_NONE, 2801 NULL, // Reserved 2802 &ccHand); 2803 if(crtn) { 2804 printError("cspRefKeyToRawWithFormat/CreateContext", crtn); 2805 return crtn; 2806 } 2807 2808 /* Add the spec for the resulting format */ 2809 crtn = AddContextAttribute(ccHand, 2810 attrType, 2811 sizeof(uint32), 2812 CAT_Uint32, 2813 NULL, 2814 format); 2815 2816 crtn = CSSM_WrapKey(ccHand, 2817 &creds, 2818 refKey, 2819 &descData, // DescriptiveData 2820 rawKey); 2821 if(crtn != CSSM_OK) { 2822 printError("CSSM_WrapKey", crtn); 2823 } 2824 if(rawKey->KeyHeader.Format != format) { 2825 printf("***cspRefKeyToRawWithFormat format scewup\n"); 2826 crtn = CSSMERR_CSP_INTERNAL_ERROR; 2827 } 2828 if(CSSM_DeleteContext(ccHand)) { 2829 printf("CSSM_DeleteContext failure\n"); 2830 } 2831 return crtn; 2832} 2833 2834/* unwrap raw key --> ref */ 2835CSSM_RETURN cspRawKeyToRef( 2836 CSSM_CSP_HANDLE cspHand, 2837 const CSSM_KEY *rawKey, 2838 CSSM_KEY_PTR refKey) // init'd and RETURNED 2839{ 2840 CSSM_DATA descData = {0, 0}; 2841 2842 memset(refKey, 0, sizeof(CSSM_KEY)); 2843 return cspUnwrapKey(cspHand, 2844 rawKey, 2845 NULL, // unwrappingKey 2846 CSSM_ALGID_NONE, 2847 CSSM_ALGMODE_NONE, 2848 CSSM_PADDING_NONE, 2849 NULL, // init vector 2850 refKey, 2851 &descData, 2852 "noLabel", 2853 7); 2854} 2855 2856 2857#pragma mark --------- FEE key/curve support --------- 2858 2859/* 2860 * Generate random key size, primeType, curveType for FEE key for specified op. 2861 * 2862 * First just enumerate the curves we know about, with ECDSA-INcapable first 2863 */ 2864 2865typedef struct { 2866 uint32 keySizeInBits; 2867 uint32 primeType; // CSSM_FEE_PRIME_TYPE_xxx 2868 uint32 curveType; // CSSM_FEE_CURVE_TYPE_xxx 2869} feeCurveParams; 2870 2871#define FEE_PROTOTYPE_CURVES 0 2872#if FEE_PROTOTYPE_CURVES 2873/* obsolete as of 4/9/2001 */ 2874static feeCurveParams feeCurves[] = { 2875 { 31, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_MONTGOMERY }, 2876 { 127, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_MONTGOMERY }, 2877 { 127, CSSM_FEE_PRIME_TYPE_GENERAL, CSSM_FEE_CURVE_TYPE_MONTGOMERY }, 2878 #define NUM_NON_ECDSA_CURVES 3 2879 2880 /* start of Weierstrass, IEEE P1363-capable curves */ 2881 { 31, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, 2882 { 40, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, 2883 { 127, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, 2884 { 160, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, 2885 { 160, CSSM_FEE_PRIME_TYPE_GENERAL, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, 2886 { 192, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, 2887}; 2888#else /* FEE_PROTOTYPE_CURVES */ 2889static feeCurveParams feeCurves[] = { 2890 { 31, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_MONTGOMERY }, 2891 { 127, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_MONTGOMERY }, 2892 #define NUM_NON_ECDSA_CURVES 2 2893 2894 /* start of Weierstrass, IEEE P1363-capable curves */ 2895 { 31, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, 2896 { 128, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, 2897 { 161, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, 2898 { 161, CSSM_FEE_PRIME_TYPE_GENERAL, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, 2899 { 192, CSSM_FEE_PRIME_TYPE_GENERAL, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, 2900}; 2901#endif /* FEE_PROTOTYPE_CURVES */ 2902#define NUM_FEE_CURVES (sizeof(feeCurves) / sizeof(feeCurveParams)) 2903 2904void randFeeKeyParams( 2905 CSSM_ALGORITHMS alg, // ALGID_FEED, CSSM_ALGID_FEE_MD5, etc. 2906 uint32 *keySizeInBits, // RETURNED 2907 uint32 *primeType, // CSSM_FEE_PRIME_TYPE_xxx, RETURNED 2908 uint32 *curveType) // CSSM_FEE_CURVE_TYPE_xxx, RETURNED 2909{ 2910 unsigned minParams; 2911 unsigned die; 2912 feeCurveParams *feeParams; 2913 2914 switch(alg) { 2915 case CSSM_ALGID_SHA1WithECDSA: 2916 minParams = NUM_NON_ECDSA_CURVES; 2917 break; 2918 default: 2919 minParams = 0; 2920 break; 2921 } 2922 die = genRand(minParams, (NUM_FEE_CURVES - 1)); 2923 feeParams = &feeCurves[die]; 2924 *keySizeInBits = feeParams->keySizeInBits; 2925 *primeType = feeParams->primeType; 2926 *curveType = feeParams->curveType; 2927} 2928 2929/* 2930 * Obtain strings for primeType and curveType. 2931 */ 2932const char *primeTypeStr(uint32 primeType) 2933{ 2934 const char *p; 2935 switch(primeType) { 2936 case CSSM_FEE_PRIME_TYPE_MERSENNE: 2937 p = "Mersenne"; 2938 break; 2939 case CSSM_FEE_PRIME_TYPE_FEE: 2940 p = "FEE"; 2941 break; 2942 case CSSM_FEE_PRIME_TYPE_GENERAL: 2943 p = "General"; 2944 break; 2945 case CSSM_FEE_PRIME_TYPE_DEFAULT: 2946 p = "Default"; 2947 break; 2948 default: 2949 p = "***UNKNOWN***"; 2950 break; 2951 } 2952 return p; 2953} 2954 2955const char *curveTypeStr(uint32 curveType) 2956{ 2957 const char *c; 2958 switch(curveType) { 2959 case CSSM_FEE_CURVE_TYPE_DEFAULT: 2960 c = "Default"; 2961 break; 2962 case CSSM_FEE_CURVE_TYPE_MONTGOMERY: 2963 c = "Montgomery"; 2964 break; 2965 case CSSM_FEE_CURVE_TYPE_WEIERSTRASS: 2966 c = "Weierstrass"; 2967 break; 2968 default: 2969 c = "***UNKNOWN***"; 2970 break; 2971 } 2972 return c; 2973} 2974 2975/* 2976 * Perform FEE Key exchange via CSSM_DeriveKey. 2977 */ 2978#if 0 2979/* Not implemented in OS X */ 2980CSSM_RETURN cspFeeKeyExchange(CSSM_CSP_HANDLE cspHand, 2981 CSSM_KEY_PTR privKey, 2982 CSSM_KEY_PTR pubKey, 2983 CSSM_KEY_PTR derivedKey, // mallocd by caller 2984 2985 /* remaining fields apply to derivedKey */ 2986 uint32 keyAlg, 2987 const char *keyLabel, 2988 unsigned keyLabelLen, 2989 uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. 2990 uint32 keySizeInBits) 2991{ 2992 CSSM_CC_HANDLE dkHand; 2993 CSSM_RETURN crtn; 2994 CSSM_DATA labelData; 2995 2996 if(derivedKey == NULL) { 2997 printf("cspFeeKeyExchange: no derivedKey\n"); 2998 return CSSMERR_CSSM_INTERNAL_ERROR; 2999 } 3000 if((pubKey == NULL) || 3001 (pubKey->KeyHeader.KeyClass != CSSM_KEYCLASS_PUBLIC_KEY) || 3002 (pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_RAW)) { 3003 printf("cspFeeKeyExchange: bad pubKey\n"); 3004 return CSSMERR_CSSM_INTERNAL_ERROR; 3005 } 3006 if((privKey == NULL) || 3007 (privKey->KeyHeader.KeyClass != CSSM_KEYCLASS_PRIVATE_KEY) || 3008 (privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE)) { 3009 printf("cspFeeKeyExchange: bad privKey\n"); 3010 return CSSMERR_CSSM_INTERNAL_ERROR; 3011 } 3012 memset(derivedKey, 0, sizeof(CSSM_KEY)); 3013 3014 crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, 3015 CSSM_ALGID_FEE_KEYEXCH, // AlgorithmID 3016 keyAlg, // alg of the derived key 3017 keySizeInBits, 3018 NULL, // access creds 3019 // FIXME 3020 0, // IterationCount 3021 NULL, // Salt 3022 NULL, // Seed 3023 NULL); // PassPhrase 3024 if(dkHand == 0) { 3025 printError("CSSM_CSP_CreateDeriveKeyContext"); 3026 return CSSM_FAIL; 3027 } 3028 labelData.Length = keyLabelLen; 3029 labelData.Data = (uint8 *)keyLabel; 3030 crtn = CSSM_DeriveKey(dkHand, 3031 privKey, 3032 &pubKey->KeyData, // Param - pub key blob 3033 keyUsage, 3034 CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | 3035 CSSM_KEYATTR_SENSITIVE, 3036 &labelData, 3037 derivedKey); 3038 3039 /* FIXME - save/restore error */ 3040 CSSM_DeleteContext(dkHand); 3041 if(crtn) { 3042 printError("CSSM_DeriveKey"); 3043 } 3044 return crtn; 3045} 3046#endif 3047 3048#pragma mark --------- Key/DL/DB support --------- 3049 3050/* 3051 * Add a DL/DB handle to a crypto context. 3052 */ 3053CSSM_RETURN cspAddDlDbToContext( 3054 CSSM_CC_HANDLE ccHand, 3055 CSSM_DL_HANDLE dlHand, 3056 CSSM_DB_HANDLE dbHand) 3057{ 3058 CSSM_DL_DB_HANDLE dlDb = { dlHand, dbHand }; 3059 return AddContextAttribute(ccHand, 3060 CSSM_ATTRIBUTE_DL_DB_HANDLE, 3061 sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE), 3062 CAT_Ptr, 3063 &dlDb, 3064 0); 3065} 3066 3067/* 3068 * Common routine to do a basic DB lookup by label and key type. 3069 * Query is aborted prior to exit. 3070 */ 3071static CSSM_DB_UNIQUE_RECORD_PTR dlLookup( 3072 CSSM_DL_DB_HANDLE dlDbHand, 3073 const CSSM_DATA *keyLabel, 3074 CT_KeyType keyType, 3075 CSSM_HANDLE *resultHand, // RETURNED 3076 CSSM_DATA_PTR theData, // RETURED 3077 CSSM_DB_RECORDTYPE *recordType) // RETURNED 3078{ 3079 CSSM_QUERY query; 3080 CSSM_SELECTION_PREDICATE predicate; 3081 CSSM_DB_UNIQUE_RECORD_PTR record = NULL; 3082 CSSM_RETURN crtn; 3083 3084 switch(keyType) { 3085 case CKT_Public: 3086 query.RecordType = *recordType = CSSM_DL_DB_RECORD_PUBLIC_KEY; 3087 break; 3088 case CKT_Private: 3089 query.RecordType = *recordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; 3090 break; 3091 case CKT_Session: 3092 query.RecordType = *recordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY; 3093 break; 3094 default: 3095 printf("Hey bozo! Give me a valid key type!\n"); 3096 return NULL; 3097 } 3098 query.Conjunctive = CSSM_DB_NONE; 3099 query.NumSelectionPredicates = 1; 3100 predicate.DbOperator = CSSM_DB_EQUAL; 3101 3102 predicate.Attribute.Info.AttributeNameFormat = 3103 CSSM_DB_ATTRIBUTE_NAME_AS_STRING; 3104 predicate.Attribute.Info.Label.AttributeName = (char *) "Label"; 3105 predicate.Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; 3106 /* hope this cast is OK */ 3107 predicate.Attribute.Value = (CSSM_DATA_PTR)keyLabel; 3108 query.SelectionPredicate = &predicate; 3109 3110 query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? 3111 query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? 3112 query.QueryFlags = CSSM_QUERY_RETURN_DATA; // FIXME - used? 3113 3114 crtn = CSSM_DL_DataGetFirst(dlDbHand, 3115 &query, 3116 resultHand, 3117 NULL, 3118 theData, 3119 &record); 3120 /* abort only on success */ 3121 if(crtn == CSSM_OK) { 3122 crtn = CSSM_DL_DataAbortQuery(dlDbHand, *resultHand); 3123 if(crtn) { 3124 printError("CSSM_DL_AbortQuery", crtn); 3125 return NULL; 3126 } 3127 } 3128 return record; 3129} 3130 3131/* 3132 * Look up a key by label and type. 3133 */ 3134CSSM_KEY_PTR cspLookUpKeyByLabel( 3135 CSSM_DL_HANDLE dlHand, 3136 CSSM_DB_HANDLE dbHand, 3137 const CSSM_DATA *labelData, 3138 CT_KeyType keyType) 3139{ 3140 CSSM_DB_UNIQUE_RECORD_PTR record; 3141 CSSM_HANDLE resultHand; 3142 CSSM_DATA theData; 3143 CSSM_KEY_PTR key; 3144 CSSM_DB_RECORDTYPE recordType; 3145 CSSM_DL_DB_HANDLE dlDbHand; 3146 3147 dlDbHand.DLHandle = dlHand; 3148 dlDbHand.DBHandle = dbHand; 3149 3150 theData.Length = 0; 3151 theData.Data = NULL; 3152 3153 record = dlLookup(dlDbHand, 3154 labelData, 3155 keyType, 3156 &resultHand, 3157 &theData, 3158 &recordType); 3159 if(record == NULL) { 3160 //printf("cspLookUpKeyByLabel: key not found\n"); 3161 return NULL; 3162 } 3163 key = (CSSM_KEY_PTR)theData.Data; 3164 CSSM_DL_FreeUniqueRecord(dlDbHand, record); 3165 return key; 3166} 3167 3168/* 3169 * Delete and free a key 3170 */ 3171CSSM_RETURN cspDeleteKey( 3172 CSSM_CSP_HANDLE cspHand, // for free 3173 CSSM_DL_HANDLE dlHand, // for delete 3174 CSSM_DB_HANDLE dbHand, // ditto 3175 const CSSM_DATA *labelData, 3176 CSSM_KEY_PTR key) 3177{ 3178 CSSM_DB_UNIQUE_RECORD_PTR record; 3179 CSSM_HANDLE resultHand; 3180 CT_KeyType keyType; 3181 CSSM_RETURN crtn = CSSM_OK; 3182 CSSM_DB_RECORDTYPE recordType; 3183 CSSM_DL_DB_HANDLE dlDbHand; 3184 3185 if(key->KeyHeader.KeyAttr & CSSM_KEYATTR_PERMANENT) { 3186 /* first do a lookup based in this key's fields */ 3187 switch(key->KeyHeader.KeyClass) { 3188 case CSSM_KEYCLASS_PUBLIC_KEY: 3189 keyType = CKT_Public; 3190 break; 3191 case CSSM_KEYCLASS_PRIVATE_KEY: 3192 keyType = CKT_Private; 3193 break; 3194 case CSSM_KEYCLASS_SESSION_KEY: 3195 keyType = CKT_Session; 3196 break; 3197 default: 3198 printf("Hey bozo! Give me a valid key type!\n"); 3199 return -1; 3200 } 3201 3202 dlDbHand.DLHandle = dlHand; 3203 dlDbHand.DBHandle = dbHand; 3204 3205 record = dlLookup(dlDbHand, 3206 labelData, 3207 keyType, 3208 &resultHand, 3209 NULL, // don't want actual data 3210 &recordType); 3211 if(record == NULL) { 3212 printf("cspDeleteKey: key not found in DL\n"); 3213 return CSSMERR_DL_RECORD_NOT_FOUND; 3214 } 3215 3216 /* OK, nuke it */ 3217 crtn = CSSM_DL_DataDelete(dlDbHand, record); 3218 if(crtn) { 3219 printError("CSSM_DL_DataDelete", crtn); 3220 } 3221 CSSM_DL_FreeUniqueRecord(dlDbHand, record); 3222 } 3223 3224 /* CSSM_FreeKey() should fail due to the delete, but it will 3225 * still free KeyData.... 3226 * FIXME - we should be able to do this in this one single call - right? 3227 */ 3228 CSSM_FreeKey(cspHand, NULL, key, CSSM_FALSE); 3229 3230 return crtn; 3231} 3232 3233/* 3234 * Given any key in either blob or reference format, 3235 * obtain the associated SHA-1 hash. 3236 */ 3237CSSM_RETURN cspKeyHash( 3238 CSSM_CSP_HANDLE cspHand, 3239 const CSSM_KEY_PTR key, /* public key */ 3240 CSSM_DATA_PTR *hashData) /* hash mallocd and RETURNED here */ 3241{ 3242 CSSM_CC_HANDLE ccHand; 3243 CSSM_RETURN crtn; 3244 CSSM_DATA_PTR dp; 3245 3246 *hashData = NULL; 3247 3248 /* validate input params */ 3249 if((key == NULL) || 3250 (hashData == NULL)) { 3251 printf("cspKeyHash: bogus args\n"); 3252 return CSSMERR_CSSM_INTERNAL_ERROR; 3253 } 3254 3255 /* cook up a context for a passthrough op */ 3256 crtn = CSSM_CSP_CreatePassThroughContext(cspHand, 3257 key, 3258 &ccHand); 3259 if(ccHand == 0) { 3260 printError("CSSM_CSP_CreatePassThroughContext", crtn); 3261 return crtn; 3262 } 3263 3264 /* now it's up to the CSP */ 3265 crtn = CSSM_CSP_PassThrough(ccHand, 3266 CSSM_APPLECSP_KEYDIGEST, 3267 NULL, 3268 (void **)&dp); 3269 if(crtn) { 3270 printError("CSSM_CSP_PassThrough(PUBKEYHASH)", crtn); 3271 } 3272 else { 3273 *hashData = dp; 3274 crtn = CSSM_OK; 3275 } 3276 CSSM_DeleteContext(ccHand); 3277 return crtn; 3278} 3279 3280