]> git.saurik.com Git - apple/security.git/blame - OSX/sec/SOSCircle/SecureObjectSync/SOSPeerInfoCollections.c
Security-57740.20.22.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSPeerInfoCollections.c
CommitLineData
d8f41ccd
A
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
5c19dc3a 25#include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
d8f41ccd
A
26
27#include <CoreFoundation/CoreFoundation.h>
28#include <utilities/SecCFWrappers.h>
29#include <utilities/SecCFError.h>
30#include <utilities/SecXPCError.h>
31#include <corecrypto/ccder.h>
5c19dc3a 32#include <Security/SecureObjectSync/SOSInternal.h>
d8f41ccd 33#include <AssertMacros.h>
5c19dc3a 34#include <SOSPeerInfoDER.h>
d8f41ccd
A
35
36//
37// PeerInfoSetby ID handling
38//
39
40//
41//
42// CFSetRetainCallback
43//
44
5c19dc3a
A
45static CFStringRef GetIDOrString(const void *object) {
46 return isSOSPeerInfo(object) ?
47 SOSPeerInfoGetPeerID((SOSPeerInfoRef)object) :
48 (isString(object) ? (CFStringRef) object : NULL);
49}
50
d8f41ccd
A
51static Boolean SOSPeerInfoIDEqual(const void *value1, const void *value2)
52{
5c19dc3a 53 return CFEqualSafe(GetIDOrString(value1), GetIDOrString(value2));
d8f41ccd
A
54}
55
56static CFHashCode SOSPeerInfoIDHash(const void *value)
57{
5c19dc3a 58 return CFHash(GetIDOrString(value));
d8f41ccd
A
59}
60
61bool SOSPeerInfoSetContainsIdenticalPeers(CFSetRef set1, CFSetRef set2){
62
63 __block bool result = true;
64
65 if(!CFEqualSafe(set1, set2))
66 return false;
67
68 CFSetForEach(set1, ^(const void *value) {
69 SOSPeerInfoRef peer1 = (SOSPeerInfoRef)value;
70 SOSPeerInfoRef peer2 = (SOSPeerInfoRef)CFSetGetValue(set2, peer1);
71 result &= CFEqualSafe(peer1, peer2);
72 });
73 return result;
74}
75const CFSetCallBacks kSOSPeerSetCallbacks = {0, SecCFRetainForCollection, SecCFReleaseForCollection, CFCopyDescription, SOSPeerInfoIDEqual, SOSPeerInfoIDHash};
76
77CFMutableSetRef CFSetCreateMutableForSOSPeerInfosByID(CFAllocatorRef allocator)
78{
79 return CFSetCreateMutable(allocator, 0, &kSOSPeerSetCallbacks);
80}
81
e0e0d90e
A
82CFMutableSetRef CFSetCreateMutableForSOSPeerInfosByIDWithArray(CFAllocatorRef allocator, CFArrayRef peerInfos)
83{
84 CFMutableSetRef newSet = CFSetCreateMutableForSOSPeerInfosByID(allocator);
85
86 CFArrayForEach(peerInfos, ^(const void *value) {
87 SOSPeerInfoRef peer = asSOSPeerInfo(value);
88 if (peer) {
89 CFSetAddValue(newSet, peer);
90 }
91 });
92
93 return newSet;
94}
95
5c19dc3a
A
96SOSPeerInfoRef SOSPeerInfoSetFindByID(CFSetRef set, CFStringRef id) {
97 return (SOSPeerInfoRef) CFSetGetValue(set, id);
98}
d8f41ccd
A
99
100//
101// CFArray of Peer Info handling
102//
103
104void CFArrayOfSOSPeerInfosSortByID(CFMutableArrayRef peerInfoArray)
105{
106 CFArraySortValues(peerInfoArray, CFRangeMake(0, CFArrayGetCount(peerInfoArray)), SOSPeerInfoCompareByID, NULL);
107}
108
109
110//
111// PeerInfoArray encoding decoding
112//
113
114CFMutableArrayRef SOSPeerInfoArrayCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error,
115 const uint8_t** der_p, const uint8_t *der_end) {
116 CFMutableArrayRef pia = CFArrayCreateMutableForCFTypes(allocator);
117
118 const uint8_t *sequence_end;
119
120 *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end);
121
122 require_action(*der_p, fail, SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Peer Info Array Sequence Header"), NULL, error));
123
124 while (sequence_end != *der_p) {
125 SOSPeerInfoRef pi = SOSPeerInfoCreateFromDER(allocator, error, der_p, sequence_end);
126
127 if (pi == NULL || *der_p == NULL) {
128 SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Peer Info Array DER"), (error != NULL ? *error : NULL), error);
129 CFReleaseNull(pi);
130 goto fail;
131 }
132
133 CFArrayAppendValue(pia, pi);
134 CFReleaseSafe(pi);
135 }
136
137 if (!pia)
138 *der_p = NULL;
139 return pia;
140
141fail:
142 CFReleaseNull(pia);
143 *der_p = NULL;
144 return NULL;
145}
146
147size_t SOSPeerInfoArrayGetDEREncodedSize(CFArrayRef pia, CFErrorRef *error) {
148 __block size_t array_size = 0;
149 __block bool fail = false;
150
151 CFArrayForEach(pia, ^(const void *value) {
152 if (isSOSPeerInfo(value)) {
153 SOSPeerInfoRef pi = (SOSPeerInfoRef) value;
154 size_t pi_size = SOSPeerInfoGetDEREncodedSize(pi, error);
155
156 fail = (pi_size == 0);
157 array_size += pi_size;
158 } else {
159 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Non SOSPeerInfo in array"), (error != NULL ? *error : NULL), error);
160 fail = true;
161 }
162 });
163
164 return fail ? 0 : ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, array_size);
165}
166
167uint8_t* SOSPeerInfoArrayEncodeToDER(CFArrayRef pia, CFErrorRef* error, const uint8_t* der, uint8_t* der_end_param) {
168
169 uint8_t* const sequence_end = der_end_param;
170 __block uint8_t* der_end = der_end_param;
171
172 CFArrayForEachReverse(pia, ^(const void *value) {
173 SOSPeerInfoRef pi = (SOSPeerInfoRef) value;
174 if (CFGetTypeID(pi) != SOSPeerInfoGetTypeID()) {
175 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Non SOSPeerInfo in array"), NULL, error);
176 der_end = NULL; // Indicate error and continue.
177 }
178 if (der_end)
179 der_end = SOSPeerInfoEncodeToDER(pi, error, der, der_end);
180 });
181
182 if (der_end == NULL)
183 return NULL;
184
185 return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, sequence_end, der, der_end);
186}
187
188
189CFMutableSetRef SOSPeerInfoSetCreateFromArrayDER(CFAllocatorRef allocator, const CFSetCallBacks *callbacks, CFErrorRef* error,
190 const uint8_t** der_p, const uint8_t *der_end) {
191 CFMutableSetRef result = NULL;
192
193 CFArrayRef peers = SOSPeerInfoArrayCreateFromDER(allocator, error, der_p, der_end);
194
195 if (peers) {
196 result = CFSetCreateMutable(allocator, 0, callbacks);
197 CFSetSetValues(result, peers);
198 }
199
200 CFReleaseNull(peers);
201 return result;
202}
203
204size_t SOSPeerInfoSetGetDEREncodedArraySize(CFSetRef pia, CFErrorRef *error) {
205 __block size_t array_size = 0;
206 __block bool fail = false;
207
208 CFSetForEach(pia, ^(const void *value) {
209 if (isSOSPeerInfo(value)) {
210 SOSPeerInfoRef pi = (SOSPeerInfoRef) value;
211 size_t pi_size = SOSPeerInfoGetDEREncodedSize(pi, error);
212
213 fail = (pi_size == 0);
214 array_size += pi_size;
215 } else {
216 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Non SOSPeerInfo in array"), (error != NULL ? *error : NULL), error);
217 fail = true;
218 }
219 });
220
221 return fail ? 0 : ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, array_size);
222}
223
224uint8_t* SOSPeerInfoSetEncodeToArrayDER(CFSetRef pis, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) {
5c19dc3a
A
225 CFMutableArrayRef pia = CFSetCopyValues(pis);
226
227 CFArrayOfSOSPeerInfosSortByID(pia);
d8f41ccd
A
228
229 uint8_t* result = SOSPeerInfoArrayEncodeToDER(pia, error, der, der_end);
230
231 CFReleaseNull(pia);
232
233 return result;
234}
235
236
237
238CFArrayRef CreateArrayOfPeerInfoWithXPCObject(xpc_object_t peerArray, CFErrorRef* error) {
239 if (!peerArray) {
240 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedNull, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Unexpected Null Array to encode"));
241 return NULL;
242 }
243
244 if (xpc_get_type(peerArray) != XPC_TYPE_DATA) {
245 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Array of peer info not array, got %@"), peerArray);
246 return NULL;
247 }
248
249 const uint8_t* der = xpc_data_get_bytes_ptr(peerArray);
250 const uint8_t* der_end = der + xpc_data_get_length(peerArray);
251
252 return SOSPeerInfoArrayCreateFromDER(kCFAllocatorDefault, error, &der, der_end);
253}
254
255xpc_object_t CreateXPCObjectWithArrayOfPeerInfo(CFArrayRef array, CFErrorRef *error) {
256 size_t data_size = SOSPeerInfoArrayGetDEREncodedSize(array, error);
257 if (data_size == 0)
258 return NULL;
259 uint8_t *data = (uint8_t *)malloc(data_size);
260 if (!data) return NULL;
261
262 xpc_object_t result = NULL;
263 if (SOSPeerInfoArrayEncodeToDER(array, error, data, data + data_size))
264 result = xpc_data_create(data, data_size);
265
266 free(data);
267 return result;
268}