/ keychain / SecureObjectSync / SOSAccountDer.m
SOSAccountDer.m
  1  /*
  2   * Copyright (c) 2013-2014 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  #include "SOSAccountPriv.h"
 26  #include "keychain/SecureObjectSync/SOSCircleDer.h"
 27  
 28  //
 29  // DER Encoding utilities
 30  //
 31  
 32  static const uint8_t* ccder_decode_null(const uint8_t* der, const uint8_t *der_end)
 33  {
 34      if (NULL == der)
 35          return NULL;
 36  
 37      size_t payload_size = 0;
 38      const uint8_t *payload = ccder_decode_tl(CCDER_NULL, &payload_size, der, der_end);
 39  
 40      if (NULL == payload || payload_size != 0) {
 41          return NULL;
 42      }
 43  
 44      return payload + payload_size;
 45  }
 46  
 47  
 48  static size_t ccder_sizeof_null(void)
 49  {
 50      return ccder_sizeof(CCDER_NULL, 0);
 51  }
 52  
 53  
 54  static uint8_t* ccder_encode_null(const uint8_t *der, uint8_t *der_end)
 55  {
 56      return ccder_encode_tl(CCDER_NULL, 0, der, der_end);
 57  }
 58  
 59  
 60  //
 61  // Encodes data or a zero length data
 62  //
 63  size_t der_sizeof_fullpeer_or_null(SOSFullPeerInfoRef full_peer, CFErrorRef* error)
 64  {
 65      if (full_peer) {
 66          return SOSFullPeerInfoGetDEREncodedSize(full_peer, error);
 67      } else {
 68          return ccder_sizeof_null();
 69      }
 70  }
 71  
 72  uint8_t* der_encode_fullpeer_or_null(SOSFullPeerInfoRef full_peer, CFErrorRef* error, const uint8_t* der, uint8_t* der_end)
 73  {
 74      if (full_peer) {
 75          return SOSFullPeerInfoEncodeToDER(full_peer, error, der, der_end);
 76      } else {
 77          return ccder_encode_null(der, der_end);
 78      }
 79  }
 80  
 81  
 82  const uint8_t* der_decode_fullpeer_or_null(CFAllocatorRef allocator, SOSFullPeerInfoRef* full_peer,
 83                                             CFErrorRef* error,
 84                                             const uint8_t* der, const uint8_t* der_end)
 85  {
 86      ccder_tag tag;
 87  
 88      require_action_quiet(ccder_decode_tag(&tag, der, der_end), fail, der = NULL);
 89  
 90      require_action_quiet(full_peer, fail, der = NULL);
 91  
 92      if (tag == CCDER_NULL) {
 93          der = ccder_decode_null(der, der_end);
 94      } else  {
 95          *full_peer = SOSFullPeerInfoCreateFromDER(kCFAllocatorDefault, error, &der, der_end);
 96      }
 97  
 98  fail:
 99      return der;
100  }
101  
102  
103  //
104  // Mark: public_bytes encode/decode
105  //
106  
107  size_t der_sizeof_public_bytes(SecKeyRef publicKey, CFErrorRef* error)
108  {
109      CFDataRef publicData = NULL;
110      
111      if (publicKey)
112          SecKeyCopyPublicBytes(publicKey, &publicData);
113      
114      size_t size = der_sizeof_data_or_null(publicData, error);
115      
116      CFReleaseNull(publicData);
117      
118      return size;
119  }
120  
121  uint8_t* der_encode_public_bytes(SecKeyRef publicKey, CFErrorRef* error, const uint8_t* der, uint8_t* der_end)
122  {
123      CFDataRef publicData = NULL;
124      
125      if (publicKey)
126          SecKeyCopyPublicBytes(publicKey, &publicData);
127      
128      uint8_t *result = der_encode_data_or_null(publicData, error, der, der_end);
129      
130      CFReleaseNull(publicData);
131      
132      return result;
133  }
134  
135  const uint8_t* der_decode_public_bytes(CFAllocatorRef allocator, CFIndex algorithmID, SecKeyRef* publicKey, CFErrorRef* error, const uint8_t* der, const uint8_t* der_end)
136  {
137      CFDataRef dataFound = NULL;
138      der = der_decode_data_or_null(allocator, &dataFound, error, der, der_end);
139      
140      if (der && dataFound && publicKey) {
141          *publicKey = SecKeyCreateFromPublicData(allocator, algorithmID, dataFound);
142      }
143      CFReleaseNull(dataFound);
144      
145      return der;
146  }
147