]> git.saurik.com Git - apple/security.git/blame - sec/Security/SecRSAKey.c
Security-55179.13.tar.gz
[apple/security.git] / sec / Security / SecRSAKey.c
CommitLineData
b1ab9ed8
A
1/*
2 * Copyright (c) 2006-2010 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 <security_utilities/debugging.h>
44#include "SecItemPriv.h"
45#include <Security/SecInternal.h>
46
47#include <corecrypto/ccn.h>
48#include <corecrypto/ccrsa.h>
49#include <corecrypto/ccsha1.h>
50
51#include <libDER/asn1Types.h>
52#include <libDER/DER_Keys.h>
53#include <libDER/DER_Encode.h>
54
55#include <CommonCrypto/CommonDigest.h>
56
57#include <corecrypto/ccrsa_priv.h>
58
59#include <stdint.h>
60#include <string.h>
61
62#define kMaximumRSAKeyBits 4096
63#define kMaximumRSAKeyBytes ccn_sizeof(kMaximumRSAKeyBits)
64
65#define RSA_PKCS1_PAD_SIGN 0x01
66#define RSA_PKCS1_PAD_ENCRYPT 0x02
67
68static void ccn_c_dump(cc_size count, const cc_unit *s)
69{
70 printf("{ ");
71 cc_size ix;
72 for (ix = count; ix--;) {
73 printf("0x%.02x, 0x%.02x, 0x%.02x, 0x%.02x, ",
74 (s[ix] >> 24) & 0xFF,
75 (s[ix] >> 16) & 0xFF,
76 (s[ix] >> 8 ) & 0xFF,
77 (s[ix] >> 0 ) & 0xFF);
78 }
79 printf("};");
80}
81
82static void ccn_cprint(cc_size count, char* prefix, const cc_unit *s)
83{
84 printf("%s", prefix);
85 ccn_c_dump(count, s);
86 printf("\n");
87}
88
89void ccrsa_dump_full_key(ccrsa_full_ctx_t key); // Suppress warnings
90void ccrsa_dump_full_key(ccrsa_full_ctx_t key) {
91 ccn_cprint(ccrsa_ctx_n(key), "uint8_t m[] = ", ccrsa_ctx_m(key));
92 ccn_cprint(ccrsa_ctx_n(key) + 1, "uint8_t rm[] = ", cczp_recip(ccrsa_ctx_zm(key)));
93 ccn_cprint(ccrsa_ctx_n(key), "uint8_t e[] = ", ccrsa_ctx_e(key));
94 ccn_cprint(ccrsa_ctx_n(key), "uint8_t d[] = ", ccrsa_ctx_d(key));
95
96 printf("cc_size np = %lu;\n", cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))));
97 ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))), "uint8_t p[] = ",
98 cczp_prime(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))));
99 ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))) + 1, "uint8_t rp[] = ",
100 cczp_recip(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))));
101 printf("cc_size nq = %lu;\n", cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))));
102 ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))), "uint8_t q[] = ",
103 cczp_prime(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))));
104 ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))) + 1, "uint8_t rq[] = ",
105 cczp_recip(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))));
106 ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))), "uint8_t dp[] = ",
107 ccrsa_ctx_private_dp(ccrsa_ctx_private(key)));
108 ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))), "uint8_t dq[] = ",
109 ccrsa_ctx_private_dq(ccrsa_ctx_private(key)));
110 ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))), "uint8_t qinv[] = ",
111 ccrsa_ctx_private_qinv(ccrsa_ctx_private(key)));
112 printf("--\n");
113}
114
115void ccrsa_dump_public_key(ccrsa_pub_ctx_t key); // Suppress warning.
116void ccrsa_dump_public_key(ccrsa_pub_ctx_t key) {
117 ccn_cprint(ccrsa_ctx_n(key), "uint8_t m[] = ", ccrsa_ctx_m(key));
118 ccn_cprint(ccrsa_ctx_n(key) + 1, "uint8_t rm[] = ", cczp_recip(ccrsa_ctx_zm(key)));
119 ccn_cprint(ccrsa_ctx_n(key), "uint8_t e[] = ", ccrsa_ctx_e(key));
120
121 printf("--\n");
122}
123
124/*
125 *
126 * Public Key
127 *
128 */
129
130/* Public key static functions. */
131static void SecRSAPublicKeyDestroy(SecKeyRef key) {
132 /* Zero out the public key */
133 ccrsa_pub_ctx_t pubkey;
134 pubkey.pub = key->key;
135 cc_zero(ccrsa_pub_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(pubkey))), pubkey.pub);
136}
137
138#define cc_skip_zeros(size, ptr) { while (size > 0 && *ptr == 0) { ++ptr; --size; } }
139
140//
141// pubkey is initilaized with an n which is the maximum it can hold
142// We set the n to its correct value given m.
143//
144static int ccrsa_pub_init(ccrsa_pub_ctx_t pubkey,
145 size_t m_size, const uint8_t* m,
146 size_t e_size, const uint8_t* e)
147{
148 cc_skip_zeros(m_size, m);
149
150 cc_size nm = ccn_nof_size(m_size);
151 if (nm > ccrsa_ctx_n(pubkey))
152 return -1;
153
154 ccrsa_ctx_n(pubkey) = nm;
155
156 ccn_read_uint(nm, ccrsa_ctx_m(pubkey), m_size, m);
157 cczp_init(ccrsa_ctx_zm(pubkey));
158
159 return ccn_read_uint(nm, ccrsa_ctx_e(pubkey), e_size, e);
160}
161
162
163static OSStatus ccrsa_pub_decode(ccrsa_pub_ctx_t pubkey, size_t pkcs1_size, const uint8_t* pkcs1)
164{
165 OSStatus result = errSecParam;
166
167 DERItem keyItem = {(DERByte *)pkcs1, pkcs1_size};
168 DERRSAPubKeyPKCS1 decodedKey;
169
170 require_noerr_action(DERParseSequence(&keyItem,
171 DERNumRSAPubKeyPKCS1ItemSpecs, DERRSAPubKeyPKCS1ItemSpecs,
172 &decodedKey, sizeof(decodedKey)),
173 errOut, result = errSecDecode);
174
175 require_noerr(ccrsa_pub_init(pubkey,
176 decodedKey.modulus.length, decodedKey.modulus.data,
177 decodedKey.pubExponent.length, decodedKey.pubExponent.data),
178 errOut);
179
180 result = errSecSuccess;
181
182errOut:
183 return result;
184}
185
186static OSStatus ccrsa_pub_decode_apple(ccrsa_pub_ctx_t pubkey, size_t pkcs1_size, const uint8_t* pkcs1)
187{
188 OSStatus result = errSecParam;
189
190 DERItem keyItem = {(DERByte *)pkcs1, pkcs1_size};
191 DERRSAPubKeyApple decodedKey;
192
193 require_noerr_action(DERParseSequence(&keyItem,
194 DERNumRSAPubKeyAppleItemSpecs, DERRSAPubKeyAppleItemSpecs,
195 &decodedKey, sizeof(decodedKey)),
196 errOut, result = errSecDecode);
197
198 // We could honor the recipricol, but we don't think this is used enough to care.
199 // Don't bother exploding the below function to try to handle this case, it computes.
200
201 require_noerr(ccrsa_pub_init(pubkey,
202 decodedKey.modulus.length, decodedKey.modulus.data,
203 decodedKey.pubExponent.length, decodedKey.pubExponent.data),
204 errOut);
205
206 result = errSecSuccess;
207
208errOut:
209 return result;
210}
211
212
213static void ccasn_encode_int(cc_size n, const cc_unit*s, size_t s_size, uint8_t **buffer)
214{
215 **buffer = ASN1_INTEGER;
216 *buffer += 1;
217
218 DERSize itemLength = 4;
219 DEREncodeLength(s_size, *buffer, &itemLength);
220 *buffer += itemLength;
221
222 ccn_write_int(n, s, s_size, *buffer);
223
224 *buffer += s_size;
225}
226
227
228static OSStatus SecRSAPublicKeyInit(SecKeyRef key,
229 const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
230
231 OSStatus result = errSecParam;
232
233 ccrsa_pub_ctx_t pubkey;
234 pubkey.pub = key->key;
235
236 // Set maximum size for parsers
237 ccrsa_ctx_n(pubkey) = ccn_nof(kMaximumRSAKeyBits);
238
239 switch (encoding) {
240 case kSecKeyEncodingBytes: // Octets is PKCS1
241 case kSecKeyEncodingPkcs1:
242 result = ccrsa_pub_decode(pubkey, keyDataLength, keyData);
243 break;
244 case kSecKeyEncodingApplePkcs1:
245 result = ccrsa_pub_decode_apple(pubkey, keyDataLength, keyData);
246 break;
247 case kSecKeyEncodingRSAPublicParams:
248 {
249 SecRSAPublicKeyParams *params = (SecRSAPublicKeyParams *)keyData;
250
251 require_noerr(ccrsa_pub_init(pubkey,
252 params->modulusLength, params->modulus,
253 params->exponentLength, params->exponent), errOut);
254
255 result = errSecSuccess;
256 break;
257 }
258 case kSecExtractPublicFromPrivate:
259 {
260 ccrsa_full_ctx_t fullKey;
261 fullKey.full = (ccrsa_full_ctx*) keyData;
262
263 cc_size fullKeyN = ccrsa_ctx_n(fullKey);
264 require(fullKeyN <= ccrsa_ctx_n(pubkey), errOut);
265 memcpy(pubkey.pub, ccrsa_ctx_public(fullKey).pub, ccrsa_pub_ctx_size(ccn_sizeof_n(fullKeyN)));
266 result = errSecSuccess;
267 break;
268 }
269 default:
270 break;
271 }
272
273errOut:
274 return result;
275}
276
277static OSStatus SecRSAPublicKeyRawVerify(SecKeyRef key, SecPadding padding,
278 const uint8_t *signedData, size_t signedDataLen,
279 const uint8_t *sig, size_t sigLen) {
280 OSStatus result = errSSLCrypto;
281
282 ccrsa_pub_ctx_t pubkey;
283 pubkey.pub = key->key;
284
285 cc_unit s[ccrsa_ctx_n(pubkey)];
286
287 ccn_read_uint(ccrsa_ctx_n(pubkey), s, sigLen, sig);
288 ccrsa_pub_crypt(pubkey, s, s);
289 ccn_swap(ccrsa_ctx_n(pubkey), s);
290
291 const uint8_t* sBytes = (uint8_t*) s;
292 const uint8_t* sEnd = (uint8_t*) (s + ccrsa_ctx_n(pubkey));
293
294 switch (padding) {
295 case kSecPaddingNone:
296 // Skip leading zeros as long as s is bigger than signedData.
297 while (((ptrdiff_t)signedDataLen < (sEnd - sBytes)) && (*sBytes == 0))
298 ++sBytes;
299 break;
300
301 case kSecPaddingPKCS1:
302 {
303 // Verify and skip PKCS1 padding:
304 //
305 // 0x00, 0x01 (RSA_PKCS1_PAD_SIGN), 0xFF .. 0x00, signedData
306 //
307 size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
308 size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(pubkey)) - m_size;
309
310 while (prefix_zeros--)
311 require_quiet(*sBytes++ == 0x00, errOut);
312
313 require_quiet(*sBytes++ == 0x00, errOut);
314 require_quiet(*sBytes++ == RSA_PKCS1_PAD_SIGN, errOut);
315
316 while (*sBytes == 0xFF) {
317 require_quiet(++sBytes < sEnd, errOut);
318 }
319 // Required to have at least 8 0xFFs
320 require_quiet((sBytes - (uint8_t*)s) - 2 >= 8, errOut);
321
322 require_quiet(*sBytes == 0x00, errOut);
323 require_quiet(++sBytes < sEnd, errOut);
324 break;
325 }
326 case kSecPaddingOAEP:
327 result = errSecParam;
328 goto errOut;
329
330 default:
331 result = errSecUnimplemented;
332 goto errOut;
333 }
334
335 // Compare the rest.
336 require_quiet((sEnd - sBytes) == (ptrdiff_t)signedDataLen, errOut);
337 require_quiet(memcmp(sBytes, signedData, signedDataLen) == 0, errOut);
338
339 result = errSecSuccess;
340
341errOut:
342 cc_zero(ccrsa_ctx_n(pubkey), s);
343
344 return result;
345}
346
347static OSStatus SecRSAPublicKeyRawEncrypt(SecKeyRef key, SecPadding padding,
348 const uint8_t *plainText, size_t plainTextLen,
349 uint8_t *cipherText, size_t *cipherTextLen) {
350 OSStatus result = errSecParam;
351 ccrsa_pub_ctx_t pubkey;
352 pubkey.pub = key->key;
353
354 cc_unit s[ccrsa_ctx_n(pubkey)];
355 const size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
356
357 require(cipherTextLen, errOut);
358 require(*cipherTextLen >= m_size, errOut);
359
360 uint8_t* sBytes = (uint8_t*) s;
361
362 switch (padding) {
363 case kSecPaddingNone:
364 require_noerr_quiet(ccn_read_uint(ccrsa_ctx_n(pubkey), s, plainTextLen, plainText), errOut);
365 require_quiet(ccn_cmp(ccrsa_ctx_n(pubkey), s, ccrsa_ctx_m(pubkey)) < 0, errOut);
366 break;
367
368 case kSecPaddingPKCS1:
369 {
370 // Create PKCS1 padding:
371 //
372 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
373 //
374 const int kMinimumPadding = 1 + 1 + 8 + 1;
375
376 require_quiet(plainTextLen < m_size - kMinimumPadding, errOut);
377
378 size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(pubkey)) - m_size;
379
380 while (prefix_zeros--)
381 *sBytes++ = 0x00;
382
383 size_t pad_size = m_size - plainTextLen;
384
385 *sBytes++ = 0x00;
386 *sBytes++ = RSA_PKCS1_PAD_ENCRYPT;
387
388 ccrng_generate(ccrng_seckey, pad_size - 3, sBytes);
389 // Remove zeroes from the random pad
390
391 const uint8_t* sEndOfPad = sBytes + (pad_size - 3);
392 while (sBytes < sEndOfPad)
393 {
394 if (*sBytes == 0x00)
395 *sBytes = 0xFF; // Michael said 0xFF was good enough.
396
397 ++sBytes;
398 }
399
400 *sBytes++ = 0x00;
401
402 memcpy(sBytes, plainText, plainTextLen);
403
404 ccn_swap(ccrsa_ctx_n(pubkey), s);
405 break;
406 }
407 case kSecPaddingOAEP:
408 {
409 const struct ccdigest_info* di = ccsha1_di();
410
411 const size_t encodingOverhead = 2 + 2 * di->output_size;
412
413 require_action(m_size > encodingOverhead, errOut, result = errSecParam);
414 require_action_quiet(plainTextLen < m_size - encodingOverhead, errOut, result = errSSLCrypto);
415
416 require_noerr_action(ccrsa_oaep_encode(di,
417 ccrng_seckey,
418 m_size, s,
419 plainTextLen, plainText), errOut, result = errSecInternal);
420 break;
421 }
422 default:
423 goto errOut;
424 }
425
426
427 ccrsa_pub_crypt(pubkey, s, s);
428
429 ccn_write_uint_padded(ccrsa_ctx_n(pubkey), s, m_size, cipherText);
430 *cipherTextLen = m_size;
431
432 result = errSecSuccess;
433
434errOut:
435 ccn_zero(ccrsa_ctx_n(pubkey), s);
436 return result;
437}
438
439static OSStatus SecRSAPublicKeyRawDecrypt(SecKeyRef key, SecPadding padding,
440 const uint8_t *cipherText, size_t cipherTextLen, uint8_t *plainText, size_t *plainTextLen) {
441 OSStatus result = errSSLCrypto;
442
443 ccrsa_pub_ctx_t pubkey;
444 pubkey.pub = key->key;
445
446 cc_unit s[ccrsa_ctx_n(pubkey)];
447
448 require_action_quiet(cipherText != NULL, errOut, result = errSecParam);
449 require_action_quiet(plainText != NULL, errOut, result = errSecParam);
450 require_action_quiet(plainTextLen != NULL, errOut, result = errSecParam);
451
452 ccn_read_uint(ccrsa_ctx_n(pubkey), s, cipherTextLen, cipherText);
453 ccrsa_pub_crypt(pubkey, s, s);
454 ccn_swap(ccrsa_ctx_n(pubkey), s);
455
456 const uint8_t* sBytes = (uint8_t*) s;
457 const uint8_t* sEnd = (uint8_t*) (s + ccrsa_ctx_n(pubkey));
458
459 switch (padding) {
460 case kSecPaddingNone:
461 // Skip leading zeros
462 // We return the bytes for a number and
463 // trim leading zeroes
464 while (sBytes < sEnd && *sBytes == 0x00)
465 ++sBytes;
466 break;
467
468 case kSecPaddingPKCS1:
469 {
470 // Verify and skip PKCS1 padding:
471 //
472 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
473 //
474 size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
475 size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(pubkey)) - m_size;
476
477 while (prefix_zeros--)
478 require_quiet(*sBytes++ == 0x00, errOut);
479
480 require_quiet(*sBytes++ == 0x00, errOut);
481 require_quiet(*sBytes++ == RSA_PKCS1_PAD_ENCRYPT, errOut);
482
483 while (*sBytes != 0x00) {
484 require_quiet(++sBytes < sEnd, errOut);
485 }
486 // Required to have at least 8 0xFFs
487 require_quiet((sBytes - (uint8_t*)s) - 2 >= 8, errOut);
488
489 require_quiet(*sBytes == 0x00, errOut);
490 require_quiet(++sBytes < sEnd, errOut);
491
492 break;
493 }
494 case kSecPaddingOAEP:
495 result = errSecParam;
496 default:
497 goto errOut;
498 }
499
500 // Return the rest.
501 require_action((sEnd - sBytes) <= (ptrdiff_t)*plainTextLen, errOut, result = errSecParam);
502
503 *plainTextLen = sEnd - sBytes;
504 memcpy(plainText, sBytes, *plainTextLen);
505
506 result = errSecSuccess;
507
508errOut:
509 ccn_zero(ccrsa_ctx_n(pubkey), s);
510
511 return result;
512}
513
514static size_t SecRSAPublicKeyBlockSize(SecKeyRef key) {
515 ccrsa_pub_ctx_t pubkey;
516 pubkey.pub = key->key;
517
518 return ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
519}
520
521
522static CFDataRef SecRSAPublicKeyCreatePKCS1(CFAllocatorRef allocator, ccrsa_pub_ctx_t pubkey)
523{
524 size_t m_size = ccn_write_int_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
525 size_t e_size = ccn_write_int_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey));
526
527 const size_t seq_size = DERLengthOfItem(ASN1_INTEGER, m_size) +
528 DERLengthOfItem(ASN1_INTEGER, e_size);
529
530 const size_t result_size = DERLengthOfItem(ASN1_SEQUENCE, seq_size);
531
532 CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size);
533
534 if (pkcs1 == NULL)
535 return NULL;
536
537 CFDataSetLength(pkcs1, result_size);
538
539 uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1);
540
541 *bytes++ = ASN1_CONSTR_SEQUENCE;
542
543 DERSize itemLength = 4;
544 DEREncodeLength(seq_size, bytes, &itemLength);
545 bytes += itemLength;
546
547 ccasn_encode_int(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), m_size, &bytes);
548 ccasn_encode_int(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey), e_size, &bytes);
549
550 return pkcs1;
551}
552
553static OSStatus SecRSAPublicKeyCopyPublicSerialization(SecKeyRef key, CFDataRef* serialized)
554{
555 ccrsa_pub_ctx_t pubkey;
556 pubkey.pub = key->key;
557
558 CFAllocatorRef allocator = CFGetAllocator(key);
559 *serialized = SecRSAPublicKeyCreatePKCS1(allocator, pubkey);
560
561 if (NULL == *serialized)
562 return errSecDecode;
563 else
564 return errSecSuccess;
565}
566
567static CFDictionaryRef SecRSAPublicKeyCopyAttributeDictionary(SecKeyRef key) {
568 return SecKeyGeneratePublicAttributeDictionary(key, kSecAttrKeyTypeRSA);
569}
570
571SecKeyDescriptor kSecRSAPublicKeyDescriptor = {
572 kSecKeyDescriptorVersion,
573 "RSAPublicKey",
574 ccrsa_pub_ctx_size(kMaximumRSAKeyBytes), /* extraBytes */
575 SecRSAPublicKeyInit,
576 SecRSAPublicKeyDestroy,
577 NULL, /* SecKeyRawSignMethod */
578 SecRSAPublicKeyRawVerify,
579 SecRSAPublicKeyRawEncrypt,
580 SecRSAPublicKeyRawDecrypt,
581 NULL, /* SecKeyComputeMethod */
582 SecRSAPublicKeyBlockSize,
583 SecRSAPublicKeyCopyAttributeDictionary,
584 NULL,
585 SecRSAPublicKeyCopyPublicSerialization,
586};
587
588/* Public Key API functions. */
589SecKeyRef SecKeyCreateRSAPublicKey(CFAllocatorRef allocator,
590 const uint8_t *keyData, CFIndex keyDataLength,
591 SecKeyEncoding encoding) {
592 return SecKeyCreate(allocator, &kSecRSAPublicKeyDescriptor, keyData,
593 keyDataLength, encoding);
594}
595
596CFDataRef SecKeyCopyModulus(SecKeyRef key) {
597 ccrsa_pub_ctx_t pubkey;
598 pubkey.pub = key->key;
599
600 size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
601
602 CFAllocatorRef allocator = CFGetAllocator(key);
603 CFMutableDataRef modulusData = CFDataCreateMutable(allocator, m_size);
604
605 if (modulusData == NULL)
606 return NULL;
607
608 CFDataSetLength(modulusData, m_size);
609
610 ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), m_size, CFDataGetMutableBytePtr(modulusData));
611
612 return modulusData;
613}
614
615CFDataRef SecKeyCopyExponent(SecKeyRef key) {
616 ccrsa_pub_ctx_t pubkey;
617 pubkey.pub = key->key;
618
619 size_t e_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey));
620
621 CFAllocatorRef allocator = CFGetAllocator(key);
622 CFMutableDataRef exponentData = CFDataCreateMutable(allocator, e_size);
623
624 if (exponentData == NULL)
625 return NULL;
626
627 CFDataSetLength(exponentData, e_size);
628
629 ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), e_size, CFDataGetMutableBytePtr(exponentData));
630
631 return exponentData;
632}
633
634
635/*
636 *
637 * Private Key
638 *
639 */
640
641/* Private key static functions. */
642static void SecRSAPrivateKeyDestroy(SecKeyRef key) {
643 /* Zero out the public key */
644 ccrsa_full_ctx_t fullkey;
645 fullkey.full = key->key;
646 cc_zero(ccrsa_full_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(fullkey))), fullkey.full);
647}
648
649static int ccrsa_priv_init(ccrsa_priv_ctx_t privkey,
650 size_t p_size, const uint8_t* p,
651 size_t q_size, const uint8_t* q,
652 size_t dp_size, const uint8_t* dp,
653 size_t dq_size, const uint8_t* dq,
654 size_t qinv_size, const uint8_t* qinv)
655{
656 int result = -1;
657
658 const cc_size np = cczp_n(ccrsa_ctx_private_zp(privkey));
659 cc_size nq = cczp_n(ccrsa_ctx_private_zq(privkey));
660
661 if (ccn_read_uint(np, CCZP_PRIME(ccrsa_ctx_private_zp(privkey)), p_size, p))
662 goto errOut;
663 cczp_init(ccrsa_ctx_private_zp(privkey));
664 if (ccn_read_uint(np, ccrsa_ctx_private_dp(privkey), dp_size, dp))
665 goto errOut;
666 if (ccn_read_uint(np, ccrsa_ctx_private_qinv(privkey), qinv_size, qinv))
667 goto errOut;
668
669 if (ccn_read_uint(nq, CCZP_PRIME(ccrsa_ctx_private_zq(privkey)), q_size, q))
670 goto errOut;
671
672 nq = ccn_n(nq, cczp_prime(ccrsa_ctx_private_zq(privkey)));
673 CCZP_N(ccrsa_ctx_private_zq(privkey)) = nq;
674
675 cczp_init(ccrsa_ctx_private_zq(privkey));
676 if (ccn_read_uint(nq, ccrsa_ctx_private_dq(privkey), dq_size, dq))
677 goto errOut;
678
679 result = 0;
680
681errOut:
682 return result;
683}
684
685
686static OSStatus ccrsa_full_decode(ccrsa_full_ctx_t fullkey, size_t pkcs1_size, const uint8_t* pkcs1)
687{
688 OSStatus result = errSecParam;
689
690 DERItem keyItem = {(DERByte *)pkcs1, pkcs1_size};
691 DERRSAKeyPair decodedKey;
692
693 require_noerr_action(DERParseSequence(&keyItem,
694 DERNumRSAKeyPairItemSpecs, DERRSAKeyPairItemSpecs,
695 &decodedKey, sizeof(decodedKey)),
696 errOut, result = errSecDecode);
697
698 require_noerr(ccrsa_pub_init(fullkey,
699 decodedKey.n.length, decodedKey.n.data,
700 decodedKey.e.length, decodedKey.e.data),
701 errOut);
702 ccn_read_uint(ccrsa_ctx_n(fullkey), ccrsa_ctx_d(fullkey),
703 decodedKey.d.length, decodedKey.d.data);
704 {
705 ccrsa_priv_ctx_t privkey = ccrsa_ctx_private(fullkey);
706 CCZP_N(ccrsa_ctx_private_zp(privkey)) = ccn_nof((ccn_bitsof_n(ccrsa_ctx_n(fullkey)) / 2) + 1);
707 CCZP_N(ccrsa_ctx_private_zq(privkey)) = cczp_n(ccrsa_ctx_private_zp(privkey));
708
709 // TODO: Actually remember decodedKey.d.
710
711 require_noerr(ccrsa_priv_init(privkey,
712 decodedKey.p.length, decodedKey.p.data,
713 decodedKey.q.length, decodedKey.q.data,
714 decodedKey.dp.length, decodedKey.dp.data,
715 decodedKey.dq.length, decodedKey.dq.data,
716 decodedKey.qInv.length, decodedKey.qInv.data),
717 errOut);
718 }
719
720 result = errSecSuccess;
721
722errOut:
723 return result;
724}
725
726static OSStatus SecRSAPrivateKeyInit(SecKeyRef key,
727 const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
728 OSStatus result = errSecParam;
729
730 ccrsa_full_ctx_t fullkey;
731 fullkey.full = key->key;
732
733 // Set maximum size for parsers
734 ccrsa_ctx_n(fullkey) = ccn_nof(kMaximumRSAKeyBits);
735
736 switch (encoding) {
737 case kSecKeyEncodingBytes: // Octets is PKCS1
738 case kSecKeyEncodingPkcs1:
739 result = ccrsa_full_decode(fullkey, keyDataLength, keyData);
740 break;
741 case kSecGenerateKey:
742 {
743 CFDictionaryRef parameters = (CFDictionaryRef) keyData;
744
745 CFTypeRef ksize = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits);
746 CFIndex keyLengthInBits = getIntValue(ksize);
747
748 if (keyLengthInBits < 256 || keyLengthInBits > kMaximumRSAKeyBits) {
749 secwarning("Invalid or missing key size in: %@", parameters);
750 return errSecKeySizeNotAllowed;
751 }
752
753 /* TODO: Add support for kSecPublicExponent parameter. */
754 static uint8_t e[] = { 0x01, 0x00, 0x01 }; // Default is 65537
755 if (!ccrsa_generate_key(keyLengthInBits, fullkey.full, sizeof(e), e, ccrng_seckey))
756 result = errSecSuccess;
757 break;
758 }
759 default:
760 break;
761 }
762
763 return result;
764}
765
766static OSStatus SecRSAPrivateKeyRawSign(SecKeyRef key, SecPadding padding,
767 const uint8_t *dataToSign, size_t dataToSignLen,
768 uint8_t *sig, size_t *sigLen) {
769
770 OSStatus result = errSecParam;
771
772 ccrsa_full_ctx_t fullkey;
773 fullkey.full = key->key;
774
775 size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey));
776 cc_unit s[ccrsa_ctx_n(fullkey)];
777
778 uint8_t* sBytes = (uint8_t*) s;
779
780 require(sigLen, errOut);
781 require(*sigLen >= m_size, errOut);
782
783 switch (padding) {
784 case kSecPaddingNone:
785 require_noerr_quiet(ccn_read_uint(ccrsa_ctx_n(fullkey), s, dataToSignLen, dataToSign), errOut);
786 require_quiet(ccn_cmp(ccrsa_ctx_n(fullkey), s, ccrsa_ctx_m(fullkey)) < 0, errOut);
787 break;
788
789 case kSecPaddingPKCS1:
790 {
791 // Create PKCS1 padding:
792 //
793 // 0x00, 0x01 (RSA_PKCS1_PAD_SIGN), 0xFF .. 0x00, signedData
794 //
795 const int kMinimumPadding = 1 + 1 + 8 + 1;
796
797 require(dataToSignLen < m_size - kMinimumPadding, errOut);
798
799 size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(fullkey)) - m_size;
800
801 while (prefix_zeros--)
802 *sBytes++ = 0x00;
803
804 size_t pad_size = m_size - dataToSignLen;
805
806 *sBytes++ = 0x00;
807 *sBytes++ = RSA_PKCS1_PAD_SIGN;
808
809 size_t ff_size;
810 for(ff_size = pad_size - 3; ff_size > 0; --ff_size)
811 *sBytes++ = 0xFF;
812
813 *sBytes++ = 0x00;
814
815 // Get the user data into s looking like a ccn.
816 memcpy(sBytes, dataToSign, dataToSignLen);
817 ccn_swap(ccrsa_ctx_n(fullkey), s);
818
819 break;
820 }
821 case kSecPaddingOAEP:
822 result = errSecParam;
823 default:
824 goto errOut;
825 }
826
827 ccrsa_priv_crypt(ccrsa_ctx_private(fullkey), s, s);
828
829 // Pad with leading zeros to fit in modulus size
830 ccn_write_uint_padded(ccrsa_ctx_n(fullkey), s, m_size, sig);
831 *sigLen = m_size;
832
833 result = errSecSuccess;
834
835errOut:
836 ccn_zero(ccrsa_ctx_n(fullkey), s);
837 return result;
838}
839
840static OSStatus SecRSAPrivateKeyRawDecrypt(SecKeyRef key, SecPadding padding,
841 const uint8_t *cipherText, size_t cipherTextLen,
842 uint8_t *plainText, size_t *plainTextLen) {
843 OSStatus result = errSSLCrypto;
844
845 ccrsa_full_ctx_t fullkey;
846 fullkey.full = key->key;
847
848 size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey));
849
850 cc_unit s[ccrsa_ctx_n(fullkey)];
851 uint8_t recoveredData[ccn_sizeof_n(ccrsa_ctx_n(fullkey))];
852
853 ccn_read_uint(ccrsa_ctx_n(fullkey), s, cipherTextLen, cipherText);
854 ccrsa_priv_crypt(ccrsa_ctx_private(fullkey), s, s);
855
856 const uint8_t* sBytes = (uint8_t*) s;
857 const uint8_t* sEnd = (uint8_t*) (s + ccrsa_ctx_n(fullkey));
858
859 require(plainTextLen, errOut);
860
861 switch (padding) {
862 case kSecPaddingNone:
863 ccn_swap(ccrsa_ctx_n(fullkey), s);
864 // Skip Zeros since our contract is to do so.
865 while (sBytes < sEnd && *sBytes == 0x00)
866 ++sBytes;
867 break;
868
869 case kSecPaddingPKCS1:
870 {
871 ccn_swap(ccrsa_ctx_n(fullkey), s);
872 // Verify and skip PKCS1 padding:
873 //
874 // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
875 //
876
877 size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(fullkey)) - m_size;
878
879 while (prefix_zeros--)
880 require_quiet(*sBytes++ == 0x00, errOut);
881
882 require_quiet(*sBytes++ == 0x00, errOut);
883 require_quiet(*sBytes++ == RSA_PKCS1_PAD_ENCRYPT, errOut);
884
885 while (*sBytes != 0x00) {
886 require_quiet(++sBytes < sEnd, errOut);
887 }
888 // Required to have at least 8 non-zeros
889 require_quiet((sBytes - (uint8_t*)s) - 2 >= 8, errOut);
890
891 require_quiet(*sBytes == 0x00, errOut);
892 require_quiet(++sBytes < sEnd, errOut);
893 break;
894 }
895 case kSecPaddingOAEP:
896 {
897 size_t length = sizeof(recoveredData);
898
899 require_noerr_quiet(ccrsa_oaep_decode(ccsha1_di(),
900 ccn_write_uint_size(ccrsa_ctx_n(fullkey),ccrsa_ctx_m(fullkey)), s,
901 &length, recoveredData), errOut);
902
903 sBytes = recoveredData;
904 sEnd = recoveredData + length;
905 break;
906 }
907 default:
908 goto errOut;
909 }
910
911 require((sEnd - sBytes) <= (ptrdiff_t)*plainTextLen, errOut);
912 *plainTextLen = sEnd - sBytes;
913 memcpy(plainText, sBytes, *plainTextLen);
914
915 result = errSecSuccess;
916
917errOut:
918 bzero(recoveredData, sizeof(recoveredData));
919 ccn_zero(ccrsa_ctx_n(fullkey), s);
920
921 return result;
922}
923
924static size_t SecRSAPrivateKeyBlockSize(SecKeyRef key) {
925 ccrsa_full_ctx_t fullkey;
926 fullkey.full = key->key;
927
928 return ccn_write_uint_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey));
929}
930
931static CFDataRef SecRSAPrivateKeyCreatePKCS1(CFAllocatorRef allocator, ccrsa_full_ctx_t fullkey)
932{
933 ccrsa_priv_ctx_t privkey = ccrsa_ctx_private(fullkey);
934
935 const cc_size np = cczp_n(ccrsa_ctx_private_zp(privkey));
936 const cc_size nq = cczp_n(ccrsa_ctx_private_zq(privkey));
937
938 size_t m_size = ccn_write_int_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey));
939 size_t e_size = ccn_write_int_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_e(fullkey));
940 size_t d_size = ccn_write_int_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_d(fullkey));
941
942 size_t p_size = ccn_write_int_size(np, cczp_prime(ccrsa_ctx_private_zp(privkey)));
943 size_t q_size = ccn_write_int_size(nq, cczp_prime(ccrsa_ctx_private_zq(privkey)));
944
945 size_t dp_size = ccn_write_int_size(np, ccrsa_ctx_private_dp(privkey));
946 size_t dq_size = ccn_write_int_size(nq, ccrsa_ctx_private_dq(privkey));
947
948 size_t qinv_size = ccn_write_int_size(np, ccrsa_ctx_private_qinv(privkey));
949
950 const size_t seq_size = 3 +
951 DERLengthOfItem(ASN1_INTEGER, m_size) +
952 DERLengthOfItem(ASN1_INTEGER, e_size) +
953 DERLengthOfItem(ASN1_INTEGER, d_size) +
954 DERLengthOfItem(ASN1_INTEGER, p_size) +
955 DERLengthOfItem(ASN1_INTEGER, q_size) +
956 DERLengthOfItem(ASN1_INTEGER, dp_size) +
957 DERLengthOfItem(ASN1_INTEGER, dq_size) +
958 DERLengthOfItem(ASN1_INTEGER, qinv_size);
959
960 const size_t result_size = DERLengthOfItem(ASN1_SEQUENCE, seq_size);
961
962 CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size);
963
964 if (pkcs1 == NULL)
965 return NULL;
966
967 CFDataSetLength(pkcs1, result_size);
968
969 uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1);
970
971 *bytes++ = ASN1_CONSTR_SEQUENCE;
972
973 DERSize itemLength = 4;
974 DEREncodeLength(seq_size, bytes, &itemLength);
975 bytes += itemLength;
976
977 *bytes++ = ASN1_INTEGER;
978 *bytes++ = 0x01;
979 *bytes++ = 0x00;
980
981 ccasn_encode_int(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey), m_size, &bytes);
982 ccasn_encode_int(ccrsa_ctx_n(fullkey), ccrsa_ctx_e(fullkey), e_size, &bytes);
983 ccasn_encode_int(ccrsa_ctx_n(fullkey), ccrsa_ctx_d(fullkey), d_size, &bytes);
984
985 ccasn_encode_int(np, cczp_prime(ccrsa_ctx_private_zp(privkey)), p_size, &bytes);
986 ccasn_encode_int(nq, cczp_prime(ccrsa_ctx_private_zq(privkey)), q_size, &bytes);
987 ccasn_encode_int(np, ccrsa_ctx_private_dp(privkey), dp_size, &bytes);
988 ccasn_encode_int(nq, ccrsa_ctx_private_dq(privkey), dq_size, &bytes);
989 ccasn_encode_int(np, ccrsa_ctx_private_qinv(privkey), qinv_size, &bytes);
990
991 return pkcs1;
992}
993
994static CFDataRef SecRSAPrivateKeyCopyPKCS1(SecKeyRef key)
995{
996 ccrsa_full_ctx_t fullkey;
997 fullkey.full = key->key;
998
999 CFAllocatorRef allocator = CFGetAllocator(key);
1000 return SecRSAPrivateKeyCreatePKCS1(allocator, fullkey);
1001}
1002
1003static OSStatus SecRSAPrivateKeyCopyPublicSerialization(SecKeyRef key, CFDataRef* serialized)
1004{
1005 ccrsa_full_ctx_t fullkey;
1006 fullkey.full = key->key;
1007
1008 CFAllocatorRef allocator = CFGetAllocator(key);
1009 *serialized = SecRSAPublicKeyCreatePKCS1(allocator, fullkey);
1010
1011 if (NULL == *serialized)
1012 return errSecDecode;
1013 else
1014 return errSecSuccess;
1015}
1016
1017
1018static CFDictionaryRef SecRSAPrivateKeyCopyAttributeDictionary(SecKeyRef key) {
1019 CFDictionaryRef dict = NULL;
1020 CFDataRef fullKeyBlob = NULL;
1021
1022 /* PKCS1 encode the key pair. */
1023 fullKeyBlob = SecRSAPrivateKeyCopyPKCS1(key);
1024 require(fullKeyBlob, errOut);
1025
1026 dict = SecKeyGeneratePrivateAttributeDictionary(key, kSecAttrKeyTypeRSA, fullKeyBlob);
1027
1028errOut:
1029 CFReleaseSafe(fullKeyBlob);
1030
1031 return dict;
1032}
1033
1034SecKeyDescriptor kSecRSAPrivateKeyDescriptor = {
1035 kSecKeyDescriptorVersion,
1036 "RSAPrivateKey",
1037 ccrsa_full_ctx_size(kMaximumRSAKeyBytes), /* extraBytes */
1038 SecRSAPrivateKeyInit,
1039 SecRSAPrivateKeyDestroy,
1040 SecRSAPrivateKeyRawSign,
1041 NULL, /* SecKeyRawVerifyMethod */
1042 NULL, /* SecKeyEncryptMethod */
1043 SecRSAPrivateKeyRawDecrypt,
1044 NULL, /* SecKeyComputeMethod */
1045 SecRSAPrivateKeyBlockSize,
1046 SecRSAPrivateKeyCopyAttributeDictionary,
1047 NULL,
1048 SecRSAPrivateKeyCopyPublicSerialization,
1049};
1050
1051/* Private Key API functions. */
1052SecKeyRef SecKeyCreateRSAPrivateKey(CFAllocatorRef allocator,
1053 const uint8_t *keyData, CFIndex keyDataLength,
1054 SecKeyEncoding encoding) {
1055 return SecKeyCreate(allocator, &kSecRSAPrivateKeyDescriptor, keyData,
1056 keyDataLength, encoding);
1057}
1058
1059
1060OSStatus SecRSAKeyGeneratePair(CFDictionaryRef parameters,
1061 SecKeyRef *rsaPublicKey, SecKeyRef *rsaPrivateKey) {
1062 OSStatus status = errSecParam;
1063
1064 CFAllocatorRef allocator = NULL; /* @@@ get from parameters. */
1065
1066 SecKeyRef pubKey = NULL;
1067 SecKeyRef privKey = SecKeyCreate(allocator, &kSecRSAPrivateKeyDescriptor,
1068 (const void*) parameters, 0, kSecGenerateKey);
1069
1070 require(privKey, errOut);
1071
1072 /* Create SecKeyRef's from the pkcs1 encoded keys. */
1073 pubKey = SecKeyCreate(allocator, &kSecRSAPublicKeyDescriptor,
1074 privKey->key, 0, kSecExtractPublicFromPrivate);
1075
1076 require(pubKey, errOut);
1077
1078 if (rsaPublicKey) {
1079 *rsaPublicKey = pubKey;
1080 pubKey = NULL;
1081 }
1082 if (rsaPrivateKey) {
1083 *rsaPrivateKey = privKey;
1084 privKey = NULL;
1085 }
1086
1087 status = errSecSuccess;
1088
1089errOut:
1090 CFReleaseSafe(pubKey);
1091 CFReleaseSafe(privKey);
1092
1093 return status;
1094}