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