/src/freeradius-server/src/protocols/der/der.h
Line | Count | Source |
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: a0bc24a6e60599dc627a952842c75b34632bb704 $ |
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 | | */ |
34 | | typedef 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 |
59 | | } fr_der_tag_t; |
60 | | |
61 | 68 | #define FR_DER_TAG_VALUE_MAX (0x1f) //!< tags >=max can't exist |
62 | | |
63 | | typedef 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. |
66 | | } fr_der_tag_constructed_t; |
67 | | |
68 | | typedef enum { |
69 | | FR_DER_CLASS_UNIVERSAL = 0x00, |
70 | | FR_DER_CLASS_APPLICATION = 0x40, |
71 | | FR_DER_CLASS_CONTEXT = 0x80, |
72 | | FR_DER_CLASS_PRIVATE = 0xC0, |
73 | | FR_DER_CLASS_INVALID = 0x04 |
74 | | } fr_der_tag_class_t; |
75 | | |
76 | 200 | #define DER_MAX_STR 16384 |
77 | | |
78 | 0 | #define DER_UTC_TIME_LEN 13 //!< Length of the UTC time string. |
79 | 0 | #define DER_GENERALIZED_TIME_LEN_MIN 15 //!< Minimum length of the generalized time string. |
80 | 0 | #define DER_GENERALIZED_TIME_PRECISION_MAX 9 //!< Maximum precision of the generalized time string (nanoseconds). |
81 | | |
82 | 0 | #define DER_TAG_CLASS_MASK 0xc0 //!< Mask to extract the class from the tag. |
83 | 0 | #define DER_TAG_CONSTRUCTED_MASK 0x20 //!< Mask to check if the tag is constructed. |
84 | 0 | #define DER_TAG_NUM_MASK 0x1f //!< Mask to extract the tag number from the tag. |
85 | | |
86 | 0 | #define DER_TAG_CONTINUATION 0x1f //!< Mask to check if the tag is a continuation. |
87 | | |
88 | 0 | #define DER_LEN_MULTI_BYTE 0x80 //!< Mask to check if the length is multi-byte. |
89 | | |
90 | 0 | #define DER_BOOLEAN_FALSE 0x00 //!< DER encoded boolean false value. |
91 | 0 | #define DER_BOOLEAN_TRUE 0xff //!< DER encoded boolean true value. |
92 | | |
93 | | typedef struct { |
94 | | fr_der_tag_class_t class; //!< tag Class |
95 | | fr_der_tag_t der_type; //!< the DER type, which is different from the FreeRADIUS type |
96 | | union { |
97 | | fr_der_tag_t sequence_of; |
98 | | fr_der_tag_t set_of; |
99 | | fr_value_box_t *default_value; |
100 | | char const *shortname; |
101 | | }; |
102 | | uint64_t max; //!< maximum count of items in a sequence, set, or string. |
103 | | uint32_t restrictions; //!< for choice of options and tags - no dups allowed |
104 | | uint8_t min; //!< mininum count |
105 | | uint8_t option; //!< an "attribute number" encoded in the tag field. |
106 | | bool is_option : 1; //!< has an option defined |
107 | | bool optional : 1; //!< optional, we MUST already have set 'option' |
108 | | bool is_sequence_of : 1; //!< sequence_of has been defined |
109 | | bool is_set_of : 1; //!< set_of has been defined |
110 | | bool is_oid_and_value : 1; //!< is OID+value |
111 | | bool is_extensions : 1; //!< a list of X.509 extensions |
112 | | bool has_default_value : 1; //!< a default value exists |
113 | | bool has_shortname : 1; //!< has a short name |
114 | | bool leaf : 1; //!< encode this OID along with its value |
115 | | bool is_choice : 1; //!< DER name "choice". |
116 | | } fr_der_attr_flags_t; |
117 | | |
118 | | typedef struct { |
119 | | TALLOC_CTX *tmp_ctx; //!< ctx under which temporary data will be allocated |
120 | | } fr_der_decode_ctx_t; |
121 | | |
122 | | static inline fr_der_attr_flags_t const *fr_der_attr_flags(fr_dict_attr_t const *da) |
123 | 78 | { |
124 | 78 | return fr_dict_attr_ext(da, FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC); |
125 | 78 | } Line | Count | Source | 123 | 78 | { | 124 | 78 | return fr_dict_attr_ext(da, FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC); | 125 | 78 | } |
Unexecuted instantiation: decode.c:fr_der_attr_flags Unexecuted instantiation: encode.c:fr_der_attr_flags |
126 | | |
127 | | #define fr_der_flag_option(_da) (fr_der_attr_flags(_da)->option) |
128 | | #define fr_der_flag_optional(_da) (fr_der_attr_flags(_da)->optional) |
129 | | #define fr_der_flag_class(_da) (fr_der_attr_flags(_da)->class) |
130 | 78 | #define fr_der_flag_der_type(_da) (fr_der_attr_flags(_da)->der_type) |
131 | | #define fr_der_flag_sequence_of(_da) (fr_der_attr_flags(_da)->sequence_of) |
132 | | #define fr_der_flag_is_sequence_of(_da) (fr_der_attr_flags(_da)->is_sequence_of) |
133 | | #define fr_der_flag_set_of(_da) (fr_der_attr_flags(_da)->set_of) |
134 | 0 | #define fr_der_flag_is_set_of(_da) (fr_der_attr_flags(_da)->is_set_of) |
135 | 0 | #define fr_der_flag_max(_da) (fr_der_attr_flags(_da)->max) |
136 | 0 | #define fr_der_flag_is_oid_and_value(_da) (fr_der_attr_flags(_da)->is_oid_and_value) |
137 | | #define fr_der_flag_is_extensions(_da) (fr_der_attr_flags(_da)->is_extensions) |
138 | | #define fr_der_flag_has_default_value(_da) (fr_der_attr_flags(_da)->has_default_value) |
139 | 0 | #define fr_der_flag_leaf(_da) (fr_der_attr_flags(_da)->leaf) |
140 | | #define fr_der_flag_is_choice(_da) (fr_der_attr_flags(_da)->is_choice) |
141 | | |
142 | | /* |
143 | | * base.c |
144 | | */ |
145 | | fr_der_tag_t fr_type_to_der_tag_default(fr_type_t type); |
146 | | bool fr_type_to_der_tag_valid(fr_type_t type, fr_der_tag_t tag); |
147 | | bool fr_der_tags_compatible(fr_der_tag_t tag1, fr_der_tag_t tag2); |
148 | | char const *fr_der_tag_to_str(fr_der_tag_t tag); |
149 | | char const *fr_der_dict_attr_to_shortname(fr_dict_attr_t const *da); |
150 | | |
151 | | int fr_der_global_init(void); |
152 | | void fr_der_global_free(void); |
153 | | |
154 | | /* |
155 | | * decode.c |
156 | | */ |
157 | | ssize_t fr_der_decode_pair_dbuff(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, |
158 | | fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx); |