/ OSX / sec / Security / SecRSAKey.c
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  }