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