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