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 <Security/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 // 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 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 *. 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. 263 result = CFDataCreateMutableWithScratch(NULL, bufferSize); 264 ccerr = ccrsa_pub_crypt(pubkey, (cc_unit *)CFDataGetMutableBytePtr((CFMutableDataRef)result), 265 (const cc_unit *)CFDataGetBytePtr(in1)); 266 } 267 break; 268 case kSecKeyOperationTypeDecrypt: 269 if (mode == kSecKeyOperationModePerform) { 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 277 // Decrypt into output buffer. 278 result = CFDataCreateMutableWithScratch(NULL, bufferSize); 279 ccerr = ccrsa_pub_crypt(pubkey, (cc_unit *)CFDataGetMutableBytePtr((CFMutableDataRef)result), 280 (const cc_unit *)CFDataGetBytePtr(in1)); 281 } 282 break; 283 default: 284 result = kCFNull; 285 break; 286 } 287 288 require_noerr_action_quiet(ccerr, out, (CFReleaseNull(result), 289 SecError(errSecParam, error, CFSTR("rsa_pub_crypt failed, ccerr=%d"), ccerr))); 290 out: 291 return result; 292 } 293 294 static size_t SecRSAPublicKeyBlockSize(SecKeyRef key) { 295 ccrsa_pub_ctx_t pubkey = key->key; 296 return ccrsa_block_size(pubkey); 297 } 298 299 300 static 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)); 304 305 const size_t seq_size = DERLengthOfItem(ASN1_INTEGER, m_size) + 306 DERLengthOfItem(ASN1_INTEGER, e_size); 307 308 const size_t result_size = DERLengthOfItem(ASN1_SEQUENCE, seq_size); 309 310 CFMutableDataRef pkcs1 = CFDataCreateMutableWithScratch(allocator, result_size); 311 uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1); 312 313 *bytes++ = ONE_BYTE_ASN1_CONSTR_SEQUENCE; 314 315 DERSize itemLength = 4; 316 DEREncodeLength(seq_size, bytes, &itemLength); 317 bytes += itemLength; 318 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); 321 322 return pkcs1; 323 } 324 325 static OSStatus SecRSAPublicKeyCopyPublicSerialization(SecKeyRef key, CFDataRef* serialized) 326 { 327 ccrsa_pub_ctx_t pubkey = key->key; 328 329 CFAllocatorRef allocator = CFGetAllocator(key); 330 *serialized = SecRSAPublicKeyCreatePKCS1(allocator, pubkey); 331 332 if (NULL == *serialized) 333 return errSecDecode; 334 else 335 return errSecSuccess; 336 } 337 338 static CFDictionaryRef SecRSAPublicKeyCopyAttributeDictionary(SecKeyRef key) { 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 347 static CFDataRef SecRSAPublicKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) { 348 ccrsa_pub_ctx_t pubkey = key->key; 349 return SecRSAPublicKeyCreatePKCS1(CFGetAllocator(key), pubkey); 350 } 351 352 static CFStringRef SecRSAPublicKeyCopyDescription(SecKeyRef key) { 353 354 CFStringRef keyDescription = NULL; 355 CFDataRef modRef = SecKeyCopyModulus(key); 356 357 ccrsa_pub_ctx_t pubkey = key->key; 358 359 CFStringRef modulusString = CFDataCopyHexString(modRef); 360 require_quiet(modulusString, fail); 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 364 fail: 365 CFReleaseSafe(modRef); 366 CFReleaseSafe(modulusString); 367 if(!keyDescription) 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 370 return keyDescription; 371 } 372 373 SecKeyDescriptor kSecRSAPublicKeyDescriptor = { 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, 385 }; 386 387 /* Public Key API functions. */ 388 SecKeyRef SecKeyCreateRSAPublicKey_ios(CFAllocatorRef allocator, 389 const uint8_t *keyData, CFIndex keyDataLength, 390 SecKeyEncoding encoding) { 391 return SecKeyCreate(allocator, &kSecRSAPublicKeyDescriptor, keyData, 392 keyDataLength, encoding); 393 } 394 395 SecKeyRef SecKeyCreateRSAPublicKey(CFAllocatorRef allocator, 396 const uint8_t *keyData, CFIndex keyDataLength, 397 SecKeyEncoding encoding) { 398 return SecKeyCreateRSAPublicKey_ios(allocator, keyData, 399 keyDataLength, encoding); 400 } 401 402 CFDataRef SecKeyCopyModulus(SecKeyRef key) { 403 CFDataRef modulus = NULL; 404 if (key->key_class == &kSecRSAPublicKeyDescriptor) { 405 ccrsa_pub_ctx_t pubkey = key->key; 406 407 size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey)); 408 409 CFAllocatorRef allocator = CFGetAllocator(key); 410 CFMutableDataRef modulusData = CFDataCreateMutable(allocator, m_size); 411 412 if (modulusData == NULL) 413 return NULL; 414 415 CFDataSetLength(modulusData, m_size); 416 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 } 426 427 return modulus; 428 } 429 430 CFDataRef SecKeyCopyExponent(SecKeyRef key) { 431 CFDataRef exponent = NULL; 432 if (key->key_class == &kSecRSAPublicKeyDescriptor) { 433 ccrsa_pub_ctx_t pubkey = key->key; 434 435 size_t e_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey)); 436 437 CFAllocatorRef allocator = CFGetAllocator(key); 438 CFMutableDataRef exponentData = CFDataCreateMutable(allocator, e_size); 439 440 if (exponentData == NULL) 441 return NULL; 442 443 CFDataSetLength(exponentData, e_size); 444 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 } 454 455 return exponent; 456 } 457 458 459 /* 460 * 461 * Private Key 462 * 463 */ 464 465 /* Private key static functions. */ 466 static void SecRSAPrivateKeyDestroy(SecKeyRef key) { 467 /* Zero out the public key */ 468 if (key->key) { 469 ccrsa_full_ctx_t fullkey = key->key; 470 cc_clear(ccrsa_full_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(fullkey))), fullkey); 471 free(key->key); 472 key->key = NULL; 473 } 474 } 475 476 static OSStatus SecRSAPrivateKeyInit(SecKeyRef key, const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) { 477 OSStatus result = errSecParam; 478 ccrsa_full_ctx_t fullkey; 479 cc_size size_n = 0; 480 481 switch (encoding) { 482 case kSecKeyEncodingBytes: // Octets is PKCS1 483 case kSecKeyEncodingPkcs1: 484 { 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); 488 489 key->key = calloc(1, ccrsa_full_ctx_size(ccn_sizeof_n(size_n))); 490 require_action_quiet(key->key, errOut, result = errSecAllocate); 491 492 fullkey = key->key; 493 ccrsa_ctx_n(fullkey) = size_n; 494 495 require_quiet(ccrsa_import_priv(fullkey, keyDataLength, keyData)==0, errOut); 496 497 result = errSecSuccess; 498 break; 499 } 500 case kSecGenerateKey: 501 { 502 CFDictionaryRef parameters = (CFDictionaryRef) keyData; 503 504 CFTypeRef ksize = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits); 505 CFIndex keyLengthInBits = getIntValue(ksize); 506 507 if (keyLengthInBits < 512 || keyLengthInBits > kMaximumRSAKeyBits) { 508 secwarning("Invalid or missing key size in: %@", parameters); 509 result = errSecKeySizeNotAllowed; 510 goto errOut; 511 } 512 513 size_n = ccn_nof(keyLengthInBits); 514 515 key->key = calloc(1, ccrsa_full_ctx_size(ccn_sizeof_n(size_n))); 516 require_action_quiet(key->key, errOut, result = errSecAllocate); 517 518 fullkey = key->key; 519 ccrsa_ctx_n(fullkey) = size_n; 520 521 /* TODO: Add support for kSecPublicExponent parameter. */ 522 static uint8_t e[] = { 0x01, 0x00, 0x01 }; // Default is 65537 523 if (!ccrsa_generate_fips186_key(keyLengthInBits, fullkey, sizeof(e), e, ccrng_seckey,ccrng_seckey)) 524 result = errSecSuccess; 525 break; 526 } 527 default: 528 break; 529 } 530 errOut: 531 return result; 532 } 533 534 static 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 539 ccrsa_full_ctx_t fullkey = key->key; 540 int ccerr = 0; 541 switch (operation) { 542 case kSecKeyOperationTypeSign: 543 if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureRawCCUnit)) { 544 if (mode == kSecKeyOperationModePerform) { 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 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 *. 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, 557 SecError(errSecParam, error, CFSTR("%@: sign - digest too big (%d bytes)"), key, 558 (int)CFDataGetLength(in1)))); 559 560 // Encrypt buffer and write it to output data. 561 result = CFDataCreateMutableWithScratch(kCFAllocatorDefault, bufferSize); 562 ccerr = ccrsa_priv_crypt(fullkey, (cc_unit *)CFDataGetMutableBytePtr((CFMutableDataRef)result), 563 (const cc_unit *)CFDataGetBytePtr(in1)); 564 } else { 565 // Operation is supported. 566 result = kCFBooleanTrue; 567 } 568 } 569 break; 570 case kSecKeyOperationTypeDecrypt: 571 if (CFEqual(algorithm, kSecKeyAlgorithmRSAEncryptionRawCCUnit)) { 572 if (mode == kSecKeyOperationModePerform) { 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 580 // Decrypt buffer and write it to output data. 581 result = CFDataCreateMutableWithScratch(NULL, bufferSize); 582 ccerr = ccrsa_priv_crypt(fullkey, (cc_unit *)CFDataGetMutableBytePtr((CFMutableDataRef)result), 583 (const cc_unit *)CFDataGetBytePtr(in1)); 584 } else { 585 // Operation is supported. 586 result = kCFBooleanTrue; 587 } 588 } 589 break; 590 default: 591 break; 592 } 593 594 require_noerr_action_quiet(ccerr, out, (CFReleaseNull(result), 595 SecError(errSecParam, error, CFSTR("rsa_priv_crypt failed, ccerr=%d"), ccerr))); 596 out: 597 return result; 598 } 599 600 static size_t SecRSAPrivateKeyBlockSize(SecKeyRef key) { 601 ccrsa_full_ctx_t fullkey = key->key; 602 603 return ccn_write_uint_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey)); 604 } 605 606 static CFDataRef SecRSAPrivateKeyCreatePKCS1(CFAllocatorRef allocator, ccrsa_full_ctx_t fullkey) 607 { 608 const size_t result_size = ccrsa_export_priv_size(fullkey); 609 610 CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size); 611 612 if (pkcs1 == NULL) { 613 return NULL; 614 } 615 616 CFDataSetLength(pkcs1, result_size); 617 618 uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1); 619 620 if (ccrsa_export_priv(fullkey,result_size,bytes)!=0) { 621 /* Decoding failed */ 622 CFReleaseNull(pkcs1); 623 return NULL; 624 } 625 626 return pkcs1; 627 } 628 629 static CFDataRef SecRSAPrivateKeyCopyPKCS1(SecKeyRef key) 630 { 631 ccrsa_full_ctx_t fullkey = key->key; 632 633 CFAllocatorRef allocator = CFGetAllocator(key); 634 return SecRSAPrivateKeyCreatePKCS1(allocator, fullkey); 635 } 636 637 static OSStatus SecRSAPrivateKeyCopyPublicSerialization(SecKeyRef key, CFDataRef* serialized) 638 { 639 ccrsa_full_ctx_t fullkey = key->key; 640 641 CFAllocatorRef allocator = CFGetAllocator(key); 642 *serialized = SecRSAPublicKeyCreatePKCS1(allocator, ccrsa_ctx_public(fullkey)); 643 644 if (NULL == *serialized) 645 return errSecDecode; 646 else 647 return errSecSuccess; 648 } 649 650 651 static CFDictionaryRef SecRSAPrivateKeyCopyAttributeDictionary(SecKeyRef key) { 652 CFDictionaryRef dict = NULL; 653 CFDataRef fullKeyBlob = NULL; 654 655 /* PKCS1 encode the key pair. */ 656 fullKeyBlob = SecRSAPrivateKeyCopyPKCS1(key); 657 require_quiet(fullKeyBlob, errOut); 658 659 dict = SecKeyGeneratePrivateAttributeDictionary(key, kSecAttrKeyTypeRSA, fullKeyBlob); 660 CFMutableDictionaryRef mutableDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); 661 CFDictionarySetValue(mutableDict, kSecAttrCanDerive, kCFBooleanFalse); 662 CFAssignRetained(dict, mutableDict); 663 664 errOut: 665 CFReleaseSafe(fullKeyBlob); 666 667 return dict; 668 } 669 670 static CFDataRef SecRSAPrivateKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) { 671 return SecRSAPrivateKeyCopyPKCS1(key); 672 } 673 674 static CFStringRef SecRSAPrivateKeyCopyDescription(SecKeyRef key){ 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 678 } 679 680 SecKeyDescriptor kSecRSAPrivateKeyDescriptor = { 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, 692 }; 693 694 /* Private Key API functions. */ 695 SecKeyRef SecKeyCreateRSAPrivateKey(CFAllocatorRef allocator, 696 const uint8_t *keyData, CFIndex keyDataLength, 697 SecKeyEncoding encoding) { 698 return SecKeyCreate(allocator, &kSecRSAPrivateKeyDescriptor, keyData, 699 keyDataLength, encoding); 700 } 701 702 703 OSStatus SecRSAKeyGeneratePair(CFDictionaryRef parameters, 704 SecKeyRef *rsaPublicKey, SecKeyRef *rsaPrivateKey) { 705 OSStatus status = errSecParam; 706 707 CFAllocatorRef allocator = NULL; /* @@@ get from parameters. */ 708 709 SecKeyRef pubKey = NULL; 710 SecKeyRef privKey = SecKeyCreate(allocator, &kSecRSAPrivateKeyDescriptor, 711 (const void*) parameters, 0, kSecGenerateKey); 712 713 require_quiet(privKey, errOut); 714 715 /* Create SecKeyRef's from the pkcs1 encoded keys. */ 716 pubKey = SecKeyCreate(allocator, &kSecRSAPublicKeyDescriptor, 717 privKey->key, 0, kSecExtractPublicFromPrivate); 718 719 require_quiet(pubKey, errOut); 720 721 if (rsaPublicKey) { 722 *rsaPublicKey = pubKey; 723 pubKey = NULL; 724 } 725 if (rsaPrivateKey) { 726 *rsaPrivateKey = privKey; 727 privKey = NULL; 728 } 729 730 status = errSecSuccess; 731 732 errOut: 733 CFReleaseSafe(pubKey); 734 CFReleaseSafe(privKey); 735 736 return status; 737 }