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