Example #1
0
const uint8_t *
ccder_decode_tl(ccder_tag expected_tag, size_t *lenp,
                               const uint8_t *der, const uint8_t *der_end) {
    ccder_tag tag;
    der = ccder_decode_tag(&tag, der, der_end);
    if (!der || tag != expected_tag)
        return NULL;

    return ccder_decode_len(lenp, der, der_end);
}
SOSCoderRef SOSCoderCreateFromData(CFDataRef exportedData, CFErrorRef *error) {
    
    SOSCoderRef p = calloc(1, sizeof(struct __OpaqueSOSCoder));
    
    const uint8_t *der = CFDataGetBytePtr(exportedData);
    const uint8_t *der_end = der + CFDataGetLength(exportedData);
    
    CFDataRef otr_data = NULL;

    ccder_tag tag;
    require(ccder_decode_tag(&tag, der, der_end),fail);

    switch (tag) {
        case CCDER_OCTET_STRING: // TODO: this code is safe to delete?
        {
            der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, der_end);
            p->waitingForDataPacket = false;
        }
        break;
        
        case CCDER_CONSTRUCTED_SEQUENCE:
        {
            const uint8_t *sequence_end = NULL;
            der = ccder_decode_sequence_tl(&sequence_end, der, der_end);
            
            require_action_quiet(sequence_end == der_end, fail, SecCFDERCreateError(kSOSErrorDecodeFailure, CFSTR("Extra data in SOS coder"), NULL, error));
            
            der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, sequence_end);
            der = der_decode_bool(&p->waitingForDataPacket, der, sequence_end);
            if (der != sequence_end) { // optionally a pending response
                der = der_decode_data(kCFAllocatorDefault, 0, &p->pendingResponse, error, der, sequence_end);
            }
        }
        break;
        
        default:
            SecCFDERCreateError(kSOSErrorDecodeFailure, CFSTR("Unsupported SOS Coder DER"), NULL, error);
            goto fail;
    }

    require(der, fail);
    
    p->sessRef = SecOTRSessionCreateFromData(NULL, otr_data);
    require(p->sessRef, fail);

    CFReleaseSafe(otr_data);
    return p;
        
fail:
    SOSCoderDispose(p);
    CFReleaseSafe(otr_data);
    return NULL;
}
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;
    }
}