]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecRSAKey.c
Security-58286.260.20.tar.gz
[apple/security.git] / OSX / sec / Security / SecRSAKey.c
1 /*
2 * Copyright (c) 2006-2010,2012-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 * SecRSAKey.c - CoreFoundation based rsa key object
26 */
27
28
29 #include "SecRSAKey.h"
30 #include "SecRSAKeyPriv.h"
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 <utilities/SecCFWrappers.h>
45 #include <utilities/SecCFError.h>
46 #include <utilities/array_size.h>
47 #include "SecItemPriv.h"
48 #include <Security/SecInternal.h>
49
50 #include <corecrypto/ccn.h>
51 #include <corecrypto/ccrsa.h>
52 #include <corecrypto/ccsha1.h>
53 #include <corecrypto/ccsha2.h>
54
55 #include <libDER/asn1Types.h>
56 #include <libDER/DER_Keys.h>
57 #include <libDER/DER_Encode.h>
58
59 #include <CommonCrypto/CommonDigest.h>
60
61 #include <corecrypto/ccrsa_priv.h>
62
63 #include <stdint.h>
64 #include <string.h>
65
66 #define kMaximumRSAKeyBits (1024 * 8)
67
68 #define RSA_PKCS1_PAD_SIGN 0x01
69 #define RSA_PKCS1_PAD_ENCRYPT 0x02
70
71 /*
72 *
73 * Public Key
74 *
75 */
76
77 /* Public key static functions. */
78 static void SecRSAPublicKeyDestroy(SecKeyRef key) {
79 /* Zero out the public key */
80 if (key->key) {
81 ccrsa_pub_ctx_t pubkey = key->key;
82 cc_clear(ccrsa_pub_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(pubkey))), pubkey);
83 free(key->key);
84 key->key = NULL;
85 }
86 }
87
88 #define cc_skip_zeros(size, ptr) { while (size > 0 && *ptr == 0) { ++ptr; --size; } }
89
90 //
91 // pubkey is initilaized with an n which is the maximum it can hold
92 // We set the n to its correct value given m.
93 //
94 static int ccrsa_pub_init(ccrsa_pub_ctx_t pubkey,
95 size_t m_size, const uint8_t* m,
96 size_t e_size, const uint8_t* e)
97 {
98 cc_skip_zeros(m_size, m);
99
100 cc_size nm = ccn_nof_size(m_size);
101 if (nm > ccrsa_ctx_n(pubkey))
102 return -1;
103
104 ccrsa_ctx_n(pubkey) = nm;
105
106 ccn_read_uint(nm, ccrsa_ctx_m(pubkey), m_size, m);
107 cczp_init(ccrsa_ctx_zm(pubkey));
108
109 return ccn_read_uint(nm, ccrsa_ctx_e(pubkey), e_size, e);
110 }
111
112
113 static OSStatus ccrsa_pub_decode_apple(ccrsa_pub_ctx_t pubkey, size_t pkcs1_size, const uint8_t* pkcs1)
114 {
115 OSStatus result = errSecParam;
116
117 DERItem keyItem = {(DERByte *)pkcs1, pkcs1_size};
118 DERRSAPubKeyApple decodedKey;
119
120 require_noerr_action_quiet(DERParseSequence(&keyItem,
121 DERNumRSAPubKeyAppleItemSpecs, DERRSAPubKeyAppleItemSpecs,
122 &decodedKey, sizeof(decodedKey)),
123 errOut, result = errSecDecode);
124
125 // We could honor the reciprocal, but we don't think this is used enough to care.
126 // Don't bother exploding the below function to try to handle this case, it computes.
127
128 require_noerr_quiet(ccrsa_pub_init(pubkey,
129 decodedKey.modulus.length, decodedKey.modulus.data,
130 decodedKey.pubExponent.length, decodedKey.pubExponent.data),
131 errOut);
132
133 result = errSecSuccess;
134
135 errOut:
136 return result;
137 }
138
139
140 static void ccasn_encode_int(cc_size n, const cc_unit*s, size_t s_size, uint8_t **buffer)
141 {
142 **buffer = ASN1_INTEGER;
143 *buffer += 1;
144
145 DERSize itemLength = 4;
146 DEREncodeLength(s_size, *buffer, &itemLength);
147 *buffer += itemLength;
148
149 ccn_write_int(n, s, s_size, *buffer);
150
151 *buffer += s_size;
152 }
153
154
155 static OSStatus SecRSAPublicKeyInit(SecKeyRef key,
156 const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
157
158 OSStatus result = errSecParam;
159 ccrsa_pub_ctx_t pubkey;
160 size_t size_n = 0;
161
162 switch (encoding) {
163 case kSecKeyEncodingBytes: // Octets is PKCS1
164 case kSecKeyEncodingPkcs1: {
165 size_n = ccrsa_import_pub_n(keyDataLength, keyData);
166 require_quiet(size_n != 0, errOut);
167 require_quiet(size_n <= ccn_nof(kMaximumRSAKeyBits), errOut);
168
169 key->key = calloc(1, ccrsa_pub_ctx_size(ccn_sizeof_n(size_n)));
170 require_action_quiet(key->key, errOut, result = errSecAllocate);
171
172 pubkey = key->key;
173 ccrsa_ctx_n(pubkey) = size_n;
174
175 require_noerr_quiet(ccrsa_import_pub(pubkey, keyDataLength, keyData), errOut);
176
177 result = errSecSuccess;
178
179 break;
180 }
181 case kSecKeyEncodingApplePkcs1:
182 /* for the few uses (I can't find any) that uses kSecKeyEncodingApplePkcs1, force largest keys */
183 size_n = ccn_nof(kMaximumRSAKeyBits);
184
185 key->key = calloc(1, ccrsa_pub_ctx_size(ccn_sizeof_n(size_n)));
186 require_action_quiet(key->key, errOut, result = errSecAllocate);
187
188 pubkey = key->key;
189 ccrsa_ctx_n(pubkey) = size_n;
190
191 result = ccrsa_pub_decode_apple(pubkey, keyDataLength, keyData);
192 break;
193 case kSecKeyEncodingRSAPublicParams:
194 {
195 SecRSAPublicKeyParams *params = (SecRSAPublicKeyParams *)keyData;
196
197 size_n = ccn_nof_size(params->modulusLength);
198
199 key->key = calloc(1, ccrsa_pub_ctx_size(ccn_sizeof_n(size_n)));
200 require_action_quiet(key->key, errOut, result = errSecAllocate);
201
202 pubkey = key->key;
203 ccrsa_ctx_n(pubkey) = size_n;
204
205 require_noerr_quiet(ccrsa_pub_init(pubkey,
206 params->modulusLength, params->modulus,
207 params->exponentLength, params->exponent), errOut);
208
209 result = errSecSuccess;
210 break;
211 }
212 case kSecExtractPublicFromPrivate:
213 {
214 ccrsa_full_ctx_t fullKey = (ccrsa_full_ctx_t) keyData;
215
216 size_n = ccrsa_ctx_n(fullKey);
217
218 key->key = calloc(1, ccrsa_pub_ctx_size(ccn_sizeof_n(size_n)));
219 require_action_quiet(key->key, errOut, result = errSecAllocate);
220
221 pubkey = key->key;
222 ccrsa_ctx_n(pubkey) = size_n;
223
224 memcpy(pubkey, ccrsa_ctx_public(fullKey), ccrsa_pub_ctx_size(ccn_sizeof_n(size_n)));
225 result = errSecSuccess;
226 break;
227 }
228 default:
229 break;
230 }
231
232 errOut:
233 return result;
234 }
235
236 static CFTypeRef SecRSAPublicKeyCopyOperationResult(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm,
237 CFArrayRef allAlgorithms, SecKeyOperationMode mode,
238 CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
239 CFTypeRef result;
240 require_action_quiet(CFEqual(algorithm, kSecKeyAlgorithmRSAEncryptionRawCCUnit), out, result = kCFNull);
241
242 ccrsa_pub_ctx_t pubkey = key->key;
243 result = kCFBooleanTrue;
244 int ccerr = 0;
245 switch (operation) {
246 case kSecKeyOperationTypeEncrypt:
247 if (mode == kSecKeyOperationModePerform) {
248 // Verify that plaintext is smaller than modulus. Note that since we already verified that input algorithm
249 // is kSecKeyAlgorithmRSAEncryptionRawCCUnit, we can safely access in1 CFDataRef contents as cc_unit *.
250 require_action_quiet(ccn_cmpn(ccn_nof_size(CFDataGetLength(in1)), (const cc_unit *)CFDataGetBytePtr(in1),
251 ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey)) < 0, out,
252 (result = NULL,
253 SecError(errSecParam, error, CFSTR("RSApubkey wrong size of buffer to encrypt"))));
254
255 // Encrypt into output buffer.
256 result = CFDataCreateMutableWithScratch(NULL, ccrsa_block_size(pubkey));
257 ccerr = ccrsa_pub_crypt(pubkey, (cc_unit *)CFDataGetMutableBytePtr((CFMutableDataRef)result),
258 (const cc_unit *)CFDataGetBytePtr(in1));
259 }
260 break;
261 case kSecKeyOperationTypeDecrypt:
262 if (mode == kSecKeyOperationModePerform) {
263 // Decrypt into output buffer.
264 result = CFDataCreateMutableWithScratch(NULL, ccrsa_block_size(pubkey));
265 ccerr = ccrsa_pub_crypt(pubkey, (cc_unit *)CFDataGetMutableBytePtr((CFMutableDataRef)result),
266 (const cc_unit *)CFDataGetBytePtr(in1));
267 }
268 break;
269 default:
270 result = kCFNull;
271 break;
272 }
273
274 require_noerr_action_quiet(ccerr, out, (CFReleaseNull(result),
275 SecError(errSecParam, error, CFSTR("rsa_pub_crypt failed, ccerr=%d"), ccerr)));
276 out:
277 return result;
278 }
279
280 static size_t SecRSAPublicKeyBlockSize(SecKeyRef key) {
281 ccrsa_pub_ctx_t pubkey = key->key;
282 return ccrsa_block_size(pubkey);
283 }
284
285
286 static CFDataRef SecRSAPublicKeyCreatePKCS1(CFAllocatorRef allocator, ccrsa_pub_ctx_t pubkey)
287 {
288 size_t m_size = ccn_write_int_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
289 size_t e_size = ccn_write_int_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey));
290
291 const size_t seq_size = DERLengthOfItem(ASN1_INTEGER, m_size) +
292 DERLengthOfItem(ASN1_INTEGER, e_size);
293
294 const size_t result_size = DERLengthOfItem(ASN1_SEQUENCE, seq_size);
295
296 CFMutableDataRef pkcs1 = CFDataCreateMutableWithScratch(allocator, result_size);
297 uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1);
298
299 *bytes++ = ONE_BYTE_ASN1_CONSTR_SEQUENCE;
300
301 DERSize itemLength = 4;
302 DEREncodeLength(seq_size, bytes, &itemLength);
303 bytes += itemLength;
304
305 ccasn_encode_int(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), m_size, &bytes);
306 ccasn_encode_int(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey), e_size, &bytes);
307
308 return pkcs1;
309 }
310
311 static OSStatus SecRSAPublicKeyCopyPublicSerialization(SecKeyRef key, CFDataRef* serialized)
312 {
313 ccrsa_pub_ctx_t pubkey = key->key;
314
315 CFAllocatorRef allocator = CFGetAllocator(key);
316 *serialized = SecRSAPublicKeyCreatePKCS1(allocator, pubkey);
317
318 if (NULL == *serialized)
319 return errSecDecode;
320 else
321 return errSecSuccess;
322 }
323
324 static CFDictionaryRef SecRSAPublicKeyCopyAttributeDictionary(SecKeyRef key) {
325 CFDictionaryRef dict = SecKeyGeneratePublicAttributeDictionary(key, kSecAttrKeyTypeRSA);
326 CFMutableDictionaryRef mutableDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
327 CFDictionarySetValue(mutableDict, kSecAttrCanDecrypt, kCFBooleanTrue);
328 CFDictionarySetValue(mutableDict, kSecAttrCanDerive, kCFBooleanFalse);
329 CFAssignRetained(dict, mutableDict);
330 return dict;
331 }
332
333 static CFDataRef SecRSAPublicKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) {
334 ccrsa_pub_ctx_t pubkey = key->key;
335 return SecRSAPublicKeyCreatePKCS1(CFGetAllocator(key), pubkey);
336 }
337
338 static CFStringRef SecRSAPublicKeyCopyDescription(SecKeyRef key) {
339
340 CFStringRef keyDescription = NULL;
341 CFDataRef modRef = SecKeyCopyModulus(key);
342
343 ccrsa_pub_ctx_t pubkey = key->key;
344
345 CFStringRef modulusString = CFDataCopyHexString(modRef);
346 require_quiet(modulusString, fail);
347
348 keyDescription = CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR( "<SecKeyRef algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, exponent: {hex: %llx, decimal: %lld}, modulus: %@, addr: %p>"), SecKeyGetAlgorithmId(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), (long long)*ccrsa_ctx_e(pubkey), (long long)*ccrsa_ctx_e(pubkey), modulusString, key);
349
350 fail:
351 CFReleaseSafe(modRef);
352 CFReleaseSafe(modulusString);
353 if(!keyDescription)
354 keyDescription = CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR("<SecKeyRef algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, addr: %p>"), (long)SecKeyGetAlgorithmId(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), key);
355
356 return keyDescription;
357 }
358
359 SecKeyDescriptor kSecRSAPublicKeyDescriptor = {
360 .version = kSecKeyDescriptorVersion,
361 .name = "RSAPublicKey",
362
363 .init = SecRSAPublicKeyInit,
364 .destroy = SecRSAPublicKeyDestroy,
365 .blockSize = SecRSAPublicKeyBlockSize,
366 .copyDictionary = SecRSAPublicKeyCopyAttributeDictionary,
367 .copyExternalRepresentation = SecRSAPublicKeyCopyExternalRepresentation,
368 .describe = SecRSAPublicKeyCopyDescription,
369 .copyPublic = SecRSAPublicKeyCopyPublicSerialization,
370 .copyOperationResult = SecRSAPublicKeyCopyOperationResult,
371 };
372
373 /* Public Key API functions. */
374 SecKeyRef SecKeyCreateRSAPublicKey_ios(CFAllocatorRef allocator,
375 const uint8_t *keyData, CFIndex keyDataLength,
376 SecKeyEncoding encoding) {
377 return SecKeyCreate(allocator, &kSecRSAPublicKeyDescriptor, keyData,
378 keyDataLength, encoding);
379 }
380
381 SecKeyRef SecKeyCreateRSAPublicKey(CFAllocatorRef allocator,
382 const uint8_t *keyData, CFIndex keyDataLength,
383 SecKeyEncoding encoding) {
384 return SecKeyCreateRSAPublicKey_ios(allocator, keyData,
385 keyDataLength, encoding);
386 }
387
388 CFDataRef SecKeyCopyModulus(SecKeyRef key) {
389 CFDataRef modulus = NULL;
390 if (key->key_class == &kSecRSAPublicKeyDescriptor) {
391 ccrsa_pub_ctx_t pubkey = key->key;
392
393 size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
394
395 CFAllocatorRef allocator = CFGetAllocator(key);
396 CFMutableDataRef modulusData = CFDataCreateMutable(allocator, m_size);
397
398 if (modulusData == NULL)
399 return NULL;
400
401 CFDataSetLength(modulusData, m_size);
402
403 ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), m_size, CFDataGetMutableBytePtr(modulusData));
404 modulus = modulusData;
405 } else if (key->key_class->copyDictionary != NULL) {
406 CFDictionaryRef dict = key->key_class->copyDictionary(key);
407 if (dict != NULL) {
408 modulus = CFRetainSafe(CFDictionaryGetValue(dict, CFSTR("_rsam")));
409 CFRelease(dict);
410 }
411 }
412
413 return modulus;
414 }
415
416 CFDataRef SecKeyCopyExponent(SecKeyRef key) {
417 CFDataRef exponent = NULL;
418 if (key->key_class == &kSecRSAPublicKeyDescriptor) {
419 ccrsa_pub_ctx_t pubkey = key->key;
420
421 size_t e_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey));
422
423 CFAllocatorRef allocator = CFGetAllocator(key);
424 CFMutableDataRef exponentData = CFDataCreateMutable(allocator, e_size);
425
426 if (exponentData == NULL)
427 return NULL;
428
429 CFDataSetLength(exponentData, e_size);
430
431 ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey), e_size, CFDataGetMutableBytePtr(exponentData));
432 exponent = exponentData;
433 } else if (key->key_class->copyDictionary != NULL) {
434 CFDictionaryRef dict = key->key_class->copyDictionary(key);
435 if (dict != NULL) {
436 exponent = CFRetainSafe(CFDictionaryGetValue(dict, CFSTR("_rsae")));
437 CFRelease(dict);
438 }
439 }
440
441 return exponent;
442 }
443
444
445 /*
446 *
447 * Private Key
448 *
449 */
450
451 /* Private key static functions. */
452 static void SecRSAPrivateKeyDestroy(SecKeyRef key) {
453 /* Zero out the public key */
454 if (key->key) {
455 ccrsa_full_ctx_t fullkey = key->key;
456 cc_clear(ccrsa_full_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(fullkey))), fullkey);
457 free(key->key);
458 key->key = NULL;
459 }
460 }
461
462 static OSStatus SecRSAPrivateKeyInit(SecKeyRef key, const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
463 OSStatus result = errSecParam;
464 ccrsa_full_ctx_t fullkey;
465 cc_size size_n = 0;
466
467 switch (encoding) {
468 case kSecKeyEncodingBytes: // Octets is PKCS1
469 case kSecKeyEncodingPkcs1:
470 {
471 size_n = ccrsa_import_priv_n(keyDataLength,keyData);
472 require_quiet(size_n != 0, errOut);
473 require_quiet(size_n <= ccn_nof(kMaximumRSAKeyBits), errOut);
474
475 key->key = calloc(1, ccrsa_full_ctx_size(ccn_sizeof_n(size_n)));
476 require_action_quiet(key->key, errOut, result = errSecAllocate);
477
478 fullkey = key->key;
479 ccrsa_ctx_n(fullkey) = size_n;
480
481 require_quiet(ccrsa_import_priv(fullkey, keyDataLength, keyData)==0, errOut);
482
483 result = errSecSuccess;
484 break;
485 }
486 case kSecGenerateKey:
487 {
488 CFDictionaryRef parameters = (CFDictionaryRef) keyData;
489
490 CFTypeRef ksize = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits);
491 CFIndex keyLengthInBits = getIntValue(ksize);
492
493 if (keyLengthInBits < 512 || keyLengthInBits > kMaximumRSAKeyBits) {
494 secwarning("Invalid or missing key size in: %@", parameters);
495 result = errSecKeySizeNotAllowed;
496 goto errOut;
497 }
498
499 size_n = ccn_nof(keyLengthInBits);
500
501 key->key = calloc(1, ccrsa_full_ctx_size(ccn_sizeof_n(size_n)));
502 require_action_quiet(key->key, errOut, result = errSecAllocate);
503
504 fullkey = key->key;
505 ccrsa_ctx_n(fullkey) = size_n;
506
507 /* TODO: Add support for kSecPublicExponent parameter. */
508 static uint8_t e[] = { 0x01, 0x00, 0x01 }; // Default is 65537
509 if (!ccrsa_generate_fips186_key(keyLengthInBits, fullkey, sizeof(e), e, ccrng_seckey,ccrng_seckey))
510 result = errSecSuccess;
511 break;
512 }
513 default:
514 break;
515 }
516 errOut:
517 return result;
518 }
519
520 static CFTypeRef SecRSAPrivateKeyCopyOperationResult(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm,
521 CFArrayRef allAlgorithms, SecKeyOperationMode mode,
522 CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
523 CFTypeRef result = kCFNull;
524
525 ccrsa_full_ctx_t fullkey = key->key;
526 int ccerr = 0;
527 switch (operation) {
528 case kSecKeyOperationTypeSign:
529 if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureRawCCUnit)) {
530 if (mode == kSecKeyOperationModePerform) {
531 // Verify that data is smaller than modulus. Note that since we already verified that input algorithm
532 // is kSecKeyAlgorithmRSASignatureRawCCUnit, we can safely access in1 CFDataRef contents as cc_unit *.
533 require_action_quiet(ccn_cmpn(ccn_nof_size(CFDataGetLength(in1)), (const cc_unit *)CFDataGetBytePtr(in1),
534 ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey)) < 0, out,
535 (result = NULL,
536 SecError(errSecParam, error, CFSTR("%@: sign - digest too big (%d bytes)"), key,
537 (int)CFDataGetLength(in1))));
538
539 // Encrypt buffer and write it to output data.
540 result = CFDataCreateMutableWithScratch(kCFAllocatorDefault, ccrsa_block_size(ccrsa_ctx_public(fullkey)));
541 ccerr = ccrsa_priv_crypt(fullkey, (cc_unit *)CFDataGetMutableBytePtr((CFMutableDataRef)result),
542 (const cc_unit *)CFDataGetBytePtr(in1));
543 } else {
544 // Operation is supported.
545 result = kCFBooleanTrue;
546 }
547 }
548 break;
549 case kSecKeyOperationTypeDecrypt:
550 if (CFEqual(algorithm, kSecKeyAlgorithmRSAEncryptionRawCCUnit)) {
551 if (mode == kSecKeyOperationModePerform) {
552 // Decrypt buffer and write it to output data.
553 result = CFDataCreateMutableWithScratch(NULL, ccrsa_block_size(ccrsa_ctx_public(fullkey)));
554 ccerr = ccrsa_priv_crypt(fullkey, (cc_unit *)CFDataGetMutableBytePtr((CFMutableDataRef)result),
555 (const cc_unit *)CFDataGetBytePtr(in1));
556 } else {
557 // Operation is supported.
558 result = kCFBooleanTrue;
559 }
560 }
561 break;
562 default:
563 break;
564 }
565
566 require_noerr_action_quiet(ccerr, out, (CFReleaseNull(result),
567 SecError(errSecParam, error, CFSTR("rsa_priv_crypt failed, ccerr=%d"), ccerr)));
568 out:
569 return result;
570 }
571
572 static size_t SecRSAPrivateKeyBlockSize(SecKeyRef key) {
573 ccrsa_full_ctx_t fullkey = key->key;
574
575 return ccn_write_uint_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey));
576 }
577
578 static CFDataRef SecRSAPrivateKeyCreatePKCS1(CFAllocatorRef allocator, ccrsa_full_ctx_t fullkey)
579 {
580 const size_t result_size = ccrsa_export_priv_size(fullkey);
581
582 CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size);
583
584 if (pkcs1 == NULL)
585 return NULL;
586
587 CFDataSetLength(pkcs1, result_size);
588
589 uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1);
590
591 if (ccrsa_export_priv(fullkey,result_size,bytes)!=0) {
592 /* Decoding failed */
593 CFReleaseNull(pkcs1);
594 return NULL;
595 }
596
597 return pkcs1;
598 }
599
600 static CFDataRef SecRSAPrivateKeyCopyPKCS1(SecKeyRef key)
601 {
602 ccrsa_full_ctx_t fullkey = key->key;
603
604 CFAllocatorRef allocator = CFGetAllocator(key);
605 return SecRSAPrivateKeyCreatePKCS1(allocator, fullkey);
606 }
607
608 static OSStatus SecRSAPrivateKeyCopyPublicSerialization(SecKeyRef key, CFDataRef* serialized)
609 {
610 ccrsa_full_ctx_t fullkey = key->key;
611
612 CFAllocatorRef allocator = CFGetAllocator(key);
613 *serialized = SecRSAPublicKeyCreatePKCS1(allocator, ccrsa_ctx_public(fullkey));
614
615 if (NULL == *serialized)
616 return errSecDecode;
617 else
618 return errSecSuccess;
619 }
620
621
622 static CFDictionaryRef SecRSAPrivateKeyCopyAttributeDictionary(SecKeyRef key) {
623 CFDictionaryRef dict = NULL;
624 CFDataRef fullKeyBlob = NULL;
625
626 /* PKCS1 encode the key pair. */
627 fullKeyBlob = SecRSAPrivateKeyCopyPKCS1(key);
628 require_quiet(fullKeyBlob, errOut);
629
630 dict = SecKeyGeneratePrivateAttributeDictionary(key, kSecAttrKeyTypeRSA, fullKeyBlob);
631 CFMutableDictionaryRef mutableDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
632 CFDictionarySetValue(mutableDict, kSecAttrCanDerive, kCFBooleanFalse);
633 CFAssignRetained(dict, mutableDict);
634
635 errOut:
636 CFReleaseSafe(fullKeyBlob);
637
638 return dict;
639 }
640
641 static CFDataRef SecRSAPrivateKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) {
642 return SecRSAPrivateKeyCopyPKCS1(key);
643 }
644
645 static CFStringRef SecRSAPrivateKeyCopyDescription(SecKeyRef key){
646
647 return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR( "<SecKeyRef algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, addr: %p>"), SecKeyGetAlgorithmId(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), key);
648
649 }
650
651 SecKeyDescriptor kSecRSAPrivateKeyDescriptor = {
652 .version = kSecKeyDescriptorVersion,
653 .name = "RSAPrivateKey",
654
655 .init = SecRSAPrivateKeyInit,
656 .destroy = SecRSAPrivateKeyDestroy,
657 .blockSize = SecRSAPrivateKeyBlockSize,
658 .copyExternalRepresentation = SecRSAPrivateKeyCopyExternalRepresentation,
659 .copyDictionary = SecRSAPrivateKeyCopyAttributeDictionary,
660 .describe = SecRSAPrivateKeyCopyDescription,
661 .copyPublic = SecRSAPrivateKeyCopyPublicSerialization,
662 .copyOperationResult = SecRSAPrivateKeyCopyOperationResult,
663 };
664
665 /* Private Key API functions. */
666 SecKeyRef SecKeyCreateRSAPrivateKey(CFAllocatorRef allocator,
667 const uint8_t *keyData, CFIndex keyDataLength,
668 SecKeyEncoding encoding) {
669 return SecKeyCreate(allocator, &kSecRSAPrivateKeyDescriptor, keyData,
670 keyDataLength, encoding);
671 }
672
673
674 OSStatus SecRSAKeyGeneratePair(CFDictionaryRef parameters,
675 SecKeyRef *rsaPublicKey, SecKeyRef *rsaPrivateKey) {
676 OSStatus status = errSecParam;
677
678 CFAllocatorRef allocator = NULL; /* @@@ get from parameters. */
679
680 SecKeyRef pubKey = NULL;
681 SecKeyRef privKey = SecKeyCreate(allocator, &kSecRSAPrivateKeyDescriptor,
682 (const void*) parameters, 0, kSecGenerateKey);
683
684 require_quiet(privKey, errOut);
685
686 /* Create SecKeyRef's from the pkcs1 encoded keys. */
687 pubKey = SecKeyCreate(allocator, &kSecRSAPublicKeyDescriptor,
688 privKey->key, 0, kSecExtractPublicFromPrivate);
689
690 require_quiet(pubKey, errOut);
691
692 if (rsaPublicKey) {
693 *rsaPublicKey = pubKey;
694 pubKey = NULL;
695 }
696 if (rsaPrivateKey) {
697 *rsaPrivateKey = privKey;
698 privKey = NULL;
699 }
700
701 status = errSecSuccess;
702
703 errOut:
704 CFReleaseSafe(pubKey);
705 CFReleaseSafe(privKey);
706
707 return status;
708 }