const uint8_t* der_decode_plist(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { if (NULL == der) return NULL; if (ccder_decode_tag == NULL) { printf("ccder functions missing, check /usr/lib/system/libcommonCrypto.dylib\n"); return NULL; } ccder_tag tag; if (NULL == ccder_decode_tag(&tag, der, der_end)) return NULL; switch (tag) { case CCDER_NULL: return der_decode_null(allocator, mutability, (CFNullRef*)pl, error, der, der_end); case CCDER_BOOLEAN: return der_decode_boolean(allocator, mutability, (CFBooleanRef*)pl, error, der, der_end); case CCDER_OCTET_STRING: return der_decode_data(allocator, mutability, (CFDataRef*)pl, error, der, der_end); case CCDER_GENERALIZED_TIME: return der_decode_date(allocator, mutability, (CFDateRef*)pl, error, der, der_end); case CCDER_CONSTRUCTED_SEQUENCE: return der_decode_array(allocator, mutability, (CFArrayRef*)pl, error, der, der_end); case CCDER_UTF8_STRING: return der_decode_string(allocator, mutability, (CFStringRef*)pl, error, der, der_end); case CCDER_INTEGER: return der_decode_number(allocator, mutability, (CFNumberRef*)pl, error, der, der_end); case CCDER_CONSTRUCTED_SET: return der_decode_dictionary(allocator, mutability, (CFDictionaryRef*)pl, error, der, der_end); default: SecCFDERCreateError(kSecDERErrorUnsupportedDERType, CFSTR("Unsupported DER Type"), NULL, error); return NULL; } }
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); } } } });