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