]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecECKey.m
Security-59754.41.1.tar.gz
[apple/security.git] / OSX / sec / Security / SecECKey.m
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.m - CoreFoundation based ECDSA key object
26 */
27
28 #include "SecECKey.h"
29 #include "SecECKeyPriv.h"
30
31 #import <Foundation/Foundation.h>
32
33 #include <Security/SecKeyInternal.h>
34 #include <Security/SecItem.h>
35 #include <Security/SecBasePriv.h>
36 #include <AssertMacros.h>
37 #include <Security/SecureTransport.h> /* For error codes. */
38 #include <CoreFoundation/CFData.h> /* For error codes. */
39 #include <CoreFoundation/CFNumber.h>
40 #include <Security/SecFramework.h>
41 #include <Security/SecRandom.h>
42 #include <utilities/debugging.h>
43 #include <Security/SecItemPriv.h>
44 #include <Security/SecInternal.h>
45 #include <utilities/SecCFError.h>
46 #include <utilities/SecCFWrappers.h>
47 #include <utilities/array_size.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 = key->key;
71 if (ccec_ctx_cp(pubkey))
72 cc_clear(ccec_pub_ctx_size(ccn_sizeof_n(ccec_ctx_n(pubkey))), pubkey);
73 }
74
75 static ccec_const_cp_t getCPForPublicSize(CFIndex encoded_length)
76 {
77 size_t keysize = ccec_x963_import_pub_size(encoded_length);
78 if(ccec_keysize_is_supported(keysize)) {
79 return ccec_get_cp(keysize);
80 }
81 return NULL;
82 }
83
84 static ccec_const_cp_t getCPForPrivateSize(CFIndex encoded_length)
85 {
86 size_t keysize = ccec_x963_import_priv_size(encoded_length);
87 if(ccec_keysize_is_supported(keysize)) {
88 return ccec_get_cp(keysize);
89 }
90 return NULL;
91 }
92
93 static ccoid_t ccoid_secp192r1 = CC_EC_OID_SECP192R1;
94 static ccoid_t ccoid_secp256r1 = CC_EC_OID_SECP256R1;
95 static ccoid_t ccoid_secp224r1 = CC_EC_OID_SECP224R1;
96 static ccoid_t ccoid_secp384r1 = CC_EC_OID_SECP384R1;
97 static ccoid_t ccoid_secp521r1 = CC_EC_OID_SECP521R1;
98
99 // <rdar://problem/66864716> OID_CERTICOM is wrong
100 static ccoid_t ccoid_libder_secp384r1 = ((unsigned char *)"\x06\x04\x2B\x84\x00\x22");
101 static ccoid_t ccoid_libder_secp521r1 = ((unsigned char *)"\x06\x04\x2B\x84\x00\x23");
102
103 static ccec_const_cp_t ccec_cp_for_oid(const unsigned char *oid)
104 {
105 if (oid!=NULL) {
106 if (ccoid_equal(oid, ccoid_secp192r1)) {
107 return ccec_cp_192();
108 } else if (ccoid_equal(oid, ccoid_secp256r1)) {
109 return ccec_cp_256();
110 } else if (ccoid_equal(oid, ccoid_secp224r1)) {
111 return ccec_cp_224();
112 } else if (ccoid_equal(oid, ccoid_secp384r1) || ccoid_equal(oid, ccoid_libder_secp384r1)) {
113 return ccec_cp_384();
114 } else if (ccoid_equal(oid, ccoid_secp521r1) || ccoid_equal(oid, ccoid_libder_secp521r1)) {
115 return ccec_cp_521();
116 }
117 }
118 return (ccec_const_cp_t){NULL};
119 }
120
121 static OSStatus SecECPublicKeyInit(SecKeyRef key,
122 const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
123 ccec_pub_ctx_t pubkey = 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 require_action_quiet(derKey->parameters && derKey->parametersLength > 2 &&
136 derKey->parameters[1] <= derKey->parametersLength - 2, errOut, err = errSecDecode);
137 ccec_const_cp_t cp = ccec_cp_for_oid(derKey->parameters);
138 require_action_quiet(cp, errOut, err = errSecDecode);
139
140 err = (ccec_import_pub(cp, derKey->keyLength, derKey->key, pubkey)
141 ? errSecDecode : errSecSuccess);
142 break;
143 }
144 case kSecKeyEncodingBytes:
145 {
146 ccec_const_cp_t cp = getCPForPublicSize(keyDataLength);
147 require_action_quiet(cp, errOut, err = errSecDecode);
148 err = (ccec_import_pub(cp, keyDataLength, keyData, pubkey)
149 ? errSecDecode : errSecSuccess);
150 break;
151 }
152 case kSecExtractPublicFromPrivate:
153 {
154 ccec_full_ctx_t fullKey = (ccec_full_ctx_t)keyData;
155
156 cc_size fullKeyN = ccec_ctx_n(fullKey);
157 require_quiet(fullKeyN <= ccn_nof(kMaximumECKeySize), errOut);
158 memcpy(pubkey, fullKey, 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 CFTypeRef SecECPublicKeyCopyOperationResult(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm,
173 CFArrayRef algorithms, SecKeyOperationMode mode,
174 CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
175 if (operation != kSecKeyOperationTypeVerify || !CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureDigestX962)) {
176 // EC public key supports only signature verification with X962 algorithm.
177 return kCFNull;
178 }
179
180 if (mode == kSecKeyOperationModePerform) {
181 bool valid = false;
182 int err = -1;
183 size_t sigLen = CFDataGetLength(in2);
184 uint8_t *sig = (uint8_t *)CFDataGetBytePtr(in2);
185 ccec_pub_ctx_t pubkey = key->key;
186
187 err = ccec_verify(pubkey, CFDataGetLength(in1), CFDataGetBytePtr(in1), sigLen, sig, &valid);
188 if (err != 0) {
189 SecError(errSecVerifyFailed, error, CFSTR("EC signature verification failed (ccerr %d)"), err);
190 return NULL;
191 } else if (!valid) {
192 SecError(errSecVerifyFailed, error, CFSTR("EC signature verification failed, no match"));
193 return NULL;
194 } else {
195 return kCFBooleanTrue;
196 }
197 } else {
198 // Algorithm is supported.
199 return kCFBooleanTrue;
200 }
201 }
202
203 static size_t SecECPublicKeyBlockSize(SecKeyRef key) {
204 /* Get key size in octets */
205 return ccec_ctx_size(ccec_ctx_pub(key->key));
206 }
207
208 /* Encode the public key and return it in a newly allocated CFDataRef. */
209 static CFDataRef SecECPublicKeyExport(CFAllocatorRef allocator,
210 ccec_pub_ctx_t pubkey) {
211 size_t pub_size = ccec_export_pub_size(pubkey);
212 CFMutableDataRef blob = CFDataCreateMutableWithScratch(allocator, pub_size);
213 ccec_export_pub(pubkey, CFDataGetMutableBytePtr(blob));
214 return blob;
215 }
216
217 static CFDataRef SecECPublicKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) {
218 ccec_pub_ctx_t pubkey = key->key;
219 return SecECPublicKeyExport(NULL, pubkey);
220 }
221
222 static OSStatus SecECPublicKeyCopyPublicOctets(SecKeyRef key, CFDataRef *serailziation)
223 {
224 ccec_pub_ctx_t pubkey = key->key;
225
226 CFAllocatorRef allocator = CFGetAllocator(key);
227 *serailziation = SecECPublicKeyExport(allocator, pubkey);
228
229 if (NULL == *serailziation)
230 return errSecDecode;
231 else
232 return errSecSuccess;
233 }
234
235 static CFDictionaryRef SecECPublicKeyCopyAttributeDictionary(SecKeyRef key) {
236 CFDictionaryRef dict = SecKeyGeneratePublicAttributeDictionary(key, kSecAttrKeyTypeEC);
237 CFMutableDictionaryRef mutableDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
238 CFDictionarySetValue(mutableDict, kSecAttrCanDerive, kCFBooleanFalse);
239 CFAssignRetained(dict, mutableDict);
240 return dict;
241 }
242
243 static const char *
244 getCurveName(SecKeyRef key)
245 {
246 SecECNamedCurve curveType = SecECKeyGetNamedCurve(key);
247
248 switch (curveType)
249 {
250 case kSecECCurveSecp256r1:
251 return "kSecECCurveSecp256r1";
252 break;
253 case kSecECCurveSecp384r1:
254 return "kSecECCurveSecp384r1";
255 break;
256 case kSecECCurveSecp521r1:
257 return "kSecECCurveSecp521r1";
258 default:
259 return "kSecECCurveNone";
260 }
261 }
262
263 static CFStringRef SecECPublicKeyCopyKeyDescription(SecKeyRef key)
264 {
265 NSMutableString *strings[2];
266 const char* curve = getCurveName(key);
267
268 ccec_pub_ctx_t ecPubkey = key->key;
269 size_t len = ccec_ctx_size(ecPubkey);
270 NSMutableData *buffer = [NSMutableData dataWithLength:len];
271 for (int i = 0; i < 2; ++i) {
272 ccn_write_uint(ccec_ctx_n(ecPubkey), (i == 0) ? ccec_ctx_x(ecPubkey) : ccec_ctx_y(ecPubkey), len, buffer.mutableBytes);
273 strings[i] = [NSMutableString stringWithCapacity:len * 2];
274 for (size_t byteIndex = 0; byteIndex < len; ++byteIndex) {
275 [strings[i] appendFormat:@"%02X", ((const uint8_t *)buffer.bytes)[byteIndex]];
276 }
277 }
278
279 NSString *description = [NSString stringWithFormat:@"<SecKeyRef curve type: %s, algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, y: %@, x: %@, addr: %p>",
280 curve, (long)SecKeyGetAlgorithmId(key), key->key_class->name, key->key_class->version,
281 8 * SecKeyGetBlockSize(key), strings[1], strings[0], key];
282 return CFBridgingRetain(description);
283 }
284
285 static const struct ccec_rfc6637_curve * get_rfc6637_curve(SecKeyRef key)
286 {
287 SecECNamedCurve curveType = SecECKeyGetNamedCurve(key);
288
289 if (curveType == kSecECCurveSecp256r1) {
290 return &ccec_rfc6637_dh_curve_p256;
291 } else if (curveType == kSecECCurveSecp521r1) {
292 return &ccec_rfc6637_dh_curve_p521;
293 }
294 return NULL;
295 }
296
297 static CFDataRef SecECKeyCopyWrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef unwrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error)
298 {
299 ccec_pub_ctx_t pubkey = key->key;
300 int err = errSecUnimplemented;
301 const struct ccec_rfc6637_curve *curve;
302 const struct ccec_rfc6637_wrap *wrap = NULL;
303 uint8_t sym_alg = 0;
304 int32_t flags = 0;
305
306 if (type != kSecKeyWrapPublicKeyPGP) {
307 SecError(errSecUnsupportedOperation, error, CFSTR("unsupported key wrapping algorithm"));
308 return NULL;
309 }
310
311 curve = get_rfc6637_curve(key);
312 if (curve == NULL) {
313 SecError(errSecUnsupportedOperation, error, CFSTR("unsupported curve"));
314 return NULL;
315 }
316
317 CFNumberRef num = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPSymAlg);
318 if (!isNumber(num) || !CFNumberGetValue(num, kCFNumberSInt8Type, &sym_alg)) {
319 SecError(errSecUnsupportedOperation, error, CFSTR("unknown symalg given"));
320 return NULL;
321 }
322
323 CFDataRef fingerprint = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPFingerprint);
324 if (!isData(fingerprint) || CFDataGetLength(fingerprint) < kSecKeyWrapPGPFingerprintMinSize) {
325 SecError(errSecUnsupportedOperation, error, CFSTR("invalid fingerprint"));
326 return NULL;
327 }
328
329 CFTypeRef wrapAlg = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPWrapAlg);
330 if (wrapAlg == NULL) {
331 SecError(errSecUnsupportedOperation, error, CFSTR("no wrap alg"));
332 return NULL;
333 } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128)) {
334 wrap = &ccec_rfc6637_wrap_sha256_kek_aes128;
335 } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256)) {
336 wrap = &ccec_rfc6637_wrap_sha512_kek_aes256;
337 } else {
338 SecError(errSecUnsupportedOperation, error, CFSTR("unknown wrap alg"));
339 return NULL;
340 }
341
342 num = CFDictionaryGetValue(parameters, _kSecKeyWrapRFC6637Flags);
343 if (isNumber(num)) {
344 if (!CFNumberGetValue(num, kCFNumberSInt32Type, &flags)) {
345 SecError(errSecUnsupportedOperation, error, CFSTR("invalid flags: %@"), num);
346 return NULL;
347 }
348 } else if (num) {
349 SecError(errSecUnsupportedOperation, error, CFSTR("unknown flags"));
350 return NULL;
351 }
352
353 CFIndex unwrappedKey_size = CFDataGetLength(unwrappedKey);
354
355 CFIndex output_size = ccec_rfc6637_wrap_key_size(pubkey, flags, unwrappedKey_size);
356 if (output_size == 0) {
357 SecError(errSecUnsupportedOperation, error, CFSTR("can't wrap that key, can't build size"));
358 return NULL;
359 }
360
361 CFMutableDataRef data = CFDataCreateMutableWithScratch(NULL, output_size);
362 require_quiet(data, errOut);
363
364 err = ccec_rfc6637_wrap_key(pubkey, CFDataGetMutableBytePtr(data), flags,
365 sym_alg, CFDataGetLength(unwrappedKey), CFDataGetBytePtr(unwrappedKey),
366 curve, wrap, CFDataGetBytePtr(fingerprint),
367 ccrng_seckey);
368 if (err) {
369 SecError(errSecUnsupportedOperation, error, CFSTR("Failed to wrap key"));
370 CFReleaseNull(data);
371 }
372
373 errOut:
374 return data;
375 }
376
377 SecKeyDescriptor kSecECPublicKeyDescriptor = {
378 .version = kSecKeyDescriptorVersion,
379 .name = "ECPublicKey",
380 .extraBytes = ccec_pub_ctx_size(ccn_sizeof(kMaximumECKeySize)),
381 .init = SecECPublicKeyInit,
382 .destroy = SecECPublicKeyDestroy,
383 .blockSize = SecECPublicKeyBlockSize,
384 .copyDictionary = SecECPublicKeyCopyAttributeDictionary,
385 .copyExternalRepresentation = SecECPublicKeyCopyExternalRepresentation,
386 .describe = SecECPublicKeyCopyKeyDescription,
387 .getAlgorithmID = SecECKeyGetAlgorithmID,
388 .copyPublic = SecECPublicKeyCopyPublicOctets,
389 .copyWrapKey = SecECKeyCopyWrapKey,
390 .copyOperationResult = SecECPublicKeyCopyOperationResult,
391 };
392
393 /* Public Key API functions. */
394 SecKeyRef SecKeyCreateECPublicKey(CFAllocatorRef allocator,
395 const uint8_t *keyData, CFIndex keyDataLength,
396 SecKeyEncoding encoding) {
397 return SecKeyCreate(allocator, &kSecECPublicKeyDescriptor, keyData,
398 keyDataLength, encoding);
399 }
400
401
402
403 /*
404 *
405 * Private Key
406 *
407 */
408
409 /* Private key static functions. */
410 static void SecECPrivateKeyDestroy(SecKeyRef key) {
411 /* Zero out the public key */
412 ccec_full_ctx_t fullkey = key->key;
413
414 if (ccec_ctx_cp(fullkey))
415 cc_clear(ccec_full_ctx_size(ccn_sizeof_n(ccec_ctx_n(fullkey))), fullkey);
416 }
417
418
419 static OSStatus SecECPrivateKeyInit(SecKeyRef key,
420 const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
421 ccec_full_ctx_t fullkey = key->key;
422 OSStatus err = errSecParam;
423
424 switch (encoding) {
425 case kSecKeyEncodingPkcs1:
426 {
427 /* TODO: DER import size (and thus cp), pub.x, pub.y and k. */
428 //err = ecc_import(keyData, keyDataLength, fullkey);
429
430 /* DER != PKCS#1, but we'll go along with it */
431 const unsigned char *oid;
432 size_t n;
433 ccec_const_cp_t cp;
434
435 require_noerr_quiet(ccec_der_import_priv_keytype(keyDataLength, keyData, (ccoid_t*)&oid, &n), abort);
436 cp = ccec_cp_for_oid(oid);
437 if (cp == NULL) {
438 cp = ccec_curve_for_length_lookup(n * 8 /* bytes -> bits */,
439 ccec_cp_192(), ccec_cp_224(), ccec_cp_256(), ccec_cp_384(), ccec_cp_521(), NULL);
440 }
441 require_action_quiet(cp != NULL, abort, err = errSecDecode);
442 ccec_ctx_init(cp, fullkey);
443
444 require_noerr_quiet(ccec_der_import_priv(cp, keyDataLength, keyData, fullkey), abort);
445 err = errSecSuccess;
446 break;
447 }
448 case kSecKeyEncodingBytes:
449 {
450 ccec_const_cp_t cp = getCPForPrivateSize(keyDataLength);
451 require_quiet(cp != NULL, abort);
452
453 ccec_ctx_init(cp, fullkey);
454 size_t pubSize = ccec_export_pub_size(ccec_ctx_pub(fullkey));
455
456 require_quiet(pubSize < (size_t) keyDataLength, abort);
457 require_noerr_action_quiet(ccec_import_pub(cp, pubSize, keyData, ccec_ctx_pub(fullkey)),
458 abort,
459 err = errSecDecode);
460
461
462 keyData += pubSize;
463 keyDataLength -= pubSize;
464
465 cc_unit *k = ccec_ctx_k(fullkey);
466 require_noerr_action_quiet(ccn_read_uint(ccec_ctx_n(fullkey), k, keyDataLength, keyData),
467 abort,
468 err = errSecDecode);
469
470 err = errSecSuccess;
471 break;
472
473 }
474 case kSecGenerateKey:
475 {
476 CFDictionaryRef parameters = (CFDictionaryRef) keyData;
477
478 CFTypeRef ksize = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits);
479 CFIndex keyLengthInBits = getIntValue(ksize);
480
481 ccec_const_cp_t cp = ccec_get_cp(keyLengthInBits);
482
483 if (!cp) {
484 secwarning("Invalid or missing key size in: %@", parameters);
485 return errSecKeySizeNotAllowed;
486 }
487
488 if (!ccec_generate_key_fips(cp, ccrng_seckey, fullkey))
489 err = errSecSuccess;
490 break;
491 }
492
493 default:
494 break;
495 }
496 abort:
497 return err;
498 }
499
500 static CFTypeRef SecECPrivateKeyCopyOperationResult(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm,
501 CFArrayRef allAlgorithms, SecKeyOperationMode mode,
502 CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
503 // Default answer is 'unsupported', unless we find out that we can support it.
504 CFTypeRef result = kCFNull;
505
506 ccec_full_ctx_t fullkey = key->key;
507 switch (operation) {
508 case kSecKeyOperationTypeSign: {
509 if (CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureDigestX962)) {
510 if (mode == kSecKeyOperationModePerform) {
511 // Perform x962 mode of signature.
512 size_t size = ccec_sign_max_size(ccec_ctx_cp(fullkey));
513 result = CFDataCreateMutableWithScratch(NULL, size);
514 int err = ccec_sign(fullkey, CFDataGetLength(in1), CFDataGetBytePtr(in1),
515 &size, CFDataGetMutableBytePtr((CFMutableDataRef)result), ccrng_seckey);
516 require_action_quiet(err == 0, out, (CFReleaseNull(result),
517 SecError(errSecParam, error, CFSTR("%@: X962 signing failed (ccerr %d)"),
518 key, err)));
519 CFDataSetLength((CFMutableDataRef)result, size);
520 } else {
521 // Operation is supported.
522 result = kCFBooleanTrue;
523 }
524 }
525 break;
526 }
527 case kSecKeyOperationTypeKeyExchange:
528 if (CFEqual(algorithm, kSecKeyAlgorithmECDHKeyExchangeStandard) ||
529 CFEqual(algorithm, kSecKeyAlgorithmECDHKeyExchangeCofactor)) {
530 if (mode == kSecKeyOperationModePerform) {
531 int err;
532 ccec_const_cp_t cp = getCPForPublicSize(CFDataGetLength(in1));
533 require_action_quiet(cp != NULL, out,
534 SecError(errSecParam, error, CFSTR("ECpriv sharedsecret: bad public key")));
535 ccec_pub_ctx_decl_cp(cp, pubkey);
536 err = ccec_import_pub(cp, CFDataGetLength(in1), CFDataGetBytePtr(in1), pubkey);
537 require_noerr_action_quiet(err, out, SecError(errSecParam, error,
538 CFSTR("ECpriv sharedsecret: bad public key (err %d)"), err));
539 size_t size = ccec_ccn_size(cp);
540 result = CFDataCreateMutableWithScratch(NULL, size);
541 err = ccecdh_compute_shared_secret(fullkey, pubkey, &size,
542 CFDataGetMutableBytePtr((CFMutableDataRef)result), ccrng_seckey);
543 require_noerr_action_quiet(err, out, (CFReleaseNull(result),
544 SecError(errSecDecode, error,
545 CFSTR("ECpriv failed to compute shared secret (err %d)"), err)));
546 CFDataSetLength((CFMutableDataRef)result, size);
547 } else {
548 // Operation is supported.
549 result = kCFBooleanTrue;
550 }
551 }
552 break;
553 default:
554 break;
555 }
556
557 out:
558 return result;
559 }
560
561 static size_t SecECPrivateKeyBlockSize(SecKeyRef key) {
562 ccec_full_ctx_t fullkey = key->key;
563 /* Get key size in octets */
564 return ccec_ctx_size(fullkey);
565 }
566
567 static OSStatus SecECPrivateKeyCopyPublicOctets(SecKeyRef key, CFDataRef *serailziation)
568 {
569 ccec_full_ctx_t fullkey = key->key;
570
571 CFAllocatorRef allocator = CFGetAllocator(key);
572 *serailziation = SecECPublicKeyExport(allocator, ccec_ctx_pub(fullkey));
573
574 if (NULL == *serailziation)
575 return errSecDecode;
576 else
577 return errSecSuccess;
578 }
579
580 static CFDataRef SecECPrivateKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) {
581 ccec_full_ctx_t fullkey = key->key;
582 size_t prime_size = ccec_cp_prime_size(ccec_ctx_cp(fullkey));
583 size_t key_size = ccec_export_pub_size(ccec_ctx_pub(fullkey)) + prime_size;
584 CFMutableDataRef blob = CFDataCreateMutableWithScratch(NULL, key_size);
585 ccec_export_pub(ccec_ctx_pub(fullkey), CFDataGetMutableBytePtr(blob));
586 UInt8 *dest = CFDataGetMutableBytePtr(blob) + ccec_export_pub_size(ccec_ctx_pub(fullkey));
587 const cc_unit *k = ccec_ctx_k(fullkey);
588 ccn_write_uint_padded(ccec_ctx_n(fullkey), k, prime_size, dest);
589 return blob;
590 }
591
592 static CFDictionaryRef SecECPrivateKeyCopyAttributeDictionary(SecKeyRef key) {
593 /* Export the full ec key pair. */
594 CFDataRef fullKeyBlob = SecECPrivateKeyCopyExternalRepresentation(key, NULL);
595
596 CFDictionaryRef dict = SecKeyGeneratePrivateAttributeDictionary(key, kSecAttrKeyTypeEC, fullKeyBlob);
597 CFReleaseSafe(fullKeyBlob);
598 return dict;
599 }
600 static CFStringRef SecECPrivateKeyCopyKeyDescription(SecKeyRef key) {
601
602 const char* curve = getCurveName(key);
603
604 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);
605
606 }
607
608 static CFDataRef SecECKeyCopyUnwrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef wrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error)
609 {
610 const struct ccec_rfc6637_curve *curve;
611 const struct ccec_rfc6637_unwrap *unwrap;
612 ccec_full_ctx_t fullkey = key->key;
613 CFMutableDataRef data;
614 int res;
615 uint8_t sym_alg = 0;
616 int32_t flags = 0;
617
618 curve = get_rfc6637_curve(key);
619 if (curve == NULL) {
620 SecError(errSecUnsupportedOperation, error, CFSTR("unsupported curve"));
621 return NULL;
622 }
623
624 CFTypeRef wrapAlg = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPWrapAlg);
625 if (wrapAlg == NULL) {
626 SecError(errSecUnsupportedOperation, error, CFSTR("no wrap alg"));
627 return NULL;
628 } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128)) {
629 unwrap = &ccec_rfc6637_unwrap_sha256_kek_aes128;
630 } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256)) {
631 unwrap = &ccec_rfc6637_unwrap_sha512_kek_aes256;
632 } else {
633 SecError(errSecUnsupportedOperation, error, CFSTR("unknown wrap alg"));
634 return NULL;
635 }
636
637 CFDataRef fingerprint = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPFingerprint);
638 if (!isData(fingerprint) || CFDataGetLength(fingerprint) < kSecKeyWrapPGPFingerprintMinSize) {
639 SecError(errSecUnsupportedOperation, error, CFSTR("invalid fingerprint"));
640 return NULL;
641 }
642
643 CFNumberRef num = CFDictionaryGetValue(parameters, _kSecKeyWrapRFC6637Flags);
644 if (isNumber(num)) {
645 if (!CFNumberGetValue(num, kCFNumberSInt32Type, &flags)) {
646 SecError(errSecUnsupportedOperation, error, CFSTR("invalid flags: %@"), num);
647 return NULL;
648 }
649 } else if (num) {
650 SecError(errSecUnsupportedOperation, error, CFSTR("unknown flags"));
651 return NULL;
652 }
653
654 size_t keysize = CFDataGetLength(wrappedKey);
655 data = CFDataCreateMutableWithScratch(NULL, keysize);
656 if (data == NULL)
657 return NULL;
658
659 res = ccec_rfc6637_unwrap_key(fullkey, &keysize, CFDataGetMutableBytePtr(data),
660 flags, &sym_alg, curve, unwrap,
661 CFDataGetBytePtr(fingerprint),
662 CFDataGetLength(wrappedKey), CFDataGetBytePtr(wrappedKey));
663 if (res != 0) {
664 CFReleaseNull(data);
665 SecError(errSecUnsupportedOperation, error, CFSTR("failed to wrap key"));
666 return NULL;
667 }
668 assert(keysize <= (size_t)CFDataGetLength(data));
669 CFDataSetLength(data, keysize);
670
671 if (outParam) {
672 CFMutableDictionaryRef out = CFDictionaryCreateMutableForCFTypes(NULL);
673 if (out) {
674 CFNumberRef num = CFNumberCreate(NULL, kCFNumberSInt8Type, &sym_alg);
675 if (num) {
676 CFDictionarySetValue(out, _kSecKeyWrapPGPSymAlg, num);
677 CFRelease(num);
678 }
679 *outParam = out;
680 }
681 }
682
683 return data;
684 }
685
686 SecKeyDescriptor kSecECPrivateKeyDescriptor = {
687 .version = kSecKeyDescriptorVersion,
688 .name = "ECPrivateKey",
689 .extraBytes = ccec_full_ctx_size(ccn_sizeof(kMaximumECKeySize)),
690
691 .init = SecECPrivateKeyInit,
692 .destroy = SecECPrivateKeyDestroy,
693 .blockSize = SecECPrivateKeyBlockSize,
694 .copyDictionary = SecECPrivateKeyCopyAttributeDictionary,
695 .describe = SecECPrivateKeyCopyKeyDescription,
696 .getAlgorithmID = SecECKeyGetAlgorithmID,
697 .copyPublic = SecECPrivateKeyCopyPublicOctets,
698 .copyExternalRepresentation = SecECPrivateKeyCopyExternalRepresentation,
699 .copyWrapKey = SecECKeyCopyWrapKey,
700 .copyUnwrapKey = SecECKeyCopyUnwrapKey,
701 .copyOperationResult = SecECPrivateKeyCopyOperationResult,
702 };
703
704 /* Private Key API functions. */
705 SecKeyRef SecKeyCreateECPrivateKey(CFAllocatorRef allocator,
706 const uint8_t *keyData, CFIndex keyDataLength,
707 SecKeyEncoding encoding) {
708 return SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor, keyData,
709 keyDataLength, encoding);
710 }
711
712
713 OSStatus SecECKeyGeneratePair(CFDictionaryRef parameters,
714 SecKeyRef *publicKey, SecKeyRef *privateKey) {
715 OSStatus status = errSecParam;
716
717 CFAllocatorRef allocator = NULL; /* @@@ get from parameters. */
718 SecKeyRef pubKey = NULL;
719
720 SecKeyRef privKey = SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor,
721 (const void*) parameters, 0, kSecGenerateKey);
722
723 require_quiet(privKey, errOut);
724
725 /* Create SecKeyRef's from the pkcs1 encoded keys. */
726 pubKey = SecKeyCreate(allocator, &kSecECPublicKeyDescriptor,
727 privKey->key, 0, kSecExtractPublicFromPrivate);
728
729 require_quiet(pubKey, errOut);
730
731 if (publicKey) {
732 *publicKey = pubKey;
733 pubKey = NULL;
734 }
735 if (privateKey) {
736 *privateKey = privKey;
737 privKey = NULL;
738 }
739
740 status = errSecSuccess;
741
742 errOut:
743 CFReleaseSafe(pubKey);
744 CFReleaseSafe(privKey);
745
746 return status;
747 }
748
749
750 /* It's debatable whether this belongs here or in the ssl code since the
751 curve values come from a tls related rfc4492. */
752 SecECNamedCurve SecECKeyGetNamedCurve(SecKeyRef key) {
753 SecECNamedCurve result = kSecECCurveNone;
754 CFDictionaryRef attributes = NULL;
755 require_quiet(SecKeyGetAlgorithmId(key) == kSecECDSAAlgorithmID, out);
756 require_quiet(attributes = SecKeyCopyAttributes(key), out);
757 CFTypeRef bitsRef = CFDictionaryGetValue(attributes, kSecAttrKeySizeInBits);
758 CFIndex bits = 0;
759 require_quiet(bitsRef != NULL && CFGetTypeID(bitsRef) == CFNumberGetTypeID() &&
760 CFNumberGetValue(bitsRef, kCFNumberCFIndexType, &bits), out);
761 switch (bits) {
762 #if 0
763 case 192:
764 result = kSecECCurveSecp192r1;
765 break;
766 case 224:
767 result = kSecECCurveSecp224r1;
768 break;
769 #endif
770 case 256:
771 result = kSecECCurveSecp256r1;
772 break;
773 case 384:
774 result = kSecECCurveSecp384r1;
775 break;
776 case 521:
777 result = kSecECCurveSecp521r1;
778 break;
779 }
780
781 out:
782 CFReleaseSafe(attributes);
783 return result;
784 }
785
786 CFDataRef SecECKeyCopyPublicBits(SecKeyRef key) {
787 CFDataRef bytes = NULL;
788 SecKeyCopyPublicBytes(key, &bytes);
789 return bytes;
790 }
791
792 /* Vile accessors that get us the pub or priv key to use temporarily */
793
794 bool SecECDoWithFullKey(SecKeyRef key, CFErrorRef* error, void (^action)(ccec_full_ctx_t private)) {
795 if (key->key_class == &kSecECPrivateKeyDescriptor) {
796 action(key->key);
797 } else {
798 return SecError(errSecParam, error, CFSTR("Not an EC Full Key object, sorry can't do."));
799 }
800
801 return true;
802 }
803
804 bool SecECDoWithPubKey(SecKeyRef key, CFErrorRef* error, void (^action)(ccec_pub_ctx_t public)) {
805 if (key->key_class == &kSecECPublicKeyDescriptor) {
806 action(key->key);
807 } else {
808 return SecError(errSecParam, error, CFSTR("Not an EC Public Key object, sorry can't do."));
809 }
810
811 return true;
812 }
813