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