const uint8_t * ccder_decode_constructed_tl(ccder_tag expected_tag, const uint8_t **body_end, const uint8_t *der, const uint8_t *der_end) { size_t len; der = ccder_decode_tl(expected_tag, &len, der, der_end); *body_end = der + len; return der; }
const uint8_t * ccder_decode_oid(ccoid_t *oidp, const uint8_t *der, const uint8_t *der_end) { size_t len; const uint8_t *body = ccder_decode_tl(CCDER_OBJECT_IDENTIFIER, &len, der, der_end); if (body) { oidp->oid = der; return body + len; } return NULL; }
static const uint8_t *der_expect_SecAsn1Oid(const SecAsn1Oid* secasn_oid, const uint8_t *der, const uint8_t *der_end) { size_t len = 0; der = ccder_decode_tl(CCDER_OBJECT_IDENTIFIER, &len, der, der_end); if (secasn_oid->Length != len || memcmp(secasn_oid->Data, der, len) != 0) der = NULL; else der += len; return der; }
static const uint8_t* der_decode_bool(bool *value, const uint8_t *der, const uint8_t *der_end) { size_t payload_size = 0; der = ccder_decode_tl(CCDER_BOOLEAN, &payload_size, der, der_end); if (payload_size != 1) { der = NULL; } if (der != NULL) { *value = (*der != 0); der++; } return der; }
const uint8_t* ccder_decode_bool(bool* boolean, const uint8_t* der, const uint8_t *der_end) { if (NULL == der) return NULL; size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_BOOLEAN, &payload_size, der, der_end); if (NULL == payload || (der_end - payload) < 1 || payload_size != 1) { return NULL; } if (boolean) *boolean = (*payload != 0); return payload + payload_size; }
const uint8_t* der_decode_number(CFAllocatorRef allocator, CFOptionFlags mutability, CFNumberRef* number, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { if (NULL == der) return NULL; size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_INTEGER, &payload_size, der, der_end); if (NULL == payload || (der_end - payload) < payload_size) { SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown number encoding"), NULL, error); return NULL; } if (payload_size > sizeof(long long)) { SecCFDERCreateError(kSecDERErrorUnsupportedNumberType, CFSTR("Number too large"), NULL, error); return NULL; } long long value = 0; if (payload_size > 0) { if ((*payload & 0x80) == 0x80) value = -1; // Negative integers fill with 1s so we end up negative. const uint8_t* const payload_end = payload + payload_size; for (const uint8_t *payload_byte = payload; payload_byte < payload_end; ++payload_byte) { value <<= 8; value |= *payload_byte; } } *number = CFNumberCreate(allocator, kCFNumberLongLongType, &value); if (*number == NULL) { SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Number allocation failed"), NULL, error); return NULL; } return payload + payload_size; }
const uint8_t * ccder_decode_bitstring(const uint8_t **bit_string, size_t *bit_length, const uint8_t *der, const uint8_t *der_end) { size_t len; const uint8_t *content = ccder_decode_tl(CCDER_BIT_STRING, &len, der, der_end); if (content) { if ((len >= 1) && (((len - 1) * 8) >= (*content))) { *bit_length = ((len - 1) * 8) - *content; } else { *bit_length = 0; } *bit_string = content + 1; return content + len; } return NULL; }
const uint8_t* der_decode_null(CFAllocatorRef allocator, CFOptionFlags mutability, CFNullRef* nul, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { if (NULL == der) return NULL; size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_NULL, &payload_size, der, der_end); if (NULL == payload || payload_size != 0) { SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown null encoding"), NULL, error); return NULL; } *nul = kCFNull; return payload + payload_size; }
const uint8_t* der_decode_boolean(CFAllocatorRef allocator, CFOptionFlags mutability, CFBooleanRef* boolean, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { if (NULL == der) return NULL; size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_BOOLEAN, &payload_size, der, der_end); if (NULL == payload || (der_end - payload) < payload_size || payload_size != 1) { SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown boolean encoding"), NULL, error); return NULL; } *boolean = *payload ? kCFBooleanTrue : kCFBooleanFalse; return payload + payload_size; }
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; }
const uint8_t* der_decode_string(CFAllocatorRef allocator, CFOptionFlags mutability, CFStringRef* string, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { if (NULL == der) return NULL; size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_UTF8_STRING, &payload_size, der, der_end); if (NULL == payload || (ssize_t) (der_end - payload) < (ssize_t) payload_size){ SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown string encoding"), NULL, error); return NULL; } *string = CFStringCreateWithBytes(allocator, payload, payload_size, kCFStringEncodingUTF8, false); if (NULL == *string) { SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("String allocation failed"), NULL, error); return NULL; } return payload + payload_size; }
const uint8_t* der_decode_data(CFAllocatorRef allocator, CFOptionFlags mutability, CFDataRef* data, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { if (NULL == der) return NULL; size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payload_size, der, der_end); if (NULL == payload || (der_end - payload) < payload_size) { SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown data encoding"), NULL, error); return NULL; } *data = CFDataCreate(allocator, payload, payload_size); if (NULL == *data) { SecCFDERCreateError(kSecDERErrorUnderlyingError, CFSTR("Failed to create data"), NULL, error); return NULL; } return payload + payload_size; }