1*35c0a8c4SKyle Evans /*- 2*35c0a8c4SKyle Evans * Copyright (c) 2024 Kyle Evans <kevans@FreeBSD.org> 3*35c0a8c4SKyle Evans * 4*35c0a8c4SKyle Evans * SPDX-License-Identifier: BSD-2-Clause 5*35c0a8c4SKyle Evans */ 6*35c0a8c4SKyle Evans 7*35c0a8c4SKyle Evans #pragma once 8*35c0a8c4SKyle Evans 9*35c0a8c4SKyle Evans #include <stdbool.h> 10*35c0a8c4SKyle Evans #include <stdio.h> 11*35c0a8c4SKyle Evans #include <stdint.h> 12*35c0a8c4SKyle Evans #include <stddef.h> 13*35c0a8c4SKyle Evans 14*35c0a8c4SKyle Evans enum libder_ber_class { 15*35c0a8c4SKyle Evans BC_UNIVERSAL = 0, 16*35c0a8c4SKyle Evans BC_APPLICATION = 1, 17*35c0a8c4SKyle Evans BC_CONTEXT = 2, 18*35c0a8c4SKyle Evans BC_PRIVATE = 3, 19*35c0a8c4SKyle Evans }; 20*35c0a8c4SKyle Evans 21*35c0a8c4SKyle Evans enum libder_ber_type { 22*35c0a8c4SKyle Evans BT_RESERVED = 0x00, 23*35c0a8c4SKyle Evans BT_BOOLEAN = 0x01, 24*35c0a8c4SKyle Evans BT_INTEGER = 0x02, 25*35c0a8c4SKyle Evans BT_BITSTRING = 0x03, 26*35c0a8c4SKyle Evans BT_OCTETSTRING = 0x04, 27*35c0a8c4SKyle Evans BT_NULL = 0x05, 28*35c0a8c4SKyle Evans BT_OID = 0x06, 29*35c0a8c4SKyle Evans BT_OBJDESC = 0x07, 30*35c0a8c4SKyle Evans BT_EXTERNAL = 0x08, 31*35c0a8c4SKyle Evans BT_REAL = 0x09, 32*35c0a8c4SKyle Evans BT_ENUMERATED = 0x0a, 33*35c0a8c4SKyle Evans BT_PDV = 0x0b, 34*35c0a8c4SKyle Evans BT_UTF8STRING = 0x0c, 35*35c0a8c4SKyle Evans BT_RELOID = 0x0d, 36*35c0a8c4SKyle Evans 37*35c0a8c4SKyle Evans /* 0x10, 011 not usable */ 38*35c0a8c4SKyle Evans 39*35c0a8c4SKyle Evans BT_NUMERICSTRING = 0x012, 40*35c0a8c4SKyle Evans BT_STRING = 0x13, 41*35c0a8c4SKyle Evans BT_TELEXSTRING = 0x14, 42*35c0a8c4SKyle Evans BT_VIDEOTEXSTRING = 0x15, 43*35c0a8c4SKyle Evans BT_IA5STRING = 0x16, 44*35c0a8c4SKyle Evans BT_UTCTIME = 0x17, 45*35c0a8c4SKyle Evans BT_GENTIME = 0x18, 46*35c0a8c4SKyle Evans BT_GFXSTRING = 0x19, 47*35c0a8c4SKyle Evans BT_VISSTRING = 0x1a, 48*35c0a8c4SKyle Evans BT_GENSTRING = 0x1b, 49*35c0a8c4SKyle Evans BT_UNIVSTRING = 0x1c, 50*35c0a8c4SKyle Evans BT_CHARSTRING = 0x1d, 51*35c0a8c4SKyle Evans BT_BMPSTRING = 0x1e, 52*35c0a8c4SKyle Evans 53*35c0a8c4SKyle Evans BT_SEQUENCE = 0x30, 54*35c0a8c4SKyle Evans BT_SET = 0x31, 55*35c0a8c4SKyle Evans }; 56*35c0a8c4SKyle Evans 57*35c0a8c4SKyle Evans #define BER_TYPE_CONSTRUCTED_MASK 0x20 /* Bit 6 */ 58*35c0a8c4SKyle Evans #define BER_TYPE_CLASS_MASK 0xc0 /* Bits 7 and 8 */ 59*35c0a8c4SKyle Evans 60*35c0a8c4SKyle Evans /* 61*35c0a8c4SKyle Evans * The difference between the type and the full type is just that the full type 62*35c0a8c4SKyle Evans * will indicate the class of type, so it may be more useful for some operations. 63*35c0a8c4SKyle Evans */ 64*35c0a8c4SKyle Evans #define BER_FULL_TYPE(tval) \ 65*35c0a8c4SKyle Evans ((tval) & ~(BER_TYPE_CONSTRUCTED_MASK)) 66*35c0a8c4SKyle Evans #define BER_TYPE(tval) \ 67*35c0a8c4SKyle Evans ((tval) & ~(BER_TYPE_CLASS_MASK | BER_TYPE_CONSTRUCTED_MASK)) 68*35c0a8c4SKyle Evans #define BER_TYPE_CLASS(tval) \ 69*35c0a8c4SKyle Evans (((tval) & BER_TYPE_CLASS_MASK) >> 6) 70*35c0a8c4SKyle Evans #define BER_TYPE_CONSTRUCTED(tval) \ 71*35c0a8c4SKyle Evans (((tval) & BER_TYPE_CONSTRUCTED_MASK) != 0) 72*35c0a8c4SKyle Evans 73*35c0a8c4SKyle Evans enum libder_error { 74*35c0a8c4SKyle Evans LDE_NONE = 0x00, 75*35c0a8c4SKyle Evans LDE_NOMEM, /* Out of memory */ 76*35c0a8c4SKyle Evans LDE_INVAL, /* Invalid parameter */ 77*35c0a8c4SKyle Evans LDE_SHORTHDR, /* Header too short */ 78*35c0a8c4SKyle Evans LDE_BADVARLEN, /* Bad variable length encoding */ 79*35c0a8c4SKyle Evans LDE_LONGLEN, /* Encoded length too large (8 byte max) */ 80*35c0a8c4SKyle Evans LDE_SHORTDATA, /* Payload not available */ 81*35c0a8c4SKyle Evans LDE_GARBAGE, /* Garbage after encoded data */ 82*35c0a8c4SKyle Evans LDE_STREAMERR, /* Stream error */ 83*35c0a8c4SKyle Evans LDE_TRUNCVARLEN, /* Variable length object truncated */ 84*35c0a8c4SKyle Evans LDE_COALESCE_BADCHILD, /* Bad child encountered when coalescing */ 85*35c0a8c4SKyle Evans LDE_BADOBJECT, /* Payload not valid for object type */ 86*35c0a8c4SKyle Evans 87*35c0a8c4SKyle Evans /* Strict violations */ 88*35c0a8c4SKyle Evans LDE_STRICT_EOC, /* Strict: end-of-content violation */ 89*35c0a8c4SKyle Evans LDE_STRICT_TAG, /* Strict: tag violation */ 90*35c0a8c4SKyle Evans LDE_STRICT_PVARLEN, /* Strict: primitive using indefinite length */ 91*35c0a8c4SKyle Evans LDE_STRICT_BOOLEAN, /* Strict: boolean encoded incorrectly */ 92*35c0a8c4SKyle Evans LDE_STRICT_NULL, /* Strict: null encoded incorrectly */ 93*35c0a8c4SKyle Evans LDE_STRICT_PRIMITIVE, /* Strict: type must be primitive */ 94*35c0a8c4SKyle Evans LDE_STRICT_CONSTRUCTED, /* Strict: type must be constructed */ 95*35c0a8c4SKyle Evans LDE_STRICT_BITSTRING, /* Strict: malformed constructed bitstring */ 96*35c0a8c4SKyle Evans }; 97*35c0a8c4SKyle Evans 98*35c0a8c4SKyle Evans struct libder_ctx; 99*35c0a8c4SKyle Evans struct libder_tag; 100*35c0a8c4SKyle Evans struct libder_object; 101*35c0a8c4SKyle Evans 102*35c0a8c4SKyle Evans /* 103*35c0a8c4SKyle Evans * By default we normalize everything, but we allow some subset of the 104*35c0a8c4SKyle Evans * functionality to be disabled. Lengths are non-optional and will always be 105*35c0a8c4SKyle Evans * normalized to a fixed short or long length. The upper 32-bits of 106*35c0a8c4SKyle Evans * ctx->normalize are reserved for universal types so that we can quickly map 107*35c0a8c4SKyle Evans * those without assigning them names. 108*35c0a8c4SKyle Evans */ 109*35c0a8c4SKyle Evans 110*35c0a8c4SKyle Evans /* Normalize constructed types that should be coalesced (e.g., strings, time). */ 111*35c0a8c4SKyle Evans #define LIBDER_NORMALIZE_CONSTRUCTED 0x0000000000000001ULL 112*35c0a8c4SKyle Evans 113*35c0a8c4SKyle Evans /* 114*35c0a8c4SKyle Evans * Normalize tags on read. This is mostly a measure to ensure that 115*35c0a8c4SKyle Evans * normalization on write doesn't get thwarted; there's no reason anybody should 116*35c0a8c4SKyle Evans * be encoding low tags with the long form, but the spec doesn't appear to 117*35c0a8c4SKyle Evans * forbid it. 118*35c0a8c4SKyle Evans */ 119*35c0a8c4SKyle Evans #define LIBDER_NORMALIZE_TAGS 0x0000000000000002ULL 120*35c0a8c4SKyle Evans 121*35c0a8c4SKyle Evans /* Universal types (reserved) */ 122*35c0a8c4SKyle Evans #define LIBDER_NORMALIZE_TYPE_MASK 0xffffffff00000000ULL 123*35c0a8c4SKyle Evans #define LIBDER_NORMALIZE_TYPE_FLAG(val) ((1ULL << val) << 32ULL) 124*35c0a8c4SKyle Evans 125*35c0a8c4SKyle Evans /* All valid bits. */ 126*35c0a8c4SKyle Evans #define LIBDER_NORMALIZE_ALL \ 127*35c0a8c4SKyle Evans (LIBDER_NORMALIZE_TYPE_MASK | LIBDER_NORMALIZE_CONSTRUCTED | \ 128*35c0a8c4SKyle Evans LIBDER_NORMALIZE_TAGS) 129*35c0a8c4SKyle Evans 130*35c0a8c4SKyle Evans struct libder_ctx * libder_open(void); 131*35c0a8c4SKyle Evans void libder_close(struct libder_ctx *); 132*35c0a8c4SKyle Evans void libder_abort(struct libder_ctx *); 133*35c0a8c4SKyle Evans const char *libder_get_error(struct libder_ctx *); 134*35c0a8c4SKyle Evans bool libder_has_error(struct libder_ctx *); 135*35c0a8c4SKyle Evans uint64_t libder_get_normalize(struct libder_ctx *); 136*35c0a8c4SKyle Evans uint64_t libder_set_normalize(struct libder_ctx *, uint64_t); 137*35c0a8c4SKyle Evans bool libder_get_strict(struct libder_ctx *); 138*35c0a8c4SKyle Evans bool libder_set_strict(struct libder_ctx *, bool); 139*35c0a8c4SKyle Evans int libder_get_verbose(struct libder_ctx *); 140*35c0a8c4SKyle Evans int libder_set_verbose(struct libder_ctx *, int); 141*35c0a8c4SKyle Evans 142*35c0a8c4SKyle Evans struct libder_object *libder_read(struct libder_ctx *, const uint8_t *, size_t *); 143*35c0a8c4SKyle Evans struct libder_object *libder_read_fd(struct libder_ctx *, int, size_t *); 144*35c0a8c4SKyle Evans struct libder_object *libder_read_file(struct libder_ctx *, FILE *, size_t *); 145*35c0a8c4SKyle Evans 146*35c0a8c4SKyle Evans uint8_t *libder_write(struct libder_ctx *, struct libder_object *, uint8_t *, 147*35c0a8c4SKyle Evans size_t *); 148*35c0a8c4SKyle Evans 149*35c0a8c4SKyle Evans #define DER_CHILDREN(obj) libder_obj_children(obj) 150*35c0a8c4SKyle Evans #define DER_NEXT(obj) libder_obj_next(obj) 151*35c0a8c4SKyle Evans 152*35c0a8c4SKyle Evans #define DER_FOREACH_CHILD(var, obj) \ 153*35c0a8c4SKyle Evans for ((var) = DER_CHILDREN((obj)); \ 154*35c0a8c4SKyle Evans (var); \ 155*35c0a8c4SKyle Evans (var) = DER_NEXT((var))) 156*35c0a8c4SKyle Evans #define DER_FOREACH_CHILD_SAFE(var, obj, tvar) \ 157*35c0a8c4SKyle Evans for ((var) = DER_CHILDREN((obj)); \ 158*35c0a8c4SKyle Evans (var) && ((tvar) = DER_NEXT((var)), 1); \ 159*35c0a8c4SKyle Evans (var) = (tvar)) 160*35c0a8c4SKyle Evans 161*35c0a8c4SKyle Evans struct libder_object *libder_obj_alloc(struct libder_ctx *, struct libder_tag *, const uint8_t *, size_t); 162*35c0a8c4SKyle Evans struct libder_object *libder_obj_alloc_simple(struct libder_ctx *, uint8_t, const uint8_t *, 163*35c0a8c4SKyle Evans size_t); 164*35c0a8c4SKyle Evans void libder_obj_free(struct libder_object *); 165*35c0a8c4SKyle Evans 166*35c0a8c4SKyle Evans bool libder_obj_append(struct libder_object *, struct libder_object *); 167*35c0a8c4SKyle Evans struct libder_object *libder_obj_child(const struct libder_object *, size_t); 168*35c0a8c4SKyle Evans struct libder_object *libder_obj_children(const struct libder_object *); 169*35c0a8c4SKyle Evans struct libder_object *libder_obj_next(const struct libder_object *); 170*35c0a8c4SKyle Evans struct libder_tag *libder_obj_type(const struct libder_object *); 171*35c0a8c4SKyle Evans uint8_t libder_obj_type_simple(const struct libder_object *); 172*35c0a8c4SKyle Evans const uint8_t *libder_obj_data(const struct libder_object *, size_t *); 173*35c0a8c4SKyle Evans 174*35c0a8c4SKyle Evans /* Debugging aide -- probably shouldn't use. */ 175*35c0a8c4SKyle Evans void libder_obj_dump(const struct libder_object *, FILE *); 176*35c0a8c4SKyle Evans 177*35c0a8c4SKyle Evans struct libder_tag *libder_type_alloc_simple(struct libder_ctx *, uint8_t); 178*35c0a8c4SKyle Evans struct libder_tag *libder_type_dup(struct libder_ctx *, const struct libder_tag *); 179*35c0a8c4SKyle Evans void libder_type_free(struct libder_tag *); 180*35c0a8c4SKyle Evans #define libder_type_simple libder_type_simple_abi 181*35c0a8c4SKyle Evans uint8_t libder_type_simple(const struct libder_tag *); 182