The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
decode.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program 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
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * @file src/lib/eap_aka_sim/decode.c
19 * @brief Code common to EAP-SIM/AKA/AKA' clients and servers.
20 *
21 * The development of the EAP-SIM support was funded by Internet Foundation
22 * Austria (http://www.nic.at/ipa).
23 *
24 * @copyright 2003 Michael Richardson (mcr@sandelman.ottawa.on.ca)
25 * @copyright 2003-2016 The FreeRADIUS server project
26 */
27
28RCSID("$Id: 119d3fa11c8dca11f91fe5fed0c8b381c2a7ca4b $")
29
30#include <freeradius-devel/io/test_point.h>
31#include <freeradius-devel/server/module.h>
32#include <freeradius-devel/tls/strerror.h>
33#include <freeradius-devel/util/debug.h>
34#include <freeradius-devel/util/sha1.h>
35#include <freeradius-devel/util/decode.h>
36
37#include <freeradius-devel/eap/types.h>
38#include "attrs.h"
39#include "base.h"
40#include "crypto_priv.h"
41
42/*
43 * EAP-SIM/AKA/AKA' PACKET FORMAT
44 * ---------------- ------ ------
45 *
46 * EAP Request and Response Packet Format
47 * --- ------- --- -------- ------ ------
48 * 0 1 2 3
49 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
50 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 * | Code | Identifier | Length |
52 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 * | Type | AT-Type | AT-Length | value ... |
54 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 *
56 * With AT-Type/AT-Length/Value... repeating. Length is in units
57 * of 32 bits, and includes the Type/Length fields.
58 */
59
61 uint8_t const *data, size_t data_len, void *decode_ctx);
62
64 uint8_t const *data, size_t const attr_len, size_t const data_len,
65 void *decode_ctx);
66
67/** Extract the IV value from an AT_IV attribute
68 *
69 * SIM uses padding at the start of the attribute to make it a multiple of 4.
70 * We need to strip packet_ctx and check that it was set to zero.
71 *
72 * @param[out] out Where to write IV.
73 * @param[in] in value of AT_IV attribute.
74 * @param[in] in_len the length of the AT_IV attribute (should be 18).
75 * @return
76 * - 0 on success.
77 * - < 0 on failure (bad IV).
78 */
79static inline int sim_iv_extract(uint8_t out[AKA_SIM_IV_SIZE], uint8_t const *in, size_t in_len)
80{
81 /*
82 * Two bytes are reserved, so although
83 * the IV is actually 16 bytes, we
84 * check for 18.
85 */
86 if (in_len != (AKA_SIM_IV_SIZE + 2)) {
87 fr_strerror_printf("%s: Invalid IV length, expected %u got %zu",
88 __FUNCTION__, (AKA_SIM_IV_SIZE + 2), in_len);
89 return -1;
90 }
91
92 if ((in[0] != 0x00) || (in[1] != 0x00)) {
93 fr_strerror_printf("%s: Reserved bytes in IV are not zeroed", __FUNCTION__);
94 return -1;
95 }
96
97 /* skip reserved bytes */
98 memcpy(out, in + 2, AKA_SIM_IV_SIZE);
99
100 return 0;
101}
102
103/** Decrypt an AES-128-CBC encrypted attribute
104 *
105 * @param[in] ctx to allocate decr buffer in.
106 * @param[out] out where to write pointer to decr buffer.
107 * @param[in] data to decrypt.
108 * @param[in] attr_len length of encrypted data.
109 * @param[in] data_len length of data remaining in the packet.
110 * @param[in] decode_ctx containing keys, and the IV (if we already found it).
111 * @return
112 * - Number of decr bytes decrypted on success.
113 * - < 0 on failure.
114 */
115static ssize_t sim_value_decrypt(TALLOC_CTX *ctx, uint8_t **out,
116 uint8_t const *data, size_t const attr_len, size_t const data_len,
117 void *decode_ctx)
118{
119 fr_aka_sim_ctx_t *packet_ctx = decode_ctx;
120 EVP_CIPHER_CTX *evp_ctx;
121 EVP_CIPHER const *evp_cipher = EVP_aes_128_cbc();
122 size_t block_size = EVP_CIPHER_block_size(evp_cipher);
123 int len = 0;
124 size_t decr_len = 0;
125 uint8_t *decr = NULL;
126
127 if (!fr_cond_assert(attr_len <= data_len)) return -1;
128
129 FR_PROTO_HEX_DUMP(data, attr_len, "ciphertext");
130
131 /*
132 * Encrypted values must be a multiple of 16.
133 *
134 * There's a padding attribute to ensure they
135 * always can be...
136 */
137 if (attr_len % block_size) {
138 fr_strerror_printf("%s: Encrypted attribute is not a multiple of cipher's block size (%zu)",
139 __FUNCTION__, block_size);
140 return -1;
141 }
142
143 /*
144 * Ugh, now we have to go hunting for it....
145 */
146 if (!packet_ctx->have_iv) {
147 uint8_t const *p = data + attr_len; /* Skip to the end of packet_ctx attribute */
148 uint8_t const *end = data + data_len;
149
150 while ((size_t)(end - p) >= sizeof(uint32_t)) {
151 uint8_t sim_at = p[0];
152 size_t sim_at_len = p[1] * sizeof(uint32_t);
153
154 if (sim_at_len == 0) {
155 fr_strerror_printf("%s: Failed IV search. AT Length field is zero", __FUNCTION__);
156 return -1;
157 }
158
159 if ((p + sim_at_len) > end) {
160 fr_strerror_printf("%s: Invalid IV length, longer than remaining data", __FUNCTION__);
161 return -1;
162 }
163
164 if (sim_at == FR_IV) {
165 if (sim_iv_extract(&(packet_ctx->iv[0]), p + 2, sim_at_len - 2) < 0) return -1;
166 packet_ctx->have_iv = true;
167 break;
168 }
169 p += sim_at_len;
170 }
171
172 if (!packet_ctx->have_iv) {
173 fr_strerror_printf("%s: No IV present in packet, can't decrypt data", __FUNCTION__);
174 return -1;
175 }
176 }
177
178 if (unlikely(!packet_ctx->k_encr)) {
179 fr_strerror_printf("%s: No k_encr set, cannot decrypt attributes", __FUNCTION__);
181 }
182
183 evp_ctx = aka_sim_crypto_cipher_ctx();
184 if (!EVP_DecryptInit_ex(evp_ctx, evp_cipher, NULL, packet_ctx->k_encr, packet_ctx->iv)) {
185 fr_tls_strerror_printf("%s: Failed setting decryption parameters", __FUNCTION__);
186 error:
187 talloc_free(decr);
188 return -1;
189 }
190
191 MEM(decr = talloc_zero_array(ctx, uint8_t, attr_len));
192
193 /*
194 * By default OpenSSL expects 16 bytes of cleartext
195 * to produce 32 bytes of ciphertext, due to padding
196 * being added if the decr is a multiple of 16.
197 *
198 * There's no way for OpenSSL to determine if a
199 * 16 byte ciphertext was padded or not, so we need to
200 * inform OpenSSL explicitly that there's no padding.
201 */
202 EVP_CIPHER_CTX_set_padding(evp_ctx, 0);
203 if (!EVP_DecryptUpdate(evp_ctx, decr, &len, data, (int)attr_len)) {
204 fr_tls_strerror_printf("%s: Failed decrypting attribute", __FUNCTION__);
205 goto error;
206 }
207 decr_len = len;
208
209 if (!EVP_DecryptFinal_ex(evp_ctx, decr + decr_len, &len)) {
210 fr_tls_strerror_printf("%s: Failed decrypting attribute", __FUNCTION__);
211 goto error;
212 }
213 decr_len += len;
214
215 /*
216 * Note: packet_ctx implicitly validates the length of the padding
217 * attribute (if present), so we don't have to do it later.
218 */
219 if (decr_len % block_size) {
220 fr_strerror_printf("%s: Expected decrypted value length to be multiple of %zu, got %zu",
221 __FUNCTION__, block_size, decr_len);
222 goto error;
223 }
224
225 /*
226 * Ciphertext should be same length as plaintext.
227 */
228 if (unlikely(attr_len != decr_len)) {
229 fr_strerror_printf("%s: Invalid plaintext length, expected %zu, got %zu",
230 __FUNCTION__, attr_len, decr_len);
231 goto error;
232 }
233
234 FR_PROTO_TRACE("decryption successful, got %zu bytes of cleartext", decr_len);
235 FR_PROTO_HEX_DUMP(decr, decr_len, "cleartext");
236
237 *out = decr;
238
239 return decr_len;
240}
241
242/** Returns the number of array members for arrays with fixed element sizes
243 *
244 * @param[out] out The element length.
245 * @param[in] len the total length of the array.
246 * @param[in] da the specifying the array type.
247 * @return
248 * - The number of elements in the array on success.
249 * - < 0 on error (array length not a multiple of element size).
250 */
251static ssize_t sim_array_members(size_t *out, size_t len, fr_dict_attr_t const *da)
252{
253 size_t element_len;
254
255 /*
256 * Could be an array of bytes, integers, etc.
257 */
258 switch (da->type) {
259 case FR_TYPE_OCTETS:
260 if (da->flags.length == 0) {
261 fr_strerror_printf("%s: Octets array must have fixed length elements", __FUNCTION__);
262 return -1;
263 }
264 element_len = da->flags.length;
265 break;
266
267 default:
268 element_len = fr_aka_sim_attr_sizes[da->type][0];
269 break;
270 }
271
272 if (element_len == 1) {
273 *out = 1;
274 return 1; /* Fast path */
275 }
276
277 if (!fr_cond_assert(element_len > 0)) return -1;
278
279 if (element_len > len) {
280 fr_strerror_printf("%s: Element length (%zu) > array length (%zu)", __FUNCTION__,
281 element_len, len);
282 return -1;
283 }
284
285 /*
286 * Number of elements must divide exactly
287 */
288 if (len % element_len) {
289 fr_strerror_printf("%s: Expected array actual length to be multiple of %zu, got %zu",
290 __FUNCTION__, element_len, len);
291 return -1;
292 }
293 *out = element_len;
294
295 return len / element_len;
296}
297
299 fr_dict_attr_t const *parent,
300 uint8_t const *data, size_t const attr_len, UNUSED size_t data_len,
301 void *decode_ctx)
302{
303 uint8_t const *p = data, *end = p + attr_len;
304 uint16_t actual_len;
305 ssize_t elements, i;
306 size_t element_len;
307 ssize_t ret;
308
309 FR_PROTO_TRACE("Array attribute");
310
311 fr_assert(parent->flags.array);
312 fr_assert(attr_len >= 2); /* Should have been caught earlier */
313
314 /*
315 * Arrays with fixed length members that
316 * are a multiple of 4 don't need an
317 * actual_len value, as we can get the
318 * number of elements from the attribute
319 * length.
320 */
321 if (!parent->flags.length || (parent->flags.length % 4)) {
322 actual_len = fr_nbo_to_uint16(p);
323 if (actual_len > (attr_len - 2)) {
324 fr_strerror_printf("%s: Actual length field value (%hu) > attribute value length (%zu)",
325 __FUNCTION__, actual_len, attr_len - 2);
326 return -1;
327 }
328 } else {
329 actual_len = attr_len - 2; /* -2 for the reserved bytes */
330 }
331 p += 2;
332
333 /*
334 * Zero length array
335 */
336 if (!actual_len) return p - data;
337
338 /*
339 * Get the number of elements
340 */
341 elements = sim_array_members(&element_len, actual_len, parent);
342 if (elements < 0) return elements;
343
344 for (i = 0; i < elements; i++) {
345 ret = sim_decode_pair_value(ctx, out, parent, p, element_len, end - p, decode_ctx);
346 if (ret < 0) return ret;
347
348 p += ret;
349
350 if (!fr_cond_assert(p <= end)) break;
351 }
352
353 return attr_len; /* Say we consumed attr_len because it may have padding */
354}
355
356/** Break apart a TLV attribute into individual attributes
357 *
358 * @param[in] ctx to allocate new attributes in.
359 * @param[in] out to add new attributes to.
360 * @param[in] parent the current attribute TLV attribute we're processing.
361 * @param[in] data to parse. Points to the data field of the attribute.
362 * @param[in] attr_len length of the TLV attribute.
363 * @param[in] data_len remaining data in the packet.
364 * @param[in] decode_ctx IVs, keys etc...
365 * @return
366 * - Length on success.
367 * - < 0 on malformed attribute.
368 */
369static ssize_t sim_decode_tlv(TALLOC_CTX *ctx, fr_pair_list_t *out,
370 fr_dict_attr_t const *parent,
371 uint8_t const *data, size_t const attr_len, size_t data_len,
372 void *decode_ctx)
373{
374 uint8_t const *p = data, *end = p + attr_len;
375 uint8_t *decr = NULL;
376 ssize_t decr_len;
377 fr_dict_attr_t const *child;
378 fr_pair_t *tlv;
379 ssize_t ret;
380
381 if (data_len < 2) {
382 fr_strerror_printf("%s: Insufficient data", __FUNCTION__);
383 return -1; /* minimum attr size */
384 }
385
386 tlv = fr_pair_afrom_da(ctx, parent);
387 if (!tlv) return PAIR_DECODE_OOM;
388
389 /*
390 * We have an AES-128-CBC encrypted attribute
391 *
392 * IV is from AT_IV, key is from k_encr.
393 *
394 * unfortunately the ordering of these two attributes
395 * aren't specified, so we may have to hunt for the IV.
396 */
398 FR_PROTO_TRACE("found encrypted attribute '%s'", parent->name);
399
400 decr_len = sim_value_decrypt(ctx, &decr, p + 2,
401 attr_len - 2, data_len - 2, decode_ctx); /* Skip reserved */
402 if (decr_len < 0) return -1;
403
404 p = decr;
405 end = p + decr_len;
406 } else {
407 p += 2; /* Skip the reserved bytes */
408 }
409
410 FR_PROTO_HEX_DUMP(p, end - p, "tlvs");
411
412 /*
413 * Record where we were in the list when packet_ctx function was called
414 */
415 while ((size_t)(end - p) >= sizeof(uint32_t)) {
416 uint8_t sim_at = p[0];
417 size_t sim_at_len = ((size_t)p[1]) << 2;
418 fr_dict_attr_t const *unknown_child = NULL;
419
420 if ((p + sim_at_len) > end) {
421 fr_strerror_printf("%s: Malformed nested attribute %d: Length field (%zu bytes) value "
422 "longer than remaining data in parent (%zu bytes)",
423 __FUNCTION__, sim_at, sim_at_len, (size_t) (end - p));
424
425 error:
426 talloc_free(decr);
427 talloc_free(tlv);
428 return -1;
429 }
430
431 if (sim_at_len == 0) {
432 fr_strerror_printf("%s: Malformed nested attribute %d: Length field 0", __FUNCTION__, sim_at);
433 goto error;
434 }
435
436 /*
437 * Padding attributes are cleartext inside of
438 * encrypted TLVs to pad out the value to the
439 * correct length for the block cipher
440 * (16 in the case of AES-128-CBC).
441 */
442 if (sim_at == FR_PADDING) {
443 uint8_t zero = 0;
444 uint8_t i;
445
447 fr_strerror_printf("%s: Found padding attribute outside of an encrypted TLV",
448 __FUNCTION__);
449 goto error;
450 }
451
452 if (!fr_cond_assert(data_len % 4)) goto error;
453
454 if (sim_at_len > 12) {
455 fr_strerror_printf("%s: Expected padding attribute length <= 12 bytes, got %zu bytes",
456 __FUNCTION__, sim_at_len);
457 goto error;
458 }
459
460 /*
461 * RFC says we MUST verify that FR_PADDING
462 * data is zeroed out.
463 */
464 for (i = 2; i < sim_at_len; i++) zero |= p[i];
465 if (zero) {
466 fr_strerror_printf("%s: Padding attribute value not zeroed 0x%pH", __FUNCTION__,
467 fr_box_octets(p + 2, sim_at_len - 2));
468 goto error;
469 }
470
471 p += sim_at_len;
472 continue;
473 }
474
475 child = fr_dict_attr_child_by_num(parent, p[0]);
476 if (!child) {
477 FR_PROTO_TRACE("Failed to find child %u of TLV %s", p[0], parent->name);
478
479 /*
480 * Encountered none skippable attribute
481 *
482 * RFC says we need to die on these if we don't
483 * understand them. non-skippables are < 128.
484 */
485 if (sim_at <= AKA_SIM_SKIPPABLE_MAX) {
486 fr_strerror_printf("%s: Unknown (non-skippable) attribute %i",
487 __FUNCTION__, sim_at);
488 goto error;
489 }
490
491 /*
492 * Build an unknown attr
493 */
494 unknown_child = fr_dict_attr_unknown_raw_afrom_num(ctx, parent, p[0]);
495 if (!unknown_child) goto error;
496 child = unknown_child;
497 }
498 FR_PROTO_TRACE("decode context changed %s -> %s", parent->name, child->name);
499
500 ret = sim_decode_pair_value(tlv, &tlv->vp_group, child, p + 2, sim_at_len - 2, (end - p) - 2,
501 decode_ctx);
502 fr_dict_attr_unknown_free(&unknown_child);
503 if (ret < 0) goto error;
504 p += sim_at_len;
505 }
506 fr_pair_append(out, tlv);
507
508 talloc_free(decr);
509
510 return attr_len;
511}
512
513/** Create any kind of VP from the attribute contents
514 *
515 * @param[in] ctx to allocate new attributes in.
516 * @param[in] out to add new attributes to.
517 * @param[in] parent the current attribute we're processing.
518 * @param[in] data to parse. Points to the data field of the attribute.
519 * @param[in] attr_len length of the attribute being parsed.
520 * @param[in] data_len length of the remaining data in the packet.
521 * @param[in] decode_ctx IVs, keys etc...
522 * @return
523 * - Length on success.
524 * - -1 on failure.
525 */
527 uint8_t const *data, size_t const attr_len, size_t const data_len,
528 void *decode_ctx)
529{
530 fr_pair_t *vp;
531 uint8_t const *p = data;
532 size_t prefix = 0;
533
534 fr_aka_sim_ctx_t *packet_ctx = decode_ctx;
535
536 if (!fr_cond_assert(attr_len <= data_len)) return -1;
537 if (!fr_cond_assert(parent)) return -1;
538
539 FR_PROTO_TRACE("Parent %s len %zu", parent->name, attr_len);
540 FR_PROTO_HEX_DUMP(data, attr_len, __FUNCTION__ );
541
542 FR_PROTO_TRACE("Type \"%s\" (%u)", fr_type_to_str(parent->type), parent->type);
543
544 /*
545 * Special cases, attributes that either have odd formats, or need
546 * have information we need to decode the packet.
547 */
548 switch (parent->attr) {
549 /*
550 * We need to record packet_ctx so we can decrypt AT_ENCR attributes.
551 *
552 * If we don't find it before, then that's fine, we'll try and
553 * find it in the rest of the packet after the encrypted
554 * attribute.
555 *
556 * 0 1 2 3
557 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
558 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
559 * | AT_IV | Length = 5 | Reserved |
560 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
561 * | |
562 * | Initialization Vector |
563 * | |
564 * | |
565 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
566 */
567 case FR_IV:
568 if (sim_iv_extract(&packet_ctx->iv[0], data, attr_len) < 0) return -1;
569 packet_ctx->have_iv = true;
570 break; /* Now create the attribute */
571
572 /*
573 * AT_RES - Special case (RES length is in bits)
574 *
575 * 0 1 2 3
576 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
577 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
578 * | AT_RES | Length | RES Length |
579 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
580 * | |
581 * | RES |
582 * | |
583 * | |
584 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
585 */
586 case FR_RES:
587 {
588 uint16_t res_len;
589
590 if (attr_len < 2) goto raw; /* Need at least two bytes for the length field */
591
592 res_len = fr_nbo_to_uint16(p);
593 if (res_len % 8) {
594 fr_strerror_printf("%s: RES Length (%hu) is not a multiple of 8",
595 __FUNCTION__, res_len);
596 return -1;
597 }
598 res_len /= 8;
599
600 if (res_len > (attr_len - 2)) {
601 fr_strerror_printf("%s: RES Length field value (%d bits) > attribute value length (%zu bits)",
602 __FUNCTION__, res_len * 8, (attr_len - 2) * 8);
603 return -1;
604 }
605
606 if ((res_len < 4) || (res_len > 16)) {
607 fr_strerror_printf("%s: RES Length field value must be between 32-128 bits, got %d bits",
608 __FUNCTION__, (res_len * 8));
609 return -1;
610 }
611
612 vp = fr_pair_afrom_da(ctx, parent);
613 if (!vp) return -1;
614
615 fr_pair_value_memdup(vp, p + 2, res_len, true);
616 }
617 goto done;
618
619 /*
620 * AT_CHECKCODE - Special case (Variable length with no length field)
621 *
622 * 0 1 2 3
623 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
624 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
625 * | AT_CHECKCODE | Length | Reserved |
626 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
627 * | |
628 * | Checkcode (0 or 20 bytes) |
629 * | |
630 * | |
631 * | |
632 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
633 */
634 case FR_CHECKCODE:
635 if (attr_len < 2) goto raw; /* Need at least two bytes for reserved field */
636
637 vp = fr_pair_afrom_da(ctx, parent);
638 if (!vp) return -1;
639
640 fr_pair_value_memdup(vp, p + 2, attr_len - 2, true);
641 goto done;
642
643 default:
644 break;
645 }
646
647 switch (parent->type) {
648 case FR_TYPE_STRING:
649 if (attr_len < 2) goto raw; /* Need at least two bytes for the length field */
650 if (parent->flags.length && (attr_len != parent->flags.length)) {
651 wrong_len:
652 fr_strerror_printf("%s: Attribute \"%s\" needs a value of exactly %zu bytes, "
653 "but value was %zu bytes", __FUNCTION__,
654 parent->name, (size_t)parent->flags.length, attr_len);
655 goto raw;
656 }
657 break;
658
659 case FR_TYPE_OCTETS:
660 if (parent->flags.is_unknown) goto raw;
661
662 /*
663 * Get the number of bytes we expect before the value
664 */
666 if (attr_len < prefix) goto raw;
667 if (parent->flags.length && (attr_len != (parent->flags.length + prefix))) goto wrong_len;
668 break;
669
670 case FR_TYPE_BOOL:
671 case FR_TYPE_UINT8:
672 case FR_TYPE_UINT16:
673 case FR_TYPE_UINT32:
674 case FR_TYPE_UINT64:
675 if (attr_len != fr_aka_sim_attr_sizes[parent->type][0]) goto raw;
676 break;
677
678 case FR_TYPE_TLV:
679 if (attr_len < 2) goto raw;
680
681 /*
682 * We presume that the TLVs all fit into one
683 * attribute, OR they've already been grouped
684 * into a contiguous memory buffer.
685 */
686 return sim_decode_tlv(ctx, out, parent, p, attr_len, data_len, decode_ctx);
687
688 default:
689 raw:
690 /*
691 * We can't create unknowns for non-skippable attributes
692 * as we're prohibited from continuing by the SIM RFCs.
693 */
694 if (parent->attr <= AKA_SIM_SKIPPABLE_MAX) {
695 fr_strerror_printf_push("%s: Failed parsing non-skippable attribute '%s'",
696 __FUNCTION__, parent->name);
697 return -1;
698 }
699
700#ifdef STATIC_ANALYZER
701 if (!parent->parent) return -1; /* stupid static analyzers */
702#endif
703 fr_assert(parent->parent);
704
705 if (fr_pair_raw_from_network(ctx, out, parent, p, attr_len) < 0) return -1;
706
707 return attr_len;
708 }
709
710 fr_assert(!parent->flags.is_unknown);
711
712 vp = fr_pair_afrom_da(ctx, parent);
713 if (!vp) return -1;
714
715 switch (parent->type) {
716 /*
717 * 0 1 2 3
718 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
719 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
720 * | AT_<STRING> | Length | Actual <STRING> Length |
721 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
722 * | |
723 * . String .
724 * . .
725 * | |
726 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
727 */
728 case FR_TYPE_STRING:
729 {
730 uint16_t actual_len = fr_nbo_to_uint16(p);
731
732 if (actual_len > (attr_len - 2)) {
733 fr_strerror_printf("%s: Actual length field value (%hu) > attribute value length (%zu)",
734 __FUNCTION__, actual_len, attr_len - 2);
735 return -1;
736 }
737
738 fr_pair_value_bstrndup(vp, (char const *)p + 2, actual_len, true);
739 }
740 break;
741
742 case FR_TYPE_OCTETS:
743 /*
744 * Variable length octets buffer
745 */
746 if (!parent->flags.length) {
747 uint16_t actual_len = fr_nbo_to_uint16(p);
748
749 if (actual_len > (attr_len - prefix)) {
750 fr_strerror_printf("%s: Actual length field value (%hu) > attribute value length (%zu)",
751 __FUNCTION__, actual_len, attr_len - 2);
752 return -1;
753 }
754
755 fr_pair_value_memdup(vp, p + prefix, actual_len, true);
756 /*
757 * Fixed length octets buffer
758 */
759 } else {
760 fr_pair_value_memdup(vp, p + prefix, attr_len - prefix, true);
761 }
762 break;
763
764 /*
765 * Not proper bool. We Use packet_ctx to represent
766 * flag attributes like AT_FULLAUTH_ID_REQ
767 *
768 * 0 1 2 3
769 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
770 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
771 * | AT_<BOOL> | Length = 1 | Reserved |
772 * +---------------+---------------+-------------------------------+
773 */
774 case FR_TYPE_BOOL:
775 vp->vp_bool = true;
776 break;
777
778 /*
779 * Numbers are network byte order.
780 *
781 * In the base RFCs only short (16bit) unsigned integers are used.
782 * We add support for more, just for completeness.
783 *
784 * 0 1 2 3
785 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
786 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
787 * | AT_<SHORT> | Length = 1 | Short 1 | Short 2 |
788 * +---------------+---------------+-------------------------------+
789 */
790 case FR_TYPE_UINT8:
791 vp->vp_uint8 = p[0];
792 break;
793
794 case FR_TYPE_UINT16:
795 vp->vp_uint16 = fr_nbo_to_uint16(p);
796 break;
797
798 case FR_TYPE_UINT32:
799 vp->vp_uint32 = fr_nbo_to_uint32(p);
800 break;
801
802 case FR_TYPE_UINT64:
803 vp->vp_uint64 = fr_nbo_to_uint64(p);
804 break;
805
806 default:
808 fr_strerror_printf_push("%s[%d]: Internal sanity check failed", __FUNCTION__, __LINE__);
809 return -1;
810 }
811
812done:
814
815 return attr_len;
816}
817
818/** Decode SIM/AKA/AKA' attributes
819 *
820 * @param[in] ctx to allocate attributes in.
821 * @param[in] out where to insert the attributes.
822 * @param[in] parent of current attribute being decoded.
823 * @param[in] data data to parse.
824 * @param[in] data_len length of data. For top level attributes packet_ctx must be the length
825 * of the packet (so we can hunt for AT_IV), for Sub-TLVs it should
826 * be the length of the container value.
827 * @param[in] decode_ctx extra context to pass to the decoder.
828 * @return
829 * - The number of bytes parsed.
830 * - -1 on error.
831 */
833 uint8_t const *data, size_t data_len, void *decode_ctx)
834{
835 uint8_t sim_at;
836 size_t sim_at_len;
837
838 ssize_t ret;
839 fr_dict_attr_t const *da;
840
841
842 /*
843 * We need at least 2 bytes. We really need 4 but it's
844 * useful to print the attribute number in the errors.
845 */
846 if (data_len < 2) {
847 fr_strerror_printf("%s: Insufficient data: Expected >= 2 bytes, got %zu bytes",
848 __FUNCTION__, data_len);
849 return -1;
850 }
851
852 sim_at = data[0];
853
854 sim_at_len = ((size_t)data[1]) << 2;
855 if (sim_at_len > data_len) {
856 fr_strerror_printf("%s: Insufficient data for attribute %d: Length field %zu, remaining data %zu",
857 __FUNCTION__, sim_at, sim_at_len, data_len);
858 return -1;
859 }
860
861 if (sim_at_len == 0) {
862 fr_strerror_printf("%s: Malformed attribute %d: Length field 0", __FUNCTION__, sim_at);
863 return -1;
864 }
865
866 da = fr_dict_attr_child_by_num(parent, sim_at);
867 if (!da) {
868 FR_PROTO_TRACE("Unknown attribute %u", sim_at);
869
870 /*
871 * Encountered none skippable attribute
872 *
873 * RFC says we need to die on these if we don't
874 * understand them. non-skippables are < 128.
875 */
876 if (sim_at <= AKA_SIM_SKIPPABLE_MAX) {
877 fr_strerror_printf("Unknown (non-skippable) attribute %i", sim_at);
878 return -1;
879 }
881 }
882 if (!da) return -1;
883
884 FR_PROTO_TRACE("decode context changed %s -> %s", da->parent->name, da->name);
885
886 if (da->flags.array) {
887 ret = sim_decode_array(ctx, out, da, data + 2, sim_at_len - 2, data_len - 2, decode_ctx);
888 } else {
889 ret = sim_decode_pair_value(ctx, out, da, data + 2, sim_at_len - 2, data_len - 2, decode_ctx);
890 }
891 if (ret < 0) return ret;
892
893 return 2 + ret;
894}
895
896/** Decode SIM/AKA/AKA' attributes
897 *
898 * @param[in] ctx to allocate attributes in.
899 * @param[in] out where to insert the attributes.
900 * @param[in] parent for looking up attributes.
901 * @param[in] data data to parse.
902 * @param[in] data_len length of data. For top level attributes packet_ctx must be the length
903 * of the packet (so we can hunt for AT_IV), for Sub-TLVs it should
904 * be the length of the container value.
905 * @param[in] decode_ctx extra context to pass to the decoder.
906 * @return
907 * - The number of bytes parsed.
908 * - -1 on error.
909 */
911 uint8_t const *data, size_t data_len, void *decode_ctx)
912{
913 return sim_decode_pair_internal(ctx, out, parent, data, data_len, decode_ctx);
914}
915
916/** Decode SIM/AKA/AKA' specific packet data
917 *
918 * @note data should point to the subtype field in the EAP packet.
919 *
920 * Extracts the SUBTYPE and adds it an attribute, then decodes any TLVs in the
921 * SIM/AKA/AKA' packet.
922 *
923 * 0 1 2 3
924 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
925 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
926 * | Code | Identifier | Length |
927 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
928 * | Type | Subtype | Reserved |
929 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
930 *
931 * The first byte of the data pointer should be the subtype.
932 *
933 * @param[in] ctx where to allocate the pairs.
934 * @param[in] out where to write out attributes.
935 * @param[in] dict for looking up attributes.
936 * @param[in] data to convert to pairs.
937 * @param[in] data_len length of data to convert.
938 * @param[in] decode_ctx holds the state of the decoder.
939 * @return
940 * - 0 on success.
941 * - -1 on failure.
942 */
943int fr_aka_sim_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_t const *dict,
944 uint8_t const *data, size_t data_len, fr_aka_sim_ctx_t *decode_ctx)
945{
946 ssize_t ret;
947 uint8_t const *p = data;
948 uint8_t const *end = p + data_len;
949 fr_dict_attr_t const *parent;
950
951 /*
952 * We need at least enough data for the subtype
953 * and reserved bytes.
954 *
955 * Note: Not all packets should contain attrs.
956 * When the client acknowledges an
957 * AKA-Notification from the server, the
958 * AKA-Notification is returns contains no
959 * attributes.
960 */
961 if (data_len < 3) {
962 fr_strerror_printf("Packet data too small, expected at least 3 bytes got %zu bytes", data_len);
963 return -1;
964 }
965 p += 3;
967
968 /*
969 * Loop over all the attributes decoding
970 * them into the appropriate attributes
971 * in the SIM/AKA/AKA' dict.
972 */
973 while (p < end) {
974 ret = fr_aka_sim_decode_pair(ctx, out, parent, p, end - p, decode_ctx);
975 if (ret <= 0) {
976 fr_strerror_const_push("Failed decoding AT");
977 error:
978 fr_pair_list_free(out); /* Free any attributes we added */
979 return -1;
980 }
981
982 p += ret;
983 fr_assert(p <= end);
984 }
985
986 /*
987 * No point in doing packet_ctx until we known the rest
988 * of the data is OK!
989 */
990 {
991 fr_pair_t *vp;
992
993 vp = fr_pair_afrom_child_num(ctx, parent, FR_SUBTYPE);
994 if (!vp) {
995 fr_strerror_const("Failed allocating subtype attribute");
996 goto error;
997 }
998 vp->vp_uint8 = data[0];
1000 }
1001
1002 return 0;
1003}
1004
1006{
1008
1009 return 0;
1010}
1011
1012static fr_aka_sim_ctx_t *test_ctx_init(TALLOC_CTX *ctx, uint8_t const *k_encr, size_t k_encr_len)
1013{
1015
1016 if (fr_aka_sim_init() < 0) return NULL;
1017
1018 test_ctx = talloc_zero(ctx, fr_aka_sim_ctx_t);
1019 test_ctx->k_encr = talloc_memdup(test_ctx, k_encr, k_encr_len);
1020 talloc_set_destructor(test_ctx, _test_ctx_free);
1021
1022 return test_ctx;
1023}
1024/*
1025 * Test ctx data
1026 */
1027static int decode_test_ctx_sim(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict,
1029{
1031 static uint8_t k_encr[] = { 0x00, 0x01, 0x02, 0x03, 0x04 ,0x05, 0x06, 0x07,
1032 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
1033
1034 test_ctx = test_ctx_init(ctx, k_encr, sizeof(k_encr));
1035 if (!test_ctx) return -1;
1036
1037 test_ctx->have_iv = true; /* Ensures IV is all zeros */
1038
1039 *out = test_ctx;
1040
1041 return 0;
1042}
1043
1044
1045static int decode_test_ctx_aka(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict,
1047{
1049 static uint8_t k_encr[] = { 0x00, 0x01, 0x02, 0x03, 0x04 ,0x05, 0x06, 0x07,
1050 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
1051
1052 test_ctx = test_ctx_init(ctx, k_encr, sizeof(k_encr));
1053 if (!test_ctx) return -1;
1054
1055 test_ctx->have_iv = true; /* Ensures IV is all zeros */
1056
1057 *out = test_ctx;
1058
1059 return 0;
1060}
1061
1062static int decode_test_ctx_sim_rfc4186(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict,
1064{
1066 static uint8_t k_encr[] = { 0x53, 0x6e, 0x5e, 0xbc, 0x44 ,0x65, 0x58, 0x2a,
1067 0xa6, 0xa8, 0xec, 0x99, 0x86, 0xeb, 0xb6, 0x20 };
1068
1069 test_ctx = test_ctx_init(ctx, k_encr, sizeof(k_encr));
1070 if (!test_ctx) return -1;
1071
1072 *out = test_ctx;
1073
1074 return 0;
1075}
1076
1077/*
1078 * Test points
1079 */
1085
1091
static int packet_ctx
the tests pass only the address of packet_ctx
#define RCSID(id)
Definition build.h:603
#define unlikely(_x)
Definition build.h:486
#define UNUSED
Definition build.h:415
fr_dict_t * dict
Definition common.c:31
fr_dict_attr_t const * root_da
Definition common.c:32
EAP-SIM/EAP-AKA Private crypto functions.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:177
#define MEM(x)
Definition debug.h:38
static fr_dict_attr_t * fr_dict_attr_unknown_raw_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr)
Definition dict.h:635
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2717
void fr_dict_attr_unknown_free(fr_dict_attr_t const **da)
Free dynamically allocated (unknown attributes)
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
Definition dict_util.c:3667
static fr_aka_sim_attr_flags_encrypt_t fr_aka_sim_flag_encrypted(fr_dict_attr_t const *da)
Definition base.h:295
#define AKA_SIM_IV_SIZE
Length of the IV used when processing AT_ENCR.
Definition base.h:41
#define AKA_SIM_SKIPPABLE_MAX
The last non-skippable attribute.
Definition base.h:63
Encoder/decoder ctx.
Definition base.h:238
talloc_free(hp)
#define PAIR_DECODE_OOM
Fatal error - Out of memory.
Definition pair.h:45
#define PAIR_DECODE_FATAL_ERROR
Fatal error - Failed decoding the packet.
Definition pair.h:49
void fr_aka_sim_free(void)
Definition base.c:319
int fr_aka_sim_init(void)
Definition base.c:288
size_t fr_aka_sim_octets_prefix_len(fr_dict_attr_t const *da)
Return the number of bytes before the octets value.
Definition base.c:280
size_t const fr_aka_sim_attr_sizes[FR_TYPE_MAX+1][2]
SIM AT on-the-wire format attribute sizes.
Definition base.c:214
EVP_CIPHER_CTX * aka_sim_crypto_cipher_ctx(void)
Allocate and reset a resumable EVP_CIPHER_CTX for each thread.
Definition crypto.c:69
ssize_t fr_aka_sim_decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decode_ctx)
Decode SIM/AKA/AKA' attributes.
Definition decode.c:910
static int sim_iv_extract(uint8_t out[AKA_SIM_IV_SIZE], uint8_t const *in, size_t in_len)
Extract the IV value from an AT_IV attribute.
Definition decode.c:79
static ssize_t sim_decode_pair_value(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const attr_len, size_t const data_len, void *decode_ctx)
Create any kind of VP from the attribute contents.
Definition decode.c:526
static ssize_t sim_value_decrypt(TALLOC_CTX *ctx, uint8_t **out, uint8_t const *data, size_t const attr_len, size_t const data_len, void *decode_ctx)
Decrypt an AES-128-CBC encrypted attribute.
Definition decode.c:115
fr_test_point_pair_decode_t aka_tp_decode
Definition decode.c:1093
fr_test_point_pair_decode_t sim_tp_decode_rfc4186
Definition decode.c:1087
static ssize_t sim_array_members(size_t *out, size_t len, fr_dict_attr_t const *da)
Returns the number of array members for arrays with fixed element sizes.
Definition decode.c:251
static int decode_test_ctx_aka(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict, UNUSED fr_dict_attr_t const *root_da)
Definition decode.c:1045
static ssize_t sim_decode_array(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const attr_len, UNUSED size_t data_len, void *decode_ctx)
Definition decode.c:298
int fr_aka_sim_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_t const *dict, uint8_t const *data, size_t data_len, fr_aka_sim_ctx_t *decode_ctx)
Decode SIM/AKA/AKA' specific packet data.
Definition decode.c:943
static int decode_test_ctx_sim_rfc4186(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict, UNUSED fr_dict_attr_t const *root_da)
Definition decode.c:1062
static ssize_t sim_decode_tlv(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const attr_len, size_t data_len, void *decode_ctx)
Break apart a TLV attribute into individual attributes.
Definition decode.c:369
fr_test_point_pair_decode_t sim_tp_decode
Definition decode.c:1081
static fr_aka_sim_ctx_t * test_ctx_init(TALLOC_CTX *ctx, uint8_t const *k_encr, size_t k_encr_len)
Definition decode.c:1012
static int decode_test_ctx_sim(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict, UNUSED fr_dict_attr_t const *root_da)
Definition decode.c:1027
static int _test_ctx_free(UNUSED fr_aka_sim_ctx_t *ctx)
Definition decode.c:1005
static ssize_t sim_decode_pair_internal(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decode_ctx)
Decode SIM/AKA/AKA' attributes.
Definition decode.c:832
ssize_t fr_pair_raw_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *da, uint8_t const *data, size_t data_len)
Create a "raw" pair from malformed network data.
Definition decode.c:86
static const uint8_t * zero
Definition md4.c:359
unsigned short uint16_t
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_OCTETS
Raw octets.
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
unsigned long int size_t
static uint64_t fr_nbo_to_uint64(uint8_t const data[static sizeof(uint64_t)])
Read an unsigned 64bit integer from wire format (big endian)
Definition nbo.h:177
static uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
Read an unsigned 16bit integer from wire format (big endian)
Definition nbo.h:146
static uint32_t fr_nbo_to_uint32(uint8_t const data[static sizeof(uint32_t)])
Read an unsigned 32bit integer from wire format (big endian)
Definition nbo.h:167
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
Definition pair.c:2906
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition pair.c:1306
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition pair.c:284
int fr_pair_value_bstrndup(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Copy data into a "string" type value pair.
Definition pair.c:2756
fr_pair_t * fr_pair_afrom_child_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr)
Create a new valuepair.
Definition pair.c:390
VQP attributes.
#define fr_assert(_expr)
Definition rad_assert.h:37
static bool done
Definition radclient.c:80
static fr_radius_bio_verify_t test_ctx(void)
Make a verify context which allows Access-Request and Access-Accept.
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Definition test_point.h:86
Entry point for pair decoders.
Definition test_point.h:85
Master include file to access all functions and structures in the library.
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
static fr_slen_t parent
Definition pair.h:864
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
Definition proto.h:42
#define FR_PROTO_TRACE(_fmt,...)
Definition proto.h:41
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
Definition strerror.h:84
#define fr_strerror_const_push(_msg)
Definition strerror.h:227
#define fr_strerror_const(_msg)
Definition strerror.h:223
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:454
static fr_sbuff_err_t char size_t fr_sbuff_t * in
Definition value.h:1061
static fr_slen_t data
Definition value.h:1366
static fr_sbuff_err_t char ** out
Definition value.h:1061
static fr_sbuff_err_t char size_t * len
Definition value.h:1061
#define fr_box_octets(_val, _len)
Definition value.h:342