1/* 2 * Copyright (c) 2002-2012 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include "SecKey.h" 25#include "SecKeyPriv.h" 26#include "SecItem.h" 27#include "SecItemPriv.h" 28#include <libDER/asn1Types.h> 29#include <libDER/DER_Encode.h> 30#include <libDER/DER_Decode.h> 31#include <libDER/DER_Keys.h> 32#include <Security/SecAsn1Types.h> 33#include <Security/SecAsn1Coder.h> 34#include <security_keychain/KeyItem.h> 35#include <CommonCrypto/CommonKeyDerivation.h> 36 37#include "SecBridge.h" 38 39#include <security_keychain/Access.h> 40#include <security_keychain/Keychains.h> 41#include <security_keychain/KeyItem.h> 42#include <string.h> 43#include <syslog.h> 44 45#include <security_cdsa_utils/cuCdsaUtils.h> 46#include <security_cdsa_client/wrapkey.h> 47 48#include "SecImportExportCrypto.h" 49 50CFTypeID 51SecKeyGetTypeID(void) 52{ 53 BEGIN_SECAPI 54 55 return gTypes().KeyItem.typeID; 56 57 END_SECAPI1(_kCFRuntimeNotATypeID) 58} 59 60static OSStatus SecKeyCreatePairInternal( 61 SecKeychainRef keychainRef, 62 CSSM_ALGORITHMS algorithm, 63 uint32 keySizeInBits, 64 CSSM_CC_HANDLE contextHandle, 65 CSSM_KEYUSE publicKeyUsage, 66 uint32 publicKeyAttr, 67 CSSM_KEYUSE privateKeyUsage, 68 uint32 privateKeyAttr, 69 SecAccessRef initialAccess, 70 SecKeyRef* publicKeyRef, 71 SecKeyRef* privateKeyRef) 72{ 73 BEGIN_SECAPI 74 75 Keychain keychain = Keychain::optional(keychainRef); 76 SecPointer<Access> theAccess(initialAccess ? Access::required(initialAccess) : new Access("<key>")); 77 SecPointer<KeyItem> pubItem, privItem; 78 79 Mutex *keychainMutex = keychain->getKeychainMutex(); 80 StLock<Mutex> _(*keychainMutex); 81 82 KeyItem::createPair(keychain, 83 algorithm, 84 keySizeInBits, 85 contextHandle, 86 publicKeyUsage, 87 publicKeyAttr, 88 privateKeyUsage, 89 privateKeyAttr, 90 theAccess, 91 pubItem, 92 privItem); 93 94 // Return the generated keys. 95 if (publicKeyRef) 96 *publicKeyRef = pubItem->handle(); 97 if (privateKeyRef) 98 *privateKeyRef = privItem->handle(); 99 100 END_SECAPI 101} 102 103OSStatus 104SecKeyCreatePair( 105 SecKeychainRef keychainRef, 106 CSSM_ALGORITHMS algorithm, 107 uint32 keySizeInBits, 108 CSSM_CC_HANDLE contextHandle, 109 CSSM_KEYUSE publicKeyUsage, 110 uint32 publicKeyAttr, 111 CSSM_KEYUSE privateKeyUsage, 112 uint32 privateKeyAttr, 113 SecAccessRef initialAccess, 114 SecKeyRef* publicKeyRef, 115 SecKeyRef* privateKeyRef) 116{ 117 OSStatus result = SecKeyCreatePairInternal(keychainRef, algorithm, keySizeInBits, contextHandle, publicKeyUsage, 118 publicKeyAttr, privateKeyUsage, privateKeyAttr, initialAccess, publicKeyRef, privateKeyRef); 119 120 return result; 121} 122 123 124 125OSStatus 126SecKeyGetCSSMKey(SecKeyRef key, const CSSM_KEY **cssmKey) 127{ 128 BEGIN_SECAPI 129 130 Required(cssmKey) = KeyItem::required(key)->key(); 131 132 END_SECAPI 133} 134 135 136// 137// Private APIs 138// 139 140OSStatus 141SecKeyGetCSPHandle(SecKeyRef keyRef, CSSM_CSP_HANDLE *cspHandle) 142{ 143 BEGIN_SECAPI 144 145 SecPointer<KeyItem> keyItem(KeyItem::required(keyRef)); 146 Required(cspHandle) = keyItem->csp()->handle(); 147 148 END_SECAPI 149} 150 151/* deprecated as of 10.8 */ 152OSStatus 153SecKeyGetAlgorithmID(SecKeyRef keyRef, const CSSM_X509_ALGORITHM_IDENTIFIER **algid) 154{ 155 BEGIN_SECAPI 156 157 SecPointer<KeyItem> keyItem(KeyItem::required(keyRef)); 158 Required(algid) = &keyItem->algorithmIdentifier(); 159 160 END_SECAPI 161} 162 163/* new for 10.8 */ 164CFIndex 165SecKeyGetAlgorithmId(SecKeyRef key) 166{ 167 const CSSM_KEY *cssmKey; 168 169 if (SecKeyGetCSSMKey(key, &cssmKey) != errSecSuccess) 170 return kSecNullAlgorithmID; 171 172 switch (cssmKey->KeyHeader.AlgorithmId) { 173 case CSSM_ALGID_RSA: 174 return kSecRSAAlgorithmID; 175 case CSSM_ALGID_DSA: 176 return kSecDSAAlgorithmID; 177 case CSSM_ALGID_ECDSA: 178 return kSecECDSAAlgorithmID; 179 default: 180 assert(0); /* other algorithms TBA */ 181 return kSecNullAlgorithmID; 182 } 183} 184 185OSStatus 186SecKeyGetStrengthInBits(SecKeyRef keyRef, const CSSM_X509_ALGORITHM_IDENTIFIER *algid, unsigned int *strength) 187{ 188 BEGIN_SECAPI 189 190 SecPointer<KeyItem> keyItem(KeyItem::required(keyRef)); 191 Required(strength) = keyItem->strengthInBits(algid); 192 193 END_SECAPI 194} 195 196OSStatus 197SecKeyGetCredentials( 198 SecKeyRef keyRef, 199 CSSM_ACL_AUTHORIZATION_TAG operation, 200 SecCredentialType credentialType, 201 const CSSM_ACCESS_CREDENTIALS **outCredentials) 202{ 203 BEGIN_SECAPI 204 205 SecPointer<KeyItem> keyItem(KeyItem::required(keyRef)); 206 Required(outCredentials) = keyItem->getCredentials(operation, credentialType); 207 208 END_SECAPI 209} 210 211OSStatus 212SecKeyImportPair( 213 SecKeychainRef keychainRef, 214 const CSSM_KEY *publicCssmKey, 215 const CSSM_KEY *privateCssmKey, 216 SecAccessRef initialAccess, 217 SecKeyRef* publicKey, 218 SecKeyRef* privateKey) 219{ 220 BEGIN_SECAPI 221 222 Keychain keychain = Keychain::optional(keychainRef); 223 SecPointer<Access> theAccess(initialAccess ? Access::required(initialAccess) : new Access("<key>")); 224 SecPointer<KeyItem> pubItem, privItem; 225 226 KeyItem::importPair(keychain, 227 Required(publicCssmKey), 228 Required(privateCssmKey), 229 theAccess, 230 pubItem, 231 privItem); 232 233 // Return the generated keys. 234 if (publicKey) 235 *publicKey = pubItem->handle(); 236 if (privateKey) 237 *privateKey = privItem->handle(); 238 239 END_SECAPI 240} 241 242static OSStatus 243SecKeyGenerateWithAttributes( 244 SecKeychainAttributeList* attrList, 245 SecKeychainRef keychainRef, 246 CSSM_ALGORITHMS algorithm, 247 uint32 keySizeInBits, 248 CSSM_CC_HANDLE contextHandle, 249 CSSM_KEYUSE keyUsage, 250 uint32 keyAttr, 251 SecAccessRef initialAccess, 252 SecKeyRef* keyRef) 253{ 254 BEGIN_SECAPI 255 256 Keychain keychain; 257 SecPointer<Access> theAccess; 258 259 if (keychainRef) 260 keychain = KeychainImpl::required(keychainRef); 261 if (initialAccess) 262 theAccess = Access::required(initialAccess); 263 264 SecPointer<KeyItem> item = KeyItem::generateWithAttributes(attrList, 265 keychain, 266 algorithm, 267 keySizeInBits, 268 contextHandle, 269 keyUsage, 270 keyAttr, 271 theAccess); 272 273 // Return the generated key. 274 if (keyRef) 275 *keyRef = item->handle(); 276 277 END_SECAPI 278} 279 280OSStatus 281SecKeyGenerate( 282 SecKeychainRef keychainRef, 283 CSSM_ALGORITHMS algorithm, 284 uint32 keySizeInBits, 285 CSSM_CC_HANDLE contextHandle, 286 CSSM_KEYUSE keyUsage, 287 uint32 keyAttr, 288 SecAccessRef initialAccess, 289 SecKeyRef* keyRef) 290{ 291 return SecKeyGenerateWithAttributes(NULL, 292 keychainRef, algorithm, keySizeInBits, 293 contextHandle, keyUsage, keyAttr, 294 initialAccess, keyRef); 295} 296 297 298/* new in 10.6 */ 299/* Create a key from supplied data and parameters */ 300SecKeyRef 301SecKeyCreate(CFAllocatorRef allocator, 302 const SecKeyDescriptor *keyClass, 303 const uint8_t *keyData, 304 CFIndex keyDataLength, 305 SecKeyEncoding encoding) 306{ 307 SecKeyRef keyRef = NULL; 308 OSStatus __secapiresult; 309 try { 310 //FIXME: needs implementation 311 312 __secapiresult=errSecSuccess; 313 } 314 catch (const MacOSError &err) { __secapiresult=err.osStatus(); } 315 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } 316 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } 317 catch (...) { __secapiresult=errSecInternalComponent; } 318 return keyRef; 319} 320 321/* new in 10.6 */ 322/* Generate a floating key reference from a CSSM_KEY */ 323OSStatus 324SecKeyCreateWithCSSMKey(const CSSM_KEY *cssmKey, 325 SecKeyRef *keyRef) 326{ 327 BEGIN_SECAPI 328 329 Required(cssmKey); 330 CssmClient::CSP csp(cssmKey->KeyHeader.CspId); 331 CssmClient::Key key(csp, *cssmKey); 332 KeyItem *item = new KeyItem(key); 333 334 // Return the generated key. 335 if (keyRef) 336 *keyRef = item->handle(); 337 338 END_SECAPI 339} 340 341 342 343static u_int32_t ConvertCFStringToInteger(CFStringRef ref) 344{ 345 if (ref == NULL) 346 { 347 return 0; 348 } 349 350 // figure out the size of the string 351 CFIndex numChars = CFStringGetMaximumSizeForEncoding(CFStringGetLength(ref), kCFStringEncodingUTF8); 352 char buffer[numChars]; 353 if (!CFStringGetCString(ref, buffer, numChars, kCFStringEncodingUTF8)) 354 { 355 MacOSError::throwMe(errSecParam); 356 } 357 358 return atoi(buffer); 359} 360 361 362 363static OSStatus CheckAlgorithmType(CFDictionaryRef parameters, CSSM_ALGORITHMS &algorithms) 364{ 365 // figure out the algorithm to use 366 CFStringRef ktype = (CFStringRef) CFDictionaryGetValue(parameters, kSecAttrKeyType); 367 if (ktype == NULL) 368 { 369 return errSecParam; 370 } 371 372 if (CFEqual(ktype, kSecAttrKeyTypeRSA)) { 373 algorithms = CSSM_ALGID_RSA; 374 return errSecSuccess; 375 } else if(CFEqual(ktype, kSecAttrKeyTypeECDSA) || 376 CFEqual(ktype, kSecAttrKeyTypeEC)) { 377 algorithms = CSSM_ALGID_ECDSA; 378 return errSecSuccess; 379 } else if(CFEqual(ktype, kSecAttrKeyTypeAES)) { 380 algorithms = CSSM_ALGID_AES; 381 return errSecSuccess; 382 } else if(CFEqual(ktype, kSecAttrKeyType3DES)) { 383 algorithms = CSSM_ALGID_3DES; 384 return errSecSuccess; 385 } else { 386 return errSecUnsupportedAlgorithm; 387 } 388} 389 390 391 392static OSStatus GetKeySize(CFDictionaryRef parameters, CSSM_ALGORITHMS algorithms, uint32 &keySizeInBits) 393{ 394 395 // get the key size and check it for validity 396 CFTypeRef ref = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits); 397 398 keySizeInBits = kSecDefaultKeySize; 399 400 CFTypeID bitSizeType = CFGetTypeID(ref); 401 if (bitSizeType == CFStringGetTypeID()) 402 keySizeInBits = ConvertCFStringToInteger((CFStringRef) ref); 403 else if (bitSizeType == CFNumberGetTypeID()) 404 CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &keySizeInBits); 405 else return errSecParam; 406 407 408 switch (algorithms) { 409 case CSSM_ALGID_ECDSA: 410 if(keySizeInBits == kSecDefaultKeySize) keySizeInBits = kSecp256r1; 411 if(keySizeInBits == kSecp192r1 || keySizeInBits == kSecp256r1 || keySizeInBits == kSecp384r1 || keySizeInBits == kSecp521r1 ) return errSecSuccess; 412 break; 413 case CSSM_ALGID_RSA: 414 if(keySizeInBits % 8) return errSecParam; 415 if(keySizeInBits == kSecDefaultKeySize) keySizeInBits = 2048; 416 if(keySizeInBits >= kSecRSAMin && keySizeInBits <= kSecRSAMax) return errSecSuccess; 417 break; 418 case CSSM_ALGID_AES: 419 if(keySizeInBits == kSecDefaultKeySize) keySizeInBits = kSecAES128; 420 if(keySizeInBits == kSecAES128 || keySizeInBits == kSecAES192 || keySizeInBits == kSecAES256) return errSecSuccess; 421 break; 422 case CSSM_ALGID_3DES: 423 if(keySizeInBits == kSecDefaultKeySize) keySizeInBits = kSec3DES192; 424 if(keySizeInBits == kSec3DES192) return errSecSuccess; 425 break; 426 default: 427 break; 428 } 429 return errSecParam; 430} 431 432 433 434enum AttributeType 435{ 436 kStringType, 437 kBooleanType, 438 kIntegerType 439}; 440 441 442 443struct ParameterAttribute 444{ 445 const CFTypeRef *name; 446 AttributeType type; 447}; 448 449 450 451static ParameterAttribute gAttributes[] = 452{ 453 { 454 &kSecAttrLabel, 455 kStringType 456 }, 457 { 458 &kSecAttrIsPermanent, 459 kBooleanType 460 }, 461 { 462 &kSecAttrApplicationTag, 463 kStringType 464 }, 465 { 466 &kSecAttrEffectiveKeySize, 467 kBooleanType 468 }, 469 { 470 &kSecAttrCanEncrypt, 471 kBooleanType 472 }, 473 { 474 &kSecAttrCanDecrypt, 475 kBooleanType 476 }, 477 { 478 &kSecAttrCanDerive, 479 kBooleanType 480 }, 481 { 482 &kSecAttrCanSign, 483 kBooleanType 484 }, 485 { 486 &kSecAttrCanVerify, 487 kBooleanType 488 }, 489 { 490 &kSecAttrCanUnwrap, 491 kBooleanType 492 } 493}; 494 495const int kNumberOfAttributes = sizeof(gAttributes) / sizeof(ParameterAttribute); 496 497static OSStatus ScanDictionaryForParameters(CFDictionaryRef parameters, void* attributePointers[]) 498{ 499 int i; 500 for (i = 0; i < kNumberOfAttributes; ++i) 501 { 502 // see if the corresponding tag exists in the dictionary 503 CFTypeRef value = CFDictionaryGetValue(parameters, *(gAttributes[i].name)); 504 if (value != NULL) 505 { 506 switch (gAttributes[i].type) 507 { 508 case kStringType: 509 // just return the value 510 *(CFTypeRef*) attributePointers[i] = value; 511 break; 512 513 case kBooleanType: 514 { 515 CFBooleanRef bRef = (CFBooleanRef) value; 516 *(bool*) attributePointers[i] = CFBooleanGetValue(bRef); 517 } 518 break; 519 520 case kIntegerType: 521 { 522 CFNumberRef nRef = (CFNumberRef) value; 523 CFNumberGetValue(nRef, kCFNumberSInt32Type, attributePointers[i]); 524 } 525 break; 526 } 527 } 528 } 529 530 return errSecSuccess; 531} 532 533 534 535static OSStatus GetKeyParameters(CFDictionaryRef parameters, int keySize, bool isPublic, CSSM_KEYUSE &keyUse, uint32 &attrs, CFTypeRef &labelRef, CFDataRef &applicationTagRef) 536{ 537 // establish default values 538 labelRef = NULL; 539 bool isPermanent = false; 540 applicationTagRef = NULL; 541 CFTypeRef effectiveKeySize = NULL; 542 bool canDecrypt = isPublic ? false : true; 543 bool canEncrypt = !canDecrypt; 544 bool canDerive = true; 545 bool canSign = isPublic ? false : true; 546 bool canVerify = !canSign; 547 bool canUnwrap = isPublic ? false : true; 548 attrs = CSSM_KEYATTR_EXTRACTABLE; 549 keyUse = 0; 550 551 void* attributePointers[] = {&labelRef, &isPermanent, &applicationTagRef, &effectiveKeySize, &canEncrypt, &canDecrypt, 552 &canDerive, &canSign, &canVerify, &canUnwrap}; 553 554 // look for modifiers in the general dictionary 555 OSStatus result = ScanDictionaryForParameters(parameters, attributePointers); 556 if (result != errSecSuccess) 557 { 558 return result; 559 } 560 561 // see if we have anything which modifies the defaults 562 CFTypeRef key; 563 if (isPublic) 564 { 565 key = kSecPublicKeyAttrs; 566 } 567 else 568 { 569 key = kSecPrivateKeyAttrs; 570 } 571 572 CFTypeRef dType = CFDictionaryGetValue(parameters, key); 573 if (dType != NULL) 574 { 575 // this had better be a dictionary 576 if (CFGetTypeID(dType) != CFDictionaryGetTypeID()) 577 { 578 return errSecParam; 579 } 580 581 // pull any additional parameters out of this dictionary 582 result = ScanDictionaryForParameters((CFDictionaryRef)dType, attributePointers); 583 if (result != errSecSuccess) 584 { 585 return result; 586 } 587 } 588 589 // figure out the key usage 590 keyUse = 0; 591 if (canDecrypt) 592 { 593 keyUse |= CSSM_KEYUSE_DECRYPT; 594 } 595 596 if (canEncrypt) 597 { 598 keyUse |= CSSM_KEYUSE_ENCRYPT; 599 } 600 601 if (canDerive) 602 { 603 keyUse |= CSSM_KEYUSE_DERIVE; 604 } 605 606 if (canSign) 607 { 608 keyUse |= CSSM_KEYUSE_SIGN; 609 } 610 611 if (canVerify) 612 { 613 keyUse |= CSSM_KEYUSE_VERIFY; 614 } 615 616 if (canUnwrap) 617 { 618 keyUse |= CSSM_KEYUSE_UNWRAP; 619 } 620 621 // public key is always extractable; 622 // private key is extractable by default unless explicitly set to false 623 CFTypeRef value = NULL; 624 if (!isPublic && CFDictionaryGetValueIfPresent(parameters, kSecAttrIsExtractable, (const void **)&value) && value) 625 { 626 Boolean keyIsExtractable = CFEqual(kCFBooleanTrue, value); 627 if (!keyIsExtractable) 628 attrs = 0; 629 } 630 631 attrs |= CSSM_KEYATTR_PERMANENT; 632 633 return errSecSuccess; 634} 635 636 637 638static OSStatus MakeKeyGenParametersFromDictionary(CFDictionaryRef parameters, 639 CSSM_ALGORITHMS &algorithms, 640 uint32 &keySizeInBits, 641 CSSM_KEYUSE &publicKeyUse, 642 uint32 &publicKeyAttr, 643 CFTypeRef &publicKeyLabelRef, 644 CFDataRef &publicKeyAttributeTagRef, 645 CSSM_KEYUSE &privateKeyUse, 646 uint32 &privateKeyAttr, 647 CFTypeRef &privateKeyLabelRef, 648 CFDataRef &privateKeyAttributeTagRef, 649 SecAccessRef &initialAccess) 650{ 651 OSStatus result; 652 653 result = CheckAlgorithmType(parameters, algorithms); 654 if (result != errSecSuccess) 655 { 656 return result; 657 } 658 659 result = GetKeySize(parameters, algorithms, keySizeInBits); 660 if (result != errSecSuccess) 661 { 662 return result; 663 } 664 665 result = GetKeyParameters(parameters, keySizeInBits, false, privateKeyUse, privateKeyAttr, privateKeyLabelRef, privateKeyAttributeTagRef); 666 if (result != errSecSuccess) 667 { 668 return result; 669 } 670 671 result = GetKeyParameters(parameters, keySizeInBits, true, publicKeyUse, publicKeyAttr, publicKeyLabelRef, publicKeyAttributeTagRef); 672 if (result != errSecSuccess) 673 { 674 return result; 675 } 676 677 if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrAccess, (const void **)&initialAccess)) 678 { 679 initialAccess = NULL; 680 } 681 else if (SecAccessGetTypeID() != CFGetTypeID(initialAccess)) 682 { 683 return errSecParam; 684 } 685 686 return errSecSuccess; 687} 688 689 690 691static OSStatus SetKeyLabelAndTag(SecKeyRef keyRef, CFTypeRef label, CFDataRef tag) 692{ 693 int numToModify = 0; 694 if (label != NULL) 695 { 696 numToModify += 1; 697 } 698 699 if (tag != NULL) 700 { 701 numToModify += 1; 702 } 703 704 if (numToModify == 0) 705 { 706 return errSecSuccess; 707 } 708 709 SecKeychainAttributeList attrList; 710 SecKeychainAttribute attributes[numToModify]; 711 712 int i = 0; 713 714 if (label != NULL) 715 { 716 if (CFStringGetTypeID() == CFGetTypeID(label)) { 717 CFStringRef label_string = static_cast<CFStringRef>(label); 718 attributes[i].tag = kSecKeyPrintName; 719 attributes[i].data = (void*) CFStringGetCStringPtr(label_string, kCFStringEncodingUTF8); 720 if (NULL == attributes[i].data) { 721 CFIndex buffer_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(label_string), kCFStringEncodingUTF8); 722 attributes[i].data = alloca((size_t)buffer_length); 723 if (NULL == attributes[i].data) { 724 UnixError::throwMe(ENOMEM); 725 } 726 if (!CFStringGetCString(label_string, static_cast<char *>(attributes[i].data), buffer_length, kCFStringEncodingUTF8)) { 727 MacOSError::throwMe(errSecParam); 728 } 729 } 730 attributes[i].length = (UInt32)strlen(static_cast<char *>(attributes[i].data)); 731 } else if (CFDataGetTypeID() == CFGetTypeID(label)) { 732 // 10.6 bug compatibility 733 CFDataRef label_data = static_cast<CFDataRef>(label); 734 attributes[i].tag = kSecKeyLabel; 735 attributes[i].data = (void*) CFDataGetBytePtr(label_data); 736 attributes[i].length = (UInt32)CFDataGetLength(label_data); 737 } else { 738 MacOSError::throwMe(errSecParam); 739 } 740 i++; 741 } 742 743 if (tag != NULL) 744 { 745 attributes[i].tag = kSecKeyApplicationTag; 746 attributes[i].data = (void*) CFDataGetBytePtr(tag); 747 attributes[i].length = (UInt32)CFDataGetLength(tag); 748 i++; 749 } 750 751 attrList.count = numToModify; 752 attrList.attr = attributes; 753 754 return SecKeychainItemModifyAttributesAndData((SecKeychainItemRef) keyRef, &attrList, 0, NULL); 755} 756 757 758 759/* new in 10.6 */ 760/* Generate a private/public keypair. */ 761OSStatus 762SecKeyGeneratePair( 763 CFDictionaryRef parameters, 764 SecKeyRef *publicKey, 765 SecKeyRef *privateKey) 766{ 767 BEGIN_SECAPI 768 769 Required(parameters); 770 Required(publicKey); 771 Required(privateKey); 772 773 CSSM_ALGORITHMS algorithms; 774 uint32 keySizeInBits; 775 CSSM_KEYUSE publicKeyUse; 776 uint32 publicKeyAttr; 777 CFTypeRef publicKeyLabelRef; 778 CFDataRef publicKeyAttributeTagRef; 779 CSSM_KEYUSE privateKeyUse; 780 uint32 privateKeyAttr; 781 CFTypeRef privateKeyLabelRef; 782 CFDataRef privateKeyAttributeTagRef; 783 SecAccessRef initialAccess; 784 SecKeychainRef keychain; 785 786 OSStatus result = MakeKeyGenParametersFromDictionary(parameters, algorithms, keySizeInBits, publicKeyUse, publicKeyAttr, publicKeyLabelRef, 787 publicKeyAttributeTagRef, privateKeyUse, privateKeyAttr, privateKeyLabelRef, privateKeyAttributeTagRef, 788 initialAccess); 789 790 if (result != errSecSuccess) 791 { 792 return result; 793 } 794 795 // verify keychain parameter 796 keychain = NULL; 797 if (!CFDictionaryGetValueIfPresent(parameters, kSecUseKeychain, (const void **)&keychain)) 798 keychain = NULL; 799 else if (SecKeychainGetTypeID() != CFGetTypeID(keychain)) 800 keychain = NULL; 801 802 // do the key generation 803 result = SecKeyCreatePair(keychain, algorithms, keySizeInBits, 0, publicKeyUse, publicKeyAttr, privateKeyUse, privateKeyAttr, initialAccess, publicKey, privateKey); 804 if (result != errSecSuccess) 805 { 806 return result; 807 } 808 809 // set the label and print attributes on the keys 810 SetKeyLabelAndTag(*publicKey, publicKeyLabelRef, publicKeyAttributeTagRef); 811 SetKeyLabelAndTag(*privateKey, privateKeyLabelRef, privateKeyAttributeTagRef); 812 return result; 813 814 END_SECAPI 815} 816 817/* new in 10.6 */ 818OSStatus 819SecKeyRawSign( 820 SecKeyRef key, 821 SecPadding padding, 822 const uint8_t *dataToSign, 823 size_t dataToSignLen, 824 uint8_t *sig, 825 size_t *sigLen) 826{ 827 BEGIN_SECAPI 828 829 Required(key); 830 SecPointer<KeyItem> keyItem(KeyItem::required(key)); 831 CSSM_DATA dataInput; 832 833 dataInput.Data = (uint8_t*) dataToSign; 834 dataInput.Length = dataToSignLen; 835 836 CSSM_DATA output; 837 output.Data = sig; 838 output.Length = *sigLen; 839 840 const AccessCredentials* credentials = keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault); 841 842 keyItem->RawSign(padding, dataInput, credentials, output); 843 *sigLen = output.Length; 844 845 END_SECAPI 846} 847 848OSStatus SecKeyRawVerifyOSX( 849 SecKeyRef key, /* Public key */ 850 SecPadding padding, /* kSecPaddingNone or kSecPaddingPKCS1 */ 851 const uint8_t *signedData, /* signature over this data */ 852 size_t signedDataLen, /* length of dataToSign */ 853 const uint8_t *sig, /* signature */ 854 size_t sigLen) 855{ 856 return SecKeyRawVerify(key,padding,signedData,signedDataLen,sig,sigLen); 857} 858 859/* new in 10.6 */ 860OSStatus 861SecKeyRawVerify( 862 SecKeyRef key, 863 SecPadding padding, 864 const uint8_t *signedData, 865 size_t signedDataLen, 866 const uint8_t *sig, 867 size_t sigLen) 868{ 869 BEGIN_SECAPI 870 871 Required(key); 872 873 SecPointer<KeyItem> keyItem(KeyItem::required(key)); 874 CSSM_DATA dataInput; 875 876 dataInput.Data = (uint8_t*) signedData; 877 dataInput.Length = signedDataLen; 878 879 CSSM_DATA signature; 880 signature.Data = (uint8_t*) sig; 881 signature.Length = sigLen; 882 883 const AccessCredentials* credentials = keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ANY, kSecCredentialTypeDefault); 884 885 keyItem->RawVerify(padding, dataInput, credentials, signature); 886 887 END_SECAPI 888} 889 890/* new in 10.6 */ 891OSStatus 892SecKeyEncrypt( 893 SecKeyRef key, 894 SecPadding padding, 895 const uint8_t *plainText, 896 size_t plainTextLen, 897 uint8_t *cipherText, 898 size_t *cipherTextLen) 899{ 900 BEGIN_SECAPI 901 902 SecPointer<KeyItem> keyItem(KeyItem::required(key)); 903 CSSM_DATA inData, outData; 904 inData.Data = (uint8*) plainText; 905 inData.Length = plainTextLen; 906 outData.Data = cipherText; 907 outData.Length = *cipherTextLen; 908 909 const AccessCredentials* credentials = keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ENCRYPT, kSecCredentialTypeDefault); 910 911 keyItem->Encrypt(padding, inData, credentials, outData); 912 *cipherTextLen = outData.Length; 913 914 END_SECAPI 915} 916 917/* new in 10.6 */ 918OSStatus 919SecKeyDecrypt( 920 SecKeyRef key, /* Private key */ 921 SecPadding padding, /* kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingOAEP */ 922 const uint8_t *cipherText, 923 size_t cipherTextLen, /* length of cipherText */ 924 uint8_t *plainText, 925 size_t *plainTextLen) /* IN/OUT */ 926{ 927 BEGIN_SECAPI 928 929 SecPointer<KeyItem> keyItem(KeyItem::required(key)); 930 CSSM_DATA inData, outData; 931 inData.Data = (uint8*) cipherText; 932 inData.Length = cipherTextLen; 933 outData.Data = plainText; 934 outData.Length = *plainTextLen; 935 936 const AccessCredentials* credentials = keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_DECRYPT, kSecCredentialTypeDefault); 937 938 keyItem->Decrypt(padding, inData, credentials, outData); 939 *plainTextLen = outData.Length; 940 941 END_SECAPI 942} 943 944/* new in 10.6 */ 945size_t 946SecKeyGetBlockSize(SecKeyRef key) 947{ 948 size_t blockSize = 0; 949 OSStatus __secapiresult; 950 try { 951 CSSM_KEY cssmKey = KeyItem::required(key)->key(); 952 switch(cssmKey.KeyHeader.AlgorithmId) 953 { 954 case CSSM_ALGID_RSA: 955 case CSSM_ALGID_DSA: 956 blockSize = cssmKey.KeyHeader.LogicalKeySizeInBits / 8; 957 break; 958 case CSSM_ALGID_ECDSA: 959 { 960 /* Block size is up to 9 bytes of DER encoding for sequence of 2 integers, 961 * plus both coordinates for the point used */ 962 #define ECDSA_KEY_SIZE_IN_BYTES(bits) (((bits) + 7) / 8) 963 #define ECDSA_MAX_COORD_SIZE_IN_BYTES(n) (ECDSA_KEY_SIZE_IN_BYTES(n) + 1) 964 size_t coordSize = ECDSA_MAX_COORD_SIZE_IN_BYTES(cssmKey.KeyHeader.LogicalKeySizeInBits); 965 assert(coordSize < 256); /* size must fit in a byte for DER */ 966 size_t coordDERLen = (coordSize > 127) ? 2 : 1; 967 size_t coordLen = 1 + coordDERLen + coordSize; 968 969 size_t pointSize = 2 * coordLen; 970 assert(pointSize < 256); /* size must fit in a byte for DER */ 971 size_t pointDERLen = (pointSize > 127) ? 2 : 1; 972 size_t pointLen = 1 + pointDERLen + pointSize; 973 974 blockSize = pointLen; 975 } 976 break; 977 case CSSM_ALGID_AES: 978 blockSize = 16; /* all AES keys use 128-bit blocks */ 979 break; 980 case CSSM_ALGID_DES: 981 case CSSM_ALGID_3DES_3KEY: 982 blockSize = 8; /* all DES keys use 64-bit blocks */ 983 break; 984 default: 985 assert(0); /* some other key algorithm */ 986 blockSize = 16; /* FIXME: revisit this */ 987 break; 988 } 989 __secapiresult=errSecSuccess; 990 } 991 catch (const MacOSError &err) { __secapiresult=err.osStatus(); } 992 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } 993 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } 994 catch (...) { __secapiresult=errSecInternalComponent; } 995 return blockSize; 996} 997 998 999/* 1000 M4 Additions 1001*/ 1002 1003static CFTypeRef 1004utilGetStringFromCFDict(CFDictionaryRef parameters, CFTypeRef key, CFTypeRef defaultValue) 1005{ 1006 CFTypeRef value = CFDictionaryGetValue(parameters, key); 1007 if (value != NULL) return value; 1008 return defaultValue; 1009} 1010 1011static uint32_t 1012utilGetNumberFromCFDict(CFDictionaryRef parameters, CFTypeRef key, uint32_t defaultValue) 1013{ 1014 uint32_t integerValue; 1015 CFTypeRef value = CFDictionaryGetValue(parameters, key); 1016 if (value != NULL) { 1017 CFNumberRef nRef = (CFNumberRef) value; 1018 CFNumberGetValue(nRef, kCFNumberSInt32Type, &integerValue); 1019 return integerValue; 1020 } 1021 return defaultValue; 1022 } 1023 1024static uint32_t 1025utilGetMaskValFromCFDict(CFDictionaryRef parameters, CFTypeRef key, uint32_t maskValue) 1026{ 1027 CFTypeRef value = CFDictionaryGetValue(parameters, key); 1028 if (value != NULL) { 1029 CFBooleanRef bRef = (CFBooleanRef) value; 1030 if(CFBooleanGetValue(bRef)) return maskValue; 1031 } 1032 return 0; 1033} 1034 1035static void 1036utilGetKeyParametersFromCFDict(CFDictionaryRef parameters, CSSM_ALGORITHMS *algorithm, uint32 *keySizeInBits, CSSM_KEYUSE *keyUsage, CSSM_KEYCLASS *keyClass) 1037{ 1038 CFTypeRef algorithmDictValue = utilGetStringFromCFDict(parameters, kSecAttrKeyType, kSecAttrKeyTypeAES); 1039 CFTypeRef keyClassDictValue = utilGetStringFromCFDict(parameters, kSecAttrKeyClass, kSecAttrKeyClassSymmetric); 1040 1041 if(CFEqual(algorithmDictValue, kSecAttrKeyTypeAES)) { 1042 *algorithm = CSSM_ALGID_AES; 1043 *keySizeInBits = 128; 1044 *keyClass = CSSM_KEYCLASS_SESSION_KEY; 1045 } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeDES)) { 1046 *algorithm = CSSM_ALGID_DES; 1047 *keySizeInBits = 128; 1048 *keyClass = CSSM_KEYCLASS_SESSION_KEY; 1049 } else if(CFEqual(algorithmDictValue, kSecAttrKeyType3DES)) { 1050 *algorithm = CSSM_ALGID_3DES_3KEY_EDE; 1051 *keySizeInBits = 128; 1052 *keyClass = CSSM_KEYCLASS_SESSION_KEY; 1053 } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeRC4)) { 1054 *algorithm = CSSM_ALGID_RC4; 1055 *keySizeInBits = 128; 1056 *keyClass = CSSM_KEYCLASS_SESSION_KEY; 1057 } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeRC2)) { 1058 *algorithm = CSSM_ALGID_RC2; 1059 *keySizeInBits = 128; 1060 *keyClass = CSSM_KEYCLASS_SESSION_KEY; 1061 } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeCAST)) { 1062 *algorithm = CSSM_ALGID_CAST; 1063 *keySizeInBits = 128; 1064 *keyClass = CSSM_KEYCLASS_SESSION_KEY; 1065 } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeRSA)) { 1066 *algorithm = CSSM_ALGID_RSA; 1067 *keySizeInBits = 128; 1068 *keyClass = CSSM_KEYCLASS_PRIVATE_KEY; 1069 } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeDSA)) { 1070 *algorithm = CSSM_ALGID_DSA; 1071 *keySizeInBits = 128; 1072 *keyClass = CSSM_KEYCLASS_PRIVATE_KEY; 1073 } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeECDSA) || 1074 CFEqual(algorithmDictValue, kSecAttrKeyTypeEC)) { 1075 *algorithm = CSSM_ALGID_ECDSA; 1076 *keySizeInBits = 128; 1077 *keyClass = CSSM_KEYCLASS_PRIVATE_KEY; 1078 } else { 1079 *algorithm = CSSM_ALGID_AES; 1080 *keySizeInBits = 128; 1081 *keyClass = CSSM_KEYCLASS_SESSION_KEY; 1082 } 1083 1084 if(CFEqual(keyClassDictValue, kSecAttrKeyClassPublic)) { 1085 *keyClass = CSSM_KEYCLASS_PUBLIC_KEY; 1086 } else if(CFEqual(keyClassDictValue, kSecAttrKeyClassPrivate)) { 1087 *keyClass = CSSM_KEYCLASS_PRIVATE_KEY; 1088 } else if(CFEqual(keyClassDictValue, kSecAttrKeyClassSymmetric)) { 1089 *keyClass = CSSM_KEYCLASS_SESSION_KEY; 1090 } 1091 1092 *keySizeInBits = utilGetNumberFromCFDict(parameters, kSecAttrKeySizeInBits, *keySizeInBits); 1093 *keyUsage = utilGetMaskValFromCFDict(parameters, kSecAttrCanEncrypt, CSSM_KEYUSE_ENCRYPT) | 1094 utilGetMaskValFromCFDict(parameters, kSecAttrCanDecrypt, CSSM_KEYUSE_DECRYPT) | 1095 utilGetMaskValFromCFDict(parameters, kSecAttrCanWrap, CSSM_KEYUSE_WRAP) | 1096 utilGetMaskValFromCFDict(parameters, kSecAttrCanUnwrap, CSSM_KEYUSE_UNWRAP); 1097 1098 1099 if(*keyClass == CSSM_KEYCLASS_PRIVATE_KEY || *keyClass == CSSM_KEYCLASS_PUBLIC_KEY) { 1100 *keyUsage |= utilGetMaskValFromCFDict(parameters, kSecAttrCanSign, CSSM_KEYUSE_SIGN) | 1101 utilGetMaskValFromCFDict(parameters, kSecAttrCanVerify, CSSM_KEYUSE_VERIFY); 1102 } 1103 1104 if(*keyUsage == 0) { 1105 switch (*keyClass) { 1106 case CSSM_KEYCLASS_PRIVATE_KEY: 1107 *keyUsage = CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_UNWRAP | CSSM_KEYUSE_SIGN; 1108 break; 1109 case CSSM_KEYCLASS_PUBLIC_KEY: 1110 *keyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP; 1111 break; 1112 default: 1113 *keyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP | CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY; 1114 break; 1115 } 1116 } 1117} 1118 1119static CFStringRef 1120utilCopyDefaultKeyLabel(void) 1121{ 1122 // generate a default label from the current date 1123 CFDateRef dateNow = CFDateCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent()); 1124 CFStringRef defaultLabel = CFCopyDescription(dateNow); 1125 CFRelease(dateNow); 1126 1127 return defaultLabel; 1128} 1129 1130SecKeyRef 1131SecKeyGenerateSymmetric(CFDictionaryRef parameters, CFErrorRef *error) 1132{ 1133 OSStatus result = errSecParam; // default result for an early exit 1134 SecKeyRef key = NULL; 1135 SecKeychainRef keychain = NULL; 1136 SecAccessRef access; 1137 CFStringRef label; 1138 CFStringRef appLabel; 1139 CFStringRef appTag; 1140 CFStringRef dateLabel = NULL; 1141 1142 CSSM_ALGORITHMS algorithm; 1143 uint32 keySizeInBits; 1144 CSSM_KEYUSE keyUsage; 1145 uint32 keyAttr = CSSM_KEYATTR_RETURN_DEFAULT; 1146 CSSM_KEYCLASS keyClass; 1147 CFTypeRef value; 1148 Boolean isPermanent; 1149 Boolean isExtractable; 1150 1151 // verify keychain parameter 1152 if (!CFDictionaryGetValueIfPresent(parameters, kSecUseKeychain, (const void **)&keychain)) 1153 keychain = NULL; 1154 else if (SecKeychainGetTypeID() != CFGetTypeID(keychain)) { 1155 keychain = NULL; 1156 goto errorExit; 1157 } 1158 else 1159 CFRetain(keychain); 1160 1161 // verify permanent parameter 1162 if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrIsPermanent, (const void **)&value)) 1163 isPermanent = false; 1164 else if (!value || (CFBooleanGetTypeID() != CFGetTypeID(value))) 1165 goto errorExit; 1166 else 1167 isPermanent = CFEqual(kCFBooleanTrue, value); 1168 if (isPermanent) { 1169 if (keychain == NULL) { 1170 // no keychain was specified, so use the default keychain 1171 result = SecKeychainCopyDefault(&keychain); 1172 } 1173 keyAttr |= CSSM_KEYATTR_PERMANENT; 1174 } 1175 1176 // verify extractable parameter 1177 if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrIsExtractable, (const void **)&value)) 1178 isExtractable = true; // default to extractable if value not specified 1179 else if (!value || (CFBooleanGetTypeID() != CFGetTypeID(value))) 1180 goto errorExit; 1181 else 1182 isExtractable = CFEqual(kCFBooleanTrue, value); 1183 if (isExtractable) 1184 keyAttr |= CSSM_KEYATTR_EXTRACTABLE; 1185 1186 // verify access parameter 1187 if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrAccess, (const void **)&access)) 1188 access = NULL; 1189 else if (SecAccessGetTypeID() != CFGetTypeID(access)) 1190 goto errorExit; 1191 1192 // verify label parameter 1193 if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrLabel, (const void **)&label)) 1194 label = (dateLabel = utilCopyDefaultKeyLabel()); // no label provided, so use default 1195 else if (CFStringGetTypeID() != CFGetTypeID(label)) 1196 goto errorExit; 1197 1198 // verify application label parameter 1199 if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrApplicationLabel, (const void **)&appLabel)) 1200 appLabel = (dateLabel) ? dateLabel : (dateLabel = utilCopyDefaultKeyLabel()); 1201 else if (CFStringGetTypeID() != CFGetTypeID(appLabel)) 1202 goto errorExit; 1203 1204 // verify application tag parameter 1205 if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrApplicationTag, (const void **)&appTag)) 1206 appTag = NULL; 1207 else if (CFStringGetTypeID() != CFGetTypeID(appTag)) 1208 goto errorExit; 1209 1210 utilGetKeyParametersFromCFDict(parameters, &algorithm, &keySizeInBits, &keyUsage, &keyClass); 1211 1212 if (!keychain) { 1213 // the generated key will not be stored in any keychain 1214 result = SecKeyGenerate(keychain, algorithm, keySizeInBits, 0, keyUsage, keyAttr, access, &key); 1215 } 1216 else { 1217 // we can set the label attributes on the generated key if it's a keychain item 1218 size_t labelBufLen = (label) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(label), kCFStringEncodingUTF8) + 1 : 0; 1219 char *labelBuf = (char *)malloc(labelBufLen); 1220 size_t appLabelBufLen = (appLabel) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appLabel), kCFStringEncodingUTF8) + 1 : 0; 1221 char *appLabelBuf = (char *)malloc(appLabelBufLen); 1222 size_t appTagBufLen = (appTag) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appTag), kCFStringEncodingUTF8) + 1 : 0; 1223 char *appTagBuf = (char *)malloc(appTagBufLen); 1224 1225 if (label && !CFStringGetCString(label, labelBuf, labelBufLen-1, kCFStringEncodingUTF8)) 1226 labelBuf[0]=0; 1227 if (appLabel && !CFStringGetCString(appLabel, appLabelBuf, appLabelBufLen-1, kCFStringEncodingUTF8)) 1228 appLabelBuf[0]=0; 1229 if (appTag && !CFStringGetCString(appTag, appTagBuf, appTagBufLen-1, kCFStringEncodingUTF8)) 1230 appTagBuf[0]=0; 1231 1232 SecKeychainAttribute attrs[] = { 1233 { kSecKeyPrintName, (UInt32)strlen(labelBuf), (char *)labelBuf }, 1234 { kSecKeyLabel, (UInt32)strlen(appLabelBuf), (char *)appLabelBuf }, 1235 { kSecKeyApplicationTag, (UInt32)strlen(appTagBuf), (char *)appTagBuf } }; 1236 SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs }; 1237 if (!appTag) --attributes.count; 1238 1239 result = SecKeyGenerateWithAttributes(&attributes, 1240 keychain, algorithm, keySizeInBits, 0, 1241 keyUsage, keyAttr, access, &key); 1242 1243 free(labelBuf); 1244 free(appLabelBuf); 1245 free(appTagBuf); 1246 } 1247 1248errorExit: 1249 if (result && error) { 1250 *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, result, NULL); 1251 } 1252 if (dateLabel) 1253 CFRelease(dateLabel); 1254 if (keychain) 1255 CFRelease(keychain); 1256 1257 return key; 1258} 1259 1260 1261 1262SecKeyRef 1263SecKeyCreateFromData(CFDictionaryRef parameters, CFDataRef keyData, CFErrorRef *error) 1264{ 1265 CSSM_ALGORITHMS algorithm; 1266 uint32 keySizeInBits; 1267 CSSM_KEYUSE keyUsage; 1268 CSSM_KEYCLASS keyClass; 1269 CSSM_RETURN crtn; 1270 1271 utilGetKeyParametersFromCFDict(parameters, &algorithm, &keySizeInBits, &keyUsage, &keyClass); 1272 1273 CSSM_CSP_HANDLE cspHandle = cuCspStartup(CSSM_FALSE); // TRUE => CSP, FALSE => CSPDL 1274 1275 SecKeyImportExportParameters iparam; 1276 memset(&iparam, 0, sizeof(iparam)); 1277 iparam.keyUsage = keyUsage; 1278 1279 SecExternalItemType itype; 1280 switch (keyClass) { 1281 case CSSM_KEYCLASS_PRIVATE_KEY: 1282 itype = kSecItemTypePrivateKey; 1283 break; 1284 case CSSM_KEYCLASS_PUBLIC_KEY: 1285 itype = kSecItemTypePublicKey; 1286 break; 1287 case CSSM_KEYCLASS_SESSION_KEY: 1288 itype = kSecItemTypeSessionKey; 1289 break; 1290 default: 1291 itype = kSecItemTypeUnknown; 1292 break; 1293 } 1294 1295 CFMutableArrayRef ka = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1296 // NOTE: if we had a way to specify values other then kSecFormatUnknown we might be more useful. 1297 crtn = impExpImportRawKey(keyData, kSecFormatUnknown, itype, algorithm, NULL, cspHandle, 0, NULL, NULL, ka); 1298 if (crtn == CSSM_OK && CFArrayGetCount((CFArrayRef)ka)) { 1299 SecKeyRef sk = (SecKeyRef)CFArrayGetValueAtIndex((CFArrayRef)ka, 0); 1300 CFRetain(sk); 1301 CFRelease(ka); 1302 return sk; 1303 } else { 1304 if (error) { 1305 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, crtn ? crtn : CSSM_ERRCODE_INTERNAL_ERROR, NULL); 1306 } 1307 return NULL; 1308 } 1309} 1310 1311 1312void 1313SecKeyGeneratePairAsync(CFDictionaryRef parametersWhichMightBeMutiable, dispatch_queue_t deliveryQueue, 1314 SecKeyGeneratePairBlock result) 1315{ 1316 CFDictionaryRef parameters = CFDictionaryCreateCopy(NULL, parametersWhichMightBeMutiable); 1317 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 1318 SecKeyRef publicKey = NULL; 1319 SecKeyRef privateKey = NULL; 1320 OSStatus status = SecKeyGeneratePair(parameters, &publicKey, &privateKey); 1321 dispatch_async(deliveryQueue, ^{ 1322 CFErrorRef error = NULL; 1323 if (errSecSuccess != status) { 1324 error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, status, NULL); 1325 } 1326 result(publicKey, privateKey, error); 1327 if (error) { 1328 CFRelease(error); 1329 } 1330 if (publicKey) { 1331 CFRelease(publicKey); 1332 } 1333 if (privateKey) { 1334 CFRelease(privateKey); 1335 } 1336 CFRelease(parameters); 1337 }); 1338 }); 1339} 1340 1341SecKeyRef 1342SecKeyDeriveFromPassword(CFStringRef password, CFDictionaryRef parameters, CFErrorRef *error) 1343{ 1344 char *thePassword = NULL; 1345 CFIndex passwordLen; 1346 uint8_t *salt = NULL; 1347 size_t saltLen; 1348 CCPBKDFAlgorithm algorithm; 1349 uint rounds; 1350 uint8_t *derivedKey = NULL; 1351 size_t derivedKeyLen; 1352 CFDataRef saltDictValue, algorithmDictValue; 1353 1354 /* Pick Values from parameters */ 1355 1356 if((saltDictValue = (CFDataRef) CFDictionaryGetValue(parameters, kSecAttrSalt)) == NULL) { 1357 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecMissingAlgorithmParms, NULL); 1358 return NULL; 1359 } 1360 1361 derivedKeyLen = utilGetNumberFromCFDict(parameters, kSecAttrKeySizeInBits, 128); 1362 // This value come in bits but the rest of the code treats it as bytes 1363 derivedKeyLen /= 8; 1364 1365 algorithmDictValue = (CFDataRef) utilGetStringFromCFDict(parameters, kSecAttrPRF, kSecAttrPRFHmacAlgSHA256); 1366 1367 rounds = utilGetNumberFromCFDict(parameters, kSecAttrRounds, 0); 1368 1369 /* Convert any remaining parameters and get the password bytes */ 1370 1371 saltLen = CFDataGetLength(saltDictValue); 1372 if((salt = (uint8_t *) malloc(saltLen)) == NULL) { 1373 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL); 1374 return NULL; 1375 } 1376 1377 CFDataGetBytes(saltDictValue, CFRangeMake(0, saltLen), (UInt8 *) salt); 1378 1379 passwordLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(password), kCFStringEncodingUTF8) + 1; 1380 if((thePassword = (char *) malloc(passwordLen)) == NULL) { 1381 free(salt); 1382 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL); 1383 return NULL; 1384 } 1385 CFStringGetBytes(password, CFRangeMake(0, CFStringGetLength(password)), kCFStringEncodingUTF8, '?', FALSE, (UInt8*)thePassword, passwordLen, &passwordLen); 1386 1387 if((derivedKey = (uint8_t *) malloc(derivedKeyLen)) == NULL) { 1388 free(salt); 1389 bzero(thePassword, strlen(thePassword)); 1390 free(thePassword); 1391 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL); 1392 return NULL; 1393 } 1394 1395 1396 if(algorithmDictValue == NULL) { 1397 algorithm = kCCPRFHmacAlgSHA1; /* default */ 1398 } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA1)) { 1399 algorithm = kCCPRFHmacAlgSHA1; 1400 } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA224)) { 1401 algorithm = kCCPRFHmacAlgSHA224; 1402 } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA256)) { 1403 algorithm = kCCPRFHmacAlgSHA256; 1404 } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA384)) { 1405 algorithm = kCCPRFHmacAlgSHA384; 1406 } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA512)) { 1407 algorithm = kCCPRFHmacAlgSHA512; 1408 } else { 1409#warning "This else clause is here to prevent the use of unitialized variable, but really, this should return an error, without leaking." 1410 algorithm = kCCPRFHmacAlgSHA1; 1411 } 1412 1413 if(rounds == 0) { 1414 rounds = 33333; // we need to pass back a consistent value since there's no way to record the round count. 1415 } 1416 1417 1418 if(CCKeyDerivationPBKDF(kCCPBKDF2, thePassword, passwordLen, salt, saltLen, algorithm, rounds, derivedKey, derivedKeyLen)) { 1419#warning "Aren't we leaking salt and thePassword when this fail???" 1420 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInternalError, NULL); 1421 return NULL; 1422 } 1423 1424 free(salt); 1425 bzero(thePassword, strlen(thePassword)); 1426 free(thePassword); 1427 1428 CFDataRef keyData = CFDataCreate(NULL, derivedKey, derivedKeyLen); 1429 bzero(derivedKey, derivedKeyLen); 1430 free(derivedKey); 1431 1432 SecKeyRef retval = SecKeyCreateFromData(parameters, keyData, error); 1433 return retval; 1434 1435} 1436 1437CFDataRef 1438SecKeyWrapSymmetric(SecKeyRef keyToWrap, SecKeyRef wrappingKey, CFDictionaryRef parameters, CFErrorRef *error) 1439{ 1440 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecUnimplemented, NULL); 1441 return NULL; 1442} 1443 1444SecKeyRef 1445SecKeyUnwrapSymmetric(CFDataRef *keyToUnwrap, SecKeyRef unwrappingKey, CFDictionaryRef parameters, CFErrorRef *error) 1446{ 1447 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecUnimplemented, NULL); 1448 return NULL; 1449} 1450 1451 1452/* iOS SecKey shim functions */ 1453 1454#define MAX_DIGEST_LEN (CC_SHA512_DIGEST_LENGTH) 1455 1456/* Currently length of SHA512 oid + 1 */ 1457#define MAX_OID_LEN (10) 1458 1459#define DER_MAX_DIGEST_INFO_LEN (10 + MAX_DIGEST_LEN + MAX_OID_LEN) 1460 1461/* Encode the digestInfo header into digestInfo and return the offset from 1462 digestInfo at which to put the actual digest. Returns 0 if digestInfo 1463 won't fit within digestInfoLength bytes. 1464 1465 0x30, topLen, 1466 0x30, algIdLen, 1467 0x06, oid.Len, oid.Data, 1468 0x05, 0x00 1469 0x04, digestLen 1470 digestData 1471 */ 1472static size_t DEREncodeDigestInfoPrefix(const SecAsn1Oid *oid, 1473 size_t digestLength, 1474 uint8_t *digestInfo, 1475 size_t digestInfoLength) 1476{ 1477 size_t algIdLen = oid->Length + 4; 1478 size_t topLen = algIdLen + digestLength + 4; 1479 size_t totalLen = topLen + 2; 1480 1481 if (totalLen > digestInfoLength) { 1482 return 0; 1483 } 1484 1485 size_t ix = 0; 1486 digestInfo[ix++] = (SEC_ASN1_SEQUENCE | SEC_ASN1_CONSTRUCTED); 1487 digestInfo[ix++] = topLen; 1488 digestInfo[ix++] = (SEC_ASN1_SEQUENCE | SEC_ASN1_CONSTRUCTED); 1489 digestInfo[ix++] = algIdLen; 1490 digestInfo[ix++] = SEC_ASN1_OBJECT_ID; 1491 digestInfo[ix++] = oid->Length; 1492 memcpy(&digestInfo[ix], oid->Data, oid->Length); 1493 ix += oid->Length; 1494 digestInfo[ix++] = SEC_ASN1_NULL; 1495 digestInfo[ix++] = 0; 1496 digestInfo[ix++] = SEC_ASN1_OCTET_STRING; 1497 digestInfo[ix++] = digestLength; 1498 1499 return ix; 1500} 1501 1502static OSStatus SecKeyGetDigestInfo(SecKeyRef key, const SecAsn1AlgId *algId, 1503 const uint8_t *data, size_t dataLen, bool digestData, 1504 uint8_t *digestInfo, size_t *digestInfoLen /* IN/OUT */) 1505{ 1506 unsigned char *(*digestFcn)(const void *, CC_LONG, unsigned char *); 1507 CFIndex keyAlgID = kSecNullAlgorithmID; 1508 const SecAsn1Oid *digestOid; 1509 size_t digestLen; 1510 size_t offset = 0; 1511 1512 /* Since these oids all have the same prefix, use switch. */ 1513 if ((algId->algorithm.Length == CSSMOID_RSA.Length) && 1514 !memcmp(algId->algorithm.Data, CSSMOID_RSA.Data, 1515 algId->algorithm.Length - 1)) { 1516 keyAlgID = kSecRSAAlgorithmID; 1517 switch (algId->algorithm.Data[algId->algorithm.Length - 1]) { 1518#if 0 1519 case 2: /* oidMD2WithRSA */ 1520 digestFcn = CC_MD2; 1521 digestLen = CC_MD2_DIGEST_LENGTH; 1522 digestOid = &CSSMOID_MD2; 1523 break; 1524 case 3: /* oidMD4WithRSA */ 1525 digestFcn = CC_MD4; 1526 digestLen = CC_MD4_DIGEST_LENGTH; 1527 digestOid = &CSSMOID_MD4; 1528 break; 1529 case 4: /* oidMD5WithRSA */ 1530 digestFcn = CC_MD5; 1531 digestLen = CC_MD5_DIGEST_LENGTH; 1532 digestOid = &CSSMOID_MD5; 1533 break; 1534#endif /* 0 */ 1535 case 5: /* oidSHA1WithRSA */ 1536 digestFcn = CC_SHA1; 1537 digestLen = CC_SHA1_DIGEST_LENGTH; 1538 digestOid = &CSSMOID_SHA1; 1539 break; 1540 case 11: /* oidSHA256WithRSA */ 1541 digestFcn = CC_SHA256; 1542 digestLen = CC_SHA256_DIGEST_LENGTH; 1543 digestOid = &CSSMOID_SHA256; 1544 break; 1545 case 12: /* oidSHA384WithRSA */ 1546 /* pkcs1 12 */ 1547 digestFcn = CC_SHA384; 1548 digestLen = CC_SHA384_DIGEST_LENGTH; 1549 digestOid = &CSSMOID_SHA384; 1550 break; 1551 case 13: /* oidSHA512WithRSA */ 1552 digestFcn = CC_SHA512; 1553 digestLen = CC_SHA512_DIGEST_LENGTH; 1554 digestOid = &CSSMOID_SHA512; 1555 break; 1556 case 14: /* oidSHA224WithRSA */ 1557 digestFcn = CC_SHA224; 1558 digestLen = CC_SHA224_DIGEST_LENGTH; 1559 digestOid = &CSSMOID_SHA224; 1560 break; 1561 default: 1562 secdebug("key", "unsupported rsa signature algorithm"); 1563 return errSecUnsupportedAlgorithm; 1564 } 1565 } else if ((algId->algorithm.Length == CSSMOID_ECDSA_WithSHA224.Length) && 1566 !memcmp(algId->algorithm.Data, CSSMOID_ECDSA_WithSHA224.Data, 1567 algId->algorithm.Length - 1)) { 1568 keyAlgID = kSecECDSAAlgorithmID; 1569 switch (algId->algorithm.Data[algId->algorithm.Length - 1]) { 1570 case 1: /* oidSHA224WithECDSA */ 1571 digestFcn = CC_SHA224; 1572 digestLen = CC_SHA224_DIGEST_LENGTH; 1573 break; 1574 case 2: /* oidSHA256WithECDSA */ 1575 digestFcn = CC_SHA256; 1576 digestLen = CC_SHA256_DIGEST_LENGTH; 1577 break; 1578 case 3: /* oidSHA384WithECDSA */ 1579 /* pkcs1 12 */ 1580 digestFcn = CC_SHA384; 1581 digestLen = CC_SHA384_DIGEST_LENGTH; 1582 break; 1583 case 4: /* oidSHA512WithECDSA */ 1584 digestFcn = CC_SHA512; 1585 digestLen = CC_SHA512_DIGEST_LENGTH; 1586 break; 1587 default: 1588 secdebug("key", "unsupported ecdsa signature algorithm"); 1589 return errSecUnsupportedAlgorithm; 1590 } 1591 } else if (SecAsn1OidCompare(&algId->algorithm, &CSSMOID_ECDSA_WithSHA1)) { 1592 keyAlgID = kSecECDSAAlgorithmID; 1593 digestFcn = CC_SHA1; 1594 digestLen = CC_SHA1_DIGEST_LENGTH; 1595 } else if (SecAsn1OidCompare(&algId->algorithm, &CSSMOID_SHA1)) { 1596 digestFcn = CC_SHA1; 1597 digestLen = CC_SHA1_DIGEST_LENGTH; 1598 digestOid = &CSSMOID_SHA1; 1599 } else if ((algId->algorithm.Length == CSSMOID_SHA224.Length) && 1600 !memcmp(algId->algorithm.Data, CSSMOID_SHA224.Data, algId->algorithm.Length - 1)) 1601 { 1602 switch (algId->algorithm.Data[algId->algorithm.Length - 1]) { 1603 case 4: /* OID_SHA224 */ 1604 digestFcn = CC_SHA224; 1605 digestLen = CC_SHA224_DIGEST_LENGTH; 1606 digestOid = &CSSMOID_SHA224; 1607 break; 1608 case 1: /* OID_SHA256 */ 1609 digestFcn = CC_SHA256; 1610 digestLen = CC_SHA256_DIGEST_LENGTH; 1611 digestOid = &CSSMOID_SHA256; 1612 break; 1613 case 2: /* OID_SHA384 */ 1614 /* pkcs1 12 */ 1615 digestFcn = CC_SHA384; 1616 digestLen = CC_SHA384_DIGEST_LENGTH; 1617 digestOid = &CSSMOID_SHA384; 1618 break; 1619 case 3: /* OID_SHA512 */ 1620 digestFcn = CC_SHA512; 1621 digestLen = CC_SHA512_DIGEST_LENGTH; 1622 digestOid = &CSSMOID_SHA512; 1623 break; 1624 default: 1625 secdebug("key", "unsupported sha-2 signature algorithm"); 1626 return errSecUnsupportedAlgorithm; 1627 } 1628 } else if (SecAsn1OidCompare(&algId->algorithm, &CSSMOID_MD5)) { 1629 digestFcn = CC_MD5; 1630 digestLen = CC_MD5_DIGEST_LENGTH; 1631 digestOid = &CSSMOID_MD5; 1632 } else { 1633 secdebug("key", "unsupported digesting algorithm"); 1634 return errSecUnsupportedAlgorithm; 1635 } 1636 1637 /* check key is appropriate for signature (superfluous for digest only oid) */ 1638 { 1639 CFIndex supportedKeyAlgID = kSecNullAlgorithmID; 1640 #if TARGET_OS_EMBEDDED 1641 supportedKeyAlgID = SecKeyGetAlgorithmID(key); 1642 #else 1643 const CSSM_KEY* temporaryKey; 1644 SecKeyGetCSSMKey(key, &temporaryKey); 1645 CSSM_ALGORITHMS tempAlgorithm = temporaryKey->KeyHeader.AlgorithmId; 1646 if (CSSM_ALGID_RSA == tempAlgorithm) { 1647 supportedKeyAlgID = kSecRSAAlgorithmID; 1648 } else if (CSSM_ALGID_ECDSA == tempAlgorithm) { 1649 supportedKeyAlgID = kSecECDSAAlgorithmID; 1650 } 1651 #endif 1652 1653 if (keyAlgID == kSecNullAlgorithmID) { 1654 keyAlgID = supportedKeyAlgID; 1655 } 1656 else if (keyAlgID != supportedKeyAlgID) { 1657 return errSecUnsupportedAlgorithm; 1658 } 1659 } 1660 1661 switch(keyAlgID) { 1662 case kSecRSAAlgorithmID: 1663 offset = DEREncodeDigestInfoPrefix(digestOid, digestLen, 1664 digestInfo, *digestInfoLen); 1665 if (!offset) 1666 return errSecBufferTooSmall; 1667 break; 1668 case kSecDSAAlgorithmID: 1669 if (digestOid != &CSSMOID_SHA1) 1670 return errSecUnsupportedAlgorithm; 1671 break; 1672 case kSecECDSAAlgorithmID: 1673 break; 1674 default: 1675 secdebug("key", "unsupported signature algorithm"); 1676 return errSecUnsupportedAlgorithm; 1677 } 1678 1679 if (digestData) { 1680 if(dataLen>UINT32_MAX) /* Check for overflow with CC_LONG cast */ 1681 return errSecParam; 1682 digestFcn(data, (CC_LONG)dataLen, &digestInfo[offset]); 1683 *digestInfoLen = offset + digestLen; 1684 } else { 1685 if (dataLen != digestLen) 1686 return errSecParam; 1687 memcpy(&digestInfo[offset], data, dataLen); 1688 *digestInfoLen = offset + dataLen; 1689 } 1690 1691 return errSecSuccess; 1692} 1693 1694OSStatus SecKeyVerifyDigest( 1695 SecKeyRef key, /* Private key */ 1696 const SecAsn1AlgId *algId, /* algorithm oid/params */ 1697 const uint8_t *digestData, /* signature over this digest */ 1698 size_t digestDataLen, /* length of dataToDigest */ 1699 const uint8_t *sig, /* signature to verify */ 1700 size_t sigLen) /* length of sig */ 1701{ 1702 size_t digestInfoLength = DER_MAX_DIGEST_INFO_LEN; 1703 uint8_t digestInfo[digestInfoLength]; 1704 OSStatus status; 1705 1706 status = SecKeyGetDigestInfo(key, algId, digestData, digestDataLen, false /* data is digest */, 1707 digestInfo, &digestInfoLength); 1708 if (status) 1709 return status; 1710 return SecKeyRawVerify(key, kSecPaddingPKCS1, 1711 digestInfo, digestInfoLength, sig, sigLen); 1712} 1713 1714OSStatus SecKeySignDigest( 1715 SecKeyRef key, /* Private key */ 1716 const SecAsn1AlgId *algId, /* algorithm oid/params */ 1717 const uint8_t *digestData, /* signature over this digest */ 1718 size_t digestDataLen, /* length of digestData */ 1719 uint8_t *sig, /* signature, RETURNED */ 1720 size_t *sigLen) /* IN/OUT */ 1721{ 1722 size_t digestInfoLength = DER_MAX_DIGEST_INFO_LEN; 1723 uint8_t digestInfo[digestInfoLength]; 1724 OSStatus status; 1725 1726 status = SecKeyGetDigestInfo(key, algId, digestData, digestDataLen, false, 1727 digestInfo, &digestInfoLength); 1728 if (status) 1729 return status; 1730 return SecKeyRawSign(key, kSecPaddingPKCS1, 1731 digestInfo, digestInfoLength, sig, sigLen); 1732} 1733 1734/* It's debatable whether this belongs here or in the ssl code since the 1735 curve values come from a tls related rfc4492. */ 1736SecECNamedCurve SecECKeyGetNamedCurve(SecKeyRef key) 1737{ 1738 try { 1739 SecPointer<KeyItem> keyItem(KeyItem::required(key)); 1740 switch (keyItem->key().header().LogicalKeySizeInBits) { 1741#if 0 1742 case 192: 1743 return kSecECCurveSecp192r1; 1744 case 224: 1745 return kSecECCurveSecp224r1; 1746#endif 1747 case 256: 1748 return kSecECCurveSecp256r1; 1749 case 384: 1750 return kSecECCurveSecp384r1; 1751 case 521: 1752 return kSecECCurveSecp521r1; 1753 } 1754 } 1755 catch (...) {} 1756 return kSecECCurveNone; 1757} 1758 1759static inline CFDataRef _CFDataCreateReferenceFromRange(CFAllocatorRef allocator, CFDataRef sourceData, CFRange range) 1760{ 1761 return CFDataCreateWithBytesNoCopy(allocator, 1762 CFDataGetBytePtr(sourceData) + range.location, range.length, 1763 kCFAllocatorNull); 1764} 1765 1766static inline CFDataRef _CFDataCreateCopyFromRange(CFAllocatorRef allocator, CFDataRef sourceData, CFRange range) 1767{ 1768 return CFDataCreate(allocator, CFDataGetBytePtr(sourceData) + range.location, range.length); 1769} 1770 1771static inline bool _CFDataEquals(CFDataRef left, CFDataRef right) 1772{ 1773 return (left != NULL) && 1774 (right != NULL) && 1775 (CFDataGetLength(left) == CFDataGetLength(right)) && 1776 (0 == memcmp(CFDataGetBytePtr(left), CFDataGetBytePtr(right), (size_t)CFDataGetLength(left))); 1777} 1778 1779#if ECDSA_DEBUG 1780void secdump(const unsigned char *data, unsigned long len) 1781{ 1782 unsigned long i; 1783 char s[128]; 1784 char t[32]; 1785 s[0]=0; 1786 for(i=0;i<len;i++) 1787 { 1788 if((i&0xf)==0) { 1789 sprintf(t, "%04lx :", i); 1790 strcat(s, t); 1791 } 1792 sprintf(t, " %02x", data[i]); 1793 strcat(s, t); 1794 if((i&0xf)==0xf) { 1795 strcat(s, "\n"); 1796 syslog(LOG_NOTICE, s); 1797 s[0]=0; 1798 } 1799 } 1800 strcat(s, "\n"); 1801 syslog(LOG_NOTICE, s); 1802} 1803#endif 1804 1805OSStatus SecKeyCopyPublicBytes(SecKeyRef key, CFDataRef* publicBytes) 1806{ 1807 CFIndex keyAlgId; 1808#if TARGET_OS_EMBEDDED 1809 keyAlgId = SecKeyGetAlgorithmID(key); 1810#else 1811 keyAlgId = SecKeyGetAlgorithmId(key); 1812#endif 1813 1814 OSStatus ecStatus = errSecParam; 1815 CFDataRef tempPublicData = NULL; 1816 CFDataRef headerlessPublicData = NULL; 1817 CFIndex headerLength = 0; 1818 const UInt8* pData_Ptr = NULL; 1819 1820 if (kSecRSAAlgorithmID == keyAlgId) 1821 { 1822 return SecItemExport(key, kSecFormatBSAFE, 0, NULL, publicBytes); 1823 } 1824 1825 if (kSecECDSAAlgorithmID == keyAlgId) 1826 { 1827 // First export the key so there is access to the underlying key material 1828 ecStatus = SecItemExport(key, kSecFormatOpenSSL, 0, NULL, &tempPublicData); 1829 if(ecStatus != errSecSuccess) 1830 { 1831 secdebug("key", "SecKeyCopyPublicBytes: SecItemExport error (%d) for ECDSA public key %p", 1832 ecStatus, (uintptr_t)key); 1833 1834 return ecStatus; 1835 } 1836 1837 1838 // Get a pointer to the first byte of the exported data 1839 pData_Ptr = CFDataGetBytePtr(tempPublicData); 1840 1841 // the first byte should be a sequence 0x30 1842 if (*pData_Ptr != 0x30) 1843 { 1844 secdebug("key", "SecKeyCopyPublicBytes: exported data is invalid"); 1845 if (NULL != tempPublicData) 1846 CFRelease(tempPublicData); 1847 1848 ecStatus = errSecParam; 1849 return ecStatus; 1850 } 1851 1852 // move past the sequence byte 1853 pData_Ptr++; 1854 1855 // Check to see if the high bit is set which 1856 // indicates that the length will be at least 1857 // two bytes. If the high bit is set then 1858 // The lower seven bits specifies the number of 1859 // bytes used for the length. The additonal 1 1860 // is for the current byte. Otherwise just move past the 1861 // single length byte 1862 pData_Ptr += (*pData_Ptr & 0x80) ? ((*pData_Ptr & 0x7F) + 1) : 1; 1863 1864 // The current byte should be a sequence 0x30 1865 if (*pData_Ptr != 0x30) 1866 { 1867 secdebug("key", "SecKeyCopyPublicBytes: Could not find the key sequence"); 1868 if (NULL != tempPublicData) 1869 CFRelease(tempPublicData); 1870 1871 ecStatus = errSecParam; 1872 1873 return ecStatus; 1874 } 1875 1876 // The next bytes will always be the same 1877 // 0x30 = SEQUENCE 1878 // XX Length Byte 1879 // 0x06 OBJECT ID 1880 // 0x07 Length Byte 1881 // ECDSA public KEY OID value 0x2a,0x86,0x48,0xce,0x3d,0x02,0x01 1882 // 0x06 OBJECT ID 1883 // This is a total of 12 bytes 1884 pData_Ptr += 12; 1885 1886 // Next byte is the length of the ECDSA curve OID 1887 // Move past the length byte and the curve OID 1888 pData_Ptr += (((int)*pData_Ptr) + 1); 1889 1890 // Should be at a BINARY String which is specifed by a 0x3 1891 if (*pData_Ptr != 0x03) 1892 { 1893 secdebug("key", "SecKeyCopyPublicBytes: Invalid key structure"); 1894 if (NULL != tempPublicData) 1895 CFRelease(tempPublicData); 1896 1897 ecStatus = errSecParam; 1898 1899 return ecStatus; 1900 } 1901 1902 // Move past the BINARY String specifier 0x03 1903 pData_Ptr++; 1904 1905 1906 // Check to see if the high bit is set which 1907 // indicates that the length will be at least 1908 // two bytes. If the high bit is set then 1909 // The lower seven bits specifies the number of 1910 // bytes used for the length. The additonal 1 1911 // is for the current byte. Otherwise just move past the 1912 // single length byte 1913 pData_Ptr += (*pData_Ptr & 0x80) ? ((*pData_Ptr & 0x7F) + 1) : 1; 1914 1915 // Move past the beginning marker for the BINARY String 0x00 1916 pData_Ptr++; 1917 1918 // pData_Ptr now points to the first bytes of the key material 1919 headerLength = (CFIndex)(((intptr_t)pData_Ptr) - ((intptr_t)CFDataGetBytePtr(tempPublicData))); 1920 1921 headerlessPublicData = _CFDataCreateCopyFromRange(kCFAllocatorDefault, 1922 tempPublicData, CFRangeMake(headerLength, CFDataGetLength(tempPublicData) - headerLength)); 1923 1924 if (!headerlessPublicData) 1925 { 1926 printf("SecKeyCopyPublicBytes: headerlessPublicData is nil (1)\n"); 1927 if (NULL != tempPublicData) 1928 CFRelease(tempPublicData); 1929 1930 ecStatus = errSecParam; 1931 1932 return ecStatus; 1933 } 1934 1935 if (publicBytes) 1936 { 1937 *publicBytes = headerlessPublicData; 1938 } 1939 1940 ecStatus = errSecSuccess; 1941 1942 if (NULL != tempPublicData) 1943 CFRelease(tempPublicData); 1944 1945 return ecStatus; 1946 } 1947 1948 return errSecParam; 1949} 1950 1951 1952CFDataRef SecECKeyCopyPublicBits(SecKeyRef key) 1953{ 1954 CFDataRef exportedKey; 1955 if(SecKeyCopyPublicBytes(key, &exportedKey) != errSecSuccess) { 1956 exportedKey = NULL; 1957 } 1958 return exportedKey; 1959} 1960 1961SecKeyRef SecKeyCreateFromPublicData(CFAllocatorRef allocator, CFIndex algorithmID, CFDataRef publicBytes) 1962{ 1963 SecExternalFormat externalFormat = kSecFormatOpenSSL; 1964 SecExternalItemType externalItemType = kSecItemTypePublicKey; 1965 CFDataRef workingData = NULL; 1966 CFArrayRef outArray = NULL; 1967 SecKeyRef retVal = NULL; 1968 1969 if (kSecRSAAlgorithmID == algorithmID) { 1970 /* 1971 * kSecFormatBSAFE uses the original PKCS#1 definition: 1972 * RSAPublicKey ::= SEQUENCE { 1973 * modulus INTEGER, -- n 1974 * publicExponent INTEGER -- e 1975 * } 1976 * kSecFormatOpenSSL uses different ASN.1 encoding. 1977 */ 1978 externalFormat = kSecFormatBSAFE; 1979 workingData = _CFDataCreateReferenceFromRange(kCFAllocatorDefault, publicBytes, CFRangeMake(0, CFDataGetLength(publicBytes))); 1980 } else if (kSecECDSAAlgorithmID == algorithmID) { 1981 CFMutableDataRef tempData; 1982 uint8 headerBytes[] = { 0x30,0x59,0x30,0x13,0x06,0x07,0x2a,0x86, 1983 0x48,0xce,0x3d,0x02,0x01,0x06,0x08,0x2a, 1984 0x86,0x48,0xce,0x3d,0x03,0x01,0x07,0x03, 1985 0x42,0x00 }; 1986 1987 /* FIXME: this code only handles one specific curve type; need to expand this */ 1988 tempData = CFDataCreateMutable(kCFAllocatorDefault, 0); 1989 CFDataAppendBytes(tempData, headerBytes, sizeof(headerBytes)); 1990 CFDataAppendBytes(tempData, CFDataGetBytePtr(publicBytes), CFDataGetLength(publicBytes)); 1991 workingData = tempData; 1992 } 1993 if(SecItemImport(workingData, NULL, &externalFormat, &externalItemType, 0, NULL, NULL, &outArray) != errSecSuccess) { 1994 goto cleanup; 1995 } 1996 if(!outArray || CFArrayGetCount(outArray) == 0) { 1997 goto cleanup; 1998 } 1999 retVal = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0); 2000 CFRetain(retVal); 2001 2002cleanup: 2003 if(workingData) CFRelease(workingData); 2004 if(outArray) CFRelease(outArray); 2005 return retVal; 2006} 2007 2008SecKeyRef SecKeyCreateRSAPublicKey(CFAllocatorRef allocator, 2009 const uint8_t *keyData, CFIndex keyDataLength, 2010 SecKeyEncoding encoding) 2011{ 2012 CFDataRef pubKeyData = NULL; 2013 if(kSecKeyEncodingPkcs1 == encoding) { 2014 /* DER-encoded according to PKCS1. */ 2015 pubKeyData = CFDataCreate(allocator, keyData, keyDataLength); 2016 2017 } else if(kSecKeyEncodingApplePkcs1 == encoding) { 2018 /* DER-encoded according to PKCS1 with Apple Extensions. */ 2019 /* FIXME: need to actually handle extensions */ 2020 return NULL; 2021 2022 } else if(kSecKeyEncodingRSAPublicParams == encoding) { 2023 /* SecRSAPublicKeyParams format; we must encode as PKCS1. */ 2024 SecRSAPublicKeyParams *params = (SecRSAPublicKeyParams *)keyData; 2025 DERSize m_size = params->modulusLength; 2026 DERSize e_size = params->exponentLength; 2027 const DERSize seq_size = DERLengthOfItem(ASN1_INTEGER, m_size) + 2028 DERLengthOfItem(ASN1_INTEGER, e_size); 2029 const DERSize result_size = DERLengthOfItem(ASN1_SEQUENCE, seq_size); 2030 DERSize r_size, remaining_size = result_size; 2031 DERReturn drtn; 2032 2033 CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size); 2034 if (pkcs1 == NULL) { 2035 return NULL; 2036 } 2037 CFDataSetLength(pkcs1, result_size); 2038 uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1); 2039 2040 *bytes++ = ASN1_CONSTR_SEQUENCE; 2041 remaining_size--; 2042 r_size = 4; 2043 drtn = DEREncodeLength(seq_size, bytes, &r_size); 2044 if (r_size <= remaining_size) { 2045 bytes += r_size; 2046 remaining_size -= r_size; 2047 } 2048 r_size = remaining_size; 2049 drtn = DEREncodeItem(ASN1_INTEGER, m_size, (const DERByte *)params->modulus, (DERByte *)bytes, &r_size); 2050 if (r_size <= remaining_size) { 2051 bytes += r_size; 2052 remaining_size -= r_size; 2053 } 2054 r_size = remaining_size; 2055 drtn = DEREncodeItem(ASN1_INTEGER, e_size, (const DERByte *)params->exponent, (DERByte *)bytes, &r_size); 2056 2057 pubKeyData = pkcs1; 2058 2059 } else { 2060 /* unsupported encoding */ 2061 return NULL; 2062 } 2063 SecKeyRef publicKey = SecKeyCreateFromPublicData(allocator, kSecRSAAlgorithmID, pubKeyData); 2064 CFRelease(pubKeyData); 2065 return publicKey; 2066} 2067 2068#if !TARGET_OS_EMBEDDED 2069// 2070// Given a CSSM public key, copy its modulus and/or exponent data. 2071// Caller is responsible for releasing the returned CFDataRefs. 2072// 2073static 2074OSStatus _SecKeyCopyRSAPublicModulusAndExponent(SecKeyRef key, CFDataRef *modulus, CFDataRef *exponent) 2075{ 2076 const CSSM_KEY *pubKey; 2077 const CSSM_KEYHEADER *hdr; 2078 CSSM_DATA pubKeyBlob; 2079 OSStatus result; 2080 2081 result = SecKeyGetCSSMKey(key, &pubKey); 2082 if(result != errSecSuccess) { 2083 return result; 2084 } 2085 hdr = &pubKey->KeyHeader; 2086 if(hdr->KeyClass != CSSM_KEYCLASS_PUBLIC_KEY) { 2087 return errSSLInternal; 2088 } 2089 if(hdr->AlgorithmId != CSSM_ALGID_RSA) { 2090 return errSSLInternal; 2091 } 2092 switch(hdr->BlobType) { 2093 case CSSM_KEYBLOB_RAW: 2094 pubKeyBlob.Length = pubKey->KeyData.Length; 2095 pubKeyBlob.Data = pubKey->KeyData.Data; 2096 break; 2097 case CSSM_KEYBLOB_REFERENCE: 2098 // FIXME: currently SSL only uses raw public keys, obtained from the CL 2099 default: 2100 return errSSLInternal; 2101 } 2102 assert(hdr->BlobType == CSSM_KEYBLOB_RAW); 2103 // at this point we should have a PKCS1-encoded blob 2104 2105 DERItem keyItem = {(DERByte *)pubKeyBlob.Data, pubKeyBlob.Length}; 2106 DERRSAPubKeyPKCS1 decodedKey; 2107 if(DERParseSequence(&keyItem, DERNumRSAPubKeyPKCS1ItemSpecs, 2108 DERRSAPubKeyPKCS1ItemSpecs, 2109 &decodedKey, sizeof(decodedKey)) != DR_Success) { 2110 return errSecDecode; 2111 } 2112 if(modulus) { 2113 *modulus = CFDataCreate(kCFAllocatorDefault, decodedKey.modulus.data, decodedKey.modulus.length); 2114 if(*modulus == NULL) { 2115 return errSecDecode; 2116 } 2117 } 2118 if(exponent) { 2119 *exponent = CFDataCreate(kCFAllocatorDefault, decodedKey.pubExponent.data, decodedKey.pubExponent.length); 2120 if(*exponent == NULL) { 2121 return errSecDecode; 2122 } 2123 } 2124 2125 return errSecSuccess; 2126} 2127#endif /* !TARGET_OS_EMBEDDED */ 2128 2129CFDataRef SecKeyCopyModulus(SecKeyRef key) 2130{ 2131#if TARGET_OS_EMBEDDED 2132 ccrsa_pub_ctx_t pubkey; 2133 pubkey.pub = key->key; 2134 2135 size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey)); 2136 2137 CFAllocatorRef allocator = CFGetAllocator(key); 2138 CFMutableDataRef modulusData = CFDataCreateMutable(allocator, m_size); 2139 2140 if (modulusData == NULL) 2141 return NULL; 2142 2143 CFDataSetLength(modulusData, m_size); 2144 2145 ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), m_size, CFDataGetMutableBytePtr(modulusData)); 2146#else 2147 CFDataRef modulusData; 2148 OSStatus status = _SecKeyCopyRSAPublicModulusAndExponent(key, &modulusData, NULL); 2149 if(status != errSecSuccess) { 2150 modulusData = NULL; 2151 } 2152#endif 2153 2154 return modulusData; 2155} 2156 2157CFDataRef SecKeyCopyExponent(SecKeyRef key) 2158{ 2159#if TARGET_OS_EMBEDDED 2160 ccrsa_pub_ctx_t pubkey; 2161 pubkey.pub = key->key; 2162 2163 size_t e_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey)); 2164 2165 CFAllocatorRef allocator = CFGetAllocator(key); 2166 CFMutableDataRef exponentData = CFDataCreateMutable(allocator, e_size); 2167 2168 if (exponentData == NULL) 2169 return NULL; 2170 2171 CFDataSetLength(exponentData, e_size); 2172 2173 ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), e_size, CFDataGetMutableBytePtr(exponentData)); 2174#else 2175 CFDataRef exponentData; 2176 OSStatus status = _SecKeyCopyRSAPublicModulusAndExponent(key, NULL, &exponentData); 2177 if(status != errSecSuccess) { 2178 exponentData = NULL; 2179 } 2180#endif 2181 2182 return exponentData; 2183} 2184 2185SecKeyRef SecKeyCreatePublicFromPrivate(SecKeyRef privateKey) { 2186 OSStatus status = errSecParam; 2187 2188 CFDataRef serializedPublic = NULL; 2189 2190 status = SecKeyCopyPublicBytes(privateKey, &serializedPublic); 2191 if ((status == errSecSuccess) && (serializedPublic != NULL)) { 2192 SecKeyRef publicKeyRef = SecKeyCreateFromPublicData(kCFAllocatorDefault, SecKeyGetAlgorithmId(privateKey), serializedPublic); 2193 CFRelease(serializedPublic); 2194 if (publicKeyRef != NULL) { 2195 return publicKeyRef; 2196 } 2197 } 2198 2199 const void *keys[] = { kSecClass, kSecValueRef, kSecReturnAttributes }; 2200 const void *values[] = { kSecClassKey, privateKey, kCFBooleanTrue }; 2201 CFDictionaryRef query= CFDictionaryCreate(NULL, keys, values, 2202 (sizeof(values) / sizeof(*values)), 2203 &kCFTypeDictionaryKeyCallBacks, 2204 &kCFTypeDictionaryValueCallBacks); 2205 CFTypeRef foundItem = NULL; 2206 status = SecItemCopyMatching(query, &foundItem); 2207 2208 if (status == errSecSuccess) { 2209 if (CFGetTypeID(foundItem) == CFDictionaryGetTypeID()) { 2210 CFMutableDictionaryRef query2 = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 2211 CFDictionaryAddValue(query2, kSecClass, kSecClassKey); 2212 CFDictionaryAddValue(query2, kSecAttrKeyClass, kSecAttrKeyClassPublic); 2213 CFDictionaryAddValue(query2, kSecAttrApplicationLabel, CFDictionaryGetValue((CFDictionaryRef)foundItem, kSecAttrApplicationLabel)); 2214 CFDictionaryAddValue(query2, kSecReturnRef, kCFBooleanTrue); 2215 2216 CFTypeRef foundKey = NULL; 2217 status = SecItemCopyMatching(query2, &foundKey); 2218 if (status == errSecSuccess) { 2219 if (CFGetTypeID(foundKey) == SecKeyGetTypeID()) { 2220 CFRelease(query); 2221 CFRelease(query2); 2222 CFRelease(foundItem); 2223 return (SecKeyRef)foundKey; 2224 } else { 2225 status = errSecItemNotFound; 2226 } 2227 } 2228 CFRelease(query2); 2229 2230 } else { 2231 status = errSecItemNotFound; 2232 } 2233 CFRelease(foundItem); 2234 } 2235 2236 CFRelease(query); 2237 return NULL; 2238} 2239 2240