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