static uint8_t *ccder_encode_nanoseconds(CFAbsoluteTime at, const uint8_t *der,
                                         uint8_t *der_end) {
    int dotoff;
    int sign;
    char *end;
    char *str = __dtoa(at, 0, 0, &dotoff, &sign, &end);
    char *begin = str + (dotoff < 0 ? 0 : dotoff);
    // Compute 1.0000000 - fraction in ascii space
    if (at < 0.0 && begin < end) {
        char *p = end - 1;
        // Borrow for last digit
        *p = ('9' + 1) - (*p - '0');
        while (p-- > begin) {
            // Every other digit is a 9 since we borrowed from the last one
            *p = '9' - (*p - '0');
        }
    }

    ptrdiff_t len = end - str;
    if (len > dotoff) {
        if (dotoff < 0) {
            assert(-1.0 < at && at < 1.0);
            der_end = ccder_encode_body(len, (const uint8_t *)str, der, der_end);
            der_end = ccder_encode_body_nocopy(-dotoff, der, der_end);
            if (der_end)
                memset(der_end, at < 0.0 ? '9' : '0', -dotoff);
        } else {
            der_end = ccder_encode_body(len - dotoff, (const uint8_t *)(str + dotoff), der, der_end);
        }
        der_end = ccder_encode_byte('.', der, der_end);
    }
    __freedtoa(str);

    return der_end;
}
Esempio n. 2
0
uint8_t* ccder_encode_bool(bool value, const uint8_t *der, uint8_t *der_end)
{
    uint8_t value_byte = value;
    
    return ccder_encode_tl(CCDER_BOOLEAN, 1, der,
                           ccder_encode_body(1, &value_byte, der, der_end));
}
Esempio n. 3
0
uint8_t* der_encode_string(CFStringRef string, CFErrorRef *error,
                           const uint8_t *der, uint8_t *der_end)
{
    // Obey the NULL allowed rules.
    if (!der_end)
        return NULL;

    const CFIndex str_length = CFStringGetLength(string);

    ptrdiff_t der_space = der_end - der;
    CFIndex bytes_used = 0;
    uint8_t *buffer = der_end - der_space;
    CFIndex converted = CFStringGetBytes(string, CFRangeMake(0, str_length), kCFStringEncodingUTF8, 0, false, buffer, der_space, &bytes_used);
    if (converted != str_length){
        SecCFDERCreateError(kSecDERErrorUnsupportedCFObject, CFSTR("String extraction failed"), NULL, error);
        return NULL;
    }

    return ccder_encode_tl(CCDER_UTF8_STRING, bytes_used, der,
           ccder_encode_body(bytes_used, buffer, der, der_end));

}
size_t der_sizeof_dictionary(CFDictionaryRef dict, CFErrorRef *error)
{
    struct size_context context = { .success = true, .size = 0, .error = error };

    
    CFDictionaryApplyFunction(dict, add_key_value_size, &context);
    
    if (!context.success)
        return 0;

    return ccder_sizeof(CCDER_CONSTRUCTED_SET, context.size);
}

static uint8_t* der_encode_key_value(CFPropertyListRef key, CFPropertyListRef value, CFErrorRef *error,
                                     const uint8_t* der, uint8_t *der_end)
{
    return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der,
           der_encode_plist(key, error, der,
           der_encode_plist(value, error, der, der_end)));
}

struct encode_context {
    bool         success;
    CFErrorRef * error;
    CFMutableArrayRef list;
    CFAllocatorRef allocator;
};

static void add_sequence_to_array(const void *key_void, const void *value_void, void *context_void)
{
    struct encode_context *context = (struct encode_context *) context_void;
    if (context->success) {
        CFTypeRef key = (CFTypeRef) key_void;
        CFTypeRef value = (CFTypeRef) value_void;

        size_t der_size = der_sizeof_key_value(key, value, context->error);
        if (der_size == 0) {
            context-> success = false;
        } else {
            CFMutableDataRef encoded_kv = CFDataCreateMutable(context->allocator, der_size);
            CFDataSetLength(encoded_kv, der_size);

            uint8_t* const encode_begin = CFDataGetMutableBytePtr(encoded_kv);
            uint8_t* encode_end = encode_begin + der_size;

            encode_end = der_encode_key_value(key, value, context->error, encode_begin, encode_end);

            if (encode_end != NULL) {
                CFDataDeleteBytes(encoded_kv, CFRangeMake(0, (encode_end - encode_begin)));
                CFArrayAppendValue(context->list, encoded_kv);
            } else {
                context-> success = false;
            }

            CFReleaseNull(encoded_kv);
        }
    }
}

static CFComparisonResult cfdata_compare_contents(const void *val1, const void *val2, void *context __unused)
{
    return CFDataCompare((CFDataRef) val1, (CFDataRef) val2);
}


uint8_t* der_encode_dictionary(CFDictionaryRef dictionary, CFErrorRef *error,
                               const uint8_t *der, uint8_t *der_end)
{
    CFMutableArrayRef elements = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
    
    struct encode_context context = { .success = true, .error = error, .list = elements };
    CFDictionaryApplyFunction(dictionary, add_sequence_to_array, &context);
    
    if (!context.success) {
        CFReleaseNull(elements);
        return NULL;
    }
    
    CFRange allOfThem = CFRangeMake(0, CFArrayGetCount(elements));

    CFArraySortValues(elements, allOfThem, cfdata_compare_contents, NULL);

    uint8_t* original_der_end = der_end;

    for(CFIndex position = CFArrayGetCount(elements); position > 0;) {
        --position;
        CFDataRef data = CFArrayGetValueAtIndex(elements, position);
        der_end = ccder_encode_body(CFDataGetLength(data), CFDataGetBytePtr(data), der, der_end);
    }

    CFReleaseNull(elements);

    return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SET, original_der_end, der, der_end);

}
static uint8_t *der_encode_SecAsn1Oid(const SecAsn1Oid* secasn_oid, const uint8_t *der, uint8_t *der_end)
{
    return ccder_encode_tl(CCDER_OBJECT_IDENTIFIER, secasn_oid->Length, der,
           ccder_encode_body(secasn_oid->Length, secasn_oid->Data, der, der_end));
}