The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
der.h
Go to the documentation of this file.
1#pragma once
2/*
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16 */
17
18/**
19 * $Id: 996145539af9a14b0d68f82044e53fc15435736d $
20 *
21 * @file protocols/der/der.c
22 * @brief Structures and prototypes for base DER functionality.
23 *
24 * @author Ethan Thompson (ethan.thompson@inkbridge.io)
25 *
26 * @copyright 2025 Network RADIUS SAS (legal@networkradius.com)
27 */
28
29#include <freeradius-devel/build.h>
30#include <freeradius-devel/util/value.h>
31
32/** Enumeration describing the data types in a DER encoded structure
33 */
34typedef enum {
35 FR_DER_TAG_INVALID = 0x00, //!< Invalid tag.
36 FR_DER_TAG_BOOLEAN = 0x01, //!< Boolean true/false
37 FR_DER_TAG_INTEGER = 0x02, //!< Arbitrary width signed integer.
38 FR_DER_TAG_BITSTRING = 0x03, //!< String of bits (length field specifies bits).
39 FR_DER_TAG_OCTETSTRING = 0x04, //!< String of octets (length field specifies bytes).
40 FR_DER_TAG_NULL = 0x05, //!< An empty value.
41 FR_DER_TAG_OID = 0x06, //!< Reference to an OID based attribute.
42 FR_DER_TAG_ENUMERATED = 0x0a, //!< An enumerated value.
43 FR_DER_TAG_UTF8_STRING = 0x0c, //!< String of UTF8 chars.
44 FR_DER_TAG_SEQUENCE = 0x10, //!< A sequence of DER encoded data (a structure).
45 FR_DER_TAG_SET = 0x11, //!< A set of DER encoded data (a structure).
46 FR_DER_TAG_PRINTABLE_STRING = 0x13, //!< String of printable chars.
47 FR_DER_TAG_T61_STRING = 0x14, //!< String of T61 (8bit) chars.
48 FR_DER_TAG_IA5_STRING = 0x16, //!< String of IA5 (7bit) chars.
49 FR_DER_TAG_UTC_TIME = 0x17, //!< A time in UTC "YYMMDDhhmmssZ" format.
50 FR_DER_TAG_GENERALIZED_TIME = 0x18, //!< A time in "YYYYMMDDHHMMSS[.fff]Z" format.
51 FR_DER_TAG_VISIBLE_STRING = 0x1a, //!< String of visible chars.
52 FR_DER_TAG_GENERAL_STRING = 0x1b, //!< String of general chars.
53 FR_DER_TAG_UNIVERSAL_STRING = 0x1c, //!< String of universal chars.
54 FR_DER_TAG_BMP_STRING = 0x1e, //!< String of BMP chars.
55
56 FR_DER_TAG_CHOICE = 0x23, //!< A choice of types. Techically not a DER tag, but used to represent a choice.
57
58 FR_DER_TAG_MAX = 0x24
60
61#define FR_DER_TAG_VALUE_MAX (0x1f) //!< tags >=max can't exist
62
63typedef enum {
64 FR_DER_TAG_PRIMITIVE = 0x00, //!< This is a leaf value, it contains no children.
65 FR_DER_TAG_CONSTRUCTED = 0x20 //!< This is a sequence or set, it contains children.
67
75
76#define DER_MAX_STR 16384
77
78#define DER_UTC_TIME_LEN 13 //!< Length of the UTC time string.
79#define DER_GENERALIZED_TIME_LEN_MIN 15 //!< Minimum length of the generalized time string.
80#define DER_GENERALIZED_TIME_PRECISION_MAX 9 //!< Maximum precision of the generalized time string (nanoseconds).
81
82#define DER_TAG_CLASS_MASK 0xc0 //!< Mask to extract the class from the tag.
83#define DER_TAG_CONSTRUCTED_MASK 0x20 //!< Mask to check if the tag is constructed.
84#define DER_TAG_NUM_MASK 0x1f //!< Mask to extract the tag number from the tag.
85
86#define DER_TAG_CONTINUATION 0x1f //!< Mask to check if the tag is a continuation.
87
88#define DER_LEN_MULTI_BYTE 0x80 //!< Mask to check if the length is multi-byte.
89
90#define DER_BOOLEAN_FALSE 0x00 //!< DER encoded boolean false value.
91#define DER_BOOLEAN_TRUE 0xff //!< DER encoded boolean true value.
92
93/** Which member of the fr_der_attr_flags_t union is in use
94 *
95 */
96typedef enum {
97 FR_DER_ATTR_FLAG_NONE = 0, //!< no member is in use
98 FR_DER_ATTR_FLAG_SEQUENCE_OF, //!< sequence_of has been defined
99 FR_DER_ATTR_FLAG_SETOF, //!< set_of has been defined
100 FR_DER_ATTR_FLAG_DEFAULT_VALUE, //!< a default value exists
101 FR_DER_ATTR_FLAG_SHORTNAME //!< has a short name
103
104typedef struct {
105 fr_der_tag_class_t class; //!< tag Class
106 fr_der_tag_t der_type; //!< the DER type, which is different from the FreeRADIUS type
107
108 /*
109 * The member which is in use is given by 'flag_type'.
110 */
111 union {
112 fr_der_tag_t sequence_of;
113 fr_der_tag_t set_of;
114 fr_value_box_t *default_value;
115 char const *shortname;
116 };
117 uint64_t max; //!< maximum count of items in a sequence, set, or string.
118 uint32_t restrictions; //!< for choice of options and tags - no dups allowed
119 uint8_t min; //!< mininum count
120 uint8_t option; //!< an "attribute number" encoded in the tag field.
121 fr_der_attr_flag_type_t flag_type : 3; //!< which member of the union is in use
122 unsigned int is_option : 1; //!< has an option defined
123 unsigned int optional : 1; //!< optional, we MUST already have set 'option'
124 unsigned int is_constructed : 1; //!< for raw attributes, the data said that the
125 ///< value was constructed
126 unsigned int is_oid_and_value : 1; //!< is OID+value
127 unsigned int is_extensions : 1; //!< a list of X.509 extensions
128 unsigned int leaf : 1; //!< encode this OID along with its value
129 unsigned int is_choice : 1; //!< DER name "choice".
131
132/*
133 * Which member of the union is in use. These take a fr_der_attr_flags_t, where the
134 * fr_der_attr_*() functions below take a fr_dict_attr_t.
135 */
136#define fr_der_flag_has_none(_flags) ((_flags)->flag_type == FR_DER_ATTR_FLAG_NONE)
137#define fr_der_flag_has_sequence_of(_flags) ((_flags)->flag_type == FR_DER_ATTR_FLAG_SEQUENCE_OF)
138#define fr_der_flag_has_set_of(_flags) ((_flags)->flag_type == FR_DER_ATTR_FLAG_SETOF)
139#define fr_der_flag_has_value(_flags) ((_flags)->flag_type == FR_DER_ATTR_FLAG_DEFAULT_VALUE)
140#define fr_der_flag_has_shortname(_flags) ((_flags)->flag_type == FR_DER_ATTR_FLAG_SHORTNAME)
141
142typedef struct {
143 TALLOC_CTX *tmp_ctx; //!< ctx under which temporary data will be allocated
144 fr_dict_attr_t const *root; //!< where to start decoding from
146
148
149/** Return DER-specific flags for a given attribute
150 *
151 * Assert in debug builds when the attribute belongs to another dictionary, as
152 * the flags of one protocol say nothing about an attribute of another.
153 *
154 * If the attribute does not carry the protocol-specific extension, then assert.
155 * Other builds log the error and return zeroed flags instead of NULL.
156 */
158{
159 static fr_der_attr_flags_t const no_flags = {};
160 fr_der_attr_flags_t const *flags;
161
163 "%s is not a DER attribute, it is from the \"%s\" dictionary",
164 da->name, fr_dict_root(da->dict)->name);
165
167 if (!fr_cond_assert_msg(flags, "%s is not a DER attribute, it has no protocol extension",
168 da->name)) return &no_flags;
169
170 return flags;
171}
172
174{
175 return fr_der_attr_flags(da)->option;
176}
177
178static inline bool fr_der_attr_optional(fr_dict_attr_t const *da)
179{
180 return fr_der_attr_flags(da)->optional;
181}
182
184{
185 return fr_der_attr_flags(da)->class;
186}
187
189{
190 return fr_der_attr_flags(da)->der_type;
191}
192
194{
195 fr_der_attr_flags_t const *flags = fr_der_attr_flags(da);
196
198 "%s is not a 'sequence_of=...' attribute, so the union does not hold 'sequence_of'",
199 da->name);
200
201 return flags->sequence_of;
202}
203
204static inline bool fr_der_attr_is_sequence_of(fr_dict_attr_t const *da)
205{
207}
208
210{
211 fr_der_attr_flags_t const *flags = fr_der_attr_flags(da);
212
214 "%s is not a 'set_of=...' attribute, so the union does not hold 'set_of'",
215 da->name);
216
217 return flags->set_of;
218}
219
220static inline bool fr_der_attr_is_set_of(fr_dict_attr_t const *da)
221{
223}
224
225static inline uint64_t fr_der_attr_max(fr_dict_attr_t const *da)
226{
227 return fr_der_attr_flags(da)->max;
228}
229
230static inline bool fr_der_attr_is_oid_and_value(fr_dict_attr_t const *da)
231{
233}
234
235static inline bool fr_der_attr_is_extensions(fr_dict_attr_t const *da)
236{
238}
239
241{
243}
244
245static inline bool fr_der_attr_leaf(fr_dict_attr_t const *da)
246{
247 return fr_der_attr_flags(da)->leaf;
248}
249
250static inline bool fr_der_attr_is_choice(fr_dict_attr_t const *da)
251{
252 return fr_der_attr_flags(da)->is_choice;
253}
254
255/*
256 * base.c
257 */
261char const *fr_der_tag_to_str(fr_der_tag_t tag);
262char const *fr_der_dict_attr_to_shortname(fr_dict_attr_t const *da);
263
264int fr_der_global_init(void);
265void fr_der_global_free(void);
266
267/*
268 * decode.c
269 */
271 fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx);
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:248
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:194
static fr_der_tag_t fr_der_attr_sequence_of(fr_dict_attr_t const *da)
Definition der.h:193
fr_der_tag_t
Enumeration describing the data types in a DER encoded structure.
Definition der.h:34
@ FR_DER_TAG_IA5_STRING
String of IA5 (7bit) chars.
Definition der.h:48
@ FR_DER_TAG_SEQUENCE
A sequence of DER encoded data (a structure).
Definition der.h:44
@ FR_DER_TAG_SET
A set of DER encoded data (a structure).
Definition der.h:45
@ FR_DER_TAG_BMP_STRING
String of BMP chars.
Definition der.h:54
@ FR_DER_TAG_INTEGER
Arbitrary width signed integer.
Definition der.h:37
@ FR_DER_TAG_BOOLEAN
Boolean true/false.
Definition der.h:36
@ FR_DER_TAG_CHOICE
A choice of types. Techically not a DER tag, but used to represent a choice.
Definition der.h:56
@ FR_DER_TAG_UTF8_STRING
String of UTF8 chars.
Definition der.h:43
@ FR_DER_TAG_UTC_TIME
A time in UTC "YYMMDDhhmmssZ" format.
Definition der.h:49
@ FR_DER_TAG_GENERALIZED_TIME
A time in "YYYYMMDDHHMMSS[.fff]Z" format.
Definition der.h:50
@ FR_DER_TAG_INVALID
Invalid tag.
Definition der.h:35
@ FR_DER_TAG_NULL
An empty value.
Definition der.h:40
@ FR_DER_TAG_OCTETSTRING
String of octets (length field specifies bytes).
Definition der.h:39
@ FR_DER_TAG_VISIBLE_STRING
String of visible chars.
Definition der.h:51
@ FR_DER_TAG_BITSTRING
String of bits (length field specifies bits).
Definition der.h:38
@ FR_DER_TAG_T61_STRING
String of T61 (8bit) chars.
Definition der.h:47
@ FR_DER_TAG_ENUMERATED
An enumerated value.
Definition der.h:42
@ FR_DER_TAG_UNIVERSAL_STRING
String of universal chars.
Definition der.h:53
@ FR_DER_TAG_PRINTABLE_STRING
String of printable chars.
Definition der.h:46
@ FR_DER_TAG_GENERAL_STRING
String of general chars.
Definition der.h:52
@ FR_DER_TAG_OID
Reference to an OID based attribute.
Definition der.h:41
@ FR_DER_TAG_MAX
Definition der.h:58
bool fr_der_tags_compatible(fr_der_tag_t tag1, fr_der_tag_t tag2)
Definition base.c:102
static bool fr_der_attr_is_sequence_of(fr_dict_attr_t const *da)
Definition der.h:204
fr_der_attr_flag_type_t
Which member of the fr_der_attr_flags_t union is in use.
Definition der.h:96
@ FR_DER_ATTR_FLAG_NONE
no member is in use
Definition der.h:97
@ FR_DER_ATTR_FLAG_SHORTNAME
has a short name
Definition der.h:101
@ FR_DER_ATTR_FLAG_SEQUENCE_OF
sequence_of has been defined
Definition der.h:98
@ FR_DER_ATTR_FLAG_SETOF
set_of has been defined
Definition der.h:99
@ FR_DER_ATTR_FLAG_DEFAULT_VALUE
a default value exists
Definition der.h:100
void fr_der_global_free(void)
Definition base.c:221
static fr_der_tag_class_t fr_der_attr_class(fr_dict_attr_t const *da)
Definition der.h:183
static fr_der_tag_t fr_der_attr_der_type(fr_dict_attr_t const *da)
Definition der.h:188
fr_der_tag_t der_type
the DER type, which is different from the FreeRADIUS type
Definition der.h:106
static bool fr_der_attr_is_set_of(fr_dict_attr_t const *da)
Definition der.h:220
static bool fr_der_attr_has_default_value(fr_dict_attr_t const *da)
Definition der.h:240
TALLOC_CTX * tmp_ctx
ctx under which temporary data will be allocated
Definition der.h:143
unsigned int optional
optional, we MUST already have set 'option'
Definition der.h:123
static fr_der_tag_t fr_der_attr_set_of(fr_dict_attr_t const *da)
Definition der.h:209
int fr_der_global_init(void)
Definition base.c:198
uint32_t restrictions
for choice of options and tags - no dups allowed
Definition der.h:118
fr_dict_attr_t const * root
where to start decoding from
Definition der.h:144
fr_dict_protocol_t libfreeradius_der_dict_protocol
Definition base.c:1094
bool fr_type_to_der_tag_valid(fr_type_t type, fr_der_tag_t tag)
Definition base.c:178
static bool fr_der_attr_is_oid_and_value(fr_dict_attr_t const *da)
Definition der.h:230
#define fr_der_flag_has_value(_flags)
Definition der.h:139
fr_der_attr_flag_type_t flag_type
which member of the union is in use
Definition der.h:121
fr_der_tag_t fr_type_to_der_tag_default(fr_type_t type)
Definition base.c:892
char const * fr_der_tag_to_str(fr_der_tag_t tag)
Definition base.c:79
unsigned int leaf
encode this OID along with its value
Definition der.h:128
static bool fr_der_attr_optional(fr_dict_attr_t const *da)
Definition der.h:178
#define fr_der_flag_has_set_of(_flags)
Definition der.h:138
static uint64_t fr_der_attr_max(fr_dict_attr_t const *da)
Definition der.h:225
char const * fr_der_dict_attr_to_shortname(fr_dict_attr_t const *da)
Definition base.c:186
unsigned int is_constructed
for raw attributes, the data said that the value was constructed
Definition der.h:124
fr_der_tag_constructed_t
Definition der.h:63
@ FR_DER_TAG_CONSTRUCTED
This is a sequence or set, it contains children.
Definition der.h:65
@ FR_DER_TAG_PRIMITIVE
This is a leaf value, it contains no children.
Definition der.h:64
unsigned int is_choice
DER name "choice".
Definition der.h:129
unsigned int is_oid_and_value
is OID+value
Definition der.h:126
#define fr_der_flag_has_sequence_of(_flags)
Definition der.h:137
unsigned int is_extensions
a list of X.509 extensions
Definition der.h:127
uint8_t min
mininum count
Definition der.h:119
static bool fr_der_attr_leaf(fr_dict_attr_t const *da)
Definition der.h:245
ssize_t fr_der_decode_pair_dbuff(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx)
Definition decode.c:2640
static bool fr_der_attr_is_choice(fr_dict_attr_t const *da)
Definition der.h:250
static fr_der_attr_flags_t const * fr_der_attr_flags(fr_dict_attr_t const *da)
Return DER-specific flags for a given attribute.
Definition der.h:157
unsigned int is_option
has an option defined
Definition der.h:122
uint8_t option
an "attribute number" encoded in the tag field.
Definition der.h:120
static bool fr_der_attr_is_extensions(fr_dict_attr_t const *da)
Definition der.h:235
fr_der_tag_class_t class
tag Class
Definition der.h:105
static uint8_t fr_der_attr_option(fr_dict_attr_t const *da)
Definition der.h:173
uint64_t max
maximum count of items in a sequence, set, or string.
Definition der.h:117
fr_der_tag_class_t
Definition der.h:68
@ FR_DER_CLASS_APPLICATION
Definition der.h:70
@ FR_DER_CLASS_CONTEXT
Definition der.h:71
@ FR_DER_CLASS_UNIVERSAL
Definition der.h:69
@ FR_DER_CLASS_INVALID
Definition der.h:73
@ FR_DER_CLASS_PRIVATE
Definition der.h:72
fr_dict_protocol_t const * fr_dict_protocol(fr_dict_t const *dict)
Return the protocol descriptor for the dictionary.
Definition dict_util.c:5392
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2720
@ FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC
Protocol specific extensions.
Definition dict.h:190
Protocol-specific callbacks in libfreeradius-PROTOCOL.
Definition dict.h:479
static void * fr_dict_attr_ext(fr_dict_attr_t const *da, fr_dict_attr_ext_t ext)
Definition dict_ext.h:122
fr_type_t
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
fr_aka_sim_id_type_t type
static fr_slen_t parent
Definition pair.h:864
static fr_sbuff_err_t char size_t fr_sbuff_t * in
Definition value.h:1061
static fr_sbuff_err_t char ** out
Definition value.h:1061