static const uint8_t *get_oid(const uint8_t *der, const uint8_t *der_end) {
    ccoid_t oid;
    if((der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &der_end, der, der_end)) == NULL) return NULL;
    if((der = ccder_decode_oid(&oid, der, der_end)) == NULL) return NULL;
    if((der = ccder_decode_constructed_tl(CCASN1_NULL, &der_end, der, der_end)) == NULL) return NULL;
    return der;
}
static const uint8_t* der_decode_key_value(CFAllocatorRef allocator, CFOptionFlags mutability,
                                           CFPropertyListRef* key, CFPropertyListRef* value, CFErrorRef *error,
                                           const uint8_t* der, const uint8_t *der_end)
{
    const uint8_t *payload_end = 0;
    const uint8_t *payload = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &payload_end, der, der_end);

    if (NULL == payload) {
        SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown data encoding, expected CCDER_CONSTRUCTED_SEQUENCE"), NULL, error);
        return NULL;
    }

    CFTypeRef keyObject = NULL;
    CFTypeRef valueObject = NULL;


    payload = der_decode_plist(allocator, mutability, &keyObject, error, payload, payload_end);
    payload = der_decode_plist(allocator, mutability, &valueObject, error, payload, payload_end);

    if (payload != NULL) {
        *key = keyObject;
        *value = valueObject;
    } else {
        CFReleaseNull(keyObject);
        CFReleaseNull(valueObject);
    }
    return payload;
}
// Key is expected to be in PKCS #1 format
cc_size ccder_decode_rsa_pub_n(const uint8_t *der, const uint8_t *der_end) {
    cc_size n = ccn_nof(8192);
    cc_unit m[n];
    if((der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &der_end, der, der_end)) == NULL) return 0;
    if((der = ccder_decode_uint(n, m, der, der_end)) == NULL) return 0;
    return ccn_nof(ccn_bitlen(n, m));
}
cc_size ccder_decode_rsa_priv_n(const uint8_t *der, const uint8_t *der_end) {
	cc_unit version_0[ccn_nof(1)] = {0x00};
    cc_size n = ccn_nof(8192);
    cc_unit m[n];
    if((der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &der_end, der, der_end)) == NULL) return 0;
    if((der = ccder_decode_uint(1, version_0, der, der_end)) == NULL) return 0;
    if(version_0[0] != 0) return 0;
    if((der = ccder_decode_uint(n, m, der, der_end)) == NULL) return 0;
    return ccn_nof(ccn_bitlen(n, m));
}
const uint8_t* der_decode_dictionary(CFAllocatorRef allocator, CFOptionFlags mutability,
                                     CFDictionaryRef* dictionary, CFErrorRef *error,
                                     const uint8_t* der, const uint8_t *der_end)
{
    if (NULL == der)
        return NULL;

    const uint8_t *payload_end = 0;
    const uint8_t *payload = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SET, &payload_end, der, der_end);

    if (NULL == payload) {
        SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown data encoding, expected CCDER_CONSTRUCTED_SET"), NULL, error);
        return NULL;
    }
    
    
    CFMutableDictionaryRef dict = CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    
    if (NULL == dict) {
        SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Failed to create dictionary"), NULL, error);
        payload = NULL;
        goto exit;
    }

    while (payload != NULL && payload < payload_end) {
        CFTypeRef key = NULL;
        CFTypeRef value = NULL;
        
        payload = der_decode_key_value(allocator, mutability, &key, &value, error, payload, payload_end);
        
        if (payload) {
            CFDictionaryAddValue(dict, key, value);
        }
        
        CFReleaseNull(key);
        CFReleaseNull(value);
    }
    
    
exit:
    if (payload == payload_end) {
        *dictionary = dict;
        dict = NULL;
    }

    CFReleaseNull(dict);

    return payload;
}
const uint8_t* der_decode_date(CFAllocatorRef allocator, CFOptionFlags mutability,
                               CFDateRef* date, CFErrorRef *error,
                               const uint8_t* der, const uint8_t *der_end)
{
    if (NULL == der)
        return NULL;

    der = ccder_decode_constructed_tl(CCDER_GENERALIZED_TIME, &der_end, der, der_end);
    CFAbsoluteTime at = 0;
    der = der_decode_generalizedtime_body(&at, error, der, der_end);
    if (der) {
        *date = CFDateCreate(allocator, at);
        if (NULL == *date) {
            SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Failed to create date"), NULL, error);
            return NULL;
        }
    }
    return der;
}
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;
}
Example #8
0
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);
                }
            }
        }
    });
cc_size ccder_decode_rsa_pub_x509_n(const uint8_t *der, const uint8_t *der_end) {
    if((der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &der_end, der, der_end)) == NULL) return 0;
    if((der = get_oid(der, der_end)) == NULL) return 0;
    return get_pub_n(der, der_end);
}
static cc_size get_pub_n(const uint8_t *der, const uint8_t *der_end) {
    if((der = ccder_decode_constructed_tl(CCDER_BIT_STRING, &der_end, der, der_end)) == NULL) return 0;
    if(*der == 0) der++; // Skip the null byte
    return ccder_decode_rsa_pub_n(der, der_end);
}