xref: /freebsd/contrib/libder/libder/libder_private.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 <sys/param.h>
10 
11 #include <assert.h>
12 #include <signal.h>
13 #include <stdbool.h>
14 #ifdef __APPLE__
15 #define	__STDC_WANT_LIB_EXT1__	1	/* memset_s */
16 #endif
17 /* explicit_bzero is in one of these... */
18 #include <string.h>
19 #include <strings.h>
20 #include "libder.h"
21 
22 /* FreeBSD's sys/cdefs.h */
23 #ifndef __DECONST
24 #define	__DECONST(type, var)	((type)(uintptr_t)(const void *)(var))
25 #endif
26 #ifndef __unused
27 #define	__unused		__attribute__((__unused__))
28 #endif
29 
30 /* FreeBSD's sys/params.h */
31 #ifndef nitems
32 #define	nitems(x)	(sizeof((x)) / sizeof((x)[0]))
33 #endif
34 #ifndef MIN
35 #define	MIN(a,b) (((a)<(b))?(a):(b))
36 #endif
37 #ifndef MAX
38 #define	MAX(a,b) (((a)>(b))?(a):(b))
39 #endif
40 
41 struct libder_ctx;
42 struct libder_object;
43 
44 struct libder_ctx {
45 	uint64_t		 normalize;
46 	size_t			 buffer_size;
47 	enum libder_error	 error;
48 	int			 verbose;
49 	bool			 strict;
50 	volatile sig_atomic_t	 abort;
51 };
52 
53 struct libder_tag {
54 	union {
55 		uint8_t		 tag_short;
56 		uint8_t		*tag_long;
57 	};
58 	size_t			 tag_size;
59 	enum libder_ber_class	 tag_class;
60 	bool			 tag_constructed;
61 	bool			 tag_encoded;
62 };
63 
64 struct libder_object {
65 	struct libder_tag	*type;
66 	size_t			 length;
67 	size_t			 nchildren;
68 	size_t			 disk_size;
69 	uint8_t			*payload;	/* NULL for sequences */
70 	struct libder_object	*children;
71 	struct libder_object	*parent;
72 	struct libder_object	*next;
73 };
74 
75 static inline sig_atomic_t
libder_check_abort(struct libder_ctx * ctx)76 libder_check_abort(struct libder_ctx *ctx)
77 {
78 
79 	return (ctx->abort);
80 }
81 
82 static inline void
libder_clear_abort(struct libder_ctx * ctx)83 libder_clear_abort(struct libder_ctx *ctx)
84 {
85 
86 	ctx->abort = 1;
87 }
88 
89 #define	LIBDER_PRIVATE	__attribute__((__visibility__("hidden")))
90 
91 #define	DER_NORMALIZING(ctx, bit)	\
92     (((ctx)->normalize & (LIBDER_NORMALIZE_ ## bit)) != 0)
93 
94 static inline bool
libder_normalizing_type(const struct libder_ctx * ctx,const struct libder_tag * type)95 libder_normalizing_type(const struct libder_ctx *ctx, const struct libder_tag *type)
96 {
97 	uint8_t tagval;
98 
99 	assert(!type->tag_constructed);
100 	assert(!type->tag_encoded);
101 	assert(type->tag_class == BC_UNIVERSAL);
102 	assert(type->tag_short < 0x1f);
103 
104 	tagval = type->tag_short;
105 	return ((ctx->normalize & LIBDER_NORMALIZE_TYPE_FLAG(tagval)) != 0);
106 }
107 
108 /* All of the lower bits set. */
109 #define	BER_TYPE_LONG_MASK	0x1f
110 
111 /*
112  * Check if the type matches one of our universal types.
113  */
114 static inline bool
libder_type_is(const struct libder_tag * type,uint8_t utype)115 libder_type_is(const struct libder_tag *type, uint8_t utype)
116 {
117 
118 	if (type->tag_class != BC_UNIVERSAL || type->tag_encoded)
119 		return (false);
120 	if ((utype & BER_TYPE_CONSTRUCTED_MASK) != type->tag_constructed)
121 		return (false);
122 
123 	utype &= ~BER_TYPE_CONSTRUCTED_MASK;
124 	return (utype == type->tag_short);
125 }
126 
127 /*
128  * We'll use this one a decent amount, so we'll keep it inline.  There's also
129  * an _abi version that we expose as public interface via a 'libder_type_simple'
130  * macro.
131  */
132 #undef libder_type_simple
133 
134 static inline uint8_t
libder_type_simple(const struct libder_tag * type)135 libder_type_simple(const struct libder_tag *type)
136 {
137 	uint8_t encoded = type->tag_class << 6;
138 
139 	assert(!type->tag_encoded);
140 	if (type->tag_constructed)
141 		encoded |= BER_TYPE_CONSTRUCTED_MASK;
142 
143 	encoded |= type->tag_short;
144 	return (encoded);
145 }
146 
147 static inline void
libder_bzero(uint8_t * buf,size_t bufsz)148 libder_bzero(uint8_t *buf, size_t bufsz)
149 {
150 
151 #ifdef __APPLE__
152 	memset_s(buf, bufsz, 0, bufsz);
153 #else
154 	explicit_bzero(buf, bufsz);
155 #endif
156 }
157 
158 size_t	 libder_get_buffer_size(struct libder_ctx *);
159 void	 libder_set_error(struct libder_ctx *, int, const char *, int);
160 
161 #define	libder_set_error(ctx, error)	\
162 	libder_set_error((ctx), (error), __FILE__, __LINE__)
163 
164 struct libder_object	*libder_obj_alloc_internal(struct libder_ctx *,
165 			    struct libder_tag *, uint8_t *, size_t, uint32_t);
166 #define	LDO_OWNTAG	0x0001	/* Object owns passed in tag */
167 
168 size_t			 libder_size_length(size_t);
169 bool			 libder_is_valid_obj(struct libder_ctx *,
170 			    const struct libder_tag *, const uint8_t *, size_t, bool);
171 size_t			 libder_obj_disk_size(struct libder_object *, bool);
172 bool			 libder_obj_may_coalesce_children(const struct libder_object *);
173 bool			 libder_obj_coalesce_children(struct libder_object *, struct libder_ctx *);
174 bool			 libder_obj_normalize(struct libder_object *, struct libder_ctx *);
175 
176 struct libder_tag	*libder_type_alloc(void);
177 void			 libder_type_release(struct libder_tag *);
178 void			 libder_normalize_type(struct libder_ctx *, struct libder_tag *);
179