#ifndef _CORECRYPTO_CCDER_H_
#define _CORECRYPTO_CCDER_H_
#include <corecrypto/ccasn1.h>
#include <corecrypto/ccn.h>
#define CCDER_MULTIBYTE_TAGS 1
#ifdef CCDER_MULTIBYTE_TAGS
typedef unsigned long ccder_tag;
#else
typedef uint8_t ccder_tag;
#endif
#define CCDER_EOL CCASN1_EOL
#define CCDER_BOOLEAN CCASN1_BOOLEAN
#define CCDER_INTEGER CCASN1_INTEGER
#define CCDER_BIT_STRING CCASN1_BIT_STRING
#define CCDER_OCTET_STRING CCASN1_OCTET_STRING
#define CCDER_NULL CCASN1_NULL
#define CCDER_OBJECT_IDENTIFIER CCASN1_OBJECT_IDENTIFIER
#define CCDER_OBJECT_DESCRIPTOR CCASN1_OBJECT_DESCRIPTOR
#define CCDER_REAL CCASN1_REAL
#define CCDER_ENUMERATED CCASN1_ENUMERATED
#define CCDER_EMBEDDED_PDV CCASN1_EMBEDDED_PDV
#define CCDER_UTF8_STRING CCASN1_UTF8_STRING
#define CCDER_SEQUENCE CCASN1_SEQUENCE
#define CCDER_SET CCASN1_SET
#define CCDER_NUMERIC_STRING CCASN1_NUMERIC_STRING
#define CCDER_PRINTABLE_STRING CCASN1_PRINTABLE_STRING
#define CCDER_T61_STRING CCASN1_T61_STRING
#define CCDER_VIDEOTEX_STRING CCASN1_VIDEOTEX_STRING
#define CCDER_IA5_STRING CCASN1_IA5_STRING
#define CCDER_UTC_TIME CCASN1_UTC_TIME
#define CCDER_GENERALIZED_TIME CCASN1_GENERALIZED_TIME
#define CCDER_GRAPHIC_STRING CCASN1_GRAPHIC_STRING
#define CCDER_VISIBLE_STRING CCASN1_VISIBLE_STRING
#define CCDER_GENERAL_STRING CCASN1_GENERAL_STRING
#define CCDER_UNIVERSAL_STRING CCASN1_UNIVERSAL_STRING
#define CCDER_BMP_STRING CCASN1_BMP_STRING
#define CCDER_HIGH_TAG_NUMBER CCASN1_HIGH_TAG_NUMBER
#define CCDER_TELETEX_STRING CCDER_T61_STRING
#ifdef CCDER_MULTIBYTE_TAGS
#define CCDER_TAG_MASK ((ccder_tag)~0)
#define CCDER_TAGNUM_MASK ((ccder_tag)~((ccder_tag)7 << (sizeof(ccder_tag) * 8 - 3)))
#define CCDER_METHOD_MASK ((ccder_tag)1 << (sizeof(ccder_tag) * 8 - 3))
#define CCDER_PRIMITIVE ((ccder_tag)0 << (sizeof(ccder_tag) * 8 - 3))
#define CCDER_CONSTRUCTED ((ccder_tag)1 << (sizeof(ccder_tag) * 8 - 3))
#define CCDER_CLASS_MASK ((ccder_tag)3 << (sizeof(ccder_tag) * 8 - 2))
#define CCDER_UNIVERSAL ((ccder_tag)0 << (sizeof(ccder_tag) * 8 - 2))
#define CCDER_APPLICATION ((ccder_tag)1 << (sizeof(ccder_tag) * 8 - 2))
#define CCDER_CONTEXT_SPECIFIC ((ccder_tag)2 << (sizeof(ccder_tag) * 8 - 2))
#define CCDER_PRIVATE ((ccder_tag)3 << (sizeof(ccder_tag) * 8 - 2))
#else
#define CCDER_TAG_MASK CCASN1_TAG_MASK
#define CCDER_TAGNUM_MASK CCASN1_TAGNUM_MASK
#define CCDER_METHOD_MASK CCASN1_METHOD_MASK
#define CCDER_PRIMITIVE CCASN1_PRIMITIVE
#define CCDER_CONSTRUCTED CCASN1_CONSTRUCTED
#define CCDER_CLASS_MASK CCASN1_CLASS_MASK
#define CCDER_UNIVERSAL CCASN1_UNIVERSAL
#define CCDER_APPLICATION CCASN1_APPLICATION
#define CCDER_CONTEXT_SPECIFIC CCASN1_CONTEXT_SPECIFIC
#define CCDER_PRIVATE CCASN1_PRIVATE
#endif
#define CCDER_CONSTRUCTED_SET (CCDER_SET | CCDER_CONSTRUCTED)
#define CCDER_CONSTRUCTED_SEQUENCE (CCDER_SEQUENCE | CCDER_CONSTRUCTED)
CC_CONST
size_t ccder_sizeof(ccder_tag tag, size_t len);
CC_PURE
size_t ccder_sizeof_implicit_integer(ccder_tag implicit_tag,
cc_size n, const cc_unit *s);
CC_PURE
size_t ccder_sizeof_implicit_octet_string(ccder_tag implicit_tag,
cc_size n, const cc_unit *s);
CC_CONST
size_t ccder_sizeof_implicit_raw_octet_string(ccder_tag implicit_tag,
size_t s_size);
CC_CONST
size_t ccder_sizeof_implicit_uint64(ccder_tag implicit_tag, uint64_t value);
CC_PURE
size_t ccder_sizeof_integer(cc_size n, const cc_unit *s);
CC_CONST
size_t ccder_sizeof_len(size_t len);
CC_PURE
size_t ccder_sizeof_octet_string(cc_size n, const cc_unit *s);
CC_PURE
size_t ccder_sizeof_oid(ccoid_t oid);
CC_CONST
size_t ccder_sizeof_raw_octet_string(size_t s_size);
CC_CONST
size_t ccder_sizeof_tag(ccder_tag tag);
CC_CONST
size_t ccder_sizeof_uint64(uint64_t value);
CC_NONNULL2
uint8_t *ccder_encode_tag(ccder_tag tag, const uint8_t *der, uint8_t *der_end);
CC_NONNULL2
uint8_t *
ccder_encode_len(size_t len, const uint8_t *der, uint8_t *der_end);
CC_NONNULL3
uint8_t *
ccder_encode_tl(ccder_tag tag, size_t len, const uint8_t *der, uint8_t *der_end);
CC_PURE CC_NONNULL2
uint8_t *
ccder_encode_body_nocopy(size_t size, const uint8_t *der, uint8_t *der_end);
CC_NONNULL((2, 3))
uint8_t *
ccder_encode_constructed_tl(ccder_tag tag, const uint8_t *body_end,
const uint8_t *der, uint8_t *der_end);
CC_NONNULL_TU((1)) CC_NONNULL2
uint8_t *ccder_encode_oid(ccoid_t oid, const uint8_t *der, uint8_t *der_end);
CC_NONNULL((3, 4))
uint8_t *ccder_encode_implicit_integer(ccder_tag implicit_tag,
cc_size n, const cc_unit *s,
const uint8_t *der, uint8_t *der_end);
CC_NONNULL((2, 3))
uint8_t *ccder_encode_integer(cc_size n, const cc_unit *s,
const uint8_t *der, uint8_t *der_end);
CC_NONNULL3
uint8_t *ccder_encode_implicit_uint64(ccder_tag implicit_tag,
uint64_t value,
const uint8_t *der, uint8_t *der_end);
CC_NONNULL2
uint8_t *ccder_encode_uint64(uint64_t value,
const uint8_t *der, uint8_t *der_end);
CC_NONNULL((3, 4))
uint8_t *ccder_encode_implicit_octet_string(ccder_tag implicit_tag,
cc_size n, const cc_unit *s,
const uint8_t *der,
uint8_t *der_end);
CC_NONNULL((2, 3))
uint8_t *ccder_encode_octet_string(cc_size n, const cc_unit *s,
const uint8_t *der, uint8_t *der_end);
CC_NONNULL((3, 4))
uint8_t *ccder_encode_implicit_raw_octet_string(ccder_tag implicit_tag,
size_t s_size, const uint8_t *s,
const uint8_t *der,
uint8_t *der_end);
CC_NONNULL((2, 3))
uint8_t *ccder_encode_raw_octet_string(size_t s_size, const uint8_t *s,
const uint8_t *der, uint8_t *der_end);
size_t ccder_encode_eckey_size(size_t priv_size, ccoid_t oid, size_t pub_size);
CC_NONNULL2 CC_NONNULL5 CC_NONNULL6 CC_NONNULL7
uint8_t *ccder_encode_eckey(size_t priv_size, const uint8_t *priv_key,
ccoid_t oid,
size_t pub_size, const uint8_t *pub_key,
uint8_t *der, uint8_t *der_end);
CC_NONNULL3
uint8_t *
ccder_encode_body(size_t size, const uint8_t* body,
const uint8_t *der, uint8_t *der_end);
CC_NONNULL((1, 3))
const uint8_t *ccder_decode_tag(ccder_tag *tagp, const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((1, 3))
const uint8_t *ccder_decode_len(size_t *lenp, const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((2, 4))
const uint8_t *ccder_decode_tl(ccder_tag expected_tag, size_t *lenp,
const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((2, 4))
const uint8_t *
ccder_decode_constructed_tl(ccder_tag expected_tag, const uint8_t **body_end,
const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((1, 3))
const uint8_t *
ccder_decode_sequence_tl(const uint8_t **body_end,
const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((3))
const uint8_t *ccder_decode_uint_n(cc_size *n,
const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((4))
const uint8_t *ccder_decode_uint(cc_size n, cc_unit *r,
const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((3))
const uint8_t *ccder_decode_uint64(uint64_t* r,
const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((2, 3, 5))
const uint8_t *ccder_decode_seqii(cc_size n, cc_unit *r, cc_unit *s,
const uint8_t *der, const uint8_t *der_end);
CC_NONNULL_TU((1)) CC_NONNULL((3))
const uint8_t *ccder_decode_oid(ccoid_t *oidp,
const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((1,2,4))
const uint8_t *ccder_decode_bitstring(const uint8_t **bit_string,
size_t *bit_length,
const uint8_t *der, const uint8_t *der_end);
CC_NONNULL_TU((4)) CC_NONNULL((1,2,3,5,6,8))
const uint8_t *ccder_decode_eckey(uint64_t *version,
size_t *priv_size, const uint8_t **priv_key,
ccoid_t *oid,
size_t *pub_size, const uint8_t **pub_key,
const uint8_t *der, const uint8_t *der_end);
#define CC_EC_OID_SECP192R1 {((unsigned char *)"\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x01")}
#define CC_EC_OID_SECP256R1 {((unsigned char *)"\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07")}
#define CC_EC_OID_SECP224R1 {((unsigned char *)"\x06\x05\x2B\x81\x04\x00\x21")}
#define CC_EC_OID_SECP384R1 {((unsigned char *)"\x06\x05\x2B\x81\x04\x00\x22")}
#define CC_EC_OID_SECP521R1 {((unsigned char *)"\x06\x05\x2B\x81\x04\x00\x23")}
#endif