xref: /freebsd/contrib/libder/libder/libder.h (revision 35c0a8c449fd2b7f75029ebed5e10852240f0865)
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