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