X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/sec/SOSCircle/SecureObjectSync/SOSAccountPersistence.c?ds=inline diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSAccountPersistence.c b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountPersistence.c deleted file mode 100644 index ebaed87f..00000000 --- a/Security/sec/SOSCircle/SecureObjectSync/SOSAccountPersistence.c +++ /dev/null @@ -1,710 +0,0 @@ -/* - * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#include -#include -#include -#include -#include "SOSAccountPriv.h" - -#include -#include - -SOSAccountRef SOSAccountCreateFromDER_V1(CFAllocatorRef allocator, - SOSDataSourceFactoryRef factory, - CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end) -{ - SOSAccountRef account = NULL; - - const uint8_t *sequence_end; - *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); - - { - CFDictionaryRef decoded_gestalt = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, - *der_p, der_end); - - if (*der_p == 0) - return NULL; - - account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory); - CFReleaseNull(decoded_gestalt); - } - - CFArrayRef array = NULL; - *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); - - *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); - *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); - *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); - if (*der_p != sequence_end) - *der_p = NULL; - - __block bool success = true; - - require_quiet(array && *der_p, fail); - - CFArrayForEach(array, ^(const void *value) { - if (success) { - if (isString(value)) { - CFDictionaryAddValue(account->circles, value, kCFNull); - } else { - CFDataRef circleData = NULL; - CFDataRef fullPeerInfoData = NULL; - - if (isData(value)) { - circleData = (CFDataRef) value; - } else if (isArray(value)) { - CFArrayRef pair = (CFArrayRef) value; - - CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); - CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); - - if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { - circleData = (CFDataRef) circleObject; - fullPeerInfoData = (CFDataRef) fullPeerInfoObject; - } - } - - if (circleData) { - SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); - require_action_quiet(circle, fail, success = false); - - CFStringRef circleName = SOSCircleGetName(circle); - CFDictionaryAddValue(account->circles, circleName, circle); - - if (fullPeerInfoData) { - SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); - require_action_quiet(full_peer, fail, success = false); - - CFDictionaryAddValue(account->circle_identities, circleName, full_peer); - CFReleaseNull(full_peer); - } - fail: - CFReleaseNull(circle); - } - } - } - }); - CFReleaseNull(array); - - require_quiet(success, fail); - require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, - SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); - - return account; - -fail: - // Create a default error if we don't have one: - SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Account DER"), NULL, error); - CFReleaseNull(account); - return NULL; -} - -SOSAccountRef SOSAccountCreateFromDER_V2(CFAllocatorRef allocator, - SOSDataSourceFactoryRef factory, - CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end) -{ - SOSAccountRef account = NULL; - const uint8_t *dersave = *der_p; - const uint8_t *derend = der_end; - - const uint8_t *sequence_end; - *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); - - { - CFDictionaryRef decoded_gestalt = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, - *der_p, der_end); - - if (*der_p == 0) - return NULL; - - account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory); - CFReleaseNull(decoded_gestalt); - } - - CFArrayRef array = NULL; - *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); - - uint64_t tmp_departure_code = kSOSNeverAppliedToCircle; - *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, sequence_end); - *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); - *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); - *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); - if (*der_p != sequence_end) - *der_p = NULL; - account->departure_code = (enum DepartureReason) tmp_departure_code; - - __block bool success = true; - - require_quiet(array && *der_p, fail); - - CFArrayForEach(array, ^(const void *value) { - if (success) { - if (isString(value)) { - CFDictionaryAddValue(account->circles, value, kCFNull); - } else { - CFDataRef circleData = NULL; - CFDataRef fullPeerInfoData = NULL; - - if (isData(value)) { - circleData = (CFDataRef) value; - } else if (isArray(value)) { - CFArrayRef pair = (CFArrayRef) value; - - CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); - CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); - - if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { - circleData = (CFDataRef) circleObject; - fullPeerInfoData = (CFDataRef) fullPeerInfoObject; - } - } - - if (circleData) { - SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); - require_action_quiet(circle, fail, success = false); - - CFStringRef circleName = SOSCircleGetName(circle); - CFDictionaryAddValue(account->circles, circleName, circle); - - if (fullPeerInfoData) { - SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); - require_action_quiet(full_peer, fail, success = false); - - CFDictionaryAddValue(account->circle_identities, circleName, full_peer); - CFReleaseSafe(full_peer); - } - fail: - CFReleaseNull(circle); - } - } - } - }); - CFReleaseNull(array); - - require_quiet(success, fail); - require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, - SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); - - return account; - -fail: - // Create a default error if we don't have one: - account->factory = NULL; // give the factory back. - CFReleaseNull(account); - // Try the der inflater from the previous release. - account = SOSAccountCreateFromDER_V1(allocator, factory, error, &dersave, derend); - if(account) account->departure_code = kSOSNeverAppliedToCircle; - return account; -} - -static void SOSAccountConvertKVSDictionaryToRetirementDictionary(SOSAccountRef account) -{ - CFMutableDictionaryRef old_retired_peers = account->retired_peers; - account->retired_peers = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - - CFDictionaryForEach(old_retired_peers, ^(const void *key, const void *value) { - if (isDictionary(value)) { - CFDictionaryAddValue(account->retired_peers, key, value); - } else if (isString(key) && isData(value)) { - CFDataRef retired_peer_data = (CFDataRef) value; - CFStringRef circle_name = NULL; - CFStringRef retired_peer_id = NULL; - - if (kRetirementKey == SOSKVSKeyGetKeyTypeAndParse(key, &circle_name, &retired_peer_id, NULL)) { - CFMutableDictionaryRef circle_retirees = CFDictionaryEnsureCFDictionaryAndGetCurrentValue(account->retired_peers, circle_name); - - CFDictionarySetValue(circle_retirees, retired_peer_id, retired_peer_data); - } - - CFReleaseSafe(circle_name); - CFReleaseSafe(retired_peer_id); - } - }); - CFReleaseSafe(old_retired_peers); -} - - -#define CURRENT_ACCOUNT_PERSISTENT_VERSION 6 - -SOSAccountRef SOSAccountCreateFromDER(CFAllocatorRef allocator, - SOSDataSourceFactoryRef factory, - CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end) -{ - SOSAccountRef account = NULL; -#if UPGRADE_FROM_PREVIOUS_VERSION - const uint8_t *dersave = *der_p; - const uint8_t *derend = der_end; -#endif - uint64_t version = 0; - - const uint8_t *sequence_end; - *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); - *der_p = ccder_decode_uint64(&version, *der_p, sequence_end); - if(!(*der_p) || version < CURRENT_ACCOUNT_PERSISTENT_VERSION) { -#if UPGRADE_FROM_PREVIOUS_VERSION - return SOSAccountCreateFromDER_V3(allocator, factory, error, &dersave, derend); -#else - return NULL; -#endif - } - - { - CFDictionaryRef decoded_gestalt = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, - *der_p, der_end); - - if (*der_p == 0) - return NULL; - - account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory); - CFReleaseNull(decoded_gestalt); - } - - CFArrayRef array = NULL; - *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); - - uint64_t tmp_departure_code = kSOSNeverAppliedToCircle; - *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, sequence_end); - *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); - *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); - *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->previous_public, error, *der_p, sequence_end); - *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); - if (*der_p != sequence_end) - *der_p = NULL; - account->departure_code = (enum DepartureReason) tmp_departure_code; - - __block bool success = true; - - require_quiet(array && *der_p, fail); - - CFArrayForEach(array, ^(const void *value) { - if (success) { - if (isString(value)) { - CFDictionaryAddValue(account->circles, value, kCFNull); - } else { - CFDataRef circleData = NULL; - CFDataRef fullPeerInfoData = NULL; - - if (isData(value)) { - circleData = (CFDataRef) value; - } else if (isArray(value)) { - CFArrayRef pair = (CFArrayRef) value; - - CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); - CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); - - if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { - circleData = (CFDataRef) circleObject; - fullPeerInfoData = (CFDataRef) fullPeerInfoObject; - } - } - - if (circleData) { - SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); - require_action_quiet(circle, fail, success = false); - - CFStringRef circleName = SOSCircleGetName(circle); - CFDictionaryAddValue(account->circles, circleName, circle); - - if (fullPeerInfoData) { - SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); - require_action_quiet(full_peer, fail, success = false); - - CFDictionaryAddValue(account->circle_identities, circleName, full_peer); - CFReleaseNull(full_peer); - } - fail: - CFReleaseNull(circle); - } - } - } - }); - CFReleaseNull(array); - - require_quiet(success, fail); - - require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, - SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); - - SOSAccountConvertKVSDictionaryToRetirementDictionary(account); - - return account; - -fail: - account->factory = NULL; // give the factory back. - CFReleaseNull(account); - return NULL; -} - - -SOSAccountRef SOSAccountCreateFromDER_V3(CFAllocatorRef allocator, - SOSDataSourceFactoryRef factory, - CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end) -{ - SOSAccountRef account = NULL; - uint64_t version = 0; - - const uint8_t *sequence_end; - *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); - *der_p = ccder_decode_uint64(&version, *der_p, sequence_end); - if(!(*der_p) || version != 3) { - // In this case we want to silently fail so that an account gets newly created. - return NULL; - } - - { - CFDictionaryRef decoded_gestalt = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, - *der_p, der_end); - - if (*der_p == 0) - return NULL; - - account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory); - CFReleaseNull(decoded_gestalt); - } - - CFArrayRef array = NULL; - *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); - - uint64_t tmp_departure_code = kSOSNeverAppliedToCircle; - *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, sequence_end); - *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); - *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); - *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); - if (*der_p != sequence_end) - *der_p = NULL; - account->departure_code = (enum DepartureReason) tmp_departure_code; - - __block bool success = true; - - require_quiet(array && *der_p, fail); - - CFArrayForEach(array, ^(const void *value) { - if (success) { - if (isString(value)) { - CFDictionaryAddValue(account->circles, value, kCFNull); - } else { - CFDataRef circleData = NULL; - CFDataRef fullPeerInfoData = NULL; - - if (isData(value)) { - circleData = (CFDataRef) value; - } else if (isArray(value)) { - CFArrayRef pair = (CFArrayRef) value; - - CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); - CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); - - if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { - circleData = (CFDataRef) circleObject; - fullPeerInfoData = (CFDataRef) fullPeerInfoObject; - } - } - - if (circleData) { - SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); - require_action_quiet(circle, fail, success = false); - - CFStringRef circleName = SOSCircleGetName(circle); - CFDictionaryAddValue(account->circles, circleName, circle); - - if (fullPeerInfoData) { - SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); - require_action_quiet(full_peer, fail, success = false); - - CFDictionaryAddValue(account->circle_identities, circleName, full_peer); - CFReleaseNull(full_peer); - } - fail: - CFReleaseNull(circle); - } - } - } - }); - CFReleaseNull(array); - - require_quiet(success, fail); - require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, - SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); - - SOSAccountConvertKVSDictionaryToRetirementDictionary(account); - - return account; - -fail: - // Create a default error if we don't have one: - account->factory = NULL; // give the factory back. - CFReleaseNull(account); - // Don't try the der inflater from the previous release. - // account = SOSAccountCreateFromDER_V2(allocator, transport, factory, error, &dersave, derend); - if(account) account->departure_code = kSOSNeverAppliedToCircle; - return account; -} - -SOSAccountRef SOSAccountCreateFromData(CFAllocatorRef allocator, CFDataRef circleData, - SOSDataSourceFactoryRef factory, - CFErrorRef* error) -{ - size_t size = CFDataGetLength(circleData); - const uint8_t *der = CFDataGetBytePtr(circleData); - SOSAccountRef account = SOSAccountCreateFromDER(allocator, factory, - error, - &der, der + size); - return account; -} - -static CFMutableArrayRef SOSAccountCopyCircleArrayToEncode(SOSAccountRef account) -{ - CFMutableArrayRef arrayToEncode = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - - CFDictionaryForEach(account->circles, ^(const void *key, const void *value) { - if (isNull(value)) { - CFArrayAppendValue(arrayToEncode, key); // Encode the name of the circle that's out of date. - } else { - SOSCircleRef circle = (SOSCircleRef) value; - CFDataRef encodedCircle = SOSCircleCopyEncodedData(circle, kCFAllocatorDefault, NULL); - CFTypeRef arrayEntry = encodedCircle; - CFRetainSafe(arrayEntry); - - SOSFullPeerInfoRef full_peer = (SOSFullPeerInfoRef) CFDictionaryGetValue(account->circle_identities, key); - - if (full_peer) { - CFDataRef encodedPeer = SOSFullPeerInfoCopyEncodedData(full_peer, kCFAllocatorDefault, NULL); - CFTypeRef originalArrayEntry = arrayEntry; - arrayEntry = CFArrayCreateForCFTypes(kCFAllocatorDefault, encodedCircle, encodedPeer, NULL); - - CFReleaseSafe(originalArrayEntry); - CFReleaseNull(encodedPeer); - } - - CFArrayAppendValue(arrayToEncode, arrayEntry); - - CFReleaseSafe(arrayEntry); - CFReleaseNull(encodedCircle); - } - - }); - - return arrayToEncode; -} - -size_t SOSAccountGetDEREncodedSize(SOSAccountRef account, CFErrorRef *error) -{ - size_t sequence_size = 0; - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - uint64_t version = CURRENT_ACCOUNT_PERSISTENT_VERSION; - - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(version)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(account->departure_code)), fail); - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->previous_public, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); - - CFReleaseNull(arrayToEncode); - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); - -fail: - CFReleaseNull(arrayToEncode); - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); - return 0; -} - -uint8_t* SOSAccountEncodeToDER(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) -{ - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - uint64_t version = CURRENT_ACCOUNT_PERSISTENT_VERSION; - der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - ccder_encode_uint64(version, der, - der_encode_dictionary(account->gestalt, error, der, - der_encode_array(arrayToEncode, error, der, - ccder_encode_uint64(account->departure_code, der, - ccder_encode_bool(account->user_public_trusted, der, - der_encode_public_bytes(account->user_public, error, der, - der_encode_public_bytes(account->previous_public, error, der, - der_encode_data_or_null(account->user_key_parameters, error, der, - der_encode_dictionary(account->retired_peers, error, der, der_end)))))))))); - - CFReleaseNull(arrayToEncode); - - return der_end; -} - - - -size_t SOSAccountGetDEREncodedSize_V3(SOSAccountRef account, CFErrorRef *error) -{ - size_t sequence_size = 0; - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - uint64_t version = CURRENT_ACCOUNT_PERSISTENT_VERSION; - - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(version)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(account->departure_code)), fail); - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); - - CFReleaseNull(arrayToEncode); - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); - -fail: - CFReleaseNull(arrayToEncode); - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); - return 0; -} - -uint8_t* SOSAccountEncodeToDER_V3(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) -{ - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - uint64_t version = 3; - der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - ccder_encode_uint64(version, der, - der_encode_dictionary(account->gestalt, error, der, - der_encode_array(arrayToEncode, error, der, - ccder_encode_uint64(account->departure_code, der, - ccder_encode_bool(account->user_public_trusted, der, - der_encode_public_bytes(account->user_public, error, der, - der_encode_data_or_null(account->user_key_parameters, error, der, - der_encode_dictionary(account->retired_peers, error, der, der_end))))))))); - - CFReleaseNull(arrayToEncode); - - return der_end; -} - -/* Original V2 encoders */ - -size_t SOSAccountGetDEREncodedSize_V2(SOSAccountRef account, CFErrorRef *error) -{ - size_t sequence_size = 0; - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(account->departure_code)), fail); - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); - - CFReleaseNull(arrayToEncode); - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); - -fail: - CFReleaseNull(arrayToEncode); - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); - return 0; -} - -uint8_t* SOSAccountEncodeToDER_V2(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) -{ - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - - der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - der_encode_dictionary(account->gestalt, error, der, - der_encode_array(arrayToEncode, error, der, - ccder_encode_uint64(account->departure_code, der, - ccder_encode_bool(account->user_public_trusted, der, - der_encode_public_bytes(account->user_public, error, der, - der_encode_data_or_null(account->user_key_parameters, error, der, - der_encode_dictionary(account->retired_peers, error, der, der_end)))))))); - - CFReleaseNull(arrayToEncode); - - return der_end; -} - - -/* Original V1 encoders */ - - -size_t SOSAccountGetDEREncodedSize_V1(SOSAccountRef account, CFErrorRef *error) -{ - size_t sequence_size = 0; - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); - - CFReleaseNull(arrayToEncode); - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); - -fail: - CFReleaseNull(arrayToEncode); - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); - return 0; -} - -uint8_t* SOSAccountEncodeToDER_V1(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) -{ - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - - der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - der_encode_dictionary(account->gestalt, error, der, - der_encode_array(arrayToEncode, error, der, - ccder_encode_bool(account->user_public_trusted, der, - der_encode_public_bytes(account->user_public, error, der, - der_encode_data_or_null(account->user_key_parameters, error, der, - der_encode_dictionary(account->retired_peers, error, der, der_end))))))); - - CFReleaseNull(arrayToEncode); - - return der_end; -} - -/************************/ - -CFDataRef SOSAccountCopyEncodedData(SOSAccountRef account, CFAllocatorRef allocator, CFErrorRef *error) -{ - size_t size = SOSAccountGetDEREncodedSize(account, error); - if (size == 0) - return NULL; - uint8_t buffer[size]; - uint8_t* start = SOSAccountEncodeToDER(account, error, buffer, buffer + sizeof(buffer)); - CFDataRef result = CFDataCreate(kCFAllocatorDefault, start, size); - return result; -} -