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
27//
28// DER Encoding utilities
29//
30
31//
32// Encodes data or a zero length data
33//
34size_t der_sizeof_data_or_null(CFDataRef data, CFErrorRef* error)
35{
36	if (data) {
37		return der_sizeof_data(data, error);
38	} else {
39		return der_sizeof_null(kCFNull, error);
40	}
41}
42
43uint8_t* der_encode_data_or_null(CFDataRef data, CFErrorRef* error, const uint8_t* der, uint8_t* der_end)
44{
45    if (data) {
46		return der_encode_data(data, error, der, der_end);
47	} else {
48		return der_encode_null(kCFNull, error, der, der_end);
49	}
50}
51
52
53const uint8_t* der_decode_data_or_null(CFAllocatorRef allocator, CFDataRef* data,
54                                              CFErrorRef* error,
55                                              const uint8_t* der, const uint8_t* der_end)
56{
57    CFTypeRef value = NULL;
58	der = der_decode_plist(allocator, 0, &value, error, der, der_end);
59	if (value && CFGetTypeID(value) != CFDataGetTypeID()) {
60		CFReleaseNull(value);
61	}
62	if (data) {
63		*data = value;
64	}
65	return der;
66}
67
68
69//
70// Mark: public_bytes encode/decode
71//
72
73size_t der_sizeof_public_bytes(SecKeyRef publicKey, CFErrorRef* error)
74{
75    CFDataRef publicData = NULL;
76
77    if (publicKey)
78        SecKeyCopyPublicBytes(publicKey, &publicData);
79
80    size_t size = der_sizeof_data_or_null(publicData, error);
81
82    CFReleaseNull(publicData);
83
84    return size;
85}
86
87uint8_t* der_encode_public_bytes(SecKeyRef publicKey, CFErrorRef* error, const uint8_t* der, uint8_t* der_end)
88{
89    CFDataRef publicData = NULL;
90
91    if (publicKey)
92        SecKeyCopyPublicBytes(publicKey, &publicData);
93
94    uint8_t *result = der_encode_data_or_null(publicData, error, der, der_end);
95
96    CFReleaseNull(publicData);
97
98    return result;
99}
100
101const uint8_t* der_decode_public_bytes(CFAllocatorRef allocator, CFIndex algorithmID, SecKeyRef* publicKey, CFErrorRef* error, const uint8_t* der, const uint8_t* der_end)
102{
103    CFDataRef dataFound = NULL;
104    der = der_decode_data_or_null(allocator, &dataFound, error, der, der_end);
105
106    if (der && dataFound && publicKey) {
107        *publicKey = SecKeyCreateFromPublicData(allocator, algorithmID, dataFound);
108    }
109    CFReleaseNull(dataFound);
110
111    return der;
112}
113
114
115
116
117//
118// bool encoding/decoding
119//
120
121
122const uint8_t* ccder_decode_bool(bool* boolean, const uint8_t* der, const uint8_t *der_end)
123{
124    if (NULL == der)
125        return NULL;
126
127    size_t payload_size = 0;
128    const uint8_t *payload = ccder_decode_tl(CCDER_BOOLEAN, &payload_size, der, der_end);
129
130    if (NULL == payload || (der_end - payload) < 1 || payload_size != 1) {
131        return NULL;
132    }
133
134    if (boolean)
135        *boolean = (*payload != 0);
136
137    return payload + payload_size;
138}
139
140
141size_t ccder_sizeof_bool(bool value __unused, CFErrorRef *error)
142{
143    return ccder_sizeof(CCDER_BOOLEAN, 1);
144}
145
146
147uint8_t* ccder_encode_bool(bool value, const uint8_t *der, uint8_t *der_end)
148{
149    uint8_t value_byte = value;
150
151    return ccder_encode_tl(CCDER_BOOLEAN, 1, der,
152                           ccder_encode_body(1, &value_byte, der, der_end));
153}
154