Coverage Report

Created: 2026-04-12 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}
base.c:fr_der_attr_flags
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);