// Der encoding/decoding const uint8_t* der_decode_RecoveryKeyBag(CFAllocatorRef allocator, SOSRecoveryKeyBagRef* RecoveryKeyBag, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { if (der == NULL) return der; const uint8_t *result = NULL; SOSRecoveryKeyBagRef rb = CFTypeAllocate(SOSRecoveryKeyBag, struct __OpaqueSOSRecoveryKeyBag, allocator); require_quiet(SecAllocationError(rb, error, CFSTR("Recovery bag allocation failed")), fail); const uint8_t *sequence_end = NULL; der = ccder_decode_sequence_tl(&sequence_end, der, der_end); require_quiet(sequence_end == der_end, fail); der = der_decode_string(kCFAllocatorDefault, kCFPropertyListImmutable, &rb->accountDSID, error, der, sequence_end); rb->generation = SOSGenCountCreateFromDER(kCFAllocatorDefault, error, &der, sequence_end); der = ccder_decode_uint64(&rb->rkbVersion, der, sequence_end); der = der_decode_data(allocator, kCFPropertyListImmutable, &rb->recoveryKeyBag, error, der, sequence_end); require_quiet(SecRequirementError(der == der_end, error, CFSTR("Extra space in sequence")), fail); if (RecoveryKeyBag) CFTransferRetained(*RecoveryKeyBag, rb); result = der; fail: CFReleaseNull(rb); return result; }
static const uint8_t *der_decode_pbkdf2_params(size_t *saltLen, const uint8_t **salt, unsigned long *iterationCount, unsigned long *keyLength, const uint8_t *der, const uint8_t *der_end) { const uint8_t * body_end = NULL; der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &body_end, der, der_end); if (body_end != der_end) der = NULL; size_t salt_size = 0; const uint8_t *salt_bytes = NULL; der = ccder_decode_tl(CCDER_OCTET_STRING, &salt_size, der, body_end); salt_bytes = der; der += salt_size; uint64_t iteration_count = 0; uint64_t key_len = 0; der = ccder_decode_uint64(&iteration_count, der, body_end); if (iteration_count > UINT32_MAX) der = NULL; der = ccder_decode_uint64(&key_len, der, body_end); if (key_len > UINT32_MAX) der = NULL; der = der_expect_SecAsn1Oid(&CSSMOID_PKCS5_HMAC_SHA1, der, body_end); if (der) { if (salt) *salt = salt_bytes; if (saltLen) *saltLen = salt_size; if (iterationCount) *iterationCount = (unsigned long)iteration_count; if (keyLength) *keyLength = (unsigned long) key_len; } return der; }