The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
encode.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: c6d668648f6ec9add7f0124b575aecfd566c19cb $
19 *
20 * @file protocols/der/encode.c
21 * @brief Functions to encode DER
22 *
23 * @copyright 2025 Network RADIUS SAS (legal@networkradius.com)
24 */
25RCSID("$Id: c6d668648f6ec9add7f0124b575aecfd566c19cb $")
26
27#include <freeradius-devel/util/dbuff.h>
28#include <freeradius-devel/util/encode.h>
29#include <freeradius-devel/util/struct.h>
30
31#include <freeradius-devel/io/test_point.h>
32
33#include "der.h"
34
35extern fr_dict_attr_t const *attr_oid_tree;
36
37typedef struct {
38 uint8_t *tmp_ctx; //!< Temporary context for encoding.
40
41/** Function signature for DER encode functions
42 *
43 * @param[in] dbuff Where to encode the data.
44 * @param[in] cursor Where to encode the data from.
45 * @param[in] encode_ctx Any encode specific data.
46 * @return
47 * - > 0 on success. How many bytes were encoded.
48 * - 0 no bytes encoded.
49 * - < 0 on error. May be the offset (as a negative value) where the error occurred.
50 */
52
57
58
61
62/*
63 * We have per-type function names to make it clear that different types have different encoders.
64 * However, the methods to encode them are the same. So rather than having trampoline functions, we just
65 * use defines.
66 */
67#define fr_der_encode_enumerated fr_der_encode_integer
68
69
70static ssize_t fr_der_encode_len(fr_dbuff_t *dbuff, fr_dbuff_marker_t *length_start) CC_HINT(nonnull);
71static inline CC_HINT(always_inline) ssize_t
73 fr_der_tag_constructed_t constructed) CC_HINT(nonnull);
74static ssize_t encode_value(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void *encode_ctx);
75
76/** Compare two pairs by their tag number.
77 *
78 * @param[in] a First pair.
79 * @param[in] b Second pair.
80 * @return -1 if a < b, 0 if a == b, 1 if a > b.
81 */
82static inline CC_HINT(always_inline) int8_t fr_der_pair_cmp_by_da_tag(void const *a, void const *b)
83{
84 fr_pair_t const *my_a = a;
85 fr_pair_t const *my_b = b;
86
88}
89
90static ssize_t encode_pair(fr_dbuff_t *dbuff, UNUSED fr_da_stack_t *da_stack, UNUSED unsigned int depth, fr_dcursor_t *cursor,
91 void *encode_ctx)
92{
93 return encode_value(dbuff, cursor, encode_ctx);
94}
95
97{
98 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
99 fr_pair_t const *vp;
101
102 vp = fr_dcursor_current(cursor);
104 fr_assert(!vp->da->flags.is_raw);
105
106 /*
107 * ISO/IEC 8825-1:2021
108 * 8.2 Encoding of a boolean value
109 * 8.2.1 The encoding of a boolean value shall be primitive.
110 * The contents octets shall consist of a single octet.
111 * 8.2.2 If the boolean value is:
112 * FALSE the octet shall be zero [0x00].
113 * If the boolean value is TRUE the octet shall have any non-zero value, as a sender's option.
114 *
115 * 11.1 Boolean values
116 * If the encoding represents the boolean value TRUE, its single contents octet shall have all
117 * eight bits set to one [0xFF]. (Contrast with 8.2.2.)
118 */
119 value = vp->vp_bool;
120
122
123 return fr_dbuff_set(dbuff, &our_dbuff);
124}
125
127{
128 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
129 fr_pair_t const *vp;
130 uint64_t value;
131 uint8_t first_octet = 0;
132 size_t i, len;
133
134 vp = fr_dcursor_current(cursor);
136 fr_assert(!vp->da->flags.is_raw);
137
138 /*
139 * ISO/IEC 8825-1:2021
140 * 8.3 Encoding of an integer value
141 * 8.3.1 The encoding of an integer value shall be primitive.
142 * The contents octets shall consist of one or more octets.
143 * 8.3.2 If the contents octets of an integer value encoding consist of more than one octet,
144 * then the bits of the first octet and bit 8 of the second octet:
145 * a) shall not all be ones; and
146 * b) shall not all be zero.
147 * NOTE - These rules ensure that an integer value is always encoded in the smallest possible number
148 * of octets. 8.3.3 The contents octets shall be a two's complement binary number equal to the
149 * integer value, and consisting of bits 8 to 1 of the first octet, followed by bits 8 to 1 of the
150 * second octet, followed by bits 8 to 1 of each octet in turn up to and including the last octet of
151 * the contents octets.
152 */
153
154 /*
155 * Some 'integer' types such as serialNumber are too
156 * large for 64-bits. So we just treat them as octet
157 * strings.
158 */
159 if (vp->da->type != FR_TYPE_INT64) {
160 fr_assert(vp->da->type == FR_TYPE_OCTETS);
161 FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, vp->vp_octets, vp->vp_length);
162 return fr_dbuff_set(dbuff, &our_dbuff);
163 }
164
165 /*
166 * Yes, the type is FR_TYPE_INT64. But we encode the
167 * data as-is, without caring about things like signed
168 * math.
169 */
170 value = vp->vp_uint64;
171
172 for (i = 0, len = 0; i < sizeof(value); i++) {
173 uint8_t byte = (value >> 56) & 0xff;
174
175 value <<= 8;
176
177 if (len == 0) {
178 first_octet = byte;
179 len++;
180 continue;
181
182 } else if (len == 1) {
183 /*
184 * 8.3.2 If the contents octets of an integer value encoding consist of more than one
185 * octet, then the bits of the first octet and bit 8 of the second octet: a) shall not all
186 * be ones; and b) shall not all be zero.
187 */
188 if ((first_octet == 0xff && (byte & 0x80)) || ((first_octet == 0x00) && (byte >> 7 == 0))) {
189 if (i == sizeof(value) - 1) {
190 /*
191 * If this is the only byte, then we can encode it as a single byte.
192 */
193 FR_DBUFF_IN_RETURN(&our_dbuff, byte);
194 continue;
195 }
196
197 first_octet = byte;
198 continue;
199
200 } else {
201 FR_DBUFF_IN_RETURN(&our_dbuff, first_octet);
202 FR_DBUFF_IN_RETURN(&our_dbuff, byte);
203 len++;
204 continue;
205 }
206 }
207
208 FR_DBUFF_IN_RETURN(&our_dbuff, byte);
209 len++;
210 }
211
212 return fr_dbuff_set(dbuff, &our_dbuff);
213}
214
216{
217 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
218 fr_pair_t const *vp;
219 ssize_t slen;
220 uint8_t unused_bits = 0;
221
222 vp = fr_dcursor_current(cursor);
224 fr_assert(!vp->da->flags.is_raw);
225
226 /*
227 * ISO/IEC 8825-1:2021
228 * 8.6 Encoding of a bitstring value
229 * 8.6.1 The encoding of a bitstring value shall be either primitive or constructed at the option
230 * of the sender.
231 * NOTE - Where it is necessary to transfer part of a bit string before the entire
232 * bitstring is available, the constructed encoding is used.
233 * 8.6.2 The contents octets for the primitive encoding shall contain an initial octet followed
234 * by zero, one or more subsequent octets.
235 * 8.6.2.1 The bits in the bitstring value, commencing with the leading bit and proceeding
236 * to the trailing bit, shall be placed in bits 8 to 1 of the first subsequent
237 * octet, followed by bits 8 to 1 of the second subsequent octet, followed by bits
238 * 8 to 1 of each octet in turn, followed by as many bits as are needed of the
239 * final subsequent octet, commencing with bit 8.
240 * NOTE - The terms "leading bit" and "trailing bit" are defined in
241 * Rec. ITU-T X.680 | ISO/IEC 8824-1, 22.2.
242 * 8.6.2.2 The initial octet shall encode, as an unsigned binary integer with bit 1 as the
243 * least significant bit, the number of unused bits in the final subsequent octet.
244 * The number shall be in the range zero to seven.
245 * 8.6.2.3 If the bitstring is empty, there shall be no subsequent octets, and the initial
246 * octet shall be zero.
247 *
248 * 10.2 String encoding forms
249 * For bitstring, octetstring and restricted character string types, the constructed form of
250 * encoding shall not be used. (Contrast with 8.23.6.)
251 *
252 * 11.2 Unused bits 11.2.1 Each unused bit in the final octet of the encoding of a bit string value shall
253 * be set to zero.
254 */
255
256 if (fr_type_is_struct(vp->vp_type)) {
257 /*
258 * For struct type, we need to encode the struct as a bitstring using the
259 * fr_struct_to_network function.
260 */
261 unsigned int depth = vp->da->depth - 1;
262 fr_da_stack_t da_stack;
263 fr_dbuff_t work_dbuff = FR_DBUFF(&our_dbuff);
264 fr_dbuff_marker_t unused_bits_marker;
265 uint8_t last_byte = 0;
266
267 fr_dbuff_marker(&unused_bits_marker, &work_dbuff);
268 FR_DBUFF_ADVANCE_RETURN(&work_dbuff, 1);
269
270 fr_proto_da_stack_build(&da_stack, vp->da);
271
272 FR_PROTO_STACK_PRINT(&da_stack, depth);
273
274 slen = fr_struct_to_network(&work_dbuff, &da_stack, depth, cursor, encode_ctx, NULL, NULL);
275 if (slen < 0) {
276 fr_strerror_printf("Failed to encode struct: %s", fr_strerror());
277 return slen;
278 }
279
280 /*
281 * We need to trim any empty trailing octets
282 */
283 while ((slen > 1) && (fr_dbuff_current(&work_dbuff) != fr_dbuff_start(&work_dbuff))) {
284 uint8_t byte;
285
286 /*
287 * Move the dbuff cursor back by one byte
288 */
289 fr_dbuff_set(&work_dbuff, fr_dbuff_current(&work_dbuff) - sizeof(byte));
290
291 if (fr_dbuff_out(&byte, &work_dbuff) < 0) {
292 fr_strerror_const("Failed to read byte");
293 return -1;
294 }
295
296 if (byte != 0) break;
297
298 /*
299 * Trim this byte from the buff
300 */
301 fr_dbuff_set_end(&work_dbuff, fr_dbuff_current(&work_dbuff) - sizeof(byte));
302 fr_dbuff_set(&work_dbuff, fr_dbuff_current(&work_dbuff) - (sizeof(byte) * 2));
303 slen--;
304 }
305
306 /*
307 * Grab the last octet written to the dbuff and count the number of trailing 0 bits
308 */
309 if (fr_dbuff_out(&last_byte, &work_dbuff) < 0) {
310 fr_strerror_const("Failed to read last byte");
311 return -1;
312 }
313
314 while ((last_byte != 0) && ((last_byte & 0x01) == 0)) {
315 unused_bits++;
316 last_byte >>= 1;
317 }
318
319 /*
320 * Write the unused bits
321 */
322 fr_dbuff_set(&our_dbuff, fr_dbuff_current(&unused_bits_marker));
323 FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, &unused_bits, 1);
324
325 /*
326 * Copy the work dbuff to the output dbuff
327 */
328 fr_dbuff_set(&work_dbuff, &our_dbuff);
329 FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, &work_dbuff, (size_t)slen);
330
331 return fr_dbuff_set(dbuff, &our_dbuff);
332 }
333
334 /*
335 * For octets type, we do not need to write the unused bits portion
336 * because this information should be retained when encoding/decoding.
337 */
338 if (vp->vp_length == 0) {
339 FR_DBUFF_IN_RETURN(&our_dbuff, (uint8_t) 0x00);
340
341 } else {
342 FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, vp->vp_octets, vp->vp_length);
343 }
344
345 return fr_dbuff_set(dbuff, &our_dbuff);
346}
347
349{
350 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
351 fr_pair_t const *vp;
352
353 vp = fr_dcursor_current(cursor);
355 fr_assert(!vp->da->flags.is_raw);
356
357 /*
358 * RFC3779 Section 2.1.1.
359 *
360 * An IP address or prefix is encoded in the IP address delegation
361 * extension as a DER-encoded ASN.1 BIT STRING containing the constant
362 * most-significant bits. Recall [X.690] that the DER encoding of a BIT
363 * STRING consists of the BIT STRING type (0x03), followed by (an
364 * encoding of) the number of value octets, followed by the value. The
365 * value consists of an "initial octet" that specifies the number of
366 * unused bits in the last value octet, followed by the "subsequent
367 * octets" that contain the octets of the bit string. (For IP
368 * addresses, the encoding of the length will be just the length.)
369 */
370
371 /*
372 * The number of unused bits in the last byte is always zero.
373 */
374 FR_DBUFF_IN_RETURN(&our_dbuff, (uint8_t) 0x00);
375 FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, (uint8_t const *) &vp->vp_ipv4addr, sizeof(vp->vp_ipv4addr));
376
377 return fr_dbuff_set(dbuff, &our_dbuff);
378}
379
381{
382 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
383 fr_pair_t const *vp;
384 size_t len;
385
386 vp = fr_dcursor_current(cursor);
388 fr_assert(!vp->da->flags.is_raw);
389
390 if (vp->vp_ip.prefix == 0) {
391 FR_DBUFF_IN_RETURN(&our_dbuff, (uint8_t) 0x00);
392 return fr_dbuff_set(dbuff, &our_dbuff);
393 }
394
395 /*
396 * RFC3779 Section 2.1.1.
397 *
398 * An IP address or prefix is encoded in the IP address delegation
399 * extension as a DER-encoded ASN.1 BIT STRING containing the constant
400 * most-significant bits. Recall [X.690] that the DER encoding of a BIT
401 * STRING consists of the BIT STRING type (0x03), followed by (an
402 * encoding of) the number of value octets, followed by the value. The
403 * value consists of an "initial octet" that specifies the number of
404 * unused bits in the last value octet, followed by the "subsequent
405 * octets" that contain the octets of the bit string. (For IP
406 * addresses, the encoding of the length will be just the length.)
407 */
408 if (vp->vp_ip.prefix == 32) {
409 FR_DBUFF_IN_RETURN(&our_dbuff, (uint8_t) 0x00);
410 FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, (uint8_t const *) &vp->vp_ipv4addr, sizeof(vp->vp_ipv4addr));
411 return fr_dbuff_set(dbuff, &our_dbuff);
412 }
413
414 FR_DBUFF_IN_RETURN(&our_dbuff, (uint8_t) ((8 - (vp->vp_ip.prefix & 0x07)) & 0x07));
415
416 len = (vp->vp_ip.prefix + 0x07) >> 3;
417
418 if (len) FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, (uint8_t const *) &vp->vp_ipv4addr, len);
419
420 return fr_dbuff_set(dbuff, &our_dbuff);
421}
422
424{
425 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
426 fr_pair_t const *vp;
427
428 vp = fr_dcursor_current(cursor);
430 fr_assert(!vp->da->flags.is_raw);
431
432 /*
433 * RFC3779 Section 2.1.1.
434 *
435 * An IP address or prefix is encoded in the IP address delegation
436 * extension as a DER-encoded ASN.1 BIT STRING containing the constant
437 * most-significant bits. Recall [X.690] that the DER encoding of a BIT
438 * STRING consists of the BIT STRING type (0x03), followed by (an
439 * encoding of) the number of value octets, followed by the value. The
440 * value consists of an "initial octet" that specifies the number of
441 * unused bits in the last value octet, followed by the "subsequent
442 * octets" that contain the octets of the bit string. (For IP
443 * addresses, the encoding of the length will be just the length.)
444 */
445
446 /*
447 * The number of unused bits in the last byte is always zero.
448 */
449 FR_DBUFF_IN_RETURN(&our_dbuff, (uint8_t) 0x00);
450 FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, (uint8_t const *) &vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
451
452 return fr_dbuff_set(dbuff, &our_dbuff);
453}
454
456{
457 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
458 fr_pair_t const *vp;
459 size_t len;
460
461 vp = fr_dcursor_current(cursor);
463 fr_assert(!vp->da->flags.is_raw);
464
465 /*
466 * RFC3779 Section 2.1.1.
467 *
468 * An IP address or prefix is encoded in the IP address delegation
469 * extension as a DER-encoded ASN.1 BIT STRING containing the constant
470 * most-significant bits. Recall [X.690] that the DER encoding of a BIT
471 * STRING consists of the BIT STRING type (0x03), followed by (an
472 * encoding of) the number of value octets, followed by the value. The
473 * value consists of an "initial octet" that specifies the number of
474 * unused bits in the last value octet, followed by the "subsequent
475 * octets" that contain the octets of the bit string. (For IP
476 * addresses, the encoding of the length will be just the length.)
477 */
478
479 if (vp->vp_ip.prefix == 128) {
480 FR_DBUFF_IN_RETURN(&our_dbuff, (uint8_t) 0x00);
481 FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, (uint8_t const *) &vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
482 return fr_dbuff_set(dbuff, &our_dbuff);
483 }
484
485 FR_DBUFF_IN_RETURN(&our_dbuff, (uint8_t) ((8 - (vp->vp_ip.prefix & 0x07)) & 0x07));
486
487 len = (vp->vp_ip.prefix + 0x07) >> 3;
488
489 if (len) FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, (uint8_t const *) &vp->vp_ipv6addr, len);
490
491 return fr_dbuff_set(dbuff, &our_dbuff);
492}
493
494
496{
497 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
498 fr_pair_t const *vp;
499
500 vp = fr_dcursor_current(cursor);
502 fr_assert(!vp->da->flags.is_raw);
503
504 /*
505 * RFC5280 Section 4.2.1.6
506 *
507 * When the subjectAltName extension contains an iPAddress, the address
508 * MUST be stored in the octet string in "network byte order", as
509 * specified in [RFC791]. The least significant bit (LSB) of each octet
510 * is the LSB of the corresponding byte in the network address. For IP
511 * version 4, as specified in [RFC791], the octet string MUST contain
512 * exactly four octets. For IP version 6, as specified in
513 * [RFC2460], the octet string MUST contain exactly sixteen octets.
514 */
515 if (vp->vp_ip.af == AF_INET) {
516 FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, (uint8_t const *) &vp->vp_ipv4addr, sizeof(vp->vp_ipv4addr));
517 } else {
518 FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, (uint8_t const *) &vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
519 }
520
521 return fr_dbuff_set(dbuff, &our_dbuff);
522}
523
524
527{
528 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
529 fr_pair_t const *vp;
530
531 vp = fr_dcursor_current(cursor);
533 /* can be raw! */
534
535 /*
536 * ISO/IEC 8825-1:2021
537 * 8.7 Encoding of an octetstring value
538 * 8.7.1 The encoding of an octetstring value shall be either primitive or constructed at the
539 * option of the sender.
540 * NOTE - Where it is necessary to transfer part of an octet string before the entire
541 * octetstring is available, the constructed encoding is used.
542 * 8.7.2 The primitive encoding contains zero, one or more contents octets equal in value to the
543 * octets in the data value, in the order they appear in the data value, and with the most
544 * significant bit of an octet of the data value aligned with the most significant bit of an
545 * octet of the contents octets.
546 * 8.7.3 The contents octets for the constructed encoding shall consist of zero, one, or more
547 * encodings.
548 * NOTE - Each such encoding includes identifier, length, and contents octets, and may
549 * include end-of-contents octets if it is constructed.
550 * 8.7.3.1 To encode an octetstring value in this way, it is segmented. Each segment shall
551 * consist of a series of consecutive octets of the value. There shall be no
552 * significance placed on the segment boundaries.
553 * NOTE - A segment may be of size zero, i.e. contain no octets.
554 *
555 * 10.2 String encoding forms
556 * For bitstring, octetstring and restricted character string types, the constructed form of
557 * encoding shall not be used. (Contrast with 8.23.6.)
558 */
559 FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, vp->vp_octets, vp->vp_length);
560
561 return fr_dbuff_set(dbuff, &our_dbuff);
562}
563
564
567{
568 fr_pair_t const *vp;
569
570 vp = fr_dcursor_current(cursor);
572 fr_assert(!vp->da->flags.is_raw);
573
574 /*
575 * ISO/IEC 8825-1:2021
576 * 8.8 Encoding of a null value
577 * 8.8.1 The encoding of a null value shall be primitive.
578 * 8.8.2 The contents octets shall not contain any octets.
579 * NOTE - The length must be zero.
580 */
581 if (vp->vp_length != 0) {
582 fr_strerror_printf("Null has non-zero length %zu", vp->vp_length);
583 return -1;
584 }
585
586 return 0;
587}
588
589static ssize_t fr_der_encode_oid_from_value(fr_dbuff_t *dbuff, uint64_t value, uint64_t *component, int *count)
590{
591 fr_dbuff_t our_dbuff;
592 int i;
593 bool wrote = false;
594 uint64_t oid;
595
596 /*
597 * The first subidentifier is the encoding of the first two object identifier components, encoded as:
598 * (X * 40) + Y
599 * where X is the first number and Y is the second number.
600 * The first number is 0, 1, or 2.
601 */
602 if (*count == 0) {
603 if (!((value == 0) || (value == 1) || (value == 2))) {
604 fr_strerror_printf("Invalid value %" PRIu64 " for initial component", value);
605 return -1;
606 }
607
608 *component = value;
609 (*count)++;
610 return 0;
611 }
612
613 if (*count == 1) {
614 if ((*component < 2) && (value > 40)) {
615 fr_strerror_printf("Invalid value %" PRIu64 " for second component", value);
616 return -1;
617 }
618
619 oid = *component * 40 + value;
620 } else {
621 oid = value;
622 }
623
624 our_dbuff = FR_DBUFF(dbuff);
625
626 /*
627 * Encode the number as 7-bit chunks. Just brute-force over all bits, as doing that ends
628 * up being fast enough.
629 *
630 * i.e. if we did anything else to count bits, it would end up with pretty much the same
631 * code.
632 */
633 for (i = 63; i >= 0; i -= 7) {
634 uint8_t more, part;
635
636 /*
637 * Skip leading zeroes, but not intermediate ones.
638 */
639 part = (oid >> i) & 0x7f;
640 if (!part && !wrote && (i > 0)) continue;
641
642 more = ((uint8_t) (i > 0)) << 7;
643
644 FR_DBUFF_IN_RETURN(&our_dbuff, (uint8_t) (more | part));
645 wrote = true;
646 }
647
648 (*count)++;
649
650 return fr_dbuff_set(dbuff, &our_dbuff);
651}
652
654{
655 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
656 fr_pair_t const *vp;
657 uint64_t component;
658 int i, count = 0;
659 fr_da_stack_t da_stack;
660
661 vp = fr_dcursor_current(cursor);
663 fr_assert(!vp->da->flags.is_raw);
664 fr_assert(vp->vp_type == FR_TYPE_ATTR);
665
666 fr_proto_da_stack_build(&da_stack, vp->vp_attr);
667 FR_PROTO_STACK_PRINT(&da_stack, da_stack.depth);
668
669 /*
670 * ISO/IEC 8825-1:2021
671 * 8.19 Encoding of an object identifier value
672 * 8.19.1 The encoding of an object identifier value shall be primitive.
673 * 8.19.2 The contents octets shall be an (ordered) list of encodings of subidentifiers (see 8.19.3
674 * and 8.19.4) concatenated together. Each subidentifier is represented as a series of
675 * (one or more) octets. Bit 8 of each octet indicates whether it is the last in the series: bit 8
676 * of the last octet is zero; bit 8 of each preceding octet is one. Bits 7 to 1 of the octets in
677 * the series collectively encode the subidentifier. Conceptually, these groups of bits are
678 * concatenated to form an unsigned binary number whose most significant bit is bit 7 of the first
679 * octet and whose least significant bit is bit 1 of the last octet. The subidentifier shall be
680 * encoded in the fewest possible octets, that is, the leading octet of the subidentifier shall not
681 * have the value 8016.
682 * 8.19.3 The number of subidentifiers (N) shall be one less than the number of object identifier
683 * components in the object identifier value being encoded. 8.19.4 The numerical value of the
684 * first subidentifier is derived from the values of the first two object identifier components in
685 * the object identifier value being encoded, using the formula: (X*40) + Y where X is the value
686 * of the first object identifier component and Y is the value of the second object identifier
687 * component. NOTE - This packing of the first two object identifier components recognizes that
688 * only three values are allocated from the root node, and at most 39 subsequent values from nodes
689 * reached by X = 0 and X = 1. 8.19.5 The numerical value of the ith subidentifier, (2 <= i <= N) is
690 * that of the (i + 1)th object identifier component.
691 */
692
693 /*
694 * Parse each OID component.
695 */
696 for (i = 0; i < da_stack.depth; i++) {
697 ssize_t slen;
698
699 if ((i == 0) && (da_stack.da[0] == attr_oid_tree)) continue; /* don't encode this */
700
701 slen = fr_der_encode_oid_from_value(&our_dbuff, da_stack.da[i]->attr, &component, &count);
702 if (slen < 0) return -1;
703 }
704
705 if (count <= 2) {
706 fr_strerror_printf("Invalid OID '%s' - too short", vp->vp_strvalue);
707 return -1;
708 }
709
710 return fr_dbuff_set(dbuff, &our_dbuff);
711}
712
714{
715 fr_pair_t *vp;
716
717 vp = fr_dcursor_current(cursor);
719 fr_assert(!vp->da->flags.is_raw);
720
721 fr_assert(fr_type_is_group(vp->vp_type) || fr_type_is_tlv(vp->vp_type));
722
723 /*
724 * ISO/IEC 8825-1:2021
725 * 8.9 Encoding of a sequence value
726 * 8.9.1 The encoding of a sequence value shall be constructed.
727 * 8.9.2 The contents octets shall consist of the complete encoding of one data value from each of
728 * the types listed in the ASN.1 definition of the sequence type, in the order of their
729 * appearance in the definition, unless the type was referenced with the keyword OPTIONAL
730 * or the keyword DEFAULT.
731 * 8.9.3 The encoding of a data value may, but need not, be present for a type referenced with the
732 * keyword OPTIONAL or the keyword DEFAULT. If present, it shall appear in the order of
733 * appearance of the corresponding type in the ASN.1 definition.
734 *
735 * 11.5 Set and sequence components with default value
736 * The encoding of a set value or sequence value shall not include an encoding for any component
737 * value which is equal to its default value.
738 */
740 return fr_der_encode_oid_and_value(dbuff, cursor, encode_ctx);
741 }
742
743 return fr_der_encode_choice(dbuff, cursor, encode_ctx);
744}
745
746typedef struct {
747 uint8_t *data; //!< Pointer to the start of the encoded item (beginning of the tag)
748 size_t len; //!< Length of the encoded item (tag + length + value)
750
751/*
752 * Lexicographically sort the set of pairs
753 */
754static int CC_HINT(nonnull) fr_der_encode_set_of_cmp(void const *one, void const *two)
755{
758
759 return MEMCMP_FIELDS(a, b, data, len);
760}
761
763{
764 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
765 fr_pair_t *vp;
766 ssize_t slen;
767
768 vp = fr_dcursor_current(cursor);
770 fr_assert(!vp->da->flags.is_raw);
771
772 fr_assert(fr_type_is_tlv(vp->vp_type));
773
774 /*
775 * ISO/IEC 8825-1:2021
776 * 8.11 Encoding of a set value
777 * 8.11.1 The encoding of a set value shall be constructed.
778 * 8.11.2 The contents octets shall consist of the complete encoding of one data value from each
779 * of the types listed in the ASN.1 definition of the set type, in an order chosen by the
780 * sender, unless the type was referenced with the keyword OPTIONAL or the keyword DEFAULT.
781 * 8.11.3 The encoding of a data value may, but need not, be present for a type referenced with the
782 * keyword OPTIONAL or the keyword DEFAULT.
783 *
784 * 11.5 Set and sequence components with default value
785 * The encoding of a set value or sequence value shall not include an encoding for any component
786 * value which is equal to its default value.
787 *
788 * ISO/IEC 8825-1:2021
789 * 8.12 Encoding of a set-of value
790 * 8.12.1 The encoding of a set-of value shall be constructed.
791 * 8.12.2 The text of 8.10.2 applies.
792 * 8.12.3 The order of data values need not be preserved by the encoding and subsequent decoding.
793 *
794 * 11.6 Set-of components
795 * The encodings of the component values of a set-of value shall appear in ascending order, the
796 * encodings being compared as octet strings with the shorter components being padded at their
797 * trailing end with 0-octets.
798 * NOTE - The padding octets are for comparison purposes only and do not appear in the
799 * encodings.
800 */
801
803 /*
804 * Set-of items will all have the same tag, so we need to sort them lexicographically
805 */
806 size_t i, count;
807 fr_dbuff_t work_dbuff;
809 uint8_t *buff;
810 fr_da_stack_t da_stack;
811 fr_dcursor_t child_cursor;
812
813 /*
814 * This can happen, but is possible.
815 */
816 count = fr_pair_list_num_elements(&vp->children);
817 if (unlikely(!count)) return 0;
818
819 /*
820 * Sets can be nested, so we have to use local buffers when sorting.
821 */
822 buff = talloc_array(encode_ctx->tmp_ctx, uint8_t, fr_dbuff_remaining(&our_dbuff));
823 fr_assert(buff != NULL);
824
825 ptr_pairs = talloc_array(buff, fr_der_encode_set_of_ptr_pairs_t, count);
826 if (unlikely(ptr_pairs == NULL)) {
827 fr_strerror_const("Failed to allocate memory for set of pointers");
829 return -1;
830 }
831
832 /*
833 * Now that we have our intermediate buffers, initialize the buffers and start encoding.
834 */
835 fr_dbuff_init(&work_dbuff, buff, fr_dbuff_remaining(&our_dbuff));
836
837 fr_proto_da_stack_build(&da_stack, vp->da);
838
839 FR_PROTO_STACK_PRINT(&da_stack, vp->da->depth - 1);
840
841 fr_pair_dcursor_child_iter_init(&child_cursor, &vp->children, cursor);
842
843 for (i = 0; fr_dcursor_current(&child_cursor) != NULL; i++) {
844 ptr_pairs[i].data = fr_dbuff_current(&work_dbuff);
845
846 slen = encode_value(&work_dbuff, &child_cursor, encode_ctx);
847 if (unlikely(slen < 0)) {
848 fr_strerror_printf("Failed to encode pair: %s", fr_strerror());
850 return slen;
851 }
852
853 ptr_pairs[i].len = slen;
854 }
855
856 fr_assert(i <= count);
857 count = i;
858
859 /*
860 * If there's a "min" for this set, then we can't do anything about it.
861 */
862 if (unlikely(!count)) goto done;
863
864 /*
865 * If there's only one child, we don't need to sort it.
866 */
867 if (count > 1) qsort(ptr_pairs, count, sizeof(fr_der_encode_set_of_ptr_pairs_t), fr_der_encode_set_of_cmp);
868
869 /*
870 * The data in work_dbuff is always less than the data in the our_dbuff, so we don't need
871 * to check the return value here.
872 */
873 for (i = 0; i < count; i++) {
874 (void) fr_dbuff_in_memcpy(&our_dbuff, ptr_pairs[i].data, ptr_pairs[i].len);
875 }
876
877 done:
879
880 return fr_dbuff_set(dbuff, &our_dbuff);
881 }
882
883 /*
884 * Children of a set are ordered by tag. However, as each tag can only be used once, this is a
885 * unique order.
886 */
888
889 return fr_der_encode_choice(dbuff, cursor, encode_ctx);
890}
891
893{
894 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
895 fr_pair_t const *vp;
896 fr_sbuff_t time_sbuff;
897 char fmt_time[50] = { 0 };
898 size_t i;
899
900 fmt_time[0] = '\0';
901 time_sbuff = FR_SBUFF_OUT(fmt_time, sizeof(fmt_time));
902
903 vp = fr_dcursor_current(cursor);
905 fr_assert(!vp->da->flags.is_raw);
906
907 /*
908 * ISO/IEC 8825-1:2021
909 * 8.25 Encoding for values of the useful types
910 * The following "useful types" shall be encoded as if they had been replaced by their definitions
911 * given in clauses 46-48 of Rec. ITU-T X.680 | ISO/IEC 8824-1:
912 * - generalized time;
913 * - universal time;
914 * - object descriptor.
915 *
916 * 8.26 Encoding for values of the TIME type and the useful time types
917 * 8.26 Encoding for values of the TIME type and the useful time types 8.26.1 Encoding for values
918 * of the TIME type NOTE - The defined time types are subtypes of the TIME type, with the same
919 * tag, and have the same encoding as the TIME type. 8.26.1.1 The encoding of the TIME type shall
920 * be primitive. 8.26.1.2 The contents octets shall be the UTF-8 encoding of the value notation,
921 * after the removal of initial and final QUOTATION MARK (34) characters.
922 *
923 * 11.8 UTCTime
924 * 11.8.1 The encoding shall terminate with "Z", as described in the ITU-T X.680 | ISO/IEC 8824-1
925 * clause on UTCTime.
926 * 11.8.2 The seconds element shall always be present.
927 * 11.8.3 Midnight (GMT) shall be represented as "YYMMDD000000Z", where "YYMMDD" represents the
928 * day following the midnight in question.
929 */
930
931 /*
932 * The format of a UTC time is "YYMMDDhhmmssZ"
933 * Where:
934 * 1. YY is the year
935 * 2. MM is the month
936 * 3. DD is the day
937 * 4. hh is the hour
938 * 5. mm is the minute
939 * 6. ss is the second (not optional in DER)
940 * 7. Z is the timezone (UTC)
941 */
942 fr_unix_time_to_str(&time_sbuff, vp->vp_date, FR_TIME_RES_SEC, true);
943
944 /*
945 * Remove the century from the year
946 */
947 fr_sbuff_shift(&time_sbuff, 2, false);
948
949 /*
950 * Trim the time string of any unwanted characters
951 */
952 for (i = 0; i < sizeof(fmt_time); i++) {
953 if (fmt_time[i] == '\0') {
954 break;
955 }
956
957 if ((fmt_time[i] == '-') || (fmt_time[i] == 'T') || (fmt_time[i] == ':')) {
958 size_t j = i;
959
960 while (fmt_time[j] != '\0') {
961 fmt_time[j] = fmt_time[j + 1];
962 j++;
963 }
964
965 fmt_time[j] = '\0';
966
967 continue;
968 }
969 }
970
971 FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, fmt_time, DER_UTC_TIME_LEN);
972
973 return fr_dbuff_set(dbuff, &our_dbuff);
974}
975
978{
979 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
980 fr_pair_t const *vp;
981 fr_sbuff_t time_sbuff;
982 char fmt_time[50] = { 0 };
983 size_t i;
984
985 fmt_time[0] = '\0';
986 time_sbuff = FR_SBUFF_OUT(fmt_time, sizeof(fmt_time));
987
988 vp = fr_dcursor_current(cursor);
990 fr_assert(!vp->da->flags.is_raw);
991
992 /*
993 * ISO/IEC 8825-1:2021
994 * 8.25 Encoding for values of the useful types
995 * The following "useful types" shall be encoded as if they had been replaced by their definitions
996 * given in clauses 46-48 of Rec. ITU-T X.680 | ISO/IEC 8824-1:
997 * - generalized time;
998 * - universal time;
999 * - object descriptor.
1000 *
1001 * 8.26 Encoding for values of the TIME type and the useful time types
1002 * 8.26 Encoding for values of the TIME type and the useful time types 8.26.1 Encoding for values
1003 * of the TIME type NOTE - The defined time types are subtypes of the TIME type, with the same
1004 * tag, and have the same encoding as the TIME type. 8.26.1.1 The encoding of the TIME type shall
1005 * be primitive. 8.26.1.2 The contents octets shall be the UTF-8 encoding of the value notation,
1006 * after the removal of initial and final QUOTATION MARK (34) characters.
1007 *
1008 * 11.7 GeneralizedTime
1009 * 11.7.1 The encoding shall terminate with a "Z", as described in the Rec. ITU-T X.680 | ISO/IEC
1010 * 8824-1 clause on GeneralizedTime.
1011 * 11.7.2 The seconds element shall always be present.
1012 * 11.7.3 The fractional-seconds elements, if present, shall omit all trailing zeros; if the
1013 * elements correspond to 0, they shall be wholly omitted, and the decimal point element
1014 * also shall be omitted.
1015 */
1016
1017 /*
1018 * The format of a generalized time is "YYYYMMDDHHMMSS[.fff]Z"
1019 * Where:
1020 * 1. YYYY is the year
1021 * 2. MM is the month
1022 * 3. DD is the day
1023 * 4. HH is the hour
1024 * 5. MM is the minute
1025 * 6. SS is the second
1026 * 7. fff is the fraction of a second (optional)
1027 * 8. Z is the timezone (UTC)
1028 */
1029
1030 fr_unix_time_to_str(&time_sbuff, vp->vp_date, FR_TIME_RES_USEC, true);
1031
1032 /*
1033 * Trim the time string of any unwanted characters
1034 */
1035 for (i = 0; i < sizeof(fmt_time); i++) {
1036 if (fmt_time[i] == '\0') {
1037 break;
1038 }
1039
1040 if ((fmt_time[i] == '-') || (fmt_time[i] == 'T') || (fmt_time[i] == ':')) {
1041 size_t j = i;
1042
1043 while (fmt_time[j] != '\0') {
1044 fmt_time[j] = fmt_time[j + 1];
1045 j++;
1046 }
1047
1048 fmt_time[j] = '\0';
1049
1050 continue;
1051 }
1052
1053 if (fmt_time[i] == '.') {
1054 /*
1055 * Remove any trailing zeros
1056 */
1057 size_t j = strlen(fmt_time) - 2;
1058
1059 while (fmt_time[j] == '0') {
1060 fmt_time[j] = fmt_time[j + 1];
1061 fmt_time[j + 1] = '\0';
1062 j--;
1063 }
1064
1065 /*
1066 * Remove the decimal point if there are no fractional seconds
1067 */
1068 if (j == i) {
1069 fmt_time[i] = fmt_time[i + 1];
1070 fmt_time[i + 1] = '\0';
1071 }
1072 }
1073 }
1074
1075 FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, fmt_time, i);
1076
1077 return fr_dbuff_set(dbuff, &our_dbuff);
1078}
1079
1080/** Encode a CHOICE type
1081 *
1082 * @param[in] dbuff Buffer to write the encoded data to
1083 * @param[in] cursor Cursor to the pair to encode
1084 * @param[in] encode_ctx Encoding context
1085 *
1086 * @return Number of bytes written to the buffer, or -1 on error
1087 */
1089{
1090 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
1091 fr_pair_t const *vp;
1092 fr_da_stack_t da_stack;
1093 fr_dcursor_t child_cursor;
1094 ssize_t slen = 0;
1095
1096 vp = fr_dcursor_current(cursor);
1097 PAIR_VERIFY(vp);
1098 fr_assert(!vp->da->flags.is_raw);
1099
1100 fr_proto_da_stack_build(&da_stack, vp->da);
1101
1102 FR_PROTO_STACK_PRINT(&da_stack, vp->da->depth - 1);
1103
1104 fr_pair_dcursor_child_iter_init(&child_cursor, &vp->children, cursor);
1105
1106 slen = fr_pair_cursor_to_network(&our_dbuff, &da_stack, vp->da->depth - 1, &child_cursor, encode_ctx, encode_pair);
1107 if (slen < 0) return -1;
1108
1109 return fr_dbuff_set(dbuff, &our_dbuff);
1110}
1111
1113{
1114 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
1115 fr_dbuff_marker_t outer_seq_len_start;
1116 fr_dcursor_t child_cursor, root_cursor, parent_cursor;
1117 fr_pair_t const *vp;
1118 ssize_t slen = 0;
1119 size_t is_critical = 0;
1120 uint64_t max, num;
1121 fr_dbuff_marker_t length_start, inner_seq_len_start;
1122
1123 vp = fr_dcursor_current(cursor);
1124 PAIR_VERIFY(vp);
1125 fr_assert(!vp->da->flags.is_raw);
1126
1127 fr_assert(fr_type_is_group(vp->vp_type));
1128
1129 /*
1130 * RFC 5280 Section 4.2
1131 * The extensions defined for X.509 v3 certificates provide methods for
1132 * associating additional attributes with users or public keys and for
1133 * managing relationships between CAs. The X.509 v3 certificate format
1134 * also allows communities to define private extensions to carry
1135 * information unique to those communities. Each extension in a
1136 * certificate is designated as either critical or non-critical.
1137 *
1138 * Each extension includes an OID and an ASN.1 structure. When an
1139 * extension appears in a certificate, the OID appears as the field
1140 * extnID and the corresponding ASN.1 DER encoded structure is the value
1141 * of the octet string extnValue.
1142 *
1143 * RFC 5280 Section A.1 Explicitly Tagged Module, 1988 Syntax
1144 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
1145 *
1146 * Extension ::= SEQUENCE {
1147 * extnID OBJECT IDENTIFIER,
1148 * critical BOOLEAN DEFAULT FALSE,
1149 * extnValue OCTET STRING
1150 * -- contains the DER encoding of an ASN.1 value
1151 * -- corresponding to the extension type identified
1152 * -- by extnID
1153 * }
1154 *
1155 * So the extensions are a SEQUENCE of SEQUENCEs containing an OID, a boolean and an OCTET STRING.
1156 * Note: If the boolean value is false, it is not included in the encoding.
1157 */
1158
1159 max = fr_der_flag_max(vp->da); /* Maximum number of extensions specified in the dictionary */
1160 num = 0;
1161
1163 if (slen < 0) return slen;
1164
1165 fr_dbuff_marker(&outer_seq_len_start, &our_dbuff);
1166 FR_DBUFF_ADVANCE_RETURN(&our_dbuff, 1);
1167
1168 FR_PROTO_HEX_DUMP(fr_dbuff_start(&our_dbuff), fr_dbuff_used(&our_dbuff),"BEFORE encoded X509 extension");
1169
1170 fr_pair_dcursor_child_iter_init(&root_cursor, &vp->children, cursor);
1171 fr_dcursor_copy(&parent_cursor, &root_cursor);
1172
1173 fr_dbuff_marker(&inner_seq_len_start, &our_dbuff);
1174 fr_dbuff_marker(&length_start, &our_dbuff);
1175
1176 while (fr_dcursor_current(&parent_cursor)) {
1177 uint64_t component;
1178 int count;
1179 fr_pair_t *child;
1180
1181 /*
1182 * Extensions are sequences or sets containing 2 items:
1183 * 1. The first item is the OID
1184 * 2. The second item is the value
1185 *
1186 * Note: The value may be a constructed or primitive type
1187 */
1188
1189 if (num >= max) {
1190 fr_strerror_printf("Too many X509 extensions (%" PRIu64 ")", max);
1191 break;
1192 }
1193
1195 if (slen < 0) return slen;
1196
1197 fr_dbuff_set(&inner_seq_len_start, &our_dbuff);
1198 FR_DBUFF_ADVANCE_RETURN(&our_dbuff, 1);
1199
1200 /*
1201 * Encode the OID portion of the extension
1202 */
1204 if (slen < 0) return slen;
1205
1206 fr_dbuff_set(&length_start, &our_dbuff);
1207 FR_DBUFF_ADVANCE_RETURN(&our_dbuff, 1);
1208
1209 /*
1210 * Walk through the children until we find either an attribute marked as an extension, or one with
1211 * no children (which is an unknown OID).
1212 *
1213 * We will use this to construct the OID to encode, as well as to get the actual value of the
1214 * extension.
1215 */
1216 fr_dcursor_copy(&child_cursor, &parent_cursor);
1217 count = 0;
1218
1219 while ((child = fr_dcursor_current(&child_cursor)) != NULL) {
1220 PAIR_VERIFY(child);
1221
1222 FR_PROTO_TRACE("Child: %s", child->da->name);
1223
1224 if (!is_critical && (strcmp(child->da->name, "Critical") == 0)) {
1225 /*
1226 * We don't encode the critical flag
1227 */
1228 is_critical = fr_pair_list_num_elements(&child->children);
1229 FR_PROTO_TRACE("Critical flag: %zu", is_critical);
1230
1231 fr_pair_dcursor_child_iter_init(&parent_cursor, &child->children, &child_cursor);
1232 goto next;
1233 }
1234
1235 /*
1236 * If we find a normal leaf data type, we don't encode it. But we do encode leaf data
1237 * types which are marked up as needing OID leaf encoding.
1238 */
1239 if (!fr_type_is_structural(child->vp_type) && !fr_der_flag_leaf(child->da) && !child->da->flags.is_raw) {
1240 FR_PROTO_TRACE("Found non-structural child %s", child->da->name);
1241
1242 fr_dcursor_copy(&child_cursor, &parent_cursor);
1243 break;
1244 }
1245
1246 slen = fr_der_encode_oid_from_value(&our_dbuff, child->da->attr, &component, &count);
1247 if (unlikely(slen < 0)) return -1;
1248
1249 /*
1250 * We've encoded a leaf data type, or a raw one. Stop encoding it.
1251 */
1252 if (!fr_type_is_structural(child->vp_type)) break;
1253
1254 /*
1255 * Unless this was the last child (marked as an extension), there should only be one child
1256 * - representing the next OID in the extension
1257 */
1258 if (fr_pair_list_num_elements(&child->children) > 1) break;
1259
1260 next:
1261 if (fr_der_flag_leaf(child->da)) break;
1262
1263 fr_pair_dcursor_child_iter_init(&child_cursor, &child->children, &child_cursor);
1264 }
1265
1266 /*
1267 * Encode the length of the OID
1268 */
1269 slen = fr_der_encode_len(&our_dbuff, &length_start);
1270 if (slen < 0) return slen;
1271
1272 /*
1273 * Encode the critical flag
1274 */
1275 if (is_critical) {
1276 /*
1277 * Universal+Boolean flag is always 0x01. Length of a boolean is always 0x01.
1278 * True is always 0xff.
1279 */
1280 FR_DBUFF_IN_BYTES_RETURN(&our_dbuff, (uint8_t) 0x01, (uint8_t) 0x01, (uint8_t)(0xff));
1281 is_critical--;
1282 }
1283
1284 /*
1285 * Encode the value portion of the extension
1286 */
1288 if (slen < 0) return slen;
1289
1290 fr_dbuff_set(&length_start, &our_dbuff);
1291 FR_DBUFF_ADVANCE_RETURN(&our_dbuff, 1);
1292
1293 /*
1294 * Encode the data
1295 */
1296 slen = encode_value(&our_dbuff, &child_cursor, encode_ctx);
1297 if (slen < 0) return slen;
1298
1299 /*
1300 * Encode the length of the value
1301 */
1302 slen = fr_der_encode_len(&our_dbuff, &length_start);
1303 if (slen < 0) return slen;
1304
1305 /*
1306 * Encode the length of the extension (OID + Value portions)
1307 */
1308 slen = fr_der_encode_len(&our_dbuff, &inner_seq_len_start);
1309 if (slen < 0) return -1;
1310
1311 if (is_critical) {
1312 fr_dcursor_next(&parent_cursor);
1313 num++;
1314 continue;
1315 }
1316
1317 FR_PROTO_HEX_DUMP(fr_dbuff_start(&our_dbuff), fr_dbuff_behind(&outer_seq_len_start) + 2,
1318 "Encoded X509 extension");
1319
1320 fr_dcursor_next(&root_cursor);
1321 fr_dcursor_copy(&parent_cursor, &root_cursor);
1322 num++;
1323 }
1324
1325 /*
1326 * Encode the length of the extensions
1327 */
1328 slen = fr_der_encode_len(&our_dbuff, &outer_seq_len_start);
1329 if (slen < 0) return slen;
1330
1331 FR_PROTO_HEX_DUMP(fr_dbuff_start(&our_dbuff), slen, "Encoded X509 extensions");
1332
1333 return fr_dbuff_set(dbuff, &our_dbuff);
1334}
1335
1337{
1338 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
1339 fr_dbuff_marker_t length_start;
1340 fr_dcursor_t child_cursor, parent_cursor = *cursor;
1341 fr_pair_t const *vp, *child;
1342 ssize_t slen = 0;
1343 uint64_t component;
1344 int count;
1345
1346 vp = fr_dcursor_current(&parent_cursor);
1347 PAIR_VERIFY(vp);
1348 fr_assert(!vp->da->flags.is_raw);
1349
1350 fr_assert(fr_type_is_group(vp->vp_type));
1351
1352 /*
1353 * A very common pattern in DER encoding is ro have a sequence of set containing two things: an OID and a
1354 * value, where the OID is used to determine how to decode the value.
1355 * We will be decoding the OID first and then try to find the attribute associated with that OID to then
1356 * decode the value. If no attribute is found, one will be created and the value will be stored as raw
1357 * octets in the attribute.
1358 *
1359 * Note: The value may be a constructed or primitive type
1360 */
1361
1363 if (slen < 0) return slen;
1364
1365 fr_dbuff_marker(&length_start, &our_dbuff);
1366 FR_DBUFF_ADVANCE_RETURN(&our_dbuff, 1);
1367
1368 /*
1369 * Walk through the children until we find either an attribute marked as an oid leaf, or one with
1370 * no children (which is an unknown OID).
1371 *
1372 * We will use this to construct the OID to encode, as well as to get the actual value of the
1373 * pair.
1374 */
1375 fr_pair_dcursor_child_iter_init(&child_cursor, &vp->children, &parent_cursor);
1376 count = 0;
1377
1378 while ((child = fr_dcursor_current(&child_cursor)) != NULL) {
1379 PAIR_VERIFY(child);
1380
1381 /*
1382 * If we find a normal leaf data type, we don't encode it. But we do encode leaf data
1383 * types which are marked up as needing OID leaf encoding.
1384 */
1385 if (!fr_type_is_structural(child->vp_type) && !fr_der_flag_leaf(child->da) && !child->da->flags.is_raw) {
1386 FR_PROTO_TRACE("Found non-structural child %s", child->da->name);
1387
1388 fr_dcursor_copy(&child_cursor, &parent_cursor);
1389 break;
1390 }
1391
1392 slen = fr_der_encode_oid_from_value(&our_dbuff, child->da->attr, &component, &count);
1393 if (unlikely(slen < 0)) return -1;
1394
1395 /*
1396 * We've encoded a leaf data type, or a raw one. Stop encoding it.
1397 */
1398 if (!fr_type_is_structural(child->vp_type)) break;
1399
1400 /*
1401 * Some structural types can be marked as a leaf for the purposes of OID encoding.
1402 */
1403 if (fr_der_flag_leaf(child->da)) break;
1404
1405 /*
1406 * Unless this was the last child (marked as an oid leaf), there should only be one child
1407 * - representing the next OID in the pair
1408 */
1409 if (fr_pair_list_num_elements(&child->children) > 1) break;
1410
1411 fr_pair_dcursor_child_iter_init(&child_cursor, &child->children, &child_cursor);
1412 }
1413
1414 /*
1415 * Encode the length of the OID
1416 */
1417 slen = fr_der_encode_len(&our_dbuff, &length_start);
1418 if (slen < 0) return slen;
1419
1420 /*
1421 * And then encode the actual data.
1422 */
1423 slen = encode_value(&our_dbuff, &child_cursor, encode_ctx);
1424 if (slen < 0) return slen;
1425
1426 return fr_dbuff_set(dbuff, &our_dbuff);
1427}
1428
1430{
1431 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
1432 fr_pair_t const *vp;
1433
1434 vp = fr_dcursor_current(cursor);
1435 PAIR_VERIFY(vp);
1436 fr_assert(!vp->da->flags.is_raw);
1437
1438 /*
1439 * ISO/IEC 8825-1:2021
1440 * 8.23 Encoding for values of the restricted character string types
1441 * 8.23.1 The data value consists of a string of characters from the character set specified in
1442 * the ASN.1 type definition.
1443 * 8.23.2 Each data value shall be encoded independently of other data values of the same type.
1444 *
1445 * 10.2 String encoding forms
1446 * For bitstring, octetstring and restricted character string types, the constructed form of
1447 * encoding shall not be used. (Contrast with 8.23.6.)
1448 *
1449 * NOTE:
1450 * We DO NOT check for restricted character sets here. This should be done as a separate validation
1451 * step. Here we simply trust that administrators have done their job and are providing us with
1452 * valid data.
1453 */
1454
1455 FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, vp->vp_strvalue, vp->vp_length);
1456
1457 return fr_dbuff_set(dbuff, &our_dbuff);
1458}
1459
1462 [FR_DER_TAG_INTEGER] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_integer },
1463 [FR_DER_TAG_BITSTRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_bitstring },
1465 [FR_DER_TAG_NULL] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_null },
1466 [FR_DER_TAG_OID] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_oid },
1468 [FR_DER_TAG_UTF8_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_string },
1469 [FR_DER_TAG_SEQUENCE] = { .constructed = FR_DER_TAG_CONSTRUCTED, .encode = fr_der_encode_sequence },
1470 [FR_DER_TAG_SET] = { .constructed = FR_DER_TAG_CONSTRUCTED, .encode = fr_der_encode_set },
1472 .encode = fr_der_encode_string },
1473 [FR_DER_TAG_T61_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_string },
1474 [FR_DER_TAG_IA5_STRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_string },
1475 [FR_DER_TAG_UTC_TIME] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_utc_time },
1481 .encode = fr_der_encode_string },
1482};
1483
1492
1493
1494/** Encode the length field of a DER structure
1495 *
1496 * The input dbuff is composed of the following data:
1497 *
1498 * 1 byte of nothing (length_start). Where the "length length" will be written to.
1499 * N bytes of data. dbuff is pointing to the end of the encoded data.
1500 *
1501 * We have to either write a length to length_start (if it's < 0x7f),
1502 *
1503 * OR we figure out how many bytes we need to encode the length,
1504 * shift the data to the right to make room, and then encode the
1505 * length.
1506 *
1507 * @param dbuff The buffer to update with the length field
1508 * @param length_start The start of the length field
1509 * @return
1510 * - <0 for "cannot extend the input buffer by the needed "length length".
1511 * - 1 for "success". Note that 'length_start' WILL be updated after this call,
1512 * and the caller should just release it immediately.
1513 */
1515{
1516 size_t i, len_len;
1517 size_t tmp, datalen;
1518
1519 datalen = fr_dbuff_current(dbuff) - fr_dbuff_current(length_start) - 1;
1520
1521 /*
1522 * If the length can fit in a single byte, we don't need to extend the size of the length field
1523 */
1524 if (datalen <= 0x7f) {
1525 (void) fr_dbuff_in(length_start, (uint8_t) datalen);
1526 return 1;
1527 }
1528
1529 /*
1530 * Calculate the number of bytes needed to encode the length.
1531 */
1532 for (tmp = datalen, len_len = 0; tmp != 0; tmp >>= 8) {
1533 len_len++;
1534 }
1535
1536 /*
1537 * DER says that the length field cannot be more than
1538 * 0x7f. Since sizeof(datalen) == 8, we can always
1539 * encode the length field.
1540 */
1541 fr_assert(len_len > 0);
1542 fr_assert(len_len < 0x7f);
1543
1544 (void) fr_dbuff_in(length_start, (uint8_t) (0x80 | len_len));
1545
1546 /*
1547 * This is the only operation which can fail. The dbuff
1548 * is currently set to the end of the encoded data. We
1549 * need to ensure that there is sufficient room in the
1550 * dbuff to encode the additional bytes.
1551 *
1552 * fr_dbuff_set() checks if the length exceeds the input
1553 * buffer. But it does NOT extend the buffer by reading
1554 * more data, if more data is needed. So we need to
1555 * manually extend the dbuff here.
1556 */
1557 FR_DBUFF_EXTEND_LOWAT_OR_RETURN(dbuff, len_len);
1558
1559 /*
1560 * Reset the dbuff to the new start, where the data
1561 * should be.
1562 */
1563 fr_dbuff_set(dbuff, fr_dbuff_current(length_start) + len_len);
1564
1565 /*
1566 * Move the data over. Note that the move updates BOTH
1567 * input and output dbuffs. As a result, we have to wrap
1568 * 'length_start' in a temporary dbuff, so that it
1569 * doesn't get updated by the move.
1570 */
1571 fr_dbuff_move(dbuff, &FR_DBUFF(length_start), datalen);
1572
1573 /*
1574 * Encode high bits first, but only the non-zero ones.
1575 */
1576 for (i = len_len; i > 0; i--) {
1577 (void) fr_dbuff_in(length_start, (uint8_t)((datalen) >> ((i - 1) * 8)));
1578 }
1579
1580 return 1;
1581}
1582
1583/** Encode a DER tag
1584 *
1585 * @param dbuff The buffer to write the tag to
1586 * @param tag_num The tag number
1587 * @param tag_class The tag class
1588 * @param constructed Whether the tag is constructed
1589 *
1590 * @return The number of bytes written to the buffer
1591 */
1592static inline CC_HINT(always_inline) ssize_t
1594 fr_der_tag_constructed_t constructed)
1595{
1596 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
1597 uint8_t tag_byte;
1598
1599 tag_byte = (tag_class & DER_TAG_CLASS_MASK) | (constructed & DER_TAG_CONSTRUCTED_MASK) |
1600 (tag_num & DER_TAG_NUM_MASK);
1601
1602 FR_DBUFF_IN_RETURN(&our_dbuff, tag_byte);
1603
1604 return fr_dbuff_set(dbuff, &our_dbuff);
1605}
1606
1607/** Encode a DER structure
1608 *
1609 * @param[out] dbuff The buffer to write the structure to
1610 * @param[in] cursor The cursor to the structure to encode
1611 * @param[in] encode_ctx The encoding context
1612 *
1613 * @return The number of bytes written to the buffer
1614 */
1616{
1617 fr_pair_t const *vp;
1618 fr_dbuff_t our_dbuff;
1619 fr_dbuff_marker_t marker;
1620 fr_der_tag_encode_t const *func;
1621 fr_der_tag_t tag;
1622 fr_der_tag_class_t tag_class;
1624 ssize_t slen = 0;
1625 fr_der_attr_flags_t const *flags;
1626
1627 if (unlikely(cursor == NULL)) {
1628 fr_strerror_const("No cursor to encode");
1629 return -1;
1630 }
1631
1632 vp = fr_dcursor_current(cursor);
1633 if (unlikely(!vp)) {
1634 fr_strerror_const("No pair to encode");
1635 return -1;
1636 }
1637
1638 PAIR_VERIFY(vp);
1639
1640 FR_PROTO_TRACE("Encoding %s", vp->da->name);
1641
1642 flags = fr_der_attr_flags(vp->da);
1643 fr_assert(flags != NULL);
1644
1645 /*
1646 * Raw things get encoded as-is, so that we can encode the correct tag and class.
1647 */
1648 if (unlikely(vp->da->flags.is_raw)) {
1649 fr_assert(vp->vp_type == FR_TYPE_OCTETS);
1650
1651 slen = fr_der_encode_octetstring(dbuff, cursor, encode_ctx);
1652 if (slen < 0) return 0;
1653
1654 fr_dcursor_next(cursor);
1655 return slen;
1656 }
1657
1658 our_dbuff = FR_DBUFF(dbuff);
1659
1660 /*
1661 * ISO/IEC 8825-1:2021
1662 * The structure of a DER encoding is as follows:
1663 *
1664 * +------------+--------+-------+
1665 * | IDENTIFIER | LENGTH | VALUE |
1666 * +------------+--------+-------+
1667 *
1668 * The IDENTIFIER is a tag that specifies the type of the value field and is encoded as follows:
1669 *
1670 * 8 7 6 5 4 3 2 1
1671 * +---+---+-----+---+---+---+---+---+
1672 * | Class | P/C | Tag Number |
1673 * +---+---+-----+---+---+---+---+---+
1674 * |
1675 * |- 0 = Primitive
1676 * |- 1 = Constructed
1677 *
1678 * The CLASS field specifies the encoding class of the tag and may be one of the following values:
1679 *
1680 * +------------------+-------+-------+
1681 * | Class | Bit 8 | Bit 7 |
1682 * +------------------+-------+-------+
1683 * | UNIVERSAL | 0 | 0 |
1684 * | APPLICATION | 0 | 1 |
1685 * | CONTEXT-SPECIFIC | 1 | 0 |
1686 * | PRIVATE | 1 | 1 |
1687 * +------------------+-------+-------+
1688 *
1689 * The P/C field specifies whether the value field is primitive or constructed.
1690 * The TAG NUMBER field specifies the tag number of the value field and is encoded as an unsigned binary
1691 * integer.
1692 *
1693 * The LENGTH field specifies the length of the VALUE field and is encoded as an unsigned binary integer
1694 * and may be encoded as a single byte or multiple bytes.
1695 *
1696 * The VALUE field contains LENGTH number of bytes and is encoded according to the tag.
1697 *
1698 */
1699
1700 if (flags->has_default_value) {
1701 /*
1702 * Skip encoding the default value, as per ISO/IEC 8825-1:2021 11.5
1703 */
1704 if (fr_value_box_cmp(&vp->data, flags->default_value) == 0) {
1705 FR_PROTO_TRACE("Skipping default value");
1706 fr_dcursor_next(cursor);
1707 return 0;
1708 }
1709 }
1710
1711 if (unlikely(flags->is_choice)) {
1712 slen = fr_der_encode_choice(&our_dbuff, cursor, uctx);
1713 if (slen < 0) return slen;
1714
1715 fr_dcursor_next(cursor);
1716 return fr_dbuff_set(dbuff, &our_dbuff);
1717 }
1718
1719 tag = flags->der_type;
1720 if (!tag) tag = fr_type_to_der_tag_default(vp->vp_type);
1721
1722 if (unlikely(tag == FR_DER_TAG_INVALID)) {
1723 fr_strerror_printf("No tag defined for type %s", fr_type_to_str(vp->vp_type));
1724 return -1;
1725 }
1726
1728
1729 func = &type_funcs[vp->vp_type];
1730 if (!func->encode) func = &tag_funcs[tag];
1731
1732 fr_assert(func != NULL);
1733 fr_assert(func->encode != NULL);
1734
1735 /*
1736 * Default flag class is 0, which is FR_DER_CLASS_UNIVERSAL.
1737 */
1738 tag_class = flags->class;
1739
1740 /*
1741 * We call the DER type encoding function based on its
1742 * tag, but we might need to encode an option value
1743 * instead of a tag.
1744 */
1745 if (flags->is_option) tag = flags->option;
1746
1747 slen = fr_der_encode_tag(&our_dbuff, tag, tag_class, func->constructed);
1748 if (slen < 0) return slen;
1749
1750 /*
1751 * Mark and reserve space in the buffer for the length field
1752 */
1753 fr_dbuff_marker(&marker, &our_dbuff);
1754 FR_DBUFF_ADVANCE_RETURN(&our_dbuff, 1);
1755
1756 if (flags->is_extensions) {
1757 slen = fr_der_encode_X509_extensions(&our_dbuff, cursor, uctx);
1758 } else {
1759
1760 slen = func->encode(&our_dbuff, cursor, uctx);
1761 }
1762 if (slen < 0) return slen;
1763
1764 /*
1765 * Encode the length of the value
1766 */
1767 slen = fr_der_encode_len(&our_dbuff, &marker);
1768 if (slen < 0) return slen;
1769
1770 fr_dcursor_next(cursor);
1771 return fr_dbuff_set(dbuff, &our_dbuff);
1772}
1773
1774static ssize_t fr_der_encode_proto(UNUSED TALLOC_CTX *ctx, fr_pair_list_t *vps, uint8_t *data, size_t data_len,
1775 void *encode_ctx)
1776{
1777 fr_dbuff_t dbuff;
1778 fr_dcursor_t cursor;
1779 ssize_t slen;
1780
1781 fr_dbuff_init(&dbuff, data, data_len);
1782
1783 fr_pair_dcursor_init(&cursor, vps);
1784
1785 slen = encode_value(&dbuff, &cursor, encode_ctx);
1786
1787 if (slen < 0) {
1788 fr_strerror_printf("Failed to encode data: %s", fr_strerror());
1789 return -1;
1790 }
1791
1792 return slen;
1793}
1794
1795/*
1796 * Test points
1797 */
1798static int encode_test_ctx(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict,
1799 UNUSED fr_dict_attr_t const *root_da)
1800{
1801 fr_der_encode_ctx_t *test_ctx;
1802
1803 test_ctx = talloc_zero(ctx, fr_der_encode_ctx_t);
1804 if (!test_ctx) return -1;
1805
1806 test_ctx->tmp_ctx = talloc(test_ctx, uint8_t);
1807
1808 *out = test_ctx;
1809
1810 return 0;
1811}
1812
1818
#define RCSID(id)
Definition build.h:506
#define CMP_PREFER_SMALLER(_a, _b)
Evaluates to +1 for a > b, and -1 for a < b.
Definition build.h:105
#define unlikely(_x)
Definition build.h:402
#define UNUSED
Definition build.h:336
#define MEMCMP_FIELDS(_a, _b, _field, _len_field)
Return the comparison of two opaque fields of a structure.
Definition build.h:178
#define fr_dbuff_behind(_dbuff_or_marker)
How many bytes the dbuff or marker is behind its parent.
Definition dbuff.h:794
#define fr_dbuff_used(_dbuff_or_marker)
Return the number of bytes remaining between the start of the dbuff or marker and the current positio...
Definition dbuff.h:775
#define FR_DBUFF_ADVANCE_RETURN(_dbuff_or_marker, _len)
Advance the 'current' position in dbuff or marker by _len bytes returning if _len is out of range.
Definition dbuff.h:1097
#define FR_DBUFF_EXTEND_LOWAT_OR_RETURN(_dbuff_or_marker, _lowat)
Extend if we're below _lowat and return if we can't extend above _lowat.
Definition dbuff.h:681
struct fr_dbuff_marker_s fr_dbuff_marker_t
A position marker associated with a dbuff.
Definition dbuff.h:81
#define fr_dbuff_current(_dbuff_or_marker)
Return the 'current' position of a dbuff or marker.
Definition dbuff.h:919
#define fr_dbuff_set(_dst, _src)
Set the 'current' position in a dbuff or marker using another dbuff or marker, a char pointer,...
Definition dbuff.h:1012
#define fr_dbuff_init(_out, _start, _len_or_end)
Initialise an dbuff for encoding or decoding.
Definition dbuff.h:362
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition dbuff.h:906
#define fr_dbuff_remaining(_dbuff_or_marker)
Return the number of bytes remaining between the dbuff or marker and the end of the buffer.
Definition dbuff.h:751
static uint8_t * fr_dbuff_marker(fr_dbuff_marker_t *m, fr_dbuff_t *dbuff)
Initialises a new marker pointing to the 'current' position of the dbuff.
Definition dbuff.h:1201
#define FR_DBUFF_IN_MEMCPY_RETURN(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into dbuff or marker returning if there's insufficient space.
Definition dbuff.h:1391
#define fr_dbuff_in_memcpy(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into a dbuff or marker.
Definition dbuff.h:1359
#define fr_dbuff_in(_dbuff_or_marker, _in)
Copy data from a fixed sized C type into a dbuff or marker.
Definition dbuff.h:1576
#define FR_DBUFF_IN_RETURN(_dbuff_or_marker, _in)
Copy data from a fixed sized C type into a dbuff returning if there is insufficient space.
Definition dbuff.h:1594
#define FR_DBUFF(_dbuff_or_marker)
Create a new dbuff pointing to the same underlying buffer.
Definition dbuff.h:230
#define fr_dbuff_move(_out, _in, _len)
Copy in as many bytes as possible from one dbuff or marker to another.
Definition dbuff.h:1665
#define fr_dbuff_out(_out, _dbuff_or_marker)
Copy data from a dbuff or marker to a fixed sized C type.
Definition dbuff.h:1808
#define fr_dbuff_set_end(_dst, _end)
Set a new 'end' position in a dbuff or marker.
Definition dbuff.h:1059
#define FR_DBUFF_IN_BYTES_RETURN(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker returning if there's insufficient space.
Definition dbuff.h:1481
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition dcursor.h:288
static void fr_dcursor_copy(fr_dcursor_t *out, fr_dcursor_t const *in)
Copy cursor parameters and state.
Definition dcursor.h:190
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
Definition dcursor.h:337
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_INTEGER
Arbitrary width signed integer.
Definition der.h:37
@ FR_DER_TAG_BOOLEAN
Boolean true/false.
Definition der.h:36
@ 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 is_extensions
a list of X.509 extensions
Definition der.h:111
#define fr_der_flag_der_type(_da)
Definition der.h:130
fr_der_tag_t der_type
the DER type, which is different from the FreeRADIUS type
Definition der.h:95
bool is_option
has an option defined
Definition der.h:106
#define DER_BOOLEAN_TRUE
DER encoded boolean true value.
Definition der.h:91
#define fr_der_flag_is_oid_and_value(_da)
Definition der.h:136
#define fr_der_flag_leaf(_da)
Definition der.h:139
#define DER_BOOLEAN_FALSE
DER encoded boolean false value.
Definition der.h:90
#define fr_der_flag_is_set_of(_da)
Definition der.h:134
#define DER_TAG_CLASS_MASK
Mask to extract the class from the tag.
Definition der.h:82
#define fr_der_flag_max(_da)
Definition der.h:135
#define DER_UTC_TIME_LEN
Length of the UTC time string.
Definition der.h:78
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
#define DER_TAG_NUM_MASK
Mask to extract the tag number from the tag.
Definition der.h:84
static fr_der_attr_flags_t const * fr_der_attr_flags(fr_dict_attr_t const *da)
Definition der.h:122
bool is_choice
DER name "choice".
Definition der.h:115
uint8_t option
an "attribute number" encoded in the tag field.
Definition der.h:105
#define DER_TAG_CONSTRUCTED_MASK
Mask to check if the tag is constructed.
Definition der.h:83
bool has_default_value
a default value exists
Definition der.h:112
fr_der_tag_class_t class
tag Class
Definition der.h:94
fr_der_tag_class_t
Definition der.h:68
@ FR_DER_CLASS_UNIVERSAL
Definition der.h:69
Test enumeration values.
Definition dict_test.h:92
talloc_free(hp)
static ssize_t encode_value(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, int depth, fr_dcursor_t *cursor, void *encode_ctx)
Encodes the data portion of an attribute.
Definition encode.c:277
ssize_t fr_pair_cursor_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx, fr_encode_dbuff_t encode_pair)
Definition encode.c:73
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_MAX
Number of defined data types.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
@ FR_TYPE_OCTETS
Raw octets.
long int ssize_t
unsigned char uint8_t
static uint8_t depth(fr_minmax_heap_index_t i)
Definition minmax_heap.c:83
void fr_proto_da_stack_build(fr_da_stack_t *stack, fr_dict_attr_t const *da)
Build a complete DA stack from the da back to the root.
Definition proto.c:118
static fr_internal_encode_ctx_t encode_ctx
static int encode_test_ctx(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict, UNUSED fr_dict_attr_t const *root_da)
Definition encode.c:165
static ssize_t encode_pair(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED void *encode_ctx)
Definition base.c:39
fr_der_tag_t fr_type_to_der_tag_default(fr_type_t type)
Definition base.c:892
static ssize_t fr_der_encode_ipv4_addr(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:348
static ssize_t fr_der_encode_sequence(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:713
uint8_t * tmp_ctx
Temporary context for encoding.
Definition encode.c:38
static ssize_t fr_der_encode_octetstring(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:525
static const fr_der_tag_encode_t tag_funcs[FR_DER_TAG_MAX]
Definition encode.c:1460
static int fr_der_encode_set_of_cmp(void const *one, void const *two)
Definition encode.c:754
static ssize_t fr_der_encode_choice(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx)
Encode a CHOICE type.
Definition encode.c:1088
ssize_t(* fr_der_encode_t)(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx)
Function signature for DER encode functions.
Definition encode.c:51
static ssize_t fr_der_encode_ipv6_addr(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:423
static ssize_t fr_der_encode_oid(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:653
static ssize_t fr_der_encode_null(UNUSED fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:565
static ssize_t fr_der_encode_boolean(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:96
static ssize_t fr_der_encode_oid_and_value(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:1336
static ssize_t fr_der_encode_oid_from_value(fr_dbuff_t *dbuff, uint64_t value, uint64_t *component, int *count)
Definition encode.c:589
static ssize_t fr_der_encode_proto(UNUSED TALLOC_CTX *ctx, fr_pair_list_t *vps, uint8_t *data, size_t data_len, void *encode_ctx)
Definition encode.c:1774
static ssize_t fr_der_encode_generalized_time(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:976
size_t len
Length of the encoded item (tag + length + value)
Definition encode.c:748
static ssize_t fr_der_encode_len(fr_dbuff_t *dbuff, fr_dbuff_marker_t *length_start)
Encode the length field of a DER structure.
Definition encode.c:1514
#define fr_der_encode_enumerated
Definition encode.c:67
fr_dict_attr_t const * attr_oid_tree
Definition base.c:39
static ssize_t fr_der_encode_string(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:1429
fr_der_tag_constructed_t constructed
Definition encode.c:54
static ssize_t fr_der_encode_X509_extensions(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:1112
static int8_t fr_der_pair_cmp_by_da_tag(void const *a, void const *b)
Compare two pairs by their tag number.
Definition encode.c:82
static const fr_der_tag_encode_t type_funcs[FR_TYPE_MAX]
Definition encode.c:1484
static ssize_t fr_der_encode_combo_ip(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:495
static ssize_t fr_der_encode_set(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:762
fr_test_point_pair_encode_t der_tp_encode_pair
Definition encode.c:1814
static ssize_t fr_der_encode_bitstring(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:215
fr_test_point_proto_encode_t der_tp_encode_proto
Definition encode.c:1820
static ssize_t fr_der_encode_tag(fr_dbuff_t *dbuff, fr_der_tag_t tag_num, fr_der_tag_class_t tag_class, fr_der_tag_constructed_t constructed)
Encode a DER tag.
Definition encode.c:1593
static ssize_t fr_der_encode_ipv6_prefix(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:455
static ssize_t fr_der_encode_integer(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:126
fr_der_encode_t encode
Definition encode.c:55
static ssize_t fr_der_encode_utc_time(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:892
static ssize_t fr_der_encode_ipv4_prefix(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
Definition encode.c:380
uint8_t * data
Pointer to the start of the encoded item (beginning of the tag)
Definition encode.c:747
#define fr_assert(_expr)
Definition rad_assert.h:37
static bool done
Definition radclient.c:80
size_t fr_sbuff_shift(fr_sbuff_t *sbuff, size_t shift, bool move_end)
Shift the contents of the sbuff, returning the number of bytes we managed to shift.
Definition sbuff.c:201
#define FR_SBUFF_OUT(_start, _len_or_end)
static char buff[sizeof("18446744073709551615")+3]
Definition size_tests.c:41
return count
Definition module.c:155
fr_pair_t * vp
ssize_t fr_struct_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *parent_cursor, void *encode_ctx, fr_encode_dbuff_t encode_value, fr_encode_dbuff_t encode_pair)
Definition struct.c:753
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Definition test_point.h:94
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Definition test_point.h:76
Entry point for pair encoders.
Definition test_point.h:93
Entry point for protocol encoders.
Definition test_point.h:75
fr_slen_t fr_unix_time_to_str(fr_sbuff_t *out, fr_unix_time_t time, fr_time_res_t res, bool utc)
Convert unix time to string.
Definition time.c:1132
@ FR_TIME_RES_USEC
Definition time.h:59
@ FR_TIME_RES_SEC
Definition time.h:50
static fr_pair_t * fr_pair_dcursor_child_iter_init(fr_dcursor_t *cursor, fr_pair_list_t const *list, fr_dcursor_t const *parent)
Initializes a child dcursor from a parent cursor, with an iteration function.
Definition pair.h:622
#define PAIR_VERIFY(_x)
Definition pair.h:204
void fr_pair_list_sort(fr_pair_list_t *list, fr_cmp_t cmp)
Sort a doubly linked list of fr_pair_ts using merge sort.
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition pair.h:604
size_t fr_pair_list_num_elements(fr_pair_list_t const *list)
Get the length of a list of fr_pair_t.
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
Definition proto.h:42
#define FR_PROTO_TRACE(_fmt,...)
Definition proto.h:41
#define FR_PROTO_STACK_PRINT(_stack, _depth)
Definition proto.h:44
uint8_t depth
Deepest attribute in the stack.
Definition proto.h:56
fr_dict_attr_t const * da[FR_DICT_MAX_TLV_STACK+1]
The stack.
Definition proto.h:57
Structure for holding the stack of dictionary attributes being encoded.
Definition proto.h:55
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:553
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
#define fr_type_is_group(_x)
Definition types.h:376
#define fr_type_is_structural(_x)
Definition types.h:392
@ FR_TYPE_ATTR
A contains an attribute reference.
Definition types.h:83
#define fr_type_is_tlv(_x)
Definition types.h:372
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:454
#define fr_type_is_struct(_x)
Definition types.h:373
int8_t fr_value_box_cmp(fr_value_box_t const *a, fr_value_box_t const *b)
Compare two values.
Definition value.c:748
static fr_slen_t data
Definition value.h:1340
int nonnull(2, 5))
static size_t char ** out
Definition value.h:1030