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