/ keychain / SecureObjectSync / SOSECWrapUnwrap.c
SOSECWrapUnwrap.c
  1  //
  2  //  cc_CFData.c
  3  //  ProtectedCloudStorage
  4  //
  5  //  Copyright (c) 2014 Apple Inc. All rights reserved.
  6  //
  7  
  8  #include "keychain/SecureObjectSync/SOSInternal.h"
  9  
 10  #include <AssertMacros.h>
 11  
 12  #include <utilities/SecCFWrappers.h>
 13  #include <utilities/SecCFError.h>
 14  #include <utilities/SecBuffer.h>
 15  #import <corecrypto/ccec.h>
 16  #import <corecrypto/ccrng.h>
 17  
 18  
 19  #if 0 && defined(CCEC_RFC6637_DEBUG_KEYS)
 20  #define DEBUGKEYS CCEC_RFC6637_DEBUG_KEYS
 21  #else
 22  #define DEBUGKEYS 0
 23  #endif
 24  
 25  const char fingerprint[20] = "fingerprint";
 26  
 27  const uint8_t kAlgorithmID = 1;
 28  
 29  CFMutableDataRef
 30  SOSCopyECWrappedData(ccec_pub_ctx_t ec_ctx, CFDataRef data, CFErrorRef *error)
 31  {
 32      CFMutableDataRef result = NULL;
 33      CFMutableDataRef output = NULL;
 34      size_t outputLength;
 35      int res;
 36  
 37      require_quiet(SecRequirementError(data != NULL, error, CFSTR("data required for wrapping")), exit);
 38      require_quiet(SecRequirementError(ec_ctx != NULL, error, CFSTR("ec pub key required for wrapping")), exit);
 39      require_quiet(ec_ctx != NULL, exit);
 40  
 41      outputLength = ccec_rfc6637_wrap_key_size(ec_ctx, CCEC_RFC6637_COMPACT_KEYS | DEBUGKEYS, CFDataGetLength(data));
 42  
 43      output = CFDataCreateMutableWithScratch(NULL, outputLength);
 44      require_quiet(SecAllocationError(output, error, CFSTR("%s CFData allocation failed"), __FUNCTION__), exit);
 45  
 46      res = ccec_rfc6637_wrap_key(ec_ctx, CFDataGetMutableBytePtr(output), CCEC_RFC6637_COMPACT_KEYS | DEBUGKEYS, kAlgorithmID,
 47                                  CFDataGetLength(data), CFDataGetBytePtr(data), &ccec_rfc6637_dh_curve_p256,
 48                                  &ccec_rfc6637_wrap_sha256_kek_aes128, (const uint8_t *)fingerprint,
 49                                  ccrng(NULL));
 50      require_noerr_action(res, exit, SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("Wrap failed with %d"), res));
 51  
 52      CFTransferRetained(result, output);
 53  
 54  exit:
 55      CFReleaseNull(output);
 56      return result;
 57  }
 58  
 59  bool SOSPerformWithUnwrappedData(ccec_full_ctx_t ec_ctx, CFDataRef data, CFErrorRef *error,
 60                                   void (^operation)(size_t size, uint8_t *buffer))
 61  {
 62      __block bool result = false;
 63  
 64      PerformWithBufferAndClear(CFDataGetLength(data), ^(size_t size, uint8_t *buffer) {
 65          size_t outputLength = size;
 66          int ec_result;
 67          uint8_t alg;
 68          ec_result = ccec_rfc6637_unwrap_key(ec_ctx, &outputLength, buffer,
 69                                              CCEC_RFC6637_COMPACT_KEYS | DEBUGKEYS, &alg, &ccec_rfc6637_dh_curve_p256,
 70                                              &ccec_rfc6637_unwrap_sha256_kek_aes128, (const uint8_t *)fingerprint,
 71                                              CFDataGetLength(data), CFDataGetBytePtr(data));
 72  
 73          require_noerr_action(ec_result, exit, SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("ccec_rfc6637_unwrap_key failed with %d"), ec_result));
 74          require_quiet(SecRequirementError(alg == kAlgorithmID, error, CFSTR("Unexpected algorithm: %d"), (int)alg), exit);
 75  
 76          operation(outputLength, buffer);
 77  
 78          result = true;
 79      exit:
 80          ;
 81      });
 82  
 83      return result;
 84  }
 85  
 86  CFMutableDataRef
 87  SOSCopyECUnwrappedData(ccec_full_ctx_t ec_ctx, CFDataRef data, CFErrorRef *error)
 88  {
 89      uint8_t alg;
 90      CFMutableDataRef result = NULL;
 91      CFMutableDataRef output = NULL;
 92      size_t outputLength = CFDataGetLength(data);
 93      int res;
 94  
 95      output = CFDataCreateMutableWithScratch(NULL, outputLength);
 96      require_quiet(SecAllocationError(output, error, CFSTR("%s CFData allocation failed"), __FUNCTION__), exit);
 97  
 98      res = ccec_rfc6637_unwrap_key(ec_ctx, &outputLength, CFDataGetMutableBytePtr(output),
 99                                    CCEC_RFC6637_COMPACT_KEYS | DEBUGKEYS, &alg, &ccec_rfc6637_dh_curve_p256,
100                                    &ccec_rfc6637_unwrap_sha256_kek_aes128, (const uint8_t *)fingerprint,
101                                    CFDataGetLength(data), CFDataGetBytePtr(data));
102      require_noerr_action(res, exit, SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("Unwrap failed with %d"), res));
103      require_quiet(SecRequirementError(alg == kAlgorithmID, error, CFSTR("Unexpected algorithm: %d"), (int)alg), exit);
104  
105      CFDataSetLength(output, outputLength);
106  
107      CFTransferRetained(result, output);
108  
109  exit:
110      CFReleaseNull(output);
111      return result;
112  }