2 * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
28 #include <AssertMacros.h>
29 #include "SOSAccountPriv.h"
31 #include <utilities/SecCFWrappers.h>
32 #include <SecureObjectSync/SOSKVSKeys.h>
34 SOSAccountRef
SOSAccountCreateFromDER_V1(CFAllocatorRef allocator
,
35 SOSDataSourceFactoryRef factory
,
37 const uint8_t** der_p
, const uint8_t *der_end
)
39 SOSAccountRef account
= NULL
;
41 const uint8_t *sequence_end
;
42 *der_p
= ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, &sequence_end
, *der_p
, der_end
);
45 CFDictionaryRef decoded_gestalt
= NULL
;
46 *der_p
= der_decode_dictionary(kCFAllocatorDefault
, kCFPropertyListImmutable
, &decoded_gestalt
, error
,
52 account
= SOSAccountCreateBasic(allocator
, decoded_gestalt
, factory
);
53 CFReleaseNull(decoded_gestalt
);
56 CFArrayRef array
= NULL
;
57 *der_p
= der_decode_array(kCFAllocatorDefault
, 0, &array
, error
, *der_p
, sequence_end
);
59 *der_p
= ccder_decode_bool(&account
->user_public_trusted
, *der_p
, sequence_end
);
60 *der_p
= der_decode_public_bytes(kCFAllocatorDefault
, kSecECDSAAlgorithmID
, &account
->user_public
, error
, *der_p
, sequence_end
);
61 *der_p
= der_decode_data_or_null(kCFAllocatorDefault
, &account
->user_key_parameters
, error
, *der_p
, sequence_end
);
62 *der_p
= der_decode_dictionary(kCFAllocatorDefault
, kCFPropertyListMutableContainers
, (CFDictionaryRef
*) &account
->retired_peers
, error
, *der_p
, sequence_end
);
63 if (*der_p
!= sequence_end
)
66 __block
bool success
= true;
68 require_quiet(array
&& *der_p
, fail
);
70 CFArrayForEach(array
, ^(const void *value
) {
72 if (isString(value
)) {
73 CFDictionaryAddValue(account
->circles
, value
, kCFNull
);
75 CFDataRef circleData
= NULL
;
76 CFDataRef fullPeerInfoData
= NULL
;
79 circleData
= (CFDataRef
) value
;
80 } else if (isArray(value
)) {
81 CFArrayRef pair
= (CFArrayRef
) value
;
83 CFTypeRef circleObject
= CFArrayGetValueAtIndex(pair
, 0);
84 CFTypeRef fullPeerInfoObject
= CFArrayGetValueAtIndex(pair
, 1);
86 if (CFArrayGetCount(pair
) == 2 && isData(circleObject
) && isData(fullPeerInfoObject
)) {
87 circleData
= (CFDataRef
) circleObject
;
88 fullPeerInfoData
= (CFDataRef
) fullPeerInfoObject
;
93 SOSCircleRef circle
= SOSCircleCreateFromData(kCFAllocatorDefault
, circleData
, error
);
94 require_action_quiet(circle
, fail
, success
= false);
96 CFStringRef circleName
= SOSCircleGetName(circle
);
97 CFDictionaryAddValue(account
->circles
, circleName
, circle
);
99 if (fullPeerInfoData
) {
100 SOSFullPeerInfoRef full_peer
= SOSFullPeerInfoCreateFromData(kCFAllocatorDefault
, fullPeerInfoData
, error
);
101 require_action_quiet(full_peer
, fail
, success
= false);
103 CFDictionaryAddValue(account
->circle_identities
, circleName
, full_peer
);
104 CFReleaseNull(full_peer
);
107 CFReleaseNull(circle
);
112 CFReleaseNull(array
);
114 require_quiet(success
, fail
);
115 require_action_quiet(SOSAccountEnsureFactoryCircles(account
), fail
,
116 SOSCreateError(kSOSErrorBadFormat
, CFSTR("Cannot EnsureFactoryCircles"), (error
!= NULL
) ? *error
: NULL
, error
));
121 // Create a default error if we don't have one:
122 SOSCreateError(kSOSErrorBadFormat
, CFSTR("Bad Account DER"), NULL
, error
);
123 CFReleaseNull(account
);
127 SOSAccountRef
SOSAccountCreateFromDER_V2(CFAllocatorRef allocator
,
128 SOSDataSourceFactoryRef factory
,
130 const uint8_t** der_p
, const uint8_t *der_end
)
132 SOSAccountRef account
= NULL
;
133 const uint8_t *dersave
= *der_p
;
134 const uint8_t *derend
= der_end
;
136 const uint8_t *sequence_end
;
137 *der_p
= ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, &sequence_end
, *der_p
, der_end
);
140 CFDictionaryRef decoded_gestalt
= NULL
;
141 *der_p
= der_decode_dictionary(kCFAllocatorDefault
, kCFPropertyListImmutable
, &decoded_gestalt
, error
,
147 account
= SOSAccountCreateBasic(allocator
, decoded_gestalt
, factory
);
148 CFReleaseNull(decoded_gestalt
);
151 CFArrayRef array
= NULL
;
152 *der_p
= der_decode_array(kCFAllocatorDefault
, 0, &array
, error
, *der_p
, sequence_end
);
154 uint64_t tmp_departure_code
= kSOSNeverAppliedToCircle
;
155 *der_p
= ccder_decode_uint64(&tmp_departure_code
, *der_p
, sequence_end
);
156 *der_p
= ccder_decode_bool(&account
->user_public_trusted
, *der_p
, sequence_end
);
157 *der_p
= der_decode_public_bytes(kCFAllocatorDefault
, kSecECDSAAlgorithmID
, &account
->user_public
, error
, *der_p
, sequence_end
);
158 *der_p
= der_decode_data_or_null(kCFAllocatorDefault
, &account
->user_key_parameters
, error
, *der_p
, sequence_end
);
159 *der_p
= der_decode_dictionary(kCFAllocatorDefault
, kCFPropertyListMutableContainers
, (CFDictionaryRef
*) &account
->retired_peers
, error
, *der_p
, sequence_end
);
160 if (*der_p
!= sequence_end
)
162 account
->departure_code
= (enum DepartureReason
) tmp_departure_code
;
164 __block
bool success
= true;
166 require_quiet(array
&& *der_p
, fail
);
168 CFArrayForEach(array
, ^(const void *value
) {
170 if (isString(value
)) {
171 CFDictionaryAddValue(account
->circles
, value
, kCFNull
);
173 CFDataRef circleData
= NULL
;
174 CFDataRef fullPeerInfoData
= NULL
;
177 circleData
= (CFDataRef
) value
;
178 } else if (isArray(value
)) {
179 CFArrayRef pair
= (CFArrayRef
) value
;
181 CFTypeRef circleObject
= CFArrayGetValueAtIndex(pair
, 0);
182 CFTypeRef fullPeerInfoObject
= CFArrayGetValueAtIndex(pair
, 1);
184 if (CFArrayGetCount(pair
) == 2 && isData(circleObject
) && isData(fullPeerInfoObject
)) {
185 circleData
= (CFDataRef
) circleObject
;
186 fullPeerInfoData
= (CFDataRef
) fullPeerInfoObject
;
191 SOSCircleRef circle
= SOSCircleCreateFromData(kCFAllocatorDefault
, circleData
, error
);
192 require_action_quiet(circle
, fail
, success
= false);
194 CFStringRef circleName
= SOSCircleGetName(circle
);
195 CFDictionaryAddValue(account
->circles
, circleName
, circle
);
197 if (fullPeerInfoData
) {
198 SOSFullPeerInfoRef full_peer
= SOSFullPeerInfoCreateFromData(kCFAllocatorDefault
, fullPeerInfoData
, error
);
199 require_action_quiet(full_peer
, fail
, success
= false);
201 CFDictionaryAddValue(account
->circle_identities
, circleName
, full_peer
);
202 CFReleaseSafe(full_peer
);
205 CFReleaseNull(circle
);
210 CFReleaseNull(array
);
212 require_quiet(success
, fail
);
213 require_action_quiet(SOSAccountEnsureFactoryCircles(account
), fail
,
214 SOSCreateError(kSOSErrorBadFormat
, CFSTR("Cannot EnsureFactoryCircles"), (error
!= NULL
) ? *error
: NULL
, error
));
219 // Create a default error if we don't have one:
220 account
->factory
= NULL
; // give the factory back.
221 CFReleaseNull(account
);
222 // Try the der inflater from the previous release.
223 account
= SOSAccountCreateFromDER_V1(allocator
, factory
, error
, &dersave
, derend
);
224 if(account
) account
->departure_code
= kSOSNeverAppliedToCircle
;
228 static void SOSAccountConvertKVSDictionaryToRetirementDictionary(SOSAccountRef account
)
230 CFMutableDictionaryRef old_retired_peers
= account
->retired_peers
;
231 account
->retired_peers
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
233 CFDictionaryForEach(old_retired_peers
, ^(const void *key
, const void *value
) {
234 if (isDictionary(value
)) {
235 CFDictionaryAddValue(account
->retired_peers
, key
, value
);
236 } else if (isString(key
) && isData(value
)) {
237 CFDataRef retired_peer_data
= (CFDataRef
) value
;
238 CFStringRef circle_name
= NULL
;
239 CFStringRef retired_peer_id
= NULL
;
241 if (kRetirementKey
== SOSKVSKeyGetKeyTypeAndParse(key
, &circle_name
, &retired_peer_id
, NULL
)) {
242 CFMutableDictionaryRef circle_retirees
= CFDictionaryEnsureCFDictionaryAndGetCurrentValue(account
->retired_peers
, circle_name
);
244 CFDictionarySetValue(circle_retirees
, retired_peer_id
, retired_peer_data
);
247 CFReleaseSafe(circle_name
);
248 CFReleaseSafe(retired_peer_id
);
251 CFReleaseSafe(old_retired_peers
);
255 #define CURRENT_ACCOUNT_PERSISTENT_VERSION 6
257 SOSAccountRef
SOSAccountCreateFromDER(CFAllocatorRef allocator
,
258 SOSDataSourceFactoryRef factory
,
260 const uint8_t** der_p
, const uint8_t *der_end
)
262 SOSAccountRef account
= NULL
;
263 #if UPGRADE_FROM_PREVIOUS_VERSION
264 const uint8_t *dersave
= *der_p
;
265 const uint8_t *derend
= der_end
;
267 uint64_t version
= 0;
269 const uint8_t *sequence_end
;
270 *der_p
= ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, &sequence_end
, *der_p
, der_end
);
271 *der_p
= ccder_decode_uint64(&version
, *der_p
, sequence_end
);
272 if(!(*der_p
) || version
< CURRENT_ACCOUNT_PERSISTENT_VERSION
) {
273 #if UPGRADE_FROM_PREVIOUS_VERSION
274 return SOSAccountCreateFromDER_V3(allocator
, factory
, error
, &dersave
, derend
);
281 CFDictionaryRef decoded_gestalt
= NULL
;
282 *der_p
= der_decode_dictionary(kCFAllocatorDefault
, kCFPropertyListImmutable
, &decoded_gestalt
, error
,
288 account
= SOSAccountCreateBasic(allocator
, decoded_gestalt
, factory
);
289 CFReleaseNull(decoded_gestalt
);
292 CFArrayRef array
= NULL
;
293 *der_p
= der_decode_array(kCFAllocatorDefault
, 0, &array
, error
, *der_p
, sequence_end
);
295 uint64_t tmp_departure_code
= kSOSNeverAppliedToCircle
;
296 *der_p
= ccder_decode_uint64(&tmp_departure_code
, *der_p
, sequence_end
);
297 *der_p
= ccder_decode_bool(&account
->user_public_trusted
, *der_p
, sequence_end
);
298 *der_p
= der_decode_public_bytes(kCFAllocatorDefault
, kSecECDSAAlgorithmID
, &account
->user_public
, error
, *der_p
, sequence_end
);
299 *der_p
= der_decode_public_bytes(kCFAllocatorDefault
, kSecECDSAAlgorithmID
, &account
->previous_public
, error
, *der_p
, sequence_end
);
300 *der_p
= der_decode_data_or_null(kCFAllocatorDefault
, &account
->user_key_parameters
, error
, *der_p
, sequence_end
);
301 *der_p
= der_decode_dictionary(kCFAllocatorDefault
, kCFPropertyListMutableContainers
, (CFDictionaryRef
*) &account
->retired_peers
, error
, *der_p
, sequence_end
);
302 if (*der_p
!= sequence_end
)
304 account
->departure_code
= (enum DepartureReason
) tmp_departure_code
;
306 __block
bool success
= true;
308 require_quiet(array
&& *der_p
, fail
);
310 CFArrayForEach(array
, ^(const void *value
) {
312 if (isString(value
)) {
313 CFDictionaryAddValue(account
->circles
, value
, kCFNull
);
315 CFDataRef circleData
= NULL
;
316 CFDataRef fullPeerInfoData
= NULL
;
319 circleData
= (CFDataRef
) value
;
320 } else if (isArray(value
)) {
321 CFArrayRef pair
= (CFArrayRef
) value
;
323 CFTypeRef circleObject
= CFArrayGetValueAtIndex(pair
, 0);
324 CFTypeRef fullPeerInfoObject
= CFArrayGetValueAtIndex(pair
, 1);
326 if (CFArrayGetCount(pair
) == 2 && isData(circleObject
) && isData(fullPeerInfoObject
)) {
327 circleData
= (CFDataRef
) circleObject
;
328 fullPeerInfoData
= (CFDataRef
) fullPeerInfoObject
;
333 SOSCircleRef circle
= SOSCircleCreateFromData(kCFAllocatorDefault
, circleData
, error
);
334 require_action_quiet(circle
, fail
, success
= false);
336 CFStringRef circleName
= SOSCircleGetName(circle
);
337 CFDictionaryAddValue(account
->circles
, circleName
, circle
);
339 if (fullPeerInfoData
) {
340 SOSFullPeerInfoRef full_peer
= SOSFullPeerInfoCreateFromData(kCFAllocatorDefault
, fullPeerInfoData
, error
);
341 require_action_quiet(full_peer
, fail
, success
= false);
343 CFDictionaryAddValue(account
->circle_identities
, circleName
, full_peer
);
344 CFReleaseNull(full_peer
);
347 CFReleaseNull(circle
);
352 CFReleaseNull(array
);
354 require_quiet(success
, fail
);
356 require_action_quiet(SOSAccountEnsureFactoryCircles(account
), fail
,
357 SOSCreateError(kSOSErrorBadFormat
, CFSTR("Cannot EnsureFactoryCircles"), (error
!= NULL
) ? *error
: NULL
, error
));
359 SOSAccountConvertKVSDictionaryToRetirementDictionary(account
);
364 account
->factory
= NULL
; // give the factory back.
365 CFReleaseNull(account
);
370 SOSAccountRef
SOSAccountCreateFromDER_V3(CFAllocatorRef allocator
,
371 SOSDataSourceFactoryRef factory
,
373 const uint8_t** der_p
, const uint8_t *der_end
)
375 SOSAccountRef account
= NULL
;
376 uint64_t version
= 0;
378 const uint8_t *sequence_end
;
379 *der_p
= ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, &sequence_end
, *der_p
, der_end
);
380 *der_p
= ccder_decode_uint64(&version
, *der_p
, sequence_end
);
381 if(!(*der_p
) || version
!= 3) {
382 // In this case we want to silently fail so that an account gets newly created.
387 CFDictionaryRef decoded_gestalt
= NULL
;
388 *der_p
= der_decode_dictionary(kCFAllocatorDefault
, kCFPropertyListImmutable
, &decoded_gestalt
, error
,
394 account
= SOSAccountCreateBasic(allocator
, decoded_gestalt
, factory
);
395 CFReleaseNull(decoded_gestalt
);
398 CFArrayRef array
= NULL
;
399 *der_p
= der_decode_array(kCFAllocatorDefault
, 0, &array
, error
, *der_p
, sequence_end
);
401 uint64_t tmp_departure_code
= kSOSNeverAppliedToCircle
;
402 *der_p
= ccder_decode_uint64(&tmp_departure_code
, *der_p
, sequence_end
);
403 *der_p
= ccder_decode_bool(&account
->user_public_trusted
, *der_p
, sequence_end
);
404 *der_p
= der_decode_public_bytes(kCFAllocatorDefault
, kSecECDSAAlgorithmID
, &account
->user_public
, error
, *der_p
, sequence_end
);
405 *der_p
= der_decode_data_or_null(kCFAllocatorDefault
, &account
->user_key_parameters
, error
, *der_p
, sequence_end
);
406 *der_p
= der_decode_dictionary(kCFAllocatorDefault
, kCFPropertyListMutableContainers
, (CFDictionaryRef
*) &account
->retired_peers
, error
, *der_p
, sequence_end
);
407 if (*der_p
!= sequence_end
)
409 account
->departure_code
= (enum DepartureReason
) tmp_departure_code
;
411 __block
bool success
= true;
413 require_quiet(array
&& *der_p
, fail
);
415 CFArrayForEach(array
, ^(const void *value
) {
417 if (isString(value
)) {
418 CFDictionaryAddValue(account
->circles
, value
, kCFNull
);
420 CFDataRef circleData
= NULL
;
421 CFDataRef fullPeerInfoData
= NULL
;
424 circleData
= (CFDataRef
) value
;
425 } else if (isArray(value
)) {
426 CFArrayRef pair
= (CFArrayRef
) value
;
428 CFTypeRef circleObject
= CFArrayGetValueAtIndex(pair
, 0);
429 CFTypeRef fullPeerInfoObject
= CFArrayGetValueAtIndex(pair
, 1);
431 if (CFArrayGetCount(pair
) == 2 && isData(circleObject
) && isData(fullPeerInfoObject
)) {
432 circleData
= (CFDataRef
) circleObject
;
433 fullPeerInfoData
= (CFDataRef
) fullPeerInfoObject
;
438 SOSCircleRef circle
= SOSCircleCreateFromData(kCFAllocatorDefault
, circleData
, error
);
439 require_action_quiet(circle
, fail
, success
= false);
441 CFStringRef circleName
= SOSCircleGetName(circle
);
442 CFDictionaryAddValue(account
->circles
, circleName
, circle
);
444 if (fullPeerInfoData
) {
445 SOSFullPeerInfoRef full_peer
= SOSFullPeerInfoCreateFromData(kCFAllocatorDefault
, fullPeerInfoData
, error
);
446 require_action_quiet(full_peer
, fail
, success
= false);
448 CFDictionaryAddValue(account
->circle_identities
, circleName
, full_peer
);
449 CFReleaseNull(full_peer
);
452 CFReleaseNull(circle
);
457 CFReleaseNull(array
);
459 require_quiet(success
, fail
);
460 require_action_quiet(SOSAccountEnsureFactoryCircles(account
), fail
,
461 SOSCreateError(kSOSErrorBadFormat
, CFSTR("Cannot EnsureFactoryCircles"), (error
!= NULL
) ? *error
: NULL
, error
));
463 SOSAccountConvertKVSDictionaryToRetirementDictionary(account
);
468 // Create a default error if we don't have one:
469 account
->factory
= NULL
; // give the factory back.
470 CFReleaseNull(account
);
471 // Don't try the der inflater from the previous release.
472 // account = SOSAccountCreateFromDER_V2(allocator, transport, factory, error, &dersave, derend);
473 if(account
) account
->departure_code
= kSOSNeverAppliedToCircle
;
477 SOSAccountRef
SOSAccountCreateFromData(CFAllocatorRef allocator
, CFDataRef circleData
,
478 SOSDataSourceFactoryRef factory
,
481 size_t size
= CFDataGetLength(circleData
);
482 const uint8_t *der
= CFDataGetBytePtr(circleData
);
483 SOSAccountRef account
= SOSAccountCreateFromDER(allocator
, factory
,
489 static CFMutableArrayRef
SOSAccountCopyCircleArrayToEncode(SOSAccountRef account
)
491 CFMutableArrayRef arrayToEncode
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
493 CFDictionaryForEach(account
->circles
, ^(const void *key
, const void *value
) {
495 CFArrayAppendValue(arrayToEncode
, key
); // Encode the name of the circle that's out of date.
497 SOSCircleRef circle
= (SOSCircleRef
) value
;
498 CFDataRef encodedCircle
= SOSCircleCopyEncodedData(circle
, kCFAllocatorDefault
, NULL
);
499 CFTypeRef arrayEntry
= encodedCircle
;
500 CFRetainSafe(arrayEntry
);
502 SOSFullPeerInfoRef full_peer
= (SOSFullPeerInfoRef
) CFDictionaryGetValue(account
->circle_identities
, key
);
505 CFDataRef encodedPeer
= SOSFullPeerInfoCopyEncodedData(full_peer
, kCFAllocatorDefault
, NULL
);
506 CFTypeRef originalArrayEntry
= arrayEntry
;
507 arrayEntry
= CFArrayCreateForCFTypes(kCFAllocatorDefault
, encodedCircle
, encodedPeer
, NULL
);
509 CFReleaseSafe(originalArrayEntry
);
510 CFReleaseNull(encodedPeer
);
513 CFArrayAppendValue(arrayToEncode
, arrayEntry
);
515 CFReleaseSafe(arrayEntry
);
516 CFReleaseNull(encodedCircle
);
521 return arrayToEncode
;
524 size_t SOSAccountGetDEREncodedSize(SOSAccountRef account
, CFErrorRef
*error
)
526 size_t sequence_size
= 0;
527 CFMutableArrayRef arrayToEncode
= SOSAccountCopyCircleArrayToEncode(account
);
528 uint64_t version
= CURRENT_ACCOUNT_PERSISTENT_VERSION
;
530 require_quiet(accumulate_size(&sequence_size
, ccder_sizeof_uint64(version
)), fail
);
531 require_quiet(accumulate_size(&sequence_size
, der_sizeof_dictionary(account
->gestalt
, error
)), fail
);
532 require_quiet(accumulate_size(&sequence_size
, der_sizeof_array(arrayToEncode
, error
)), fail
);
533 require_quiet(accumulate_size(&sequence_size
, ccder_sizeof_uint64(account
->departure_code
)), fail
);
534 require_quiet(accumulate_size(&sequence_size
, ccder_sizeof_bool(account
->user_public_trusted
, error
)), fail
);
535 require_quiet(accumulate_size(&sequence_size
, der_sizeof_public_bytes(account
->user_public
, error
)), fail
);
536 require_quiet(accumulate_size(&sequence_size
, der_sizeof_public_bytes(account
->previous_public
, error
)), fail
);
537 require_quiet(accumulate_size(&sequence_size
, der_sizeof_data_or_null(account
->user_key_parameters
, error
)), fail
);
538 require_quiet(accumulate_size(&sequence_size
, der_sizeof_dictionary(account
->retired_peers
, error
)), fail
);
540 CFReleaseNull(arrayToEncode
);
541 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, sequence_size
);
544 CFReleaseNull(arrayToEncode
);
545 SecCFDERCreateError(kSecDERErrorUnknownEncoding
, CFSTR("don't know how to encode"), NULL
, error
);
549 uint8_t* SOSAccountEncodeToDER(SOSAccountRef account
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
)
551 CFMutableArrayRef arrayToEncode
= SOSAccountCopyCircleArrayToEncode(account
);
552 uint64_t version
= CURRENT_ACCOUNT_PERSISTENT_VERSION
;
553 der_end
= ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
,
554 ccder_encode_uint64(version
, der
,
555 der_encode_dictionary(account
->gestalt
, error
, der
,
556 der_encode_array(arrayToEncode
, error
, der
,
557 ccder_encode_uint64(account
->departure_code
, der
,
558 ccder_encode_bool(account
->user_public_trusted
, der
,
559 der_encode_public_bytes(account
->user_public
, error
, der
,
560 der_encode_public_bytes(account
->previous_public
, error
, der
,
561 der_encode_data_or_null(account
->user_key_parameters
, error
, der
,
562 der_encode_dictionary(account
->retired_peers
, error
, der
, der_end
))))))))));
564 CFReleaseNull(arrayToEncode
);
571 size_t SOSAccountGetDEREncodedSize_V3(SOSAccountRef account
, CFErrorRef
*error
)
573 size_t sequence_size
= 0;
574 CFMutableArrayRef arrayToEncode
= SOSAccountCopyCircleArrayToEncode(account
);
575 uint64_t version
= CURRENT_ACCOUNT_PERSISTENT_VERSION
;
577 require_quiet(accumulate_size(&sequence_size
, ccder_sizeof_uint64(version
)), fail
);
578 require_quiet(accumulate_size(&sequence_size
, der_sizeof_dictionary(account
->gestalt
, error
)), fail
);
579 require_quiet(accumulate_size(&sequence_size
, der_sizeof_array(arrayToEncode
, error
)), fail
);
580 require_quiet(accumulate_size(&sequence_size
, ccder_sizeof_uint64(account
->departure_code
)), fail
);
581 require_quiet(accumulate_size(&sequence_size
, ccder_sizeof_bool(account
->user_public_trusted
, error
)), fail
);
582 require_quiet(accumulate_size(&sequence_size
, der_sizeof_public_bytes(account
->user_public
, error
)), fail
);
583 require_quiet(accumulate_size(&sequence_size
, der_sizeof_data_or_null(account
->user_key_parameters
, error
)), fail
);
584 require_quiet(accumulate_size(&sequence_size
, der_sizeof_dictionary(account
->retired_peers
, error
)), fail
);
586 CFReleaseNull(arrayToEncode
);
587 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, sequence_size
);
590 CFReleaseNull(arrayToEncode
);
591 SecCFDERCreateError(kSecDERErrorUnknownEncoding
, CFSTR("don't know how to encode"), NULL
, error
);
595 uint8_t* SOSAccountEncodeToDER_V3(SOSAccountRef account
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
)
597 CFMutableArrayRef arrayToEncode
= SOSAccountCopyCircleArrayToEncode(account
);
598 uint64_t version
= 3;
599 der_end
= ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
,
600 ccder_encode_uint64(version
, der
,
601 der_encode_dictionary(account
->gestalt
, error
, der
,
602 der_encode_array(arrayToEncode
, error
, der
,
603 ccder_encode_uint64(account
->departure_code
, der
,
604 ccder_encode_bool(account
->user_public_trusted
, der
,
605 der_encode_public_bytes(account
->user_public
, error
, der
,
606 der_encode_data_or_null(account
->user_key_parameters
, error
, der
,
607 der_encode_dictionary(account
->retired_peers
, error
, der
, der_end
)))))))));
609 CFReleaseNull(arrayToEncode
);
614 /* Original V2 encoders */
616 size_t SOSAccountGetDEREncodedSize_V2(SOSAccountRef account
, CFErrorRef
*error
)
618 size_t sequence_size
= 0;
619 CFMutableArrayRef arrayToEncode
= SOSAccountCopyCircleArrayToEncode(account
);
621 require_quiet(accumulate_size(&sequence_size
, der_sizeof_dictionary(account
->gestalt
, error
)), fail
);
622 require_quiet(accumulate_size(&sequence_size
, der_sizeof_array(arrayToEncode
, error
)), fail
);
623 require_quiet(accumulate_size(&sequence_size
, ccder_sizeof_uint64(account
->departure_code
)), fail
);
624 require_quiet(accumulate_size(&sequence_size
, ccder_sizeof_bool(account
->user_public_trusted
, error
)), fail
);
625 require_quiet(accumulate_size(&sequence_size
, der_sizeof_public_bytes(account
->user_public
, error
)), fail
);
626 require_quiet(accumulate_size(&sequence_size
, der_sizeof_data_or_null(account
->user_key_parameters
, error
)), fail
);
627 require_quiet(accumulate_size(&sequence_size
, der_sizeof_dictionary(account
->retired_peers
, error
)), fail
);
629 CFReleaseNull(arrayToEncode
);
630 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, sequence_size
);
633 CFReleaseNull(arrayToEncode
);
634 SecCFDERCreateError(kSecDERErrorUnknownEncoding
, CFSTR("don't know how to encode"), NULL
, error
);
638 uint8_t* SOSAccountEncodeToDER_V2(SOSAccountRef account
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
)
640 CFMutableArrayRef arrayToEncode
= SOSAccountCopyCircleArrayToEncode(account
);
642 der_end
= ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
,
643 der_encode_dictionary(account
->gestalt
, error
, der
,
644 der_encode_array(arrayToEncode
, error
, der
,
645 ccder_encode_uint64(account
->departure_code
, der
,
646 ccder_encode_bool(account
->user_public_trusted
, der
,
647 der_encode_public_bytes(account
->user_public
, error
, der
,
648 der_encode_data_or_null(account
->user_key_parameters
, error
, der
,
649 der_encode_dictionary(account
->retired_peers
, error
, der
, der_end
))))))));
651 CFReleaseNull(arrayToEncode
);
657 /* Original V1 encoders */
660 size_t SOSAccountGetDEREncodedSize_V1(SOSAccountRef account
, CFErrorRef
*error
)
662 size_t sequence_size
= 0;
663 CFMutableArrayRef arrayToEncode
= SOSAccountCopyCircleArrayToEncode(account
);
665 require_quiet(accumulate_size(&sequence_size
, der_sizeof_dictionary(account
->gestalt
, error
)), fail
);
666 require_quiet(accumulate_size(&sequence_size
, der_sizeof_array(arrayToEncode
, error
)), fail
);
667 require_quiet(accumulate_size(&sequence_size
, ccder_sizeof_bool(account
->user_public_trusted
, error
)), fail
);
668 require_quiet(accumulate_size(&sequence_size
, der_sizeof_public_bytes(account
->user_public
, error
)), fail
);
669 require_quiet(accumulate_size(&sequence_size
, der_sizeof_data_or_null(account
->user_key_parameters
, error
)), fail
);
670 require_quiet(accumulate_size(&sequence_size
, der_sizeof_dictionary(account
->retired_peers
, error
)), fail
);
672 CFReleaseNull(arrayToEncode
);
673 return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, sequence_size
);
676 CFReleaseNull(arrayToEncode
);
677 SecCFDERCreateError(kSecDERErrorUnknownEncoding
, CFSTR("don't know how to encode"), NULL
, error
);
681 uint8_t* SOSAccountEncodeToDER_V1(SOSAccountRef account
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
)
683 CFMutableArrayRef arrayToEncode
= SOSAccountCopyCircleArrayToEncode(account
);
685 der_end
= ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
,
686 der_encode_dictionary(account
->gestalt
, error
, der
,
687 der_encode_array(arrayToEncode
, error
, der
,
688 ccder_encode_bool(account
->user_public_trusted
, der
,
689 der_encode_public_bytes(account
->user_public
, error
, der
,
690 der_encode_data_or_null(account
->user_key_parameters
, error
, der
,
691 der_encode_dictionary(account
->retired_peers
, error
, der
, der_end
)))))));
693 CFReleaseNull(arrayToEncode
);
698 /************************/
700 CFDataRef
SOSAccountCopyEncodedData(SOSAccountRef account
, CFAllocatorRef allocator
, CFErrorRef
*error
)
702 size_t size
= SOSAccountGetDEREncodedSize(account
, error
);
705 uint8_t buffer
[size
];
706 uint8_t* start
= SOSAccountEncodeToDER(account
, error
, buffer
, buffer
+ sizeof(buffer
));
707 CFDataRef result
= CFDataCreate(kCFAllocatorDefault
, start
, size
);