static uint8_t* der_encode_cloud_parameters(SecKeyRef publicKey, CFDataRef paramters, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) { uint8_t* original_der_end = der_end; return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, original_der_end, der, der_encode_public_bytes(publicKey, error, der, der_encode_data_or_null(paramters, error, der, der_end))); }
static uint8_t *der_encode_pbkdf2_params(size_t saltLen, const uint8_t *salt, unsigned long iterationCount, unsigned long keyLength, const uint8_t *der, uint8_t *der_end) { uint8_t* original_der_end = der_end; return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, original_der_end, der, ccder_encode_raw_octet_string(saltLen, salt, der, ccder_encode_uint64(iterationCount, der, ccder_encode_uint64(keyLength, der, der_encode_SecAsn1Oid(&CSSMOID_PKCS5_HMAC_SHA1, der, der_end))))); }
static uint8_t* SOSCoderEncodeToDER(SOSCoderRef coder, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) { if(!der_end) return NULL; uint8_t* result = NULL; CFMutableDataRef otr_state = sessSerialized(coder, error); if(otr_state) { result = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, der_encode_data(otr_state, error, der, der_encode_bool(coder->waitingForDataPacket, der, der_encode_optional_data(coder->pendingResponse, error, der, der_end)))); CFReleaseSafe(otr_state); } return result; }
uint8_t* der_encode_RecoveryKeyBag(SOSRecoveryKeyBagRef RecoveryKeyBag, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { uint8_t *result = NULL; if (der_end == NULL) return der_end; if(RecoveryKeyBag && RecoveryKeyBag->recoveryKeyBag && RecoveryKeyBag->accountDSID && RecoveryKeyBag->generation) { der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, der_encode_string(RecoveryKeyBag->accountDSID, error, der, SOSGenCountEncodeToDER(RecoveryKeyBag->generation, error, der, ccder_encode_uint64(RecoveryKeyBag->rkbVersion, der, der_encode_data(RecoveryKeyBag->recoveryKeyBag, error, der, der_end))))); require_quiet(der_end == der, errOut); result = der_end; } else { SOSCreateError(kSOSErrorEncodeFailure, CFSTR("Null RecoveryKeyBag"), NULL, error); } errOut: return result; }
uint8_t* der_encode_generalizedtime(CFAbsoluteTime at, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { return ccder_encode_constructed_tl(CCDER_GENERALIZED_TIME, der_end, der, der_encode_generalizedtime_body(at, error, der, der_end)); }
size_t der_sizeof_dictionary(CFDictionaryRef dict, CFErrorRef *error) { struct size_context context = { .success = true, .size = 0, .error = error }; CFDictionaryApplyFunction(dict, add_key_value_size, &context); if (!context.success) return 0; return ccder_sizeof(CCDER_CONSTRUCTED_SET, context.size); } static uint8_t* der_encode_key_value(CFPropertyListRef key, CFPropertyListRef value, CFErrorRef *error, const uint8_t* der, uint8_t *der_end) { return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, der_encode_plist(key, error, der, der_encode_plist(value, error, der, der_end))); } struct encode_context { bool success; CFErrorRef * error; CFMutableArrayRef list; CFAllocatorRef allocator; }; static void add_sequence_to_array(const void *key_void, const void *value_void, void *context_void) { struct encode_context *context = (struct encode_context *) context_void; if (context->success) { CFTypeRef key = (CFTypeRef) key_void; CFTypeRef value = (CFTypeRef) value_void; size_t der_size = der_sizeof_key_value(key, value, context->error); if (der_size == 0) { context-> success = false; } else { CFMutableDataRef encoded_kv = CFDataCreateMutable(context->allocator, der_size); CFDataSetLength(encoded_kv, der_size); uint8_t* const encode_begin = CFDataGetMutableBytePtr(encoded_kv); uint8_t* encode_end = encode_begin + der_size; encode_end = der_encode_key_value(key, value, context->error, encode_begin, encode_end); if (encode_end != NULL) { CFDataDeleteBytes(encoded_kv, CFRangeMake(0, (encode_end - encode_begin))); CFArrayAppendValue(context->list, encoded_kv); } else { context-> success = false; } CFReleaseNull(encoded_kv); } } } static CFComparisonResult cfdata_compare_contents(const void *val1, const void *val2, void *context __unused) { return CFDataCompare((CFDataRef) val1, (CFDataRef) val2); } uint8_t* der_encode_dictionary(CFDictionaryRef dictionary, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { CFMutableArrayRef elements = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); struct encode_context context = { .success = true, .error = error, .list = elements }; CFDictionaryApplyFunction(dictionary, add_sequence_to_array, &context); if (!context.success) { CFReleaseNull(elements); return NULL; } CFRange allOfThem = CFRangeMake(0, CFArrayGetCount(elements)); CFArraySortValues(elements, allOfThem, cfdata_compare_contents, NULL); uint8_t* original_der_end = der_end; for(CFIndex position = CFArrayGetCount(elements); position > 0;) { --position; CFDataRef data = CFArrayGetValueAtIndex(elements, position); der_end = ccder_encode_body(CFDataGetLength(data), CFDataGetBytePtr(data), der, der_end); } CFReleaseNull(elements); return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SET, original_der_end, der, der_end); }