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