]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecECKey.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / sec / Security / SecECKey.c
1 /*
2 * Copyright (c) 2010-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 /*
25 * SecECKey.c - CoreFoundation based rsa key object
26 */
27
28 #include "SecECKey.h"
29 #include "SecECKeyPriv.h"
30
31 #include <Security/SecKeyInternal.h>
32 #include <Security/SecItem.h>
33 #include <Security/SecBasePriv.h>
34 #include <AssertMacros.h>
35 #include <Security/SecureTransport.h> /* For error codes. */
36 #include <CoreFoundation/CFData.h> /* For error codes. */
37 #include <fcntl.h>
38 #include <sys/types.h>
39 #include <unistd.h>
40 #include <CoreFoundation/CFNumber.h>
41 #include <Security/SecFramework.h>
42 #include <Security/SecRandom.h>
43 #include <utilities/debugging.h>
44 #include "SecItemPriv.h"
45 #include <Security/SecInternal.h>
46 #include <utilities/SecCFError.h>
47 #include <utilities/SecCFWrappers.h>
48 #include <corecrypto/ccec.h>
49 #include <corecrypto/ccsha1.h>
50 #include <corecrypto/ccsha2.h>
51 #include <corecrypto/ccrng.h>
52 #include <corecrypto/ccder_decode_eckey.h>
53
54 #define kMaximumECKeySize 521
55
56 static CFIndex SecECKeyGetAlgorithmID(SecKeyRef key) {
57 return kSecECDSAAlgorithmID;
58 }
59
60
61 /*
62 *
63 * Public Key
64 *
65 */
66
67 /* Public key static functions. */
68 static void SecECPublicKeyDestroy(SecKeyRef key) {
69 /* Zero out the public key */
70 ccec_pub_ctx_t pubkey;
71 pubkey.pub = key->key;
72 if (ccec_ctx_cp(pubkey).zp)
73 cc_clear(ccec_pub_ctx_size(ccn_sizeof_n(ccec_ctx_n(pubkey))), pubkey.pub);
74 }
75
76 static ccec_const_cp_t getCPForPublicSize(CFIndex encoded_length)
77 {
78 size_t keysize = ccec_x963_import_pub_size(encoded_length);
79 if(ccec_keysize_is_supported(keysize)) {
80 return ccec_get_cp(keysize);
81 }
82 ccec_const_cp_t nullCP = { .zp = NULL };
83 return nullCP;
84 }
85
86 static ccec_const_cp_t getCPForPrivateSize(CFIndex encoded_length)
87 {
88 size_t keysize = ccec_x963_import_priv_size(encoded_length);
89 if(ccec_keysize_is_supported(keysize)) {
90 return ccec_get_cp(keysize);
91 }
92 ccec_const_cp_t nullCP = { .zp = NULL };
93 return nullCP;
94 }
95
96 static ccoid_t ccoid_secp192r1 = CC_EC_OID_SECP192R1;
97 static ccoid_t ccoid_secp256r1 = CC_EC_OID_SECP256R1;
98 static ccoid_t ccoid_secp224r1 = CC_EC_OID_SECP224R1;
99 static ccoid_t ccoid_secp384r1 = CC_EC_OID_SECP384R1;
100 static ccoid_t ccoid_secp521r1 = CC_EC_OID_SECP521R1;
101
102 static ccec_const_cp_t ccec_cp_for_oid(ccoid_t oid)
103 {
104 if (oid.oid) {
105 if (ccoid_equal(oid, ccoid_secp192r1)) {
106 return ccec_cp_192();
107 } else if (ccoid_equal(oid, ccoid_secp256r1)) {
108 return ccec_cp_256();
109 } else if (ccoid_equal(oid, ccoid_secp224r1)) {
110 return ccec_cp_224();
111 } else if (ccoid_equal(oid, ccoid_secp384r1)) {
112 return ccec_cp_384();
113 } else if (ccoid_equal(oid, ccoid_secp521r1)) {
114 return ccec_cp_521();
115 }
116 }
117 return (ccec_const_cp_t){NULL};
118 }
119
120 static OSStatus SecECPublicKeyInit(SecKeyRef key,
121 const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
122 ccec_pub_ctx_t pubkey;
123 pubkey.pub = key->key;
124 OSStatus err = errSecParam;
125
126 switch (encoding) {
127 case kSecDERKeyEncoding:
128 {
129 const SecDERKey *derKey = (const SecDERKey *)keyData;
130 if (keyDataLength != sizeof(SecDERKey)) {
131 err = errSecDecode;
132 break;
133 }
134
135 ccec_const_cp_t cp = getCPForPublicSize(derKey->keyLength);
136 require_action(cp.zp, errOut, err = errSecDecode);
137
138 /* TODO: Parse and use real params from passed in derKey->algId.params */
139 err = (ccec_import_pub(cp, derKey->keyLength, derKey->key, pubkey)
140 ? errSecDecode : errSecSuccess);
141 break;
142 }
143 case kSecKeyEncodingBytes:
144 {
145 ccec_const_cp_t cp = getCPForPublicSize(keyDataLength);
146 require_action(cp.zp, errOut, err = errSecDecode);
147 err = (ccec_import_pub(cp, keyDataLength, keyData, pubkey)
148 ? errSecDecode : errSecSuccess);
149 break;
150 }
151 case kSecExtractPublicFromPrivate:
152 {
153 ccec_full_ctx_t fullKey;
154 fullKey._full = (ccec_full_ctx *) keyData;
155
156 cc_size fullKeyN = ccec_ctx_n(fullKey);
157 require(fullKeyN <= ccn_nof(kMaximumECKeySize), errOut);
158 memcpy(pubkey._pub, fullKey.pub, ccec_pub_ctx_size(ccn_sizeof_n(fullKeyN)));
159 err = errSecSuccess;
160 break;
161 }
162 case kSecKeyEncodingApplePkcs1:
163 default:
164 err = errSecParam;
165 break;
166 }
167
168 errOut:
169 return err;
170 }
171
172 static OSStatus SecECPublicKeyRawVerify(SecKeyRef key, SecPadding padding,
173 const uint8_t *signedData, size_t signedDataLen,
174 const uint8_t *sig, size_t sigLen) {
175 int err = errSecInternalComponent;
176 ccec_pub_ctx_t pubkey;
177 pubkey.pub = key->key;
178 bool valid = 0;
179
180 // Perform verification
181 if (padding==kSecPaddingSigRaw) {
182 require_action_quiet(ccec_signature_r_s_size(pubkey.fullt)*2==sigLen, errOut, err = errSecParam);
183 err=ccec_verify_composite(pubkey, signedDataLen, signedData, (uint8_t*)sig, (uint8_t*)sig+(sigLen>>1),&valid);
184 }
185 else {
186 // kSecPaddingSigDERx962 or default
187 err=ccec_verify(pubkey, signedDataLen, signedData, sigLen, sig, &valid);
188 }
189
190 // Result
191 err=(!err && valid?errSecSuccess:errSSLCrypto); // TODO: Should be errSecNotSigner;
192
193 errOut:
194 return err;
195 }
196
197 static OSStatus SecECPublicKeyRawEncrypt(SecKeyRef key, SecPadding padding,
198 const uint8_t *plainText, size_t plainTextLen,
199 uint8_t *cipherText, size_t *cipherTextLen) {
200 ccec_pub_ctx_t pubkey;
201 pubkey.pub = key->key;
202 int err = errSecUnimplemented;
203
204 #if 0
205 require_noerr(err = ccec_wrap_key(pubkey, &ccsha256_di,
206 plainTextLen, plainText, cipherText), errOut);
207
208 errOut:
209 #endif
210 return err;
211 }
212
213 static size_t SecECPublicKeyBlockSize(SecKeyRef key) {
214 /* Get key size in octets */
215 ccec_pub_ctx_t pubkey;
216 pubkey.pub = key->key;
217 return ccec_ctx_size(pubkey);
218 }
219
220 /* Encode the public key and return it in a newly allocated CFDataRef. */
221 static CFDataRef SecECPublicKeyExport(CFAllocatorRef allocator,
222 ccec_pub_ctx_t pubkey) {
223 size_t pub_size = ccec_export_pub_size(pubkey);
224 CFMutableDataRef blob = CFDataCreateMutable(allocator, pub_size);
225 if (blob) {
226 CFDataSetLength(blob, pub_size);
227 ccec_export_pub(pubkey, CFDataGetMutableBytePtr(blob));
228 }
229
230 return blob;
231 }
232
233 static OSStatus SecECPublicKeyCopyPublicOctets(SecKeyRef key, CFDataRef *serailziation)
234 {
235 ccec_pub_ctx_t pubkey;
236 pubkey.pub = key->key;
237
238 CFAllocatorRef allocator = CFGetAllocator(key);
239 *serailziation = SecECPublicKeyExport(allocator, pubkey);
240
241 if (NULL == *serailziation)
242 return errSecDecode;
243 else
244 return errSecSuccess;
245 }
246
247 static CFDictionaryRef SecECPublicKeyCopyAttributeDictionary(SecKeyRef key) {
248 return SecKeyGeneratePublicAttributeDictionary(key, kSecAttrKeyTypeEC);
249 }
250
251 static const char *
252 getCurveName(SecKeyRef key)
253 {
254 SecECNamedCurve curveType = SecECKeyGetNamedCurve(key);
255
256 switch (curveType)
257 {
258 case kSecECCurveSecp256r1:
259 return "kSecECCurveSecp256r1";
260 break;
261 case kSecECCurveSecp384r1:
262 return "kSecECCurveSecp384r1";
263 break;
264 case kSecECCurveSecp521r1:
265 return "kSecECCurveSecp521r1";
266 default:
267 return "kSecECCurveNone";
268 }
269 }
270
271 static CFStringRef SecECPublicKeyCopyKeyDescription(SecKeyRef key)
272 {
273 ccec_pub_ctx_t ecPubkey;
274 CFStringRef keyDescription = NULL;
275 size_t xlen, ylen, ix;
276 CFMutableStringRef xString = NULL;
277 CFMutableStringRef yString = NULL;
278
279 ecPubkey.pub = key->key;
280
281 const char* curve = getCurveName(key);
282
283 uint8_t *xunit = (uint8_t*)ccec_ctx_x(ecPubkey);
284 require_quiet( NULL != xunit, fail);
285 xlen = (size_t)strlen((char*)xunit);
286
287
288 xString = CFStringCreateMutable(kCFAllocatorDefault, xlen * 2);
289 require_quiet( NULL != xString, fail);
290
291 for (ix = 0; ix < xlen; ++ix)
292 {
293 CFStringAppendFormat(xString, NULL, CFSTR("%02X"), xunit[ix]);
294 }
295
296 uint8_t *yunit = (uint8_t*)ccec_ctx_y(ecPubkey);
297 require_quiet( NULL != yunit, fail);
298 ylen = (size_t)strlen((char*)yunit);
299
300 yString = CFStringCreateMutable(kCFAllocatorDefault, ylen*2);
301 require_quiet( NULL != yString, fail);
302
303 for(ix = 0; ix < ylen; ++ix)
304 {
305 CFStringAppendFormat(yString, NULL, CFSTR("%02X"), yunit[ix]);
306 }
307
308 keyDescription = CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR( "<SecKeyRef curve type: %s, algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, y: %@, x: %@, addr: %p>"), curve, (long)SecKeyGetAlgorithmId(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), yString, xString, key);
309
310 fail:
311 CFReleaseSafe(xString);
312 CFReleaseSafe(yString);
313 if(!keyDescription)
314 keyDescription = CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR("<SecKeyRef curve type: %s, algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, addr: %p>"), curve,(long)SecKeyGetAlgorithmId(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), key);
315
316 return keyDescription;
317 }
318
319 static const struct ccec_rfc6637_curve * get_rfc6637_curve(SecKeyRef key)
320 {
321 SecECNamedCurve curveType = SecECKeyGetNamedCurve(key);
322
323 if (curveType == kSecECCurveSecp256r1) {
324 return &ccec_rfc6637_dh_curve_p256;
325 } else if (curveType == kSecECCurveSecp521r1) {
326 return &ccec_rfc6637_dh_curve_p521;
327 }
328 return NULL;
329 }
330
331 static CFDataRef SecECKeyCopyWrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef unwrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error)
332 {
333 ccec_pub_ctx_t pubkey;
334 int err = errSecUnimplemented;
335 const struct ccec_rfc6637_curve *curve;
336 const struct ccec_rfc6637_wrap *wrap = NULL;
337 uint8_t sym_alg = 0;
338 long flags = 0;
339
340 pubkey.pub = key->key;
341
342 if (type != kSecKeyWrapPublicKeyPGP) {
343 SecError(errSecUnsupportedOperation, error, CFSTR("unsupported key wrapping algorithm"));
344 return NULL;
345 }
346
347 curve = get_rfc6637_curve(key);
348 if (curve == NULL) {
349 SecError(errSecUnsupportedOperation, error, CFSTR("unsupported curve"));
350 return NULL;
351 }
352
353 CFNumberRef num = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPSymAlg);
354 if (!isNumber(num) || !CFNumberGetValue(num, kCFNumberSInt8Type, &sym_alg)) {
355 SecError(errSecUnsupportedOperation, error, CFSTR("unknown symalg given"));
356 return NULL;
357 }
358
359 CFDataRef fingerprint = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPFingerprint);
360 if (!isData(fingerprint) || CFDataGetLength(fingerprint) < kSecKeyWrapPGPFingerprintMinSize) {
361 SecError(errSecUnsupportedOperation, error, CFSTR("invalid fingerprint"));
362 return NULL;
363 }
364
365 CFTypeRef wrapAlg = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPWrapAlg);
366 if (wrapAlg == NULL) {
367 SecError(errSecUnsupportedOperation, error, CFSTR("no wrap alg"));
368 return NULL;
369 } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128)) {
370 wrap = &ccec_rfc6637_wrap_sha256_kek_aes128;
371 } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256)) {
372 wrap = &ccec_rfc6637_wrap_sha512_kek_aes256;
373 } else {
374 SecError(errSecUnsupportedOperation, error, CFSTR("unknown wrap alg"));
375 return NULL;
376 }
377
378 num = CFDictionaryGetValue(parameters, _kSecKeyWrapRFC6637Flags);
379 if (isNull(num)) {
380 if (!CFNumberGetValue(num, kCFNumberLongType, &flags)) {
381 SecError(errSecUnsupportedOperation, error, CFSTR("invalid flags: %@"), num);
382 return NULL;
383 }
384 } else if (num) {
385 SecError(errSecUnsupportedOperation, error, CFSTR("unknown flags"));
386 return NULL;
387 }
388
389 CFIndex unwrappedKey_size = CFDataGetLength(unwrappedKey);
390
391 CFIndex output_size = ccec_rfc6637_wrap_key_size(pubkey, flags, unwrappedKey_size);
392 if (output_size == 0) {
393 SecError(errSecUnsupportedOperation, error, CFSTR("can't wrap that key, can't build size"));
394 return NULL;
395 }
396
397 CFMutableDataRef data = CFDataCreateMutableWithScratch(NULL, output_size);
398 require(data, errOut);
399
400 err = ccec_rfc6637_wrap_key(pubkey, CFDataGetMutableBytePtr(data), flags,
401 sym_alg, CFDataGetLength(unwrappedKey), CFDataGetBytePtr(unwrappedKey),
402 curve, wrap, CFDataGetBytePtr(fingerprint),
403 ccrng_seckey);
404 if (err) {
405 SecError(errSecUnsupportedOperation, error, CFSTR("Failed to wrap key"));
406 CFReleaseNull(data);
407 }
408
409 errOut:
410 return data;
411 }
412
413
414 SecKeyDescriptor kSecECPublicKeyDescriptor = {
415 kSecKeyDescriptorVersion,
416 "ECPublicKey",
417 ccec_pub_ctx_size(ccn_sizeof(kMaximumECKeySize)), /* extraBytes */
418 SecECPublicKeyInit,
419 SecECPublicKeyDestroy,
420 NULL, /* SecKeyRawSignMethod */
421 SecECPublicKeyRawVerify,
422 SecECPublicKeyRawEncrypt,
423 NULL, /* SecKeyDecryptMethod */
424 NULL, /* SecKeyComputeMethod */
425 SecECPublicKeyBlockSize,
426 SecECPublicKeyCopyAttributeDictionary,
427 SecECPublicKeyCopyKeyDescription,
428 SecECKeyGetAlgorithmID,
429 SecECPublicKeyCopyPublicOctets,
430 SecECKeyCopyWrapKey,
431 NULL, /* SecKeyCopyUnwrapKey */
432 };
433
434 /* Public Key API functions. */
435 SecKeyRef SecKeyCreateECPublicKey(CFAllocatorRef allocator,
436 const uint8_t *keyData, CFIndex keyDataLength,
437 SecKeyEncoding encoding) {
438 return SecKeyCreate(allocator, &kSecECPublicKeyDescriptor, keyData,
439 keyDataLength, encoding);
440 }
441
442
443
444 /*
445 *
446 * Private Key
447 *
448 */
449
450 /* Private key static functions. */
451 static void SecECPrivateKeyDestroy(SecKeyRef key) {
452 /* Zero out the public key */
453 ccec_full_ctx_t fullkey;
454 fullkey.hdr = key->key;
455 if (ccec_ctx_cp(fullkey).zp)
456 cc_clear(ccec_full_ctx_size(ccn_sizeof_n(ccec_ctx_n(fullkey))), fullkey.hdr);
457 }
458
459
460 static OSStatus SecECPrivateKeyInit(SecKeyRef key,
461 const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
462 ccec_full_ctx_t fullkey;
463 fullkey.hdr = key->key;
464 OSStatus err = errSecParam;
465
466 switch (encoding) {
467 case kSecKeyEncodingPkcs1:
468 {
469 /* TODO: DER import size (and thus cp), pub.x, pub.y and k. */
470 //err = ecc_import(keyData, keyDataLength, fullkey);
471
472 /* DER != PKCS#1, but we'll go along with it */
473 ccoid_t oid;
474 size_t n;
475 ccec_const_cp_t cp;
476
477 require_noerr(ccec_der_import_priv_keytype(keyDataLength, keyData, &oid, &n), abort);
478 cp = ccec_cp_for_oid(oid);
479 if (cp.zp == NULL) {
480 cp = ccec_curve_for_length_lookup(n * 8 /* bytes -> bits */,
481 ccec_cp_192(), ccec_cp_224(), ccec_cp_256(), ccec_cp_384(), ccec_cp_521(), NULL);
482 }
483 require_action(cp.zp != NULL, abort, err = errSecDecode);
484 ccec_ctx_init(cp, fullkey);
485
486 require_noerr(ccec_der_import_priv(cp, keyDataLength, keyData, fullkey), abort);
487 err = errSecSuccess;
488 break;
489 }
490 case kSecKeyEncodingBytes:
491 {
492 ccec_const_cp_t cp = getCPForPrivateSize(keyDataLength);
493 require(cp.zp != NULL, abort);
494
495 ccec_ctx_init(cp, fullkey);
496 size_t pubSize = ccec_export_pub_size(fullkey);
497
498 require(pubSize < (size_t) keyDataLength, abort);
499 require_noerr_action(ccec_import_pub(cp, pubSize, keyData, fullkey),
500 abort,
501 err = errSecDecode);
502
503
504 keyData += pubSize;
505 keyDataLength -= pubSize;
506
507 cc_unit *k = ccec_ctx_k(fullkey);
508 require_noerr_action(ccn_read_uint(ccec_ctx_n(fullkey), k, keyDataLength, keyData),
509 abort,
510 err = errSecDecode);
511
512 err = errSecSuccess;
513 break;
514
515 }
516 case kSecGenerateKey:
517 {
518 CFDictionaryRef parameters = (CFDictionaryRef) keyData;
519
520 CFTypeRef ksize = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits);
521 CFIndex keyLengthInBits = getIntValue(ksize);
522
523 ccec_const_cp_t cp = ccec_get_cp(keyLengthInBits);
524
525 if (!cp.zp) {
526 secwarning("Invalid or missing key size in: %@", parameters);
527 return errSecKeySizeNotAllowed;
528 }
529
530 if (!ccec_generate_key_fips(cp, ccrng_seckey, fullkey))
531 err = errSecSuccess;
532 break;
533 }
534
535 default:
536 break;
537 }
538 abort:
539 return err;
540 }
541
542 static OSStatus SecECPrivateKeyRawSign(SecKeyRef key, SecPadding padding,
543 const uint8_t *dataToSign, size_t dataToSignLen,
544 uint8_t *sig, size_t *sigLen) {
545 ccec_full_ctx_t fullkey = {};
546 fullkey.hdr = key->key;
547 int err;
548 require_action_quiet(sigLen, errOut, err = errSecParam);
549
550 // Perform signature
551 if (padding==kSecPaddingSigRaw) {
552 // kSecPaddingSigRaw: {r,s} raw byte in big endian, concatenated.
553 cc_size r_s_size=ccec_signature_r_s_size(fullkey);
554 require_action_quiet(*sigLen>=(r_s_size<<1), errOut, err = errSecParam);
555 require_noerr(err = ccec_sign_composite(fullkey, dataToSignLen, dataToSign,
556 sig, sig+r_s_size, ccrng_seckey), errOut);
557 *sigLen=(r_s_size<<1);
558 }
559 else {
560 // kSecPaddingSigDERx962 or default
561 require_noerr(err = ccec_sign(fullkey, dataToSignLen, dataToSign,
562 sigLen, sig, ccrng_seckey), errOut);
563 }
564 errOut:
565 return err;
566 }
567
568 #if 0
569 static const struct ccdigest_info *
570 ccdigest_lookup_by_oid(unsigned long oid_size, const void *oid) {
571 static const struct ccdigest_info *dis[] = {
572 &ccsha1_di,
573 &ccsha224_di,
574 &ccsha256_di,
575 &ccsha384_di,
576 &ccsha512_di
577 };
578 size_t i;
579 for (i = 0; i < array_size(dis); ++i) {
580 if (oid_size == dis[i]->oid_size && !memcmp(dis[i]->oid, oid, oid_size))
581 return dis[i];
582 }
583 return NULL;
584 }
585 #endif
586
587 static OSStatus SecECPrivateKeyRawDecrypt(SecKeyRef key, SecPadding padding,
588 const uint8_t *cipherText, size_t cipherTextLen,
589 uint8_t *plainText, size_t *plainTextLen) {
590 ccec_full_ctx_t fullkey;
591 fullkey.hdr = key->key;
592 int err = errSecUnimplemented;
593
594 #if 0
595 err = ccec_unwrap_key(fullkey, ccrng_seckey, ccdigest_lookup_by_oid,
596 cipherTextLen, cipherText, plainTextLen, plainText);
597 #endif
598
599 return err;
600 }
601
602 static size_t SecECPrivateKeyBlockSize(SecKeyRef key) {
603 ccec_full_ctx_t fullkey;
604 fullkey.hdr = key->key;
605 /* Get key size in octets */
606 return ccec_ctx_size(fullkey);
607 }
608
609 static OSStatus SecECPrivateKeyCopyPublicOctets(SecKeyRef key, CFDataRef *serailziation)
610 {
611 ccec_full_ctx_t fullkey;
612 fullkey.hdr = key->key;
613
614 CFAllocatorRef allocator = CFGetAllocator(key);
615 *serailziation = SecECPublicKeyExport(allocator, fullkey);
616
617 if (NULL == *serailziation)
618 return errSecDecode;
619 else
620 return errSecSuccess;
621 }
622
623 static CFDataRef SecECPPrivateKeyExport(CFAllocatorRef allocator,
624 ccec_full_ctx_t fullkey) {
625 size_t prime_size = ccec_cp_prime_size(ccec_ctx_cp(fullkey));
626 size_t key_size = ccec_export_pub_size(fullkey) + prime_size;
627 CFMutableDataRef blob = CFDataCreateMutable(allocator, key_size);
628 if (blob) {
629 CFDataSetLength(blob, key_size);
630 ccec_export_pub(fullkey, CFDataGetMutableBytePtr(blob));
631 UInt8 *dest = CFDataGetMutableBytePtr(blob) + ccec_export_pub_size(fullkey);
632 const cc_unit *k = ccec_ctx_k(fullkey);
633 ccn_write_uint_padded(ccec_ctx_n(fullkey), k, prime_size, dest);
634 }
635
636 return blob;
637 }
638
639
640 static CFDictionaryRef SecECPrivateKeyCopyAttributeDictionary(SecKeyRef key) {
641 CFDictionaryRef dict = NULL;
642 CFAllocatorRef allocator = CFGetAllocator(key);
643
644 ccec_full_ctx_t fullkey;
645 fullkey.hdr = key->key;
646
647 CFDataRef fullKeyBlob = NULL;
648
649 /* Export the full ec key pair. */
650 require(fullKeyBlob = SecECPPrivateKeyExport(allocator, fullkey), errOut);
651
652 dict = SecKeyGeneratePrivateAttributeDictionary(key, kSecAttrKeyTypeEC, fullKeyBlob);
653
654 errOut:
655 CFReleaseSafe(fullKeyBlob);
656
657 return dict;
658 }
659 static CFStringRef SecECPrivateKeyCopyKeyDescription(SecKeyRef key) {
660
661 const char* curve = getCurveName(key);
662
663 return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR( "<SecKeyRef curve type: %s, algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, addr: %p>"), curve, (long)SecKeyGetAlgorithmId(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), key);
664
665 }
666
667 static CFDataRef SecECKeyCopyUnwrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef wrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error)
668 {
669 const struct ccec_rfc6637_curve *curve;
670 const struct ccec_rfc6637_unwrap *unwrap;
671 ccec_full_ctx_t fullkey;
672 CFMutableDataRef data;
673 int res;
674 uint8_t sym_alg = 0;
675 unsigned long flags = 0;
676
677 fullkey.hdr = key->key;
678
679 curve = get_rfc6637_curve(key);
680 if (curve == NULL) {
681 SecError(errSecUnsupportedOperation, error, CFSTR("unsupported curve"));
682 return NULL;
683 }
684
685 CFTypeRef wrapAlg = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPWrapAlg);
686 if (wrapAlg == NULL) {
687 SecError(errSecUnsupportedOperation, error, CFSTR("no wrap alg"));
688 return NULL;
689 } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128)) {
690 unwrap = &ccec_rfc6637_unwrap_sha256_kek_aes128;
691 } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256)) {
692 unwrap = &ccec_rfc6637_unwrap_sha512_kek_aes256;
693 } else {
694 SecError(errSecUnsupportedOperation, error, CFSTR("unknown wrap alg"));
695 return NULL;
696 }
697
698 CFDataRef fingerprint = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPFingerprint);
699 if (!isData(fingerprint) || CFDataGetLength(fingerprint) < kSecKeyWrapPGPFingerprintMinSize) {
700 SecError(errSecUnsupportedOperation, error, CFSTR("invalid fingerprint"));
701 return NULL;
702 }
703
704 CFNumberRef num = CFDictionaryGetValue(parameters, _kSecKeyWrapRFC6637Flags);
705 if (isNull(num)) {
706 if (!CFNumberGetValue(num, kCFNumberSInt32Type, &num)) {
707 SecError(errSecUnsupportedOperation, error, CFSTR("invalid flags: %@"), num);
708 return NULL;
709 }
710 } else if (num) {
711 SecError(errSecUnsupportedOperation, error, CFSTR("unknown flags"));
712 return NULL;
713 }
714
715 size_t keysize = CFDataGetLength(wrappedKey);
716 data = CFDataCreateMutableWithScratch(NULL, keysize);
717 if (data == NULL)
718 return NULL;
719
720 res = ccec_rfc6637_unwrap_key(fullkey, &keysize, CFDataGetMutableBytePtr(data),
721 flags, &sym_alg, curve, unwrap,
722 CFDataGetBytePtr(fingerprint),
723 CFDataGetLength(wrappedKey), CFDataGetBytePtr(wrappedKey));
724 if (res != 0) {
725 CFReleaseNull(data);
726 SecError(errSecUnsupportedOperation, error, CFSTR("failed to wrap key"));
727 return NULL;
728 }
729 assert(keysize <= (size_t)CFDataGetLength(data));
730 CFDataSetLength(data, keysize);
731
732 if (outParam) {
733 CFMutableDictionaryRef out = CFDictionaryCreateMutableForCFTypes(NULL);
734 if (out) {
735 CFNumberRef num = CFNumberCreate(NULL, kCFNumberSInt8Type, &sym_alg);
736 if (num) {
737 CFDictionarySetValue(out, _kSecKeyWrapPGPSymAlg, num);
738 CFRelease(num);
739 }
740 *outParam = out;
741 }
742 }
743
744 return data;
745 }
746
747
748 SecKeyDescriptor kSecECPrivateKeyDescriptor = {
749 kSecKeyDescriptorVersion,
750 "ECPrivateKey",
751 ccec_full_ctx_size(ccn_sizeof(kMaximumECKeySize)), /* extraBytes */
752 SecECPrivateKeyInit,
753 SecECPrivateKeyDestroy,
754 SecECPrivateKeyRawSign,
755 NULL, /* SecKeyRawVerifyMethod */
756 NULL, /* SecKeyEncryptMethod */
757 SecECPrivateKeyRawDecrypt,
758 NULL, /* SecKeyComputeMethod */
759 SecECPrivateKeyBlockSize,
760 SecECPrivateKeyCopyAttributeDictionary,
761 SecECPrivateKeyCopyKeyDescription,
762 SecECKeyGetAlgorithmID,
763 SecECPrivateKeyCopyPublicOctets,
764 SecECKeyCopyWrapKey,
765 SecECKeyCopyUnwrapKey,
766 };
767
768 /* Private Key API functions. */
769 SecKeyRef SecKeyCreateECPrivateKey(CFAllocatorRef allocator,
770 const uint8_t *keyData, CFIndex keyDataLength,
771 SecKeyEncoding encoding) {
772 return SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor, keyData,
773 keyDataLength, encoding);
774 }
775
776
777 OSStatus SecECKeyGeneratePair(CFDictionaryRef parameters,
778 SecKeyRef *publicKey, SecKeyRef *privateKey) {
779 OSStatus status = errSecParam;
780
781 CFAllocatorRef allocator = NULL; /* @@@ get from parameters. */
782 SecKeyRef pubKey = NULL;
783
784 SecKeyRef privKey = SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor,
785 (const void*) parameters, 0, kSecGenerateKey);
786
787 require(privKey, errOut);
788
789 /* Create SecKeyRef's from the pkcs1 encoded keys. */
790 pubKey = SecKeyCreate(allocator, &kSecECPublicKeyDescriptor,
791 privKey->key, 0, kSecExtractPublicFromPrivate);
792
793 require(pubKey, errOut);
794
795 if (publicKey) {
796 *publicKey = pubKey;
797 pubKey = NULL;
798 }
799 if (privateKey) {
800 *privateKey = privKey;
801 privKey = NULL;
802 }
803
804 status = errSecSuccess;
805
806 errOut:
807 CFReleaseSafe(pubKey);
808 CFReleaseSafe(privKey);
809
810 return status;
811 }
812
813
814 /* It's debatable whether this belongs here or in the ssl code since the
815 curve values come from a tls related rfc4492. */
816 SecECNamedCurve SecECKeyGetNamedCurve(SecKeyRef key) {
817 if (key->key_class != &kSecECPublicKeyDescriptor &&
818 key->key_class != &kSecECPrivateKeyDescriptor)
819 return kSecECCurveNone;
820
821 ccec_pub_ctx_t pubkey;
822 pubkey.pub = key->key;
823 switch (ccec_ctx_size(pubkey)) {
824 #if 0
825 case 24:
826 return kSecECCurveSecp192r1;
827 case 28:
828 return kSecECCurveSecp224r1;
829 #endif
830 case 32:
831 return kSecECCurveSecp256r1;
832 case 48:
833 return kSecECCurveSecp384r1;
834 case 66:
835 return kSecECCurveSecp521r1;
836 }
837 return kSecECCurveNone;
838 }
839
840 CFDataRef SecECKeyCopyPublicBits(SecKeyRef key) {
841 if (key->key_class != &kSecECPublicKeyDescriptor &&
842 key->key_class != &kSecECPrivateKeyDescriptor)
843 return NULL;
844
845 ccec_pub_ctx_t pubkey;
846 pubkey.pub = key->key;
847 return SecECPublicKeyExport(CFGetAllocator(key), pubkey);
848 }
849
850 /* Vile accessors that get us the pub or priv key to use temporarily */
851
852 bool SecECDoWithFullKey(SecKeyRef key, CFErrorRef* error, void (^action)(ccec_full_ctx_t private)) {
853 if (key->key_class == &kSecECPrivateKeyDescriptor) {
854 action(key->key);
855 } else {
856 return SecError(errSecParam, error, CFSTR("Not an EC Full Key object, sorry can't do."));
857 }
858
859 return true;
860 }
861
862 bool SecECDoWithPubKey(SecKeyRef key, CFErrorRef* error, void (^action)(ccec_pub_ctx_t public)) {
863 if (key->key_class == &kSecECPublicKeyDescriptor) {
864 action(key->key);
865 } else {
866 return SecError(errSecParam, error, CFSTR("Not an EC Public Key object, sorry can't do."));
867 }
868
869 return true;
870 }
871