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));
}
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));

}
uint8_t* der_encode_null(CFNullRef boolean __unused, CFErrorRef *error,
                            const uint8_t *der, uint8_t *der_end)
{
	return ccder_encode_tl(CCDER_NULL, 0, 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));
}