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;
    }
}
Example #2
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);
                }
            }
        }
    });