]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSCircleDer.c
Security-58286.270.3.0.1.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSCircleDer.c
1 //
2 // SOSCircleDer.c
3 // sec
4 //
5 // Created by Richard Murphy on 1/22/15.
6 //
7 //
8
9 #include <stdio.h>
10 #include <AssertMacros.h>
11 #include <CoreFoundation/CoreFoundation.h>
12 #include <CoreFoundation/CoreFoundation.h>
13 #include <CoreFoundation/CFArray.h>
14 #include <Security/SecureObjectSync/SOSCloudCircle.h>
15 #include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
16 #include <Security/SecureObjectSync/SOSCircle.h>
17 #include <Security/SecureObjectSync/SOSCirclePriv.h>
18 #include <utilities/SecCFRelease.h>
19 #include <utilities/SecCFWrappers.h>
20 #include <utilities/debugging.h>
21 #include <Security/SecureObjectSync/SOSInternal.h>
22 #include <Security/SecureObjectSync/SOSPeer.h>
23 #include <Security/SecureObjectSync/SOSPeerInfoInternal.h>
24 #include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
25 #include <Security/SecFramework.h>
26
27 #include <utilities/der_plist.h>
28 #include <utilities/der_plist_internal.h>
29 #include <corecrypto/ccder.h>
30 #include <stdlib.h>
31 #include <assert.h>
32
33 #include "SOSCircleDer.h"
34
35 static const uint8_t* der_decode_mutable_dictionary(CFAllocatorRef allocator, CFOptionFlags mutability,
36 CFMutableDictionaryRef* dictionary, CFErrorRef *error,
37 const uint8_t* der, const uint8_t *der_end)
38 {
39 CFDictionaryRef theDict;
40 const uint8_t* result = der_decode_dictionary(allocator, mutability, &theDict, error, der, der_end);
41
42 if (result != NULL)
43 *dictionary = (CFMutableDictionaryRef)theDict;
44
45 return result;
46 }
47
48
49 SOSCircleRef SOSCircleCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error,
50 const uint8_t** der_p, const uint8_t *der_end) {
51 SOSCircleRef cir = CFTypeAllocate(SOSCircle, struct __OpaqueSOSCircle, allocator);
52
53 const uint8_t *sequence_end;
54
55 cir->name = NULL;
56 cir->generation = NULL;
57 cir->peers = NULL;
58 cir->applicants = NULL;
59 cir->rejected_applicants = NULL;
60 cir->signatures = NULL;
61
62 *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end);
63 require_action_quiet(sequence_end != NULL, fail,
64 SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Circle DER"), (error != NULL) ? *error : NULL, error));
65
66 // Version first.
67 uint64_t version = 0;
68 *der_p = ccder_decode_uint64(&version, *der_p, der_end);
69
70 require_action_quiet(version == kOnlyCompatibleVersion, fail,
71 SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Bad Circle Version"), NULL, error));
72
73 *der_p = der_decode_string(allocator, 0, &cir->name, error, *der_p, sequence_end);
74 cir->generation = SOSGenCountCreateFromDER(kCFAllocatorDefault, error, der_p, sequence_end);
75
76 cir->peers = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end);
77 cir->applicants = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end);
78 cir->rejected_applicants = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end);
79
80 *der_p = der_decode_mutable_dictionary(allocator, kCFPropertyListMutableContainersAndLeaves,
81 &cir->signatures, error, *der_p, sequence_end);
82
83 require_action_quiet(*der_p == sequence_end, fail,
84 SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Circle DER"), (error != NULL) ? *error : NULL, error));
85
86 return cir;
87
88 fail:
89 CFReleaseNull(cir);
90 return NULL;
91 }
92
93 SOSCircleRef SOSCircleCreateFromData(CFAllocatorRef allocator, CFDataRef circleData, CFErrorRef *error)
94 {
95 size_t size = CFDataGetLength(circleData);
96 const uint8_t *der = CFDataGetBytePtr(circleData);
97 SOSCircleRef inflated = SOSCircleCreateFromDER(allocator, error, &der, der + size);
98 return inflated;
99 }
100
101 size_t SOSCircleGetDEREncodedSize(SOSCircleRef cir, CFErrorRef *error) {
102 SOSCircleAssertStable(cir);
103 size_t total_payload = 0;
104
105 require_quiet(accumulate_size(&total_payload, ccder_sizeof_uint64(kOnlyCompatibleVersion)), fail);
106 require_quiet(accumulate_size(&total_payload, der_sizeof_string(cir->name, error)), fail);
107 require_quiet(accumulate_size(&total_payload, SOSGenCountGetDEREncodedSize(cir->generation, error)), fail);
108 require_quiet(accumulate_size(&total_payload, SOSPeerInfoSetGetDEREncodedArraySize(cir->peers, error)), fail);
109 require_quiet(accumulate_size(&total_payload, SOSPeerInfoSetGetDEREncodedArraySize(cir->applicants, error)), fail);
110 require_quiet(accumulate_size(&total_payload, SOSPeerInfoSetGetDEREncodedArraySize(cir->rejected_applicants, error)), fail);
111 require_quiet(accumulate_size(&total_payload, der_sizeof_dictionary((CFDictionaryRef) cir->signatures, error)), fail);
112
113 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, total_payload);
114
115 fail:
116 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error);
117 return 0;
118 }
119
120 uint8_t* SOSCircleEncodeToDER(SOSCircleRef cir, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) {
121 SOSCircleAssertStable(cir);
122
123 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
124 ccder_encode_uint64(kOnlyCompatibleVersion, der,
125 der_encode_string(cir->name, error, der,
126 SOSGenCountEncodeToDER(cir->generation, error, der,
127 SOSPeerInfoSetEncodeToArrayDER(cir->peers, error, der,
128 SOSPeerInfoSetEncodeToArrayDER(cir->applicants, error, der,
129 SOSPeerInfoSetEncodeToArrayDER(cir->rejected_applicants, error, der,
130 der_encode_dictionary((CFDictionaryRef) cir->signatures, error, der, der_end))))))));
131 }
132
133 CFDataRef SOSCircleCreateIncompatibleCircleDER(CFErrorRef* error)
134 {
135 size_t total_payload = 0;
136 size_t encoded_size = 0;
137 uint8_t* der = 0;
138 uint8_t* der_end = 0;
139 CFMutableDataRef result = NULL;
140
141 require_quiet(accumulate_size(&total_payload, ccder_sizeof_uint64(kAlwaysIncompatibleVersion)), fail);
142
143 encoded_size = ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, total_payload);
144
145 result = CFDataCreateMutableWithScratch(kCFAllocatorDefault, encoded_size);
146
147 der = CFDataGetMutableBytePtr(result);
148 der_end = der + CFDataGetLength(result);
149
150 der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
151 ccder_encode_uint64(kAlwaysIncompatibleVersion, der, der_end));
152
153 fail:
154 if (der == NULL || der != der_end)
155 CFReleaseNull(result);
156
157 return result;
158 }
159
160
161 CFDataRef SOSCircleCopyEncodedData(SOSCircleRef circle, CFAllocatorRef allocator, CFErrorRef *error)
162 {
163 return CFDataCreateWithDER(kCFAllocatorDefault, SOSCircleGetDEREncodedSize(circle, error), ^uint8_t*(size_t size, uint8_t *buffer) {
164 return SOSCircleEncodeToDER(circle, error, buffer, (uint8_t *) buffer + size);
165 });
166 }
167
168 //
169 // Encodes data or a zero length data
170 //
171 size_t der_sizeof_data_or_null(CFDataRef data, CFErrorRef* error)
172 {
173 if (data) {
174 return der_sizeof_data(data, error);
175 } else {
176 return der_sizeof_null(kCFNull, error);
177 }
178 }
179
180 uint8_t* der_encode_data_or_null(CFDataRef data, CFErrorRef* error, const uint8_t* der, uint8_t* der_end)
181 {
182 if (data) {
183 return der_encode_data(data, error, der, der_end);
184 } else {
185 return der_encode_null(kCFNull, error, der, der_end);
186 }
187 }
188
189
190 const uint8_t* der_decode_data_or_null(CFAllocatorRef allocator, CFDataRef* data,
191 CFErrorRef* error,
192 const uint8_t* der, const uint8_t* der_end)
193 {
194 CFTypeRef value = NULL;
195 der = der_decode_plist(allocator, 0, &value, error, der, der_end);
196 if (value && CFGetTypeID(value) != CFDataGetTypeID()) {
197 CFReleaseNull(value);
198 }
199 if (data) {
200 *data = value;
201 }
202 return der;
203 }
204