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