]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/lib/SecKey.cpp
Security-58286.230.21.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / lib / SecKey.cpp
1 /*
2 * Copyright (c) 2002-2015 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 <security_utilities/casts.h>
36 #include <CommonCrypto/CommonKeyDerivation.h>
37
38 #include <CoreFoundation/CFPriv.h>
39 // 'verify' macro is somehow dragged in from CFPriv.h and breaks compilation of signclient.h, so undef it, we don't need it.
40 #undef verify
41
42 #include "SecBridge.h"
43
44 #include <security_keychain/Access.h>
45 #include <security_keychain/Keychains.h>
46 #include <security_keychain/KeyItem.h>
47 #include <string.h>
48 #include <syslog.h>
49
50 #include <security_cdsa_utils/cuCdsaUtils.h>
51 #include <security_cdsa_client/wrapkey.h>
52 #include <security_cdsa_client/genkey.h>
53 #include <security_cdsa_client/signclient.h>
54 #include <security_cdsa_client/cryptoclient.h>
55
56 #include "SecImportExportCrypto.h"
57
58 static OSStatus
59 SecCDSAKeyInit(SecKeyRef key, const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
60 key->key = const_cast<KeyItem *>(reinterpret_cast<const KeyItem *>(keyData));
61 key->key->initializeWithSecKeyRef(key);
62 key->credentialType = kSecCredentialTypeDefault;
63 key->cdsaKeyMutex = new Mutex();
64 return errSecSuccess;
65 }
66
67 static void
68 SecCDSAKeyDestroy(SecKeyRef keyRef) {
69 // Note: If this key is holding the last strong reference to its keychain, the keychain will be released during this operation.
70 // If we hold the keychain's mutex (the key's 'mutexForObject') during this destruction, pthread gets upset.
71 // Hold a reference to the keychain (if it exists) until after we release the keychain's mutex.
72
73 StMaybeLock<Mutex> cdsaMutex(keyRef->cdsaKeyMutex);
74
75 KeyItem *keyItem = keyRef->key;
76
77 if (keyItem == NULL) {
78 // KeyImpl::attachSecKeyRef disconnected us from KeyItem instance, there is nothing to do for us.
79 cdsaMutex.unlock();
80 delete keyRef->cdsaKeyMutex;
81 return;
82 }
83
84 Keychain kc = keyItem->keychain();
85
86 // We have a +1 reference to the KeyItem now; no need to protect our storage any more
87 cdsaMutex.unlock();
88
89 {
90 StMaybeLock<Mutex> _(keyItem->getMutexForObject());
91 keyItem = keyRef->key;
92 if (keyItem == NULL) {
93 // Second version of the check above, the definitive one because this one is performed with locked object's mutex, therefore we can be sure that KeyImpl is still connected to this keyRef instance.
94 return;
95 }
96
97 keyItem->aboutToDestruct();
98 delete keyItem;
99 }
100
101 delete keyRef->cdsaKeyMutex;
102
103 (void) kc; // Tell the compiler we're actually using this variable. At destruction time, it'll release the keychain.
104 }
105
106 static size_t
107 SecCDSAKeyGetBlockSize(SecKeyRef key) {
108
109 CFErrorRef *error = NULL;
110 BEGIN_SECKEYAPI(size_t,0)
111
112 const CssmKey::Header keyHeader = key->key->unverifiedKeyHeader();
113 switch(keyHeader.algorithm())
114 {
115 case CSSM_ALGID_RSA:
116 case CSSM_ALGID_DSA:
117 result = keyHeader.LogicalKeySizeInBits / 8;
118 break;
119 case CSSM_ALGID_ECDSA:
120 {
121 /* Block size is up to 9 bytes of DER encoding for sequence of 2 integers,
122 * plus both coordinates for the point used */
123 #define ECDSA_KEY_SIZE_IN_BYTES(bits) (((bits) + 7) / 8)
124 #define ECDSA_MAX_COORD_SIZE_IN_BYTES(n) (ECDSA_KEY_SIZE_IN_BYTES(n) + 1)
125 size_t coordSize = ECDSA_MAX_COORD_SIZE_IN_BYTES(keyHeader.LogicalKeySizeInBits);
126 assert(coordSize < 256); /* size must fit in a byte for DER */
127 size_t coordDERLen = (coordSize > 127) ? 2 : 1;
128 size_t coordLen = 1 + coordDERLen + coordSize;
129
130 size_t pointSize = 2 * coordLen;
131 assert(pointSize < 256); /* size must fit in a byte for DER */
132 size_t pointDERLen = (pointSize > 127) ? 2 : 1;
133 size_t pointLen = 1 + pointDERLen + pointSize;
134
135 result = pointLen;
136 }
137 break;
138 case CSSM_ALGID_AES:
139 result = 16; /* all AES keys use 128-bit blocks */
140 break;
141 case CSSM_ALGID_DES:
142 case CSSM_ALGID_3DES_3KEY:
143 result = 8; /* all DES keys use 64-bit blocks */
144 break;
145 default:
146 assert(0); /* some other key algorithm */
147 result = 16; /* FIXME: revisit this */
148 break;
149 }
150
151 END_SECKEYAPI
152 }
153
154 static CFIndex
155 SecCDSAKeyGetAlgorithmId(SecKeyRef key) {
156
157 CFErrorRef *error = NULL;
158 BEGIN_SECKEYAPI(CFIndex, 0)
159
160 result = kSecNullAlgorithmID;
161 switch (key->key->unverifiedKeyHeader().AlgorithmId) {
162 case CSSM_ALGID_RSA:
163 result = kSecRSAAlgorithmID;
164 break;
165 case CSSM_ALGID_DSA:
166 result = kSecDSAAlgorithmID;
167 break;
168 case CSSM_ALGID_ECDSA:
169 result = kSecECDSAAlgorithmID;
170 break;
171 default:
172 assert(0); /* other algorithms TBA */
173 }
174
175 END_SECKEYAPI
176 }
177
178 static CFDataRef SecCDSAKeyCopyPublicKeyDataFromSubjectInfo(CFDataRef pubKeyInfo) {
179 // First of all, consider x509 format and try to strip SubjPubKey envelope. If it fails, do not panic
180 // and export data as is.
181 DERItem keyItem = { (DERByte *)CFDataGetBytePtr(pubKeyInfo), int_cast<CFIndex, DERSize>(CFDataGetLength(pubKeyInfo)) }, pubKeyItem;
182 DERByte numUnused;
183 DERSubjPubKeyInfo subjPubKey;
184 if (DERParseSequence(&keyItem, DERNumSubjPubKeyInfoItemSpecs,
185 DERSubjPubKeyInfoItemSpecs,
186 &subjPubKey, sizeof(subjPubKey)) == DR_Success &&
187 DERParseBitString(&subjPubKey.pubKey, &pubKeyItem, &numUnused) == DR_Success) {
188 return CFDataCreate(kCFAllocatorDefault, pubKeyItem.data, pubKeyItem.length);
189 }
190
191 return CFDataRef(CFRetain(pubKeyInfo));
192 }
193
194 static CFDataRef SecCDSAKeyCopyPublicKeyDataWithSubjectInfo(CSSM_ALGORITHMS algorithm, uint32 keySizeInBits, CFDataRef pubKeyInfo) {
195 // First check, whether X509 pubkeyinfo is already present. If not, add it according to the key type.
196 DERItem keyItem = { (DERByte *)CFDataGetBytePtr(pubKeyInfo), int_cast<CFIndex, DERSize>(CFDataGetLength(pubKeyInfo)) };
197 DERSubjPubKeyInfo subjPubKey;
198 if (DERParseSequence(&keyItem, DERNumSubjPubKeyInfoItemSpecs,
199 DERSubjPubKeyInfoItemSpecs,
200 &subjPubKey, sizeof(subjPubKey)) == DR_Success) {
201 return CFDataRef(CFRetain(pubKeyInfo));
202 }
203
204 // We have always size rounded to full bytes so bitstring encodes leading 00.
205 CFRef<CFMutableDataRef> bitStringPubKey = CFDataCreateMutable(kCFAllocatorDefault, 0);
206 CFDataSetLength(bitStringPubKey, 1);
207 CFDataAppendBytes(bitStringPubKey, CFDataGetBytePtr(pubKeyInfo), CFDataGetLength(pubKeyInfo));
208 subjPubKey.pubKey.data = static_cast<DERByte *>(const_cast<UInt8 *>(CFDataGetBytePtr(bitStringPubKey)));
209 subjPubKey.pubKey.length = CFDataGetLength(bitStringPubKey);
210
211 // Encode algId according to algorithm used.
212 static const DERByte oidRSA[] = {
213 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
214 };
215 static const DERByte oidECsecp256[] = {
216 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
217 };
218 static const DERByte oidECsecp384[] = {
219 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22,
220 };
221 static const DERByte oidECsecp521[] = {
222 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23,
223 };
224 subjPubKey.algId.length = 0;
225 if (algorithm == CSSM_ALGID_RSA) {
226 subjPubKey.algId.data = const_cast<DERByte *>(oidRSA);
227 subjPubKey.algId.length = sizeof(oidRSA);
228 } else if (algorithm == CSSM_ALGID_ECDSA) {
229 if (keySizeInBits == 256) {
230 subjPubKey.algId.data = const_cast<DERByte *>(oidECsecp256);
231 subjPubKey.algId.length = sizeof(oidECsecp256);
232 } else if (keySizeInBits == 384) {
233 subjPubKey.algId.data = const_cast<DERByte *>(oidECsecp384);
234 subjPubKey.algId.length = sizeof(oidECsecp384);
235 } if (keySizeInBits == 521) {
236 subjPubKey.algId.data = const_cast<DERByte *>(oidECsecp521);
237 subjPubKey.algId.length = sizeof(oidECsecp521);
238 }
239 }
240 DERSize size = DERLengthOfEncodedSequence(ASN1_CONSTR_SEQUENCE, &subjPubKey,
241 DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs);
242 CFRef<CFMutableDataRef> keyData = CFDataCreateMutable(kCFAllocatorDefault, size);
243 CFDataSetLength(keyData, size);
244 if (DEREncodeSequence(ASN1_CONSTR_SEQUENCE, &subjPubKey,
245 DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs,
246 static_cast<DERByte *>(CFDataGetMutableBytePtr(keyData)), &size) == DR_Success) {
247 CFDataSetLength(keyData, size);
248 } else {
249 keyData.release();
250 }
251
252 return keyData.yield();
253 }
254
255 static OSStatus SecCDSAKeyCopyPublicBytes(SecKeyRef key, CFDataRef *serialization) {
256
257 CFErrorRef *error = NULL;
258 BEGIN_SECKEYAPI(OSStatus, errSecSuccess)
259
260 const CssmKey::Header &header = key->key->key().header();
261 switch (header.algorithm()) {
262 case CSSM_ALGID_RSA: {
263 switch (header.keyClass()) {
264 case CSSM_KEYCLASS_PRIVATE_KEY: {
265 CFRef<CFDataRef> privKeyData;
266 result = SecItemExport(key, kSecFormatOpenSSL, 0, NULL, privKeyData.take());
267 if (result == errSecSuccess) {
268 DERItem keyItem = { (DERByte *)CFDataGetBytePtr(privKeyData), int_cast<CFIndex, DERSize>(CFDataGetLength(privKeyData)) };
269 DERRSAKeyPair keyPair;
270 if (DERParseSequence(&keyItem, DERNumRSAKeyPairItemSpecs, DERRSAKeyPairItemSpecs,
271 &keyPair, sizeof(keyPair)) == DR_Success) {
272 DERRSAPubKeyPKCS1 pubKey = { keyPair.n, keyPair.e };
273 DERSize size = DERLengthOfEncodedSequence(ASN1_SEQUENCE, &pubKey,
274 DERNumRSAPubKeyPKCS1ItemSpecs, DERRSAPubKeyPKCS1ItemSpecs);
275 CFRef<CFMutableDataRef> keyData = CFDataCreateMutable(kCFAllocatorDefault, size);
276 CFDataSetLength(keyData, size);
277 UInt8 *data = CFDataGetMutableBytePtr(keyData);
278 if (DEREncodeSequence(ASN1_SEQUENCE, &pubKey,
279 DERNumRSAPubKeyPKCS1ItemSpecs, DERRSAPubKeyPKCS1ItemSpecs,
280 data, &size) == DR_Success) {
281 CFDataSetLength(keyData, size);
282 *data = ONE_BYTE_ASN1_CONSTR_SEQUENCE;
283 *serialization = keyData.yield();
284 } else {
285 *serialization = NULL;
286 result = errSecParam;
287 }
288 }
289 }
290 break;
291 }
292 case CSSM_KEYCLASS_PUBLIC_KEY:
293 result = SecItemExport(key, kSecFormatBSAFE, 0, NULL, serialization);
294 break;
295 }
296 break;
297 }
298 case CSSM_ALGID_ECDSA: {
299 *serialization = NULL;
300 CFRef<CFDataRef> tempPublicData;
301 result = SecItemExport(key, kSecFormatOpenSSL, 0, NULL, tempPublicData.take());
302 if (result == errSecSuccess) {
303 *serialization = SecCDSAKeyCopyPublicKeyDataFromSubjectInfo(tempPublicData);
304 }
305 break;
306 }
307 default:
308 result = errSecUnimplemented;
309 }
310
311 END_SECKEYAPI
312 }
313
314 typedef struct {
315 DERItem privateKey;
316 DERItem publicKey;
317 } DERECPrivateKey;
318
319 static const DERItemSpec DERECPrivateKeyItemSpecs[] =
320 {
321 { 0,
322 ASN1_INTEGER,
323 DER_DEC_SKIP },
324 { DER_OFFSET(DERECPrivateKey, privateKey),
325 ASN1_OCTET_STRING,
326 DER_DEC_NO_OPTS | DER_ENC_NO_OPTS },
327 { 0,
328 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0,
329 DER_DEC_SKIP | DER_ENC_NO_OPTS },
330 { DER_OFFSET(DERECPrivateKey, publicKey),
331 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1,
332 DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT },
333 };
334 static const DERSize DERNumECPrivateKeyItemSpecs =
335 sizeof(DERECPrivateKeyItemSpecs) / sizeof(DERItemSpec);
336
337 typedef struct {
338 DERItem bitString;
339 } DERECPrivateKeyPublicKey;
340
341 static const DERItemSpec DERECPrivateKeyPublicKeyItemSpecs[] =
342 {
343 { DER_OFFSET(DERECPrivateKeyPublicKey, bitString),
344 ASN1_BIT_STRING,
345 DER_DEC_NO_OPTS | DER_ENC_NO_OPTS },
346 };
347 static const DERSize DERNumECPrivateKeyPublicKeyItemSpecs =
348 sizeof(DERECPrivateKeyPublicKeyItemSpecs) / sizeof(DERItemSpec);
349
350 static CFDataRef
351 SecCDSAKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) {
352
353 BEGIN_SECKEYAPI(CFDataRef, NULL)
354
355 result = NULL;
356 const CssmKey::Header header = key->key->unverifiedKeyHeader();
357 CFRef<CFDataRef> keyData;
358 switch (header.algorithm()) {
359 case CSSM_ALGID_RSA:
360 MacOSError::check(SecItemExport(key, kSecFormatOpenSSL, 0, NULL, keyData.take()));
361 break;
362 case CSSM_ALGID_ECDSA: {
363 MacOSError::check(SecItemExport(key, kSecFormatOpenSSL, 0, NULL, keyData.take()));
364 if (header.keyClass() == CSSM_KEYCLASS_PRIVATE_KEY) {
365 // Convert DER format into x9.63 format, which is expected for exported key.
366 DERItem keyItem = { (DERByte *)CFDataGetBytePtr(keyData), int_cast<CFIndex, DERSize>(CFDataGetLength(keyData)) };
367 DERECPrivateKey privateKey;
368 DERECPrivateKeyPublicKey privateKeyPublicKey;
369 DERByte numUnused;
370 DERItem pubKeyItem;
371 if (DERParseSequence(&keyItem, DERNumECPrivateKeyItemSpecs, DERECPrivateKeyItemSpecs,
372 &privateKey, sizeof(privateKey)) == DR_Success &&
373 DERParseSequenceContent(&privateKey.publicKey, DERNumECPrivateKeyPublicKeyItemSpecs,
374 DERECPrivateKeyPublicKeyItemSpecs,
375 &privateKeyPublicKey, sizeof(privateKeyPublicKey)) == DR_Success &&
376 DERParseBitString(&privateKeyPublicKey.bitString, &pubKeyItem, &numUnused) == DR_Success) {
377 CFRef<CFMutableDataRef> key = CFDataCreateMutable(kCFAllocatorDefault,
378 pubKeyItem.length + privateKey.privateKey.length);
379 CFDataSetLength(key, pubKeyItem.length + privateKey.privateKey.length);
380 CFDataReplaceBytes(key, CFRangeMake(0, pubKeyItem.length), pubKeyItem.data, pubKeyItem.length);
381 CFDataReplaceBytes(key, CFRangeMake(pubKeyItem.length, privateKey.privateKey.length),
382 privateKey.privateKey.data, privateKey.privateKey.length);
383 keyData = key.as<CFDataRef>();
384 }
385 }
386 break;
387 }
388 default:
389 MacOSError::throwMe(errSecUnimplemented);
390 }
391
392 if (header.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY) {
393 result = SecCDSAKeyCopyPublicKeyDataFromSubjectInfo(keyData);
394 } else {
395 result = keyData.yield();
396 }
397
398 END_SECKEYAPI
399 }
400
401 static CFDataRef SecCDSAKeyCopyLabel(SecKeyRef key) {
402 CFDataRef label = NULL;
403 if (key->key->isPersistent()) {
404 UInt32 tags[] = { kSecKeyLabel }, formats[] = { CSSM_DB_ATTRIBUTE_FORMAT_BLOB };
405 SecKeychainAttributeInfo info = { 1, tags, formats };
406 SecKeychainAttributeList *list = NULL;
407 key->key->getAttributesAndData(&info, NULL, &list, NULL, NULL);
408 if (list->count == 1) {
409 SecKeychainAttribute *attr = list->attr;
410 label = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)attr->data, (CFIndex)attr->length);
411 }
412 key->key->freeAttributesAndData(list, NULL);
413 }
414 return label;
415 }
416
417 static CFDictionaryRef
418 SecCDSAKeyCopyAttributeDictionary(SecKeyRef key) {
419
420 CFErrorRef *error = NULL;
421 BEGIN_SECKEYAPI(CFDictionaryRef, NULL)
422
423 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks,
424 &kCFTypeDictionaryValueCallBacks);
425
426 CFDictionarySetValue(dict, kSecClass, kSecClassKey);
427
428 const CssmKey::Header header = key->key->unverifiedKeyHeader();
429 CFIndex sizeValue = header.LogicalKeySizeInBits;
430 CFRef<CFNumberRef> sizeInBits = CFNumberCreate(NULL, kCFNumberCFIndexType, &sizeValue);
431 CFDictionarySetValue(dict, kSecAttrKeySizeInBits, sizeInBits);
432 CFDictionarySetValue(dict, kSecAttrEffectiveKeySize, sizeInBits);
433
434 CFRef<CFDataRef> label = SecCDSAKeyCopyLabel(key);
435 if (!label) {
436 // For floating keys, calculate label as SHA1 of pubkey bytes.
437 CFRef<CFDataRef> pubKeyBlob;
438 if (SecCDSAKeyCopyPublicBytes(key, pubKeyBlob.take()) == errSecSuccess) {
439 uint8_t pubKeyHash[CC_SHA1_DIGEST_LENGTH];
440 CC_SHA1(CFDataGetBytePtr(pubKeyBlob), CC_LONG(CFDataGetLength(pubKeyBlob)), pubKeyHash);
441 label.take(CFDataCreate(kCFAllocatorDefault, pubKeyHash, sizeof(pubKeyHash)));
442 }
443 }
444
445 if (label) {
446 CFDictionarySetValue(dict, kSecAttrApplicationLabel, label);
447 }
448
449 CSSM_KEYATTR_FLAGS attrs = header.attributes();
450 CFDictionarySetValue(dict, kSecAttrIsPermanent, (attrs & CSSM_KEYATTR_PERMANENT) ? kCFBooleanTrue : kCFBooleanFalse);
451 CFDictionarySetValue(dict, kSecAttrIsPrivate, (attrs & CSSM_KEYATTR_PRIVATE) ? kCFBooleanTrue : kCFBooleanFalse);
452 CFDictionarySetValue(dict, kSecAttrIsModifiable, (attrs & CSSM_KEYATTR_MODIFIABLE) ? kCFBooleanTrue : kCFBooleanFalse);
453 CFDictionarySetValue(dict, kSecAttrIsSensitive, (attrs & CSSM_KEYATTR_SENSITIVE) ? kCFBooleanTrue : kCFBooleanFalse);
454 CFDictionarySetValue(dict, kSecAttrIsExtractable, (attrs & CSSM_KEYATTR_EXTRACTABLE) ? kCFBooleanTrue : kCFBooleanFalse);
455 CFDictionarySetValue(dict, kSecAttrWasAlwaysSensitive, (attrs & CSSM_KEYATTR_ALWAYS_SENSITIVE) ? kCFBooleanTrue : kCFBooleanFalse);
456 CFDictionarySetValue(dict, kSecAttrWasNeverExtractable, (attrs & CSSM_KEYATTR_NEVER_EXTRACTABLE) ? kCFBooleanTrue : kCFBooleanFalse);
457
458 CFDictionarySetValue(dict, kSecAttrCanEncrypt, (header.useFor(CSSM_KEYUSE_ENCRYPT)) ? kCFBooleanTrue : kCFBooleanFalse);
459 CFDictionarySetValue(dict, kSecAttrCanDecrypt, (header.useFor(CSSM_KEYUSE_DECRYPT)) ? kCFBooleanTrue : kCFBooleanFalse);
460 CFDictionarySetValue(dict, kSecAttrCanSign, (header.useFor(CSSM_KEYUSE_SIGN)) ? kCFBooleanTrue : kCFBooleanFalse);
461 CFDictionarySetValue(dict, kSecAttrCanVerify, (header.useFor(CSSM_KEYUSE_VERIFY)) ? kCFBooleanTrue : kCFBooleanFalse);
462 CFDictionarySetValue(dict, kSecAttrCanSignRecover, (header.useFor(CSSM_KEYUSE_SIGN_RECOVER)) ? kCFBooleanTrue : kCFBooleanFalse);
463 CFDictionarySetValue(dict, kSecAttrCanVerifyRecover, (header.useFor(CSSM_KEYUSE_VERIFY_RECOVER)) ? kCFBooleanTrue : kCFBooleanFalse);
464 CFDictionarySetValue(dict, kSecAttrCanWrap, (header.useFor(CSSM_KEYUSE_WRAP)) ? kCFBooleanTrue : kCFBooleanFalse);
465 CFDictionarySetValue(dict, kSecAttrCanUnwrap, (header.useFor(CSSM_KEYUSE_UNWRAP)) ? kCFBooleanTrue : kCFBooleanFalse);
466 CFDictionarySetValue(dict, kSecAttrCanDerive, (header.useFor(CSSM_KEYUSE_DERIVE)) ? kCFBooleanTrue : kCFBooleanFalse);
467
468 switch (header.keyClass()) {
469 case CSSM_KEYCLASS_PUBLIC_KEY:
470 CFDictionarySetValue(dict, kSecAttrKeyClass, kSecAttrKeyClassPublic);
471 break;
472 case CSSM_KEYCLASS_PRIVATE_KEY:
473 CFDictionarySetValue(dict, kSecAttrKeyClass, kSecAttrKeyClassPrivate);
474 break;
475 }
476
477 switch (header.algorithm()) {
478 case CSSM_ALGID_RSA:
479 CFDictionarySetValue(dict, kSecAttrKeyType, kSecAttrKeyTypeRSA);
480 break;
481 case CSSM_ALGID_ECDSA:
482 CFDictionarySetValue(dict, kSecAttrKeyType, kSecAttrKeyTypeECDSA);
483 break;
484 }
485
486 CFRef<CFDataRef> keyData;
487 if (SecItemExport(key, kSecFormatOpenSSL, 0, NULL, keyData.take()) == errSecSuccess) {
488 CFDictionarySetValue(dict, kSecValueData, keyData);
489 }
490
491 if (header.algorithm() == CSSM_ALGID_RSA && header.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY &&
492 header.blobType() == CSSM_KEYBLOB_RAW) {
493 const CssmData &keyData = key->key->key()->keyData();
494 DERItem keyItem = { static_cast<DERByte *>(keyData.data()), keyData.length() };
495 DERRSAPubKeyPKCS1 decodedKey;
496 if (DERParseSequence(&keyItem, DERNumRSAPubKeyPKCS1ItemSpecs,
497 DERRSAPubKeyPKCS1ItemSpecs,
498 &decodedKey, sizeof(decodedKey)) == DR_Success) {
499 CFRef<CFDataRef> modulus = CFDataCreate(kCFAllocatorDefault, decodedKey.modulus.data,
500 decodedKey.modulus.length);
501 CFDictionarySetValue(dict, CFSTR("_rsam"), modulus);
502 CFRef<CFDataRef> exponent = CFDataCreate(kCFAllocatorDefault, decodedKey.pubExponent.data,
503 decodedKey.pubExponent.length);
504 CFDictionarySetValue(dict, CFSTR("_rsae"), exponent);
505 }
506 }
507
508 result = dict;
509
510 END_SECKEYAPI
511 }
512
513 #pragma clang diagnostic push
514 #pragma clang diagnostic ignored "-Wunused-const-variable"
515 static CSSM_DB_NAME_ATTR(kInfoKeyLabel, kSecKeyLabel, (char*) "Label", 0, NULL, BLOB);
516 #pragma clang diagnostic pop
517
518 static SecKeyRef SecCDSAKeyCopyPublicKey(SecKeyRef privateKey) {
519 CFErrorRef *error = NULL;
520 BEGIN_SECKEYAPI(SecKeyRef, NULL)
521
522 result = NULL;
523 KeyItem *key = privateKey->key;
524 CFRef<CFDataRef> label = SecCDSAKeyCopyLabel(privateKey);
525 if (label) {
526 // Lookup public key in the database.
527 DbUniqueRecord uniqueId;
528 SSDb ssDb(dynamic_cast<SSDbImpl *>(&(*key->keychain()->database())));
529 SSDbCursor dbCursor(ssDb, 1);
530 dbCursor->recordType(CSSM_DL_DB_RECORD_PUBLIC_KEY);
531 dbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, CssmData(CFDataRef(label)));
532 if (dbCursor->next(NULL, NULL, uniqueId)) {
533 Item publicKey = key->keychain()->item(CSSM_DL_DB_RECORD_PUBLIC_KEY, uniqueId);
534 result = reinterpret_cast<SecKeyRef>(publicKey->handle());
535 }
536 }
537
538 if (result == NULL && key->publicKey()) {
539 SecPointer<KeyItem> publicKey(new KeyItem(key->publicKey()));
540 result = reinterpret_cast<SecKeyRef>(publicKey->handle());
541 }
542
543 END_SECKEYAPI
544 }
545
546 static KeyItem *SecCDSAKeyPrepareParameters(SecKeyRef key, SecKeyOperationType &operation, SecKeyAlgorithm algorithm,
547 CSSM_ALGORITHMS &baseAlgorithm, CSSM_ALGORITHMS &secondaryAlgorithm,
548 CSSM_ALGORITHMS &paddingAlgorithm, CFIndex &inputSizeLimit) {
549 KeyItem *keyItem = key->key;
550 CSSM_KEYCLASS keyClass = keyItem->key()->header().keyClass();
551 baseAlgorithm = keyItem->key()->header().algorithm();
552 switch (baseAlgorithm) {
553 case CSSM_ALGID_RSA:
554 if ((keyClass == CSSM_KEYCLASS_PRIVATE_KEY && operation == kSecKeyOperationTypeSign) ||
555 (keyClass == CSSM_KEYCLASS_PUBLIC_KEY && operation == kSecKeyOperationTypeVerify)) {
556 if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureRaw)) {
557 secondaryAlgorithm = CSSM_ALGID_NONE;
558 paddingAlgorithm = CSSM_PADDING_NONE;
559 inputSizeLimit = 0;
560 } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw)) {
561 secondaryAlgorithm = CSSM_ALGID_NONE;
562 paddingAlgorithm = CSSM_PADDING_PKCS1;
563 inputSizeLimit = -11;
564 } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1)) {
565 secondaryAlgorithm = CSSM_ALGID_SHA1;
566 paddingAlgorithm = CSSM_PADDING_PKCS1;
567 inputSizeLimit = 20;
568 } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224)) {
569 secondaryAlgorithm = CSSM_ALGID_SHA224;
570 paddingAlgorithm = CSSM_PADDING_PKCS1;
571 inputSizeLimit = 224 / 8;
572 } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256)) {
573 secondaryAlgorithm = CSSM_ALGID_SHA256;
574 paddingAlgorithm = CSSM_PADDING_PKCS1;
575 inputSizeLimit = 256 / 8;
576 } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384)) {
577 secondaryAlgorithm = CSSM_ALGID_SHA384;
578 paddingAlgorithm = CSSM_PADDING_PKCS1;
579 inputSizeLimit = 384 / 8;
580 } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512)) {
581 secondaryAlgorithm = CSSM_ALGID_SHA512;
582 paddingAlgorithm = CSSM_PADDING_PKCS1;
583 inputSizeLimit = 512 / 8;
584 } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5)) {
585 secondaryAlgorithm = CSSM_ALGID_MD5;
586 paddingAlgorithm = CSSM_PADDING_PKCS1;
587 inputSizeLimit = 16;
588 } else {
589 return NULL;
590 }
591 } else if ((keyClass == CSSM_KEYCLASS_PRIVATE_KEY && operation == kSecKeyOperationTypeDecrypt) ||
592 (keyClass == CSSM_KEYCLASS_PUBLIC_KEY && operation == kSecKeyOperationTypeEncrypt)) {
593 if (CFEqual(algorithm, kSecKeyAlgorithmRSAEncryptionRaw)) {
594 secondaryAlgorithm = CSSM_ALGID_NONE;
595 paddingAlgorithm = CSSM_PADDING_NONE;
596 inputSizeLimit = 0;
597 } else if (CFEqual(algorithm, kSecKeyAlgorithmRSAEncryptionPKCS1)) {
598 secondaryAlgorithm = CSSM_ALGID_NONE;
599 paddingAlgorithm = CSSM_PADDING_PKCS1;
600 inputSizeLimit = operation == kSecKeyOperationTypeEncrypt ? -11 : 0;
601 } else {
602 return NULL;
603 }
604 } else if (keyClass == CSSM_KEYCLASS_PUBLIC_KEY && operation == kSecKeyOperationTypeDecrypt &&
605 CFEqual(algorithm, kSecKeyAlgorithmRSAEncryptionRaw)) {
606 // Raw RSA decryption is identical to raw RSA encryption, so lets use encryption instead of decryption,
607 // because CDSA keys refuses to perform decrypt using public key.
608 operation = kSecKeyOperationTypeEncrypt;
609 secondaryAlgorithm = CSSM_ALGID_NONE;
610 paddingAlgorithm = CSSM_PADDING_NONE;
611 inputSizeLimit = 0;
612 } else {
613 return NULL;
614 }
615 break;
616 case CSSM_ALGID_ECDSA:
617 if ((keyClass == CSSM_KEYCLASS_PRIVATE_KEY && operation == kSecKeyOperationTypeSign) ||
618 (keyClass == CSSM_KEYCLASS_PUBLIC_KEY && operation == kSecKeyOperationTypeVerify)) {
619 if (CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureRFC4754)) {
620 secondaryAlgorithm = CSSM_ALGID_NONE;
621 paddingAlgorithm = CSSM_PADDING_SIGRAW;
622 } else if (CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureDigestX962)) {
623 secondaryAlgorithm = CSSM_ALGID_NONE;
624 paddingAlgorithm = CSSM_PADDING_PKCS1;
625 } else {
626 return NULL;
627 }
628 } else if (keyClass == CSSM_KEYCLASS_PRIVATE_KEY && operation == kSecKeyOperationTypeKeyExchange) {
629 if (CFEqual(algorithm,kSecKeyAlgorithmECDHKeyExchangeStandard) ||
630 CFEqual(algorithm, kSecKeyAlgorithmECDHKeyExchangeCofactor)) {
631 baseAlgorithm = CSSM_ALGID_ECDH;
632 } else if (CFEqual(algorithm, kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1) ||
633 CFEqual(algorithm, kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1)) {
634 baseAlgorithm = CSSM_ALGID_ECDH_X963_KDF;
635 } else {
636 return NULL;
637 }
638 } else {
639 return NULL;
640 }
641 break;
642 default:
643 MacOSError::throwMe(errSecParam);
644 }
645 return keyItem;
646 }
647
648 static CFDataRef
649 SecCDSAKeyCopyPaddedPlaintext(SecKeyRef key, CFDataRef plaintext, SecKeyAlgorithm algorithm) {
650 CFIndex blockSize = key->key->key().header().LogicalKeySizeInBits / 8;
651 CFIndex plaintextLength = CFDataGetLength(plaintext);
652 if ((algorithm == kSecKeyAlgorithmRSAEncryptionRaw || algorithm == kSecKeyAlgorithmRSASignatureRaw)
653 && plaintextLength < blockSize) {
654 // Pre-pad with zeroes.
655 CFMutableDataRef result(CFDataCreateMutable(kCFAllocatorDefault, blockSize));
656 CFDataSetLength(result, blockSize);
657 CFDataReplaceBytes(result, CFRangeMake(blockSize - plaintextLength, plaintextLength),
658 CFDataGetBytePtr(plaintext), plaintextLength);
659 return result;
660 } else {
661 return CFDataRef(CFRetain(plaintext));
662 }
663 }
664
665 static CFTypeRef SecCDSAKeyCopyOperationResult(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm,
666 CFArrayRef allAlgorithms, SecKeyOperationMode mode,
667 CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
668 BEGIN_SECKEYAPI(CFTypeRef, kCFNull)
669 CFIndex inputSizeLimit = 0;
670 CSSM_ALGORITHMS baseAlgorithm, secondaryAlgorithm, paddingAlgorithm;
671 KeyItem *keyItem = SecCDSAKeyPrepareParameters(key, operation, algorithm, baseAlgorithm, secondaryAlgorithm, paddingAlgorithm, inputSizeLimit);
672 if (keyItem == NULL) {
673 // Operation/algorithm/key combination is not supported.
674 return kCFNull;
675 } else if (mode == kSecKeyOperationModeCheckIfSupported) {
676 // Operation is supported and caller wants to just know that.
677 return kCFBooleanTrue;
678 } else if (baseAlgorithm == CSSM_ALGID_RSA) {
679 if (inputSizeLimit <= 0) {
680 inputSizeLimit += SecCDSAKeyGetBlockSize(key);
681 }
682 if (CFDataGetLength((CFDataRef)in1) > inputSizeLimit) {
683 MacOSError::throwMe(errSecParam);
684 }
685 }
686
687 switch (operation) {
688 case kSecKeyOperationTypeSign: {
689 CssmClient::Sign signContext(keyItem->csp(), baseAlgorithm, secondaryAlgorithm);
690 signContext.key(keyItem->key());
691 signContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_SIGN, key->credentialType));
692 signContext.add(CSSM_ATTRIBUTE_PADDING, paddingAlgorithm);
693 CFRef<CFDataRef> input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef<CFDataRef>::check(in1, errSecParam), algorithm);
694 CssmAutoData signature(signContext.allocator());
695 signContext.sign(CssmData(CFDataRef(input)), signature.get());
696 result = CFDataCreate(NULL, static_cast<const UInt8 *>(signature.data()), CFIndex(signature.length()));
697 break;
698 }
699 case kSecKeyOperationTypeVerify: {
700 CssmClient::Verify verifyContext(keyItem->csp(), baseAlgorithm, secondaryAlgorithm);
701 verifyContext.key(keyItem->key());
702 verifyContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ANY, key->credentialType));
703 verifyContext.add(CSSM_ATTRIBUTE_PADDING, paddingAlgorithm);
704 CFRef<CFDataRef> input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef<CFDataRef>::check(in1, errSecParam), algorithm);
705 verifyContext.verify(CssmData(CFDataRef(input)), CssmData(CFRef<CFDataRef>::check(in2, errSecParam)));
706 result = kCFBooleanTrue;
707 break;
708 }
709 case kSecKeyOperationTypeEncrypt: {
710 CssmClient::Encrypt encryptContext(keyItem->csp(), baseAlgorithm);
711 encryptContext.key(keyItem->key());
712 encryptContext.padding(paddingAlgorithm);
713 encryptContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ENCRYPT, key->credentialType));
714 CFRef<CFDataRef> input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef<CFDataRef>::check(in1, errSecParam), algorithm);
715 CssmAutoData output(encryptContext.allocator()), remainingData(encryptContext.allocator());
716 size_t length = encryptContext.encrypt(CssmData(CFDataRef(input)), output.get(), remainingData.get());
717 result = CFDataCreateMutable(kCFAllocatorDefault, output.length() + remainingData.length());
718 CFDataAppendBytes(CFMutableDataRef(result), static_cast<const UInt8 *>(output.data()), output.length());
719 CFDataAppendBytes(CFMutableDataRef(result), static_cast<const UInt8 *>(remainingData.data()), remainingData.length());
720 CFDataSetLength(CFMutableDataRef(result), length);
721 break;
722 }
723 case kSecKeyOperationTypeDecrypt: {
724 CssmClient::Decrypt decryptContext(keyItem->csp(), baseAlgorithm);
725 decryptContext.key(keyItem->key());
726 decryptContext.padding(paddingAlgorithm);
727 decryptContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_DECRYPT, key->credentialType));
728 CssmAutoData output(decryptContext.allocator()), remainingData(decryptContext.allocator());
729 size_t length = decryptContext.decrypt(CssmData(CFRef<CFDataRef>::check(in1, errSecParam)),
730 output.get(), remainingData.get());
731 result = CFDataCreateMutable(kCFAllocatorDefault, output.length() + remainingData.length());
732 CFDataAppendBytes(CFMutableDataRef(result), static_cast<const UInt8 *>(output.data()), output.length());
733 CFDataAppendBytes(CFMutableDataRef(result), static_cast<const UInt8 *>(remainingData.data()), remainingData.length());
734 CFDataSetLength(CFMutableDataRef(result), length);
735 break;
736 }
737 case kSecKeyOperationTypeKeyExchange: {
738 CFIndex requestedLength = 0;
739 CssmData sharedInfo;
740 switch (baseAlgorithm) {
741 case CSSM_ALGID_ECDH:
742 requestedLength = (keyItem->key().header().LogicalKeySizeInBits + 7) / 8;
743 break;
744 case CSSM_ALGID_ECDH_X963_KDF:
745 CFDictionaryRef params = CFRef<CFDictionaryRef>::check(in2, errSecParam);
746 CFTypeRef value = params ? CFDictionaryGetValue(params, kSecKeyKeyExchangeParameterRequestedSize) : NULL;
747 if (value == NULL || CFGetTypeID(value) != CFNumberGetTypeID() ||
748 !CFNumberGetValue(CFNumberRef(value), kCFNumberCFIndexType, &requestedLength)) {
749 MacOSError::throwMe(errSecParam);
750 }
751 value = CFDictionaryGetValue(params, kSecKeyKeyExchangeParameterSharedInfo);
752 if (value != NULL && CFGetTypeID(value) == CFDataGetTypeID()) {
753 sharedInfo = CssmData(CFDataRef(value));
754 }
755 break;
756 }
757
758 CssmClient::DeriveKey derive(keyItem->csp(), baseAlgorithm, CSSM_ALGID_AES, uint32(requestedLength * 8));
759 derive.key(keyItem->key());
760 derive.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_DERIVE, kSecCredentialTypeDefault));
761 derive.salt(sharedInfo);
762 CssmData param(CFRef<CFDataRef>::check(in1, errSecParam));
763 Key derivedKey = derive(&param, KeySpec(CSSM_KEYUSE_ANY, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE));
764
765 // Export raw data of newly derived key (by wrapping with an empty key).
766 CssmClient::WrapKey wrapper(keyItem->csp(), CSSM_ALGID_NONE);
767 Key wrappedKey = wrapper(derivedKey);
768 result = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)wrappedKey->data(), CFIndex(wrappedKey->length()));
769 break;
770 }
771 default:
772 break;
773 }
774
775 END_SECKEYAPI
776 }
777
778 static Boolean SecCDSAKeyIsEqual(SecKeyRef key1, SecKeyRef key2) {
779 CFErrorRef *error = NULL;
780 BEGIN_SECKEYAPI(Boolean, false)
781
782 result = key1->key->equal(*key2->key);
783
784 END_SECKEYAPI
785 }
786
787 static Boolean SecCDSAKeySetParameter(SecKeyRef key, CFStringRef name, CFPropertyListRef value, CFErrorRef *error) {
788 BEGIN_SECKEYAPI(Boolean, false)
789
790 if (CFEqual(name, kSecUseAuthenticationUI)) {
791 key->credentialType = CFEqual(value, kSecUseAuthenticationUIAllow) ? kSecCredentialTypeDefault : kSecCredentialTypeNoUI;
792 result = true;
793 } else {
794 result = SecError(errSecUnimplemented, error, CFSTR("Unsupported parameter '%@' for SecKeyCDSASetParameter"), name);
795 }
796
797 END_SECKEYAPI
798 }
799
800 const SecKeyDescriptor kSecCDSAKeyDescriptor = {
801 .version = kSecKeyDescriptorVersion,
802 .name = "CDSAKey",
803
804 .init = SecCDSAKeyInit,
805 .destroy = SecCDSAKeyDestroy,
806 .blockSize = SecCDSAKeyGetBlockSize,
807 .getAlgorithmID = SecCDSAKeyGetAlgorithmId,
808 .copyDictionary = SecCDSAKeyCopyAttributeDictionary,
809 .copyPublic = SecCDSAKeyCopyPublicBytes,
810 .copyExternalRepresentation = SecCDSAKeyCopyExternalRepresentation,
811 .copyPublicKey = SecCDSAKeyCopyPublicKey,
812 .copyOperationResult = SecCDSAKeyCopyOperationResult,
813 .isEqual = SecCDSAKeyIsEqual,
814 .setParameter = SecCDSAKeySetParameter,
815
816 .extraBytes = (sizeof(struct OpaqueSecKeyRef) > sizeof(struct __SecKey) ? (sizeof(struct OpaqueSecKeyRef) - sizeof(struct __SecKey)) : 0),
817 };
818
819 namespace Security {
820 namespace KeychainCore {
821 SecCFObject *KeyItem::fromSecKeyRef(CFTypeRef ptr) {
822 if (ptr == NULL || CFGetTypeID(ptr) != SecKeyGetTypeID()) {
823 return NULL;
824 }
825
826 SecKeyRef key = static_cast<SecKeyRef>(const_cast<void *>(ptr));
827 if (key->key_class == &kSecCDSAKeyDescriptor) {
828 return static_cast<SecCFObject *>(key->key);
829 }
830
831 if (key->cdsaKey == NULL) {
832 // Create CDSA key from exported data of existing key.
833 CFRef<CFDictionaryRef> keyAttributes = SecKeyCopyAttributes(key);
834 if (keyAttributes) {
835 CFRef<CFDataRef> keyData = SecKeyCopyExternalRepresentation(key, NULL);
836 if (!keyData) {
837 CFTypeRef pubKeyHash = CFDictionaryGetValue(keyAttributes, kSecAttrApplicationLabel);
838 const void *keys[] = { kSecClass, kSecAttrNoLegacy, kSecReturnRef, kSecMatchLimit };
839 const void *values[] = { kSecClassIdentity, kCFBooleanFalse, kCFBooleanTrue, kSecMatchLimitAll };
840 CFRef<CFDictionaryRef> query = CFDictionaryCreate(kCFAllocatorDefault, keys, values,
841 sizeof(keys) / sizeof(*keys),
842 &kCFTypeDictionaryKeyCallBacks,
843 &kCFTypeDictionaryValueCallBacks);
844 CFRef<CFArrayRef> identities;
845 OSStatus status = SecItemCopyMatching(query, (CFTypeRef *)identities.take());
846 if (status == errSecSuccess) {
847 for (int i = 0; i < CFArrayGetCount(identities); ++i) {
848 CFRef<SecKeyRef> privateKey;
849 if (SecIdentityCopyPrivateKey((SecIdentityRef)CFArrayGetValueAtIndex(identities, i), privateKey.take()) != errSecSuccess) {
850 continue;
851 }
852 CFRef<CFDictionaryRef> attrs = SecKeyCopyAttributes(privateKey);
853 if (CFEqual(CFDictionaryGetValue(attrs, kSecAttrApplicationLabel), pubKeyHash)) {
854 key->cdsaKey = privateKey.retain();
855 break;
856 }
857 }
858 }
859 } else {
860 key->cdsaKey = SecKeyCreateFromData(keyAttributes, keyData, NULL);
861 }
862 }
863 }
864
865 return (key->cdsaKey != NULL) ? key->cdsaKey->key : NULL;
866 }
867
868 // You need to hold this key's MutexForObject when you run this
869 void KeyItem::attachSecKeyRef() const {
870 SecKeyRef key = SecKeyCreate(NULL, &kSecCDSAKeyDescriptor, reinterpret_cast<const uint8_t *>(this), 0, 0);
871 key->key->mWeakSecKeyRef = key;
872 }
873
874 }
875 }
876
877 extern "C" Boolean SecKeyIsCDSAKey(SecKeyRef ref);
878 Boolean SecKeyIsCDSAKey(SecKeyRef ref) {
879 return ref->key_class == &kSecCDSAKeyDescriptor;
880 }
881
882
883 static OSStatus SecKeyCreatePairInternal(
884 SecKeychainRef keychainRef,
885 CSSM_ALGORITHMS algorithm,
886 uint32 keySizeInBits,
887 CSSM_CC_HANDLE contextHandle,
888 CSSM_KEYUSE publicKeyUsage,
889 uint32 publicKeyAttr,
890 CSSM_KEYUSE privateKeyUsage,
891 uint32 privateKeyAttr,
892 SecAccessRef initialAccess,
893 SecKeyRef* publicKeyRef,
894 SecKeyRef* privateKeyRef)
895 {
896 BEGIN_SECAPI
897
898 Keychain keychain;
899 SecPointer<Access> theAccess(initialAccess ? Access::required(initialAccess) : new Access("<key>"));
900 SecPointer<KeyItem> pubItem, privItem;
901 if (((publicKeyAttr | privateKeyAttr) & CSSM_KEYATTR_PERMANENT) != 0) {
902 keychain = Keychain::optional(keychainRef);
903 }
904 StMaybeLock<Mutex> _(keychain ? keychain->getKeychainMutex() : NULL);
905 KeyItem::createPair(keychain, algorithm, keySizeInBits, contextHandle, publicKeyUsage, publicKeyAttr,
906 privateKeyUsage, privateKeyAttr, theAccess, pubItem, privItem);
907
908 // Return the generated keys.
909 if (publicKeyRef)
910 *publicKeyRef = pubItem->handle();
911 if (privateKeyRef)
912 *privateKeyRef = privItem->handle();
913
914 END_SECAPI
915 }
916
917 OSStatus
918 SecKeyCreatePair(
919 SecKeychainRef keychainRef,
920 CSSM_ALGORITHMS algorithm,
921 uint32 keySizeInBits,
922 CSSM_CC_HANDLE contextHandle,
923 CSSM_KEYUSE publicKeyUsage,
924 uint32 publicKeyAttr,
925 CSSM_KEYUSE privateKeyUsage,
926 uint32 privateKeyAttr,
927 SecAccessRef initialAccess,
928 SecKeyRef* publicKeyRef,
929 SecKeyRef* privateKeyRef)
930 {
931 OSStatus result = SecKeyCreatePairInternal(keychainRef, algorithm, keySizeInBits, contextHandle, publicKeyUsage,
932 publicKeyAttr, privateKeyUsage, privateKeyAttr, initialAccess, publicKeyRef, privateKeyRef);
933
934 return result;
935 }
936
937
938
939 OSStatus
940 SecKeyGetCSSMKey(SecKeyRef key, const CSSM_KEY **cssmKey)
941 {
942 BEGIN_SECAPI
943
944 Required(cssmKey) = KeyItem::required(key)->key();
945
946 END_SECAPI
947 }
948
949
950 //
951 // Private APIs
952 //
953
954 static ModuleNexus<Mutex> gSecReturnedKeyCSPsMutex;
955 static ModuleNexus<std::set<CssmClient::CSP>> gSecReturnedKeyCSPs;
956
957 OSStatus
958 SecKeyGetCSPHandle(SecKeyRef keyRef, CSSM_CSP_HANDLE *cspHandle)
959 {
960 BEGIN_SECAPI
961
962 SecPointer<KeyItem> keyItem(KeyItem::required(keyRef));
963
964 // Once we vend this handle, we can no longer delete this CSP object via RAII (and thus call CSSM_ModuleDetach on the CSP).
965 // Keep a global pointer to it to force the CSP to stay live forever.
966 CssmClient::CSP returnedKeyCSP = keyItem->csp();
967 {
968 StLock<Mutex> _(gSecReturnedKeyCSPsMutex());
969 gSecReturnedKeyCSPs().insert(returnedKeyCSP);
970 }
971 Required(cspHandle) = returnedKeyCSP->handle();
972
973 END_SECAPI
974 }
975
976 /* deprecated as of 10.8 */
977 OSStatus
978 SecKeyGetAlgorithmID(SecKeyRef keyRef, const CSSM_X509_ALGORITHM_IDENTIFIER **algid)
979 {
980 BEGIN_SECAPI
981
982 SecPointer<KeyItem> keyItem(KeyItem::required(keyRef));
983 Required(algid) = &keyItem->algorithmIdentifier();
984
985 END_SECAPI
986 }
987
988 OSStatus
989 SecKeyGetStrengthInBits(SecKeyRef keyRef, const CSSM_X509_ALGORITHM_IDENTIFIER *algid, unsigned int *strength)
990 {
991 BEGIN_SECAPI
992
993 SecPointer<KeyItem> keyItem(KeyItem::required(keyRef));
994 Required(strength) = keyItem->strengthInBits(algid);
995
996 END_SECAPI
997 }
998
999 OSStatus
1000 SecKeyGetCredentials(
1001 SecKeyRef keyRef,
1002 CSSM_ACL_AUTHORIZATION_TAG operation,
1003 SecCredentialType credentialType,
1004 const CSSM_ACCESS_CREDENTIALS **outCredentials)
1005 {
1006 BEGIN_SECAPI
1007
1008 SecPointer<KeyItem> keyItem(KeyItem::required(keyRef));
1009 Required(outCredentials) = keyItem->getCredentials(operation, credentialType);
1010
1011 END_SECAPI
1012 }
1013
1014 OSStatus
1015 SecKeyImportPair(
1016 SecKeychainRef keychainRef,
1017 const CSSM_KEY *publicCssmKey,
1018 const CSSM_KEY *privateCssmKey,
1019 SecAccessRef initialAccess,
1020 SecKeyRef* publicKey,
1021 SecKeyRef* privateKey)
1022 {
1023 BEGIN_SECAPI
1024
1025 Keychain keychain = Keychain::optional(keychainRef);
1026 SecPointer<Access> theAccess(initialAccess ? Access::required(initialAccess) : new Access("<key>"));
1027 SecPointer<KeyItem> pubItem, privItem;
1028
1029 KeyItem::importPair(keychain,
1030 Required(publicCssmKey),
1031 Required(privateCssmKey),
1032 theAccess,
1033 pubItem,
1034 privItem);
1035
1036 // Return the generated keys.
1037 if (publicKey)
1038 *publicKey = pubItem->handle();
1039 if (privateKey)
1040 *privateKey = privItem->handle();
1041
1042 END_SECAPI
1043 }
1044
1045 static OSStatus
1046 SecKeyGenerateWithAttributes(
1047 SecKeychainAttributeList* attrList,
1048 SecKeychainRef keychainRef,
1049 CSSM_ALGORITHMS algorithm,
1050 uint32 keySizeInBits,
1051 CSSM_CC_HANDLE contextHandle,
1052 CSSM_KEYUSE keyUsage,
1053 uint32 keyAttr,
1054 SecAccessRef initialAccess,
1055 SecKeyRef* keyRef)
1056 {
1057 BEGIN_SECAPI
1058
1059 Keychain keychain;
1060 SecPointer<Access> theAccess;
1061
1062 if (keychainRef)
1063 keychain = KeychainImpl::required(keychainRef);
1064 if (initialAccess)
1065 theAccess = Access::required(initialAccess);
1066
1067 SecPointer<KeyItem> item = KeyItem::generateWithAttributes(attrList,
1068 keychain,
1069 algorithm,
1070 keySizeInBits,
1071 contextHandle,
1072 keyUsage,
1073 keyAttr,
1074 theAccess);
1075
1076 // Return the generated key.
1077 if (keyRef)
1078 *keyRef = item->handle();
1079
1080 END_SECAPI
1081 }
1082
1083 OSStatus
1084 SecKeyGenerate(
1085 SecKeychainRef keychainRef,
1086 CSSM_ALGORITHMS algorithm,
1087 uint32 keySizeInBits,
1088 CSSM_CC_HANDLE contextHandle,
1089 CSSM_KEYUSE keyUsage,
1090 uint32 keyAttr,
1091 SecAccessRef initialAccess,
1092 SecKeyRef* keyRef)
1093 {
1094 return SecKeyGenerateWithAttributes(NULL,
1095 keychainRef, algorithm, keySizeInBits,
1096 contextHandle, keyUsage, keyAttr,
1097 initialAccess, keyRef);
1098 }
1099
1100 /* new in 10.6 */
1101 /* Generate a floating key reference from a CSSM_KEY */
1102 OSStatus
1103 SecKeyCreateWithCSSMKey(const CSSM_KEY *cssmKey,
1104 SecKeyRef *keyRef)
1105 {
1106 BEGIN_SECAPI
1107
1108 Required(cssmKey);
1109 if(cssmKey->KeyData.Length == 0){
1110 MacOSError::throwMe(errSecInvalidAttributeKeyLength);
1111 }
1112 if(cssmKey->KeyData.Data == NULL){
1113 MacOSError::throwMe(errSecInvalidPointer);
1114 }
1115 CssmClient::CSP csp(cssmKey->KeyHeader.CspId);
1116 CssmClient::Key key(csp, *cssmKey);
1117 KeyItem *item = new KeyItem(key);
1118
1119 // Return the generated key.
1120 if (keyRef)
1121 *keyRef = SecKeyCreate(NULL, &kSecCDSAKeyDescriptor, (const uint8_t *)item, 0, 0);
1122
1123 END_SECAPI
1124 }
1125
1126
1127
1128 static u_int32_t ConvertCFStringToInteger(CFStringRef ref)
1129 {
1130 if (ref == NULL)
1131 {
1132 return 0;
1133 }
1134
1135 // figure out the size of the string
1136 CFIndex numChars = CFStringGetMaximumSizeForEncoding(CFStringGetLength(ref), kCFStringEncodingUTF8);
1137 char *buffer = (char *)malloc(numChars);
1138 if (NULL == buffer) {
1139 UnixError::throwMe(ENOMEM);
1140 }
1141 if (!CFStringGetCString(ref, buffer, numChars, kCFStringEncodingUTF8))
1142 {
1143 free(buffer);
1144 MacOSError::throwMe(errSecParam);
1145 }
1146
1147 u_int32_t result = atoi(buffer);
1148 free(buffer);
1149 return result;
1150 }
1151
1152
1153
1154 static OSStatus CheckAlgorithmType(CFDictionaryRef parameters, CSSM_ALGORITHMS &algorithms)
1155 {
1156 // figure out the algorithm to use
1157 CFStringRef ktype = (CFStringRef) CFDictionaryGetValue(parameters, kSecAttrKeyType);
1158 if (ktype == NULL)
1159 {
1160 return errSecParam;
1161 }
1162
1163 if (CFEqual(ktype, kSecAttrKeyTypeRSA)) {
1164 algorithms = CSSM_ALGID_RSA;
1165 return errSecSuccess;
1166 } else if(CFEqual(ktype, kSecAttrKeyTypeECDSA) ||
1167 CFEqual(ktype, kSecAttrKeyTypeEC)) {
1168 algorithms = CSSM_ALGID_ECDSA;
1169 return errSecSuccess;
1170 } else if(CFEqual(ktype, kSecAttrKeyTypeAES)) {
1171 algorithms = CSSM_ALGID_AES;
1172 return errSecSuccess;
1173 } else if(CFEqual(ktype, kSecAttrKeyType3DES)) {
1174 algorithms = CSSM_ALGID_3DES;
1175 return errSecSuccess;
1176 } else {
1177 return errSecUnsupportedAlgorithm;
1178 }
1179 }
1180
1181
1182
1183 static OSStatus GetKeySize(CFDictionaryRef parameters, CSSM_ALGORITHMS algorithms, uint32 &keySizeInBits)
1184 {
1185
1186 // get the key size and check it for validity
1187 CFTypeRef ref = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits);
1188
1189 keySizeInBits = kSecDefaultKeySize;
1190
1191 CFTypeID bitSizeType = CFGetTypeID(ref);
1192 if (bitSizeType == CFStringGetTypeID())
1193 keySizeInBits = ConvertCFStringToInteger((CFStringRef) ref);
1194 else if (bitSizeType == CFNumberGetTypeID())
1195 CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &keySizeInBits);
1196 else return errSecParam;
1197
1198
1199 switch (algorithms) {
1200 case CSSM_ALGID_ECDSA:
1201 if(keySizeInBits == kSecDefaultKeySize) keySizeInBits = kSecp256r1;
1202 if(keySizeInBits == kSecp192r1 || keySizeInBits == kSecp256r1 || keySizeInBits == kSecp384r1 || keySizeInBits == kSecp521r1 ) return errSecSuccess;
1203 break;
1204 case CSSM_ALGID_RSA:
1205 if(keySizeInBits % 8) return errSecParam;
1206 if(keySizeInBits == kSecDefaultKeySize) keySizeInBits = 2048;
1207 if(keySizeInBits >= kSecRSAMin && keySizeInBits <= kSecRSAMax) return errSecSuccess;
1208 break;
1209 case CSSM_ALGID_AES:
1210 if(keySizeInBits == kSecDefaultKeySize) keySizeInBits = kSecAES128;
1211 if(keySizeInBits == kSecAES128 || keySizeInBits == kSecAES192 || keySizeInBits == kSecAES256) return errSecSuccess;
1212 break;
1213 case CSSM_ALGID_3DES:
1214 if(keySizeInBits == kSecDefaultKeySize) keySizeInBits = kSec3DES192;
1215 if(keySizeInBits == kSec3DES192) return errSecSuccess;
1216 break;
1217 default:
1218 break;
1219 }
1220 return errSecParam;
1221 }
1222
1223
1224
1225 enum AttributeType
1226 {
1227 kStringType,
1228 kBooleanType,
1229 kIntegerType
1230 };
1231
1232
1233
1234 struct ParameterAttribute
1235 {
1236 const CFStringRef *name;
1237 AttributeType type;
1238 };
1239
1240
1241
1242 static ParameterAttribute gAttributes[] =
1243 {
1244 {
1245 &kSecAttrLabel,
1246 kStringType
1247 },
1248 {
1249 &kSecAttrIsPermanent,
1250 kBooleanType
1251 },
1252 {
1253 &kSecAttrApplicationTag,
1254 kStringType
1255 },
1256 {
1257 &kSecAttrEffectiveKeySize,
1258 kBooleanType
1259 },
1260 {
1261 &kSecAttrCanEncrypt,
1262 kBooleanType
1263 },
1264 {
1265 &kSecAttrCanDecrypt,
1266 kBooleanType
1267 },
1268 {
1269 &kSecAttrCanDerive,
1270 kBooleanType
1271 },
1272 {
1273 &kSecAttrCanSign,
1274 kBooleanType
1275 },
1276 {
1277 &kSecAttrCanVerify,
1278 kBooleanType
1279 },
1280 {
1281 &kSecAttrCanUnwrap,
1282 kBooleanType
1283 }
1284 };
1285
1286 const int kNumberOfAttributes = sizeof(gAttributes) / sizeof(ParameterAttribute);
1287
1288 static OSStatus ScanDictionaryForParameters(CFDictionaryRef parameters, void* attributePointers[])
1289 {
1290 int i;
1291 for (i = 0; i < kNumberOfAttributes; ++i)
1292 {
1293 // see if the corresponding tag exists in the dictionary
1294 CFTypeRef value = CFDictionaryGetValue(parameters, *(gAttributes[i].name));
1295 if (value != NULL)
1296 {
1297 switch (gAttributes[i].type)
1298 {
1299 case kStringType:
1300 // just return the value
1301 *(CFTypeRef*) attributePointers[i] = value;
1302 break;
1303
1304 case kBooleanType:
1305 {
1306 CFBooleanRef bRef = (CFBooleanRef) value;
1307 *(bool*) attributePointers[i] = CFBooleanGetValue(bRef);
1308 }
1309 break;
1310
1311 case kIntegerType:
1312 {
1313 CFNumberRef nRef = (CFNumberRef) value;
1314 CFNumberGetValue(nRef, kCFNumberSInt32Type, attributePointers[i]);
1315 }
1316 break;
1317 }
1318 }
1319 }
1320
1321 return errSecSuccess;
1322 }
1323
1324
1325
1326 static OSStatus GetKeyParameters(CFDictionaryRef parameters, int keySize, bool isPublic, CSSM_KEYUSE &keyUse, uint32 &attrs, CFTypeRef &labelRef, CFDataRef &applicationTagRef)
1327 {
1328 // establish default values
1329 labelRef = NULL;
1330 bool isPermanent = false;
1331 applicationTagRef = NULL;
1332 CFTypeRef effectiveKeySize = NULL;
1333 bool canDecrypt = isPublic ? false : true;
1334 bool canEncrypt = !canDecrypt;
1335 bool canDerive = true;
1336 bool canSign = isPublic ? false : true;
1337 bool canVerify = !canSign;
1338 bool canUnwrap = isPublic ? false : true;
1339 attrs = CSSM_KEYATTR_EXTRACTABLE;
1340 keyUse = 0;
1341
1342 void* attributePointers[] = {&labelRef, &isPermanent, &applicationTagRef, &effectiveKeySize, &canEncrypt, &canDecrypt,
1343 &canDerive, &canSign, &canVerify, &canUnwrap};
1344
1345 // look for modifiers in the general dictionary
1346 OSStatus result = ScanDictionaryForParameters(parameters, attributePointers);
1347 if (result != errSecSuccess)
1348 {
1349 return result;
1350 }
1351
1352 // see if we have anything which modifies the defaults
1353 CFTypeRef key;
1354 if (isPublic)
1355 {
1356 key = kSecPublicKeyAttrs;
1357 }
1358 else
1359 {
1360 key = kSecPrivateKeyAttrs;
1361 }
1362
1363 CFTypeRef dType = CFDictionaryGetValue(parameters, key);
1364 if (dType != NULL)
1365 {
1366 // this had better be a dictionary
1367 if (CFGetTypeID(dType) != CFDictionaryGetTypeID())
1368 {
1369 return errSecParam;
1370 }
1371
1372 // pull any additional parameters out of this dictionary
1373 result = ScanDictionaryForParameters((CFDictionaryRef)dType, attributePointers);
1374 if (result != errSecSuccess)
1375 {
1376 return result;
1377 }
1378 }
1379
1380 // figure out the key usage
1381 keyUse = 0;
1382 if (canDecrypt)
1383 {
1384 keyUse |= CSSM_KEYUSE_DECRYPT;
1385 }
1386
1387 if (canEncrypt)
1388 {
1389 keyUse |= CSSM_KEYUSE_ENCRYPT;
1390 }
1391
1392 if (canDerive)
1393 {
1394 keyUse |= CSSM_KEYUSE_DERIVE;
1395 }
1396
1397 if (canSign)
1398 {
1399 keyUse |= CSSM_KEYUSE_SIGN;
1400 }
1401
1402 if (canVerify)
1403 {
1404 keyUse |= CSSM_KEYUSE_VERIFY;
1405 }
1406
1407 if (canUnwrap)
1408 {
1409 keyUse |= CSSM_KEYUSE_UNWRAP;
1410 }
1411
1412 // public key is always extractable;
1413 // private key is extractable by default unless explicitly set to false
1414 CFTypeRef value = NULL;
1415 if (!isPublic && CFDictionaryGetValueIfPresent(parameters, kSecAttrIsExtractable, (const void **)&value) && value)
1416 {
1417 Boolean keyIsExtractable = CFEqual(kCFBooleanTrue, value);
1418 if (!keyIsExtractable)
1419 attrs = 0;
1420 }
1421
1422 if (isPermanent) {
1423 attrs |= CSSM_KEYATTR_PERMANENT;
1424 }
1425
1426 return errSecSuccess;
1427 }
1428
1429
1430
1431 static OSStatus MakeKeyGenParametersFromDictionary(CFDictionaryRef parameters,
1432 CSSM_ALGORITHMS &algorithms,
1433 uint32 &keySizeInBits,
1434 CSSM_KEYUSE &publicKeyUse,
1435 uint32 &publicKeyAttr,
1436 CFTypeRef &publicKeyLabelRef,
1437 CFDataRef &publicKeyAttributeTagRef,
1438 CSSM_KEYUSE &privateKeyUse,
1439 uint32 &privateKeyAttr,
1440 CFTypeRef &privateKeyLabelRef,
1441 CFDataRef &privateKeyAttributeTagRef,
1442 SecAccessRef &initialAccess)
1443 {
1444 OSStatus result;
1445
1446 result = CheckAlgorithmType(parameters, algorithms);
1447 if (result != errSecSuccess)
1448 {
1449 return result;
1450 }
1451
1452 result = GetKeySize(parameters, algorithms, keySizeInBits);
1453 if (result != errSecSuccess)
1454 {
1455 return result;
1456 }
1457
1458 result = GetKeyParameters(parameters, keySizeInBits, false, privateKeyUse, privateKeyAttr, privateKeyLabelRef, privateKeyAttributeTagRef);
1459 if (result != errSecSuccess)
1460 {
1461 return result;
1462 }
1463
1464 result = GetKeyParameters(parameters, keySizeInBits, true, publicKeyUse, publicKeyAttr, publicKeyLabelRef, publicKeyAttributeTagRef);
1465 if (result != errSecSuccess)
1466 {
1467 return result;
1468 }
1469
1470 if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrAccess, (const void **)&initialAccess))
1471 {
1472 initialAccess = NULL;
1473 }
1474 else if (SecAccessGetTypeID() != CFGetTypeID(initialAccess))
1475 {
1476 return errSecParam;
1477 }
1478
1479 return errSecSuccess;
1480 }
1481
1482
1483
1484 static OSStatus SetKeyLabelAndTag(SecKeyRef keyRef, CFTypeRef label, CFDataRef tag)
1485 {
1486 int numToModify = 0;
1487 if (label != NULL)
1488 {
1489 numToModify += 1;
1490 }
1491
1492 if (tag != NULL)
1493 {
1494 numToModify += 1;
1495 }
1496
1497 if (numToModify == 0)
1498 {
1499 return errSecSuccess;
1500 }
1501
1502 SecKeychainAttributeList attrList;
1503 SecKeychainAttribute attributes[numToModify];
1504
1505 int i = 0;
1506 void *data = NULL;
1507
1508 if (label != NULL)
1509 {
1510 if (CFStringGetTypeID() == CFGetTypeID(label)) {
1511 CFStringRef label_string = static_cast<CFStringRef>(label);
1512 attributes[i].tag = kSecKeyPrintName;
1513 attributes[i].data = (void*) CFStringGetCStringPtr(label_string, kCFStringEncodingUTF8);
1514 if (NULL == attributes[i].data) {
1515 CFIndex buffer_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(label_string), kCFStringEncodingUTF8);
1516 data = attributes[i].data = malloc((size_t)buffer_length);
1517 if (NULL == attributes[i].data) {
1518 UnixError::throwMe(ENOMEM);
1519 }
1520 if (!CFStringGetCString(label_string, static_cast<char *>(attributes[i].data), buffer_length, kCFStringEncodingUTF8)) {
1521 free(data);
1522 MacOSError::throwMe(errSecParam);
1523 }
1524 }
1525 attributes[i].length = (UInt32)strlen(static_cast<char *>(attributes[i].data));
1526 } else if (CFDataGetTypeID() == CFGetTypeID(label)) {
1527 // 10.6 bug compatibility
1528 CFDataRef label_data = static_cast<CFDataRef>(label);
1529 attributes[i].tag = kSecKeyLabel;
1530 attributes[i].data = (void*) CFDataGetBytePtr(label_data);
1531 attributes[i].length = (UInt32)CFDataGetLength(label_data);
1532 } else {
1533 MacOSError::throwMe(errSecParam);
1534 }
1535 i++;
1536 }
1537
1538 if (tag != NULL)
1539 {
1540 attributes[i].tag = kSecKeyApplicationTag;
1541 attributes[i].data = (void*) CFDataGetBytePtr(tag);
1542 attributes[i].length = (UInt32)CFDataGetLength(tag);
1543 i++;
1544 }
1545
1546 attrList.count = numToModify;
1547 attrList.attr = attributes;
1548
1549 OSStatus result = SecKeychainItemModifyAttributesAndData((SecKeychainItemRef) keyRef, &attrList, 0, NULL);
1550 if (data)
1551 {
1552 free(data);
1553 }
1554
1555 return result;
1556 }
1557
1558
1559 static CFTypeRef GetAttributeFromParams(CFDictionaryRef parameters, CFTypeRef attr, CFTypeRef subParams) {
1560 if (subParams != NULL) {
1561 CFDictionaryRef subParamsDict = (CFDictionaryRef)CFDictionaryGetValue(parameters, subParams);
1562 if (subParamsDict != NULL) {
1563 CFTypeRef value = CFDictionaryGetValue(subParamsDict, attr);
1564 if (value != NULL) {
1565 return value;
1566 }
1567 }
1568 }
1569 return CFDictionaryGetValue(parameters, attr);
1570 }
1571
1572 extern "C" OSStatus SecKeyGeneratePair_ios(CFDictionaryRef parameters, SecKeyRef *publicKey, SecKeyRef *privateKey);
1573
1574 /* new in 10.6 */
1575 /* Generate a private/public keypair. */
1576 static OSStatus
1577 SecKeyGeneratePairInternal(
1578 bool alwaysPermanent,
1579 CFDictionaryRef parameters,
1580 SecKeyRef *publicKey,
1581 SecKeyRef *privateKey)
1582 {
1583 BEGIN_SECAPI
1584
1585 Required(parameters);
1586 Required(publicKey);
1587 Required(privateKey);
1588
1589 bool forceIOSKey = false;
1590 if (_CFMZEnabled()) {
1591 // On Marzipan, always go iOS SecItem/SecKey route, do not drag CSSM keys in.
1592 forceIOSKey = true;
1593 } else {
1594 CFTypeRef tokenID = GetAttributeFromParams(parameters, kSecAttrTokenID, NULL);
1595 CFTypeRef noLegacy = GetAttributeFromParams(parameters, kSecAttrNoLegacy, NULL);
1596 CFTypeRef sync = GetAttributeFromParams(parameters, kSecAttrSynchronizable, kSecPrivateKeyAttrs);
1597 CFTypeRef accessControl = GetAttributeFromParams(parameters, kSecAttrAccessControl, kSecPrivateKeyAttrs) ?:
1598 GetAttributeFromParams(parameters, kSecAttrAccessControl, kSecPublicKeyAttrs);
1599 CFTypeRef accessGroup = GetAttributeFromParams(parameters, kSecAttrAccessGroup, kSecPrivateKeyAttrs) ?:
1600 GetAttributeFromParams(parameters, kSecAttrAccessGroup, kSecPublicKeyAttrs);
1601 // If any of these attributes are present, forward the call to iOS implementation (and create keys in iOS keychain).
1602 forceIOSKey = (tokenID != NULL ||
1603 (noLegacy != NULL && CFBooleanGetValue((CFBooleanRef)noLegacy)) ||
1604 (sync != NULL && CFBooleanGetValue((CFBooleanRef)sync)) ||
1605 accessControl != NULL || (accessGroup != NULL && CFEqual(accessGroup, kSecAttrAccessGroupToken)));
1606 }
1607
1608 if (forceIOSKey) {
1609 // Generate keys in iOS keychain.
1610 return SecKeyGeneratePair_ios(parameters, publicKey, privateKey);
1611 }
1612
1613 CSSM_ALGORITHMS algorithms;
1614 uint32 keySizeInBits;
1615 CSSM_KEYUSE publicKeyUse;
1616 uint32 publicKeyAttr;
1617 CFTypeRef publicKeyLabelRef;
1618 CFDataRef publicKeyAttributeTagRef;
1619 CSSM_KEYUSE privateKeyUse;
1620 uint32 privateKeyAttr;
1621 CFTypeRef privateKeyLabelRef;
1622 CFDataRef privateKeyAttributeTagRef;
1623 SecAccessRef initialAccess;
1624 SecKeychainRef keychain;
1625
1626 OSStatus result = MakeKeyGenParametersFromDictionary(parameters, algorithms, keySizeInBits, publicKeyUse, publicKeyAttr, publicKeyLabelRef,
1627 publicKeyAttributeTagRef, privateKeyUse, privateKeyAttr, privateKeyLabelRef, privateKeyAttributeTagRef,
1628 initialAccess);
1629
1630 if (result != errSecSuccess) {
1631 return result;
1632 }
1633
1634 // verify keychain parameter
1635 keychain = (SecKeychainRef)CFDictionaryGetValue(parameters, kSecUseKeychain);
1636 if (keychain != NULL && SecKeychainGetTypeID() != CFGetTypeID(keychain)) {
1637 keychain = NULL;
1638 }
1639
1640 if (alwaysPermanent) {
1641 publicKeyAttr |= CSSM_KEYATTR_PERMANENT;
1642 privateKeyAttr |= CSSM_KEYATTR_PERMANENT;
1643 }
1644
1645 // do the key generation
1646 result = SecKeyCreatePair(keychain, algorithms, keySizeInBits, 0, publicKeyUse, publicKeyAttr, privateKeyUse, privateKeyAttr, initialAccess, publicKey, privateKey);
1647 if (result != errSecSuccess) {
1648 return result;
1649 }
1650
1651 // set the label and print attributes on the keys
1652 SetKeyLabelAndTag(*publicKey, publicKeyLabelRef, publicKeyAttributeTagRef);
1653 SetKeyLabelAndTag(*privateKey, privateKeyLabelRef, privateKeyAttributeTagRef);
1654 return result;
1655
1656 END_SECAPI
1657 }
1658
1659 OSStatus
1660 SecKeyGeneratePair(CFDictionaryRef parameters, SecKeyRef *publicKey, SecKeyRef *privateKey) {
1661 return SecKeyGeneratePairInternal(true, parameters, publicKey, privateKey);
1662 }
1663
1664 SecKeyRef
1665 SecKeyCreateRandomKey(CFDictionaryRef parameters, CFErrorRef *error) {
1666 SecKeyRef privateKey = NULL, publicKey = NULL;
1667 OSStatus status = SecKeyGeneratePairInternal(false, parameters, &publicKey, &privateKey);
1668 SecError(status, error, CFSTR("failed to generate asymmetric keypair"));
1669 if (publicKey != NULL) {
1670 CFRelease(publicKey);
1671 }
1672 return privateKey;
1673 }
1674
1675 OSStatus SecKeyRawVerifyOSX(
1676 SecKeyRef key, /* Public key */
1677 SecPadding padding, /* kSecPaddingNone or kSecPaddingPKCS1 */
1678 const uint8_t *signedData, /* signature over this data */
1679 size_t signedDataLen, /* length of dataToSign */
1680 const uint8_t *sig, /* signature */
1681 size_t sigLen)
1682 {
1683 return SecKeyRawVerify(key,padding,signedData,signedDataLen,sig,sigLen);
1684 }
1685
1686 /*
1687 M4 Additions
1688 */
1689
1690 static CFTypeRef
1691 utilGetStringFromCFDict(CFDictionaryRef parameters, CFTypeRef key, CFTypeRef defaultValue)
1692 {
1693 CFTypeRef value = CFDictionaryGetValue(parameters, key);
1694 if (value != NULL) return value;
1695 return defaultValue;
1696 }
1697
1698 static uint32_t
1699 utilGetNumberFromCFDict(CFDictionaryRef parameters, CFTypeRef key, uint32_t defaultValue)
1700 {
1701 uint32_t integerValue;
1702 CFTypeRef value = CFDictionaryGetValue(parameters, key);
1703 if (value != NULL) {
1704 CFNumberRef nRef = (CFNumberRef) value;
1705 CFNumberGetValue(nRef, kCFNumberSInt32Type, &integerValue);
1706 return integerValue;
1707 }
1708 return defaultValue;
1709 }
1710
1711 static uint32_t
1712 utilGetMaskValFromCFDict(CFDictionaryRef parameters, CFTypeRef key, uint32_t maskValue)
1713 {
1714 CFTypeRef value = CFDictionaryGetValue(parameters, key);
1715 if (value != NULL) {
1716 CFBooleanRef bRef = (CFBooleanRef) value;
1717 if(CFBooleanGetValue(bRef)) return maskValue;
1718 }
1719 return 0;
1720 }
1721
1722 static void
1723 utilGetKeyParametersFromCFDict(CFDictionaryRef parameters, CSSM_ALGORITHMS *algorithm, uint32 *keySizeInBits, CSSM_KEYUSE *keyUsage, CSSM_KEYCLASS *keyClass)
1724 {
1725 CFTypeRef algorithmDictValue = utilGetStringFromCFDict(parameters, kSecAttrKeyType, kSecAttrKeyTypeAES);
1726 CFTypeRef keyClassDictValue = utilGetStringFromCFDict(parameters, kSecAttrKeyClass, kSecAttrKeyClassSymmetric);
1727
1728 if(CFEqual(algorithmDictValue, kSecAttrKeyTypeAES)) {
1729 *algorithm = CSSM_ALGID_AES;
1730 *keySizeInBits = 128;
1731 *keyClass = CSSM_KEYCLASS_SESSION_KEY;
1732 } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeDES)) {
1733 *algorithm = CSSM_ALGID_DES;
1734 *keySizeInBits = 128;
1735 *keyClass = CSSM_KEYCLASS_SESSION_KEY;
1736 } else if(CFEqual(algorithmDictValue, kSecAttrKeyType3DES)) {
1737 *algorithm = CSSM_ALGID_3DES_3KEY_EDE;
1738 *keySizeInBits = 128;
1739 *keyClass = CSSM_KEYCLASS_SESSION_KEY;
1740 } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeRC4)) {
1741 *algorithm = CSSM_ALGID_RC4;
1742 *keySizeInBits = 128;
1743 *keyClass = CSSM_KEYCLASS_SESSION_KEY;
1744 } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeRC2)) {
1745 *algorithm = CSSM_ALGID_RC2;
1746 *keySizeInBits = 128;
1747 *keyClass = CSSM_KEYCLASS_SESSION_KEY;
1748 } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeCAST)) {
1749 *algorithm = CSSM_ALGID_CAST;
1750 *keySizeInBits = 128;
1751 *keyClass = CSSM_KEYCLASS_SESSION_KEY;
1752 } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeRSA)) {
1753 *algorithm = CSSM_ALGID_RSA;
1754 *keySizeInBits = 128;
1755 *keyClass = CSSM_KEYCLASS_PRIVATE_KEY;
1756 } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeDSA)) {
1757 *algorithm = CSSM_ALGID_DSA;
1758 *keySizeInBits = 128;
1759 *keyClass = CSSM_KEYCLASS_PRIVATE_KEY;
1760 } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeECDSA) ||
1761 CFEqual(algorithmDictValue, kSecAttrKeyTypeEC)) {
1762 *algorithm = CSSM_ALGID_ECDSA;
1763 *keySizeInBits = 128;
1764 *keyClass = CSSM_KEYCLASS_PRIVATE_KEY;
1765 } else {
1766 *algorithm = CSSM_ALGID_AES;
1767 *keySizeInBits = 128;
1768 *keyClass = CSSM_KEYCLASS_SESSION_KEY;
1769 }
1770
1771 if(CFEqual(keyClassDictValue, kSecAttrKeyClassPublic)) {
1772 *keyClass = CSSM_KEYCLASS_PUBLIC_KEY;
1773 } else if(CFEqual(keyClassDictValue, kSecAttrKeyClassPrivate)) {
1774 *keyClass = CSSM_KEYCLASS_PRIVATE_KEY;
1775 } else if(CFEqual(keyClassDictValue, kSecAttrKeyClassSymmetric)) {
1776 *keyClass = CSSM_KEYCLASS_SESSION_KEY;
1777 }
1778
1779 *keySizeInBits = utilGetNumberFromCFDict(parameters, kSecAttrKeySizeInBits, *keySizeInBits);
1780 *keyUsage = utilGetMaskValFromCFDict(parameters, kSecAttrCanEncrypt, CSSM_KEYUSE_ENCRYPT) |
1781 utilGetMaskValFromCFDict(parameters, kSecAttrCanDecrypt, CSSM_KEYUSE_DECRYPT) |
1782 utilGetMaskValFromCFDict(parameters, kSecAttrCanWrap, CSSM_KEYUSE_WRAP) |
1783 utilGetMaskValFromCFDict(parameters, kSecAttrCanUnwrap, CSSM_KEYUSE_UNWRAP);
1784
1785
1786 if(*keyClass == CSSM_KEYCLASS_PRIVATE_KEY || *keyClass == CSSM_KEYCLASS_PUBLIC_KEY) {
1787 *keyUsage |= utilGetMaskValFromCFDict(parameters, kSecAttrCanSign, CSSM_KEYUSE_SIGN) |
1788 utilGetMaskValFromCFDict(parameters, kSecAttrCanVerify, CSSM_KEYUSE_VERIFY);
1789 }
1790
1791 if(*keyUsage == 0) {
1792 switch (*keyClass) {
1793 case CSSM_KEYCLASS_PRIVATE_KEY:
1794 *keyUsage = CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_UNWRAP | CSSM_KEYUSE_SIGN;
1795 break;
1796 case CSSM_KEYCLASS_PUBLIC_KEY:
1797 *keyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP;
1798 break;
1799 default:
1800 *keyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP | CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY;
1801 break;
1802 }
1803 }
1804 }
1805
1806 static CFStringRef
1807 utilCopyDefaultKeyLabel(void)
1808 {
1809 // generate a default label from the current date
1810 CFDateRef dateNow = CFDateCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent());
1811 CFStringRef defaultLabel = CFCopyDescription(dateNow);
1812 CFRelease(dateNow);
1813
1814 return defaultLabel;
1815 }
1816
1817 SecKeyRef
1818 SecKeyGenerateSymmetric(CFDictionaryRef parameters, CFErrorRef *error)
1819 {
1820 OSStatus result = errSecParam; // default result for an early exit
1821 SecKeyRef key = NULL;
1822 SecKeychainRef keychain = NULL;
1823 SecAccessRef access;
1824 CFStringRef label;
1825 CFStringRef appLabel;
1826 CFStringRef appTag;
1827 CFStringRef dateLabel = NULL;
1828
1829 CSSM_ALGORITHMS algorithm;
1830 uint32 keySizeInBits;
1831 CSSM_KEYUSE keyUsage;
1832 uint32 keyAttr = CSSM_KEYATTR_RETURN_DEFAULT;
1833 CSSM_KEYCLASS keyClass;
1834 CFTypeRef value;
1835 Boolean isPermanent;
1836 Boolean isExtractable;
1837
1838 // verify keychain parameter
1839 if (!CFDictionaryGetValueIfPresent(parameters, kSecUseKeychain, (const void **)&keychain))
1840 keychain = NULL;
1841 else if (SecKeychainGetTypeID() != CFGetTypeID(keychain)) {
1842 keychain = NULL;
1843 goto errorExit;
1844 }
1845 else
1846 CFRetain(keychain);
1847
1848 // verify permanent parameter
1849 if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrIsPermanent, (const void **)&value))
1850 isPermanent = false;
1851 else if (!value || (CFBooleanGetTypeID() != CFGetTypeID(value)))
1852 goto errorExit;
1853 else
1854 isPermanent = CFEqual(kCFBooleanTrue, value);
1855 if (isPermanent) {
1856 if (keychain == NULL) {
1857 // no keychain was specified, so use the default keychain
1858 result = SecKeychainCopyDefault(&keychain);
1859 }
1860 keyAttr |= CSSM_KEYATTR_PERMANENT;
1861 }
1862
1863 // verify extractable parameter
1864 if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrIsExtractable, (const void **)&value))
1865 isExtractable = true; // default to extractable if value not specified
1866 else if (!value || (CFBooleanGetTypeID() != CFGetTypeID(value)))
1867 goto errorExit;
1868 else
1869 isExtractable = CFEqual(kCFBooleanTrue, value);
1870 if (isExtractable)
1871 keyAttr |= CSSM_KEYATTR_EXTRACTABLE;
1872
1873 // verify access parameter
1874 if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrAccess, (const void **)&access))
1875 access = NULL;
1876 else if (SecAccessGetTypeID() != CFGetTypeID(access))
1877 goto errorExit;
1878
1879 // verify label parameter
1880 if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrLabel, (const void **)&label))
1881 label = (dateLabel = utilCopyDefaultKeyLabel()); // no label provided, so use default
1882 else if (CFStringGetTypeID() != CFGetTypeID(label))
1883 goto errorExit;
1884
1885 // verify application label parameter
1886 if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrApplicationLabel, (const void **)&appLabel))
1887 appLabel = (dateLabel) ? dateLabel : (dateLabel = utilCopyDefaultKeyLabel());
1888 else if (CFStringGetTypeID() != CFGetTypeID(appLabel))
1889 goto errorExit;
1890
1891 // verify application tag parameter
1892 if (!CFDictionaryGetValueIfPresent(parameters, kSecAttrApplicationTag, (const void **)&appTag))
1893 appTag = NULL;
1894 else if (CFStringGetTypeID() != CFGetTypeID(appTag))
1895 goto errorExit;
1896
1897 utilGetKeyParametersFromCFDict(parameters, &algorithm, &keySizeInBits, &keyUsage, &keyClass);
1898
1899 if (!keychain) {
1900 // the generated key will not be stored in any keychain
1901 result = SecKeyGenerate(keychain, algorithm, keySizeInBits, 0, keyUsage, keyAttr, access, &key);
1902 }
1903 else {
1904 // we can set the label attributes on the generated key if it's a keychain item
1905 size_t labelBufLen = (label) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(label), kCFStringEncodingUTF8) + 1 : 1;
1906 char *labelBuf = (char *)malloc(labelBufLen);
1907 size_t appLabelBufLen = (appLabel) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appLabel), kCFStringEncodingUTF8) + 1 : 1;
1908 char *appLabelBuf = (char *)malloc(appLabelBufLen);
1909 size_t appTagBufLen = (appTag) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appTag), kCFStringEncodingUTF8) + 1 : 1;
1910 char *appTagBuf = (char *)malloc(appTagBufLen);
1911
1912 if (!label || !CFStringGetCString(label, labelBuf, labelBufLen-1, kCFStringEncodingUTF8))
1913 labelBuf[0]=0;
1914 if (!appLabel || !CFStringGetCString(appLabel, appLabelBuf, appLabelBufLen-1, kCFStringEncodingUTF8))
1915 appLabelBuf[0]=0;
1916 if (!appTag || !CFStringGetCString(appTag, appTagBuf, appTagBufLen-1, kCFStringEncodingUTF8))
1917 appTagBuf[0]=0;
1918
1919 SecKeychainAttribute attrs[] = {
1920 { kSecKeyPrintName, (UInt32)strlen(labelBuf), (char *)labelBuf },
1921 { kSecKeyLabel, (UInt32)strlen(appLabelBuf), (char *)appLabelBuf },
1922 { kSecKeyApplicationTag, (UInt32)strlen(appTagBuf), (char *)appTagBuf } };
1923 SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
1924 if (!appTag) --attributes.count;
1925
1926 result = SecKeyGenerateWithAttributes(&attributes,
1927 keychain, algorithm, keySizeInBits, 0,
1928 keyUsage, keyAttr, access, &key);
1929
1930 free(labelBuf);
1931 free(appLabelBuf);
1932 free(appTagBuf);
1933 }
1934
1935 errorExit:
1936 if (result && error) {
1937 *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, result, NULL);
1938 }
1939 if (dateLabel)
1940 CFRelease(dateLabel);
1941 if (keychain)
1942 CFRelease(keychain);
1943
1944 return key;
1945 }
1946
1947
1948
1949 SecKeyRef
1950 SecKeyCreateFromData(CFDictionaryRef parameters, CFDataRef keyData, CFErrorRef *error)
1951 {
1952 CSSM_ALGORITHMS algorithm;
1953 uint32 keySizeInBits;
1954 CSSM_KEYUSE keyUsage;
1955 CSSM_KEYCLASS keyClass;
1956 CSSM_RETURN crtn;
1957
1958 if(keyData == NULL || CFDataGetLength(keyData) == 0){
1959 MacOSError::throwMe(errSecUnsupportedKeySize);
1960 }
1961
1962 utilGetKeyParametersFromCFDict(parameters, &algorithm, &keySizeInBits, &keyUsage, &keyClass);
1963
1964 CSSM_CSP_HANDLE cspHandle = cuCspStartup(CSSM_FALSE); // TRUE => CSP, FALSE => CSPDL
1965
1966 SecKeyImportExportParameters iparam;
1967 memset(&iparam, 0, sizeof(iparam));
1968 iparam.keyUsage = keyUsage;
1969
1970 CFRef<CFDataRef> data;
1971 SecExternalItemType itype;
1972 switch (keyClass) {
1973 case CSSM_KEYCLASS_PRIVATE_KEY:
1974 itype = kSecItemTypePrivateKey;
1975 break;
1976 case CSSM_KEYCLASS_PUBLIC_KEY: {
1977 itype = kSecItemTypePublicKey;
1978 // Public key import expects public key in SubjPublicKey X509 format. We want to accept both bare and x509 format,
1979 // so we have to detect bare format here and extend to full X509 if detected.
1980 data.take(SecCDSAKeyCopyPublicKeyDataWithSubjectInfo(algorithm, keySizeInBits, keyData));
1981 break;
1982 }
1983 case CSSM_KEYCLASS_SESSION_KEY:
1984 itype = kSecItemTypeSessionKey;
1985 break;
1986 default:
1987 itype = kSecItemTypeUnknown;
1988 break;
1989 }
1990
1991 CFMutableArrayRef ka = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1992 // NOTE: if we had a way to specify values other then kSecFormatUnknown we might be more useful.
1993 crtn = impExpImportRawKey(data ? CFDataRef(data) : keyData, kSecFormatUnknown, itype, algorithm, NULL, cspHandle, 0, NULL, NULL, ka);
1994 if (crtn == CSSM_OK && CFArrayGetCount((CFArrayRef)ka)) {
1995 SecKeyRef sk = (SecKeyRef)CFArrayGetValueAtIndex((CFArrayRef)ka, 0);
1996 CFRetain(sk);
1997 CFRelease(ka);
1998 return sk;
1999 } else {
2000 CFRelease(ka);
2001 if (error) {
2002 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, crtn ? crtn : CSSM_ERRCODE_INTERNAL_ERROR, NULL);
2003 }
2004 return NULL;
2005 }
2006 }
2007
2008
2009 void
2010 SecKeyGeneratePairAsync(CFDictionaryRef parametersWhichMightBeMutiable, dispatch_queue_t deliveryQueue,
2011 SecKeyGeneratePairBlock result)
2012 {
2013 CFDictionaryRef parameters = CFDictionaryCreateCopy(NULL, parametersWhichMightBeMutiable);
2014 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
2015 SecKeyRef publicKey = NULL;
2016 SecKeyRef privateKey = NULL;
2017 OSStatus status = SecKeyGeneratePair(parameters, &publicKey, &privateKey);
2018 dispatch_async(deliveryQueue, ^{
2019 CFErrorRef error = NULL;
2020 if (errSecSuccess != status) {
2021 error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, status, NULL);
2022 }
2023 result(publicKey, privateKey, error);
2024 if (error) {
2025 CFRelease(error);
2026 }
2027 if (publicKey) {
2028 CFRelease(publicKey);
2029 }
2030 if (privateKey) {
2031 CFRelease(privateKey);
2032 }
2033 CFRelease(parameters);
2034 });
2035 });
2036 }
2037
2038 static inline void utilClearAndFree(void *p, size_t len) {
2039 if(p) {
2040 if(len) bzero(p, len);
2041 free(p);
2042 }
2043 }
2044
2045 SecKeyRef
2046 SecKeyDeriveFromPassword(CFStringRef password, CFDictionaryRef parameters, CFErrorRef *error)
2047 {
2048 CCPBKDFAlgorithm algorithm;
2049 CFIndex passwordLen = 0;
2050 CFDataRef keyData = NULL;
2051 char *thePassword = NULL;
2052 uint8_t *salt = NULL;
2053 uint8_t *derivedKey = NULL;
2054 size_t saltLen = 0, derivedKeyLen = 0;
2055 uint rounds;
2056 CFDataRef saltDictValue, algorithmDictValue;
2057 SecKeyRef retval = NULL;
2058
2059 /* Pick Values from parameters */
2060
2061 if((saltDictValue = (CFDataRef) CFDictionaryGetValue(parameters, kSecAttrSalt)) == NULL) {
2062 if(error) {
2063 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecMissingAlgorithmParms, NULL);
2064 }
2065 goto errOut;
2066 }
2067
2068 derivedKeyLen = utilGetNumberFromCFDict(parameters, kSecAttrKeySizeInBits, 128);
2069 // This value come in bits but the rest of the code treats it as bytes
2070 derivedKeyLen /= 8;
2071
2072 algorithmDictValue = (CFDataRef) utilGetStringFromCFDict(parameters, kSecAttrPRF, kSecAttrPRFHmacAlgSHA256);
2073
2074 rounds = utilGetNumberFromCFDict(parameters, kSecAttrRounds, 0);
2075
2076 /* Convert any remaining parameters and get the password bytes */
2077
2078 saltLen = CFDataGetLength(saltDictValue);
2079 if((salt = (uint8_t *) malloc(saltLen)) == NULL) {
2080 if(error) {
2081 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL);
2082 }
2083 goto errOut;
2084 }
2085
2086 CFDataGetBytes(saltDictValue, CFRangeMake(0, saltLen), (UInt8 *) salt);
2087
2088 passwordLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(password), kCFStringEncodingUTF8) + 1;
2089 if((thePassword = (char *) malloc(passwordLen)) == NULL) {
2090 if(error) {
2091 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL);
2092 }
2093 goto errOut;
2094 }
2095 CFStringGetBytes(password, CFRangeMake(0, CFStringGetLength(password)), kCFStringEncodingUTF8, '?', FALSE, (UInt8*)thePassword, passwordLen, &passwordLen);
2096
2097 if((derivedKey = (uint8_t *) malloc(derivedKeyLen)) == NULL) {
2098 if(error) {
2099 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL);
2100 }
2101 goto errOut;
2102 }
2103
2104 if(algorithmDictValue == NULL) {
2105 algorithm = kCCPRFHmacAlgSHA1; /* default */
2106 } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA1)) {
2107 algorithm = kCCPRFHmacAlgSHA1;
2108 } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA224)) {
2109 algorithm = kCCPRFHmacAlgSHA224;
2110 } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA256)) {
2111 algorithm = kCCPRFHmacAlgSHA256;
2112 } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA384)) {
2113 algorithm = kCCPRFHmacAlgSHA384;
2114 } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA512)) {
2115 algorithm = kCCPRFHmacAlgSHA512;
2116 } else {
2117 if(error) {
2118 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidAlgorithmParms, NULL);
2119 }
2120 goto errOut;
2121 }
2122
2123 if(rounds == 0) {
2124 rounds = 33333; // we need to pass back a consistent value since there's no way to record the round count.
2125 }
2126
2127 if(CCKeyDerivationPBKDF(kCCPBKDF2, thePassword, passwordLen, salt, saltLen, algorithm, rounds, derivedKey, derivedKeyLen)) {
2128 if(error) {
2129 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInternalError, NULL);
2130 }
2131 goto errOut;
2132 }
2133
2134 if((keyData = CFDataCreate(NULL, derivedKey, derivedKeyLen)) != NULL) {
2135 retval = SecKeyCreateFromData(parameters, keyData, error);
2136 CFRelease(keyData);
2137 } else {
2138 if(error) {
2139 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInternalError, NULL);
2140 }
2141 }
2142
2143 errOut:
2144 utilClearAndFree(salt, saltLen);
2145 utilClearAndFree(thePassword, passwordLen);
2146 utilClearAndFree(derivedKey, derivedKeyLen);
2147 return retval;
2148 }
2149
2150 CFDataRef
2151 SecKeyWrapSymmetric(SecKeyRef keyToWrap, SecKeyRef wrappingKey, CFDictionaryRef parameters, CFErrorRef *error)
2152 {
2153 if(error) {
2154 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecUnimplemented, NULL);
2155 }
2156 return NULL;
2157 }
2158
2159 SecKeyRef
2160 SecKeyUnwrapSymmetric(CFDataRef *keyToUnwrap, SecKeyRef unwrappingKey, CFDictionaryRef parameters, CFErrorRef *error)
2161 {
2162 if(error) {
2163 *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecUnimplemented, NULL);
2164 }
2165 return NULL;
2166 }