28RCSID(
"$Id: 2b18253a25906232dab9609c3b4a897bf5b37d4b $")
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>
37#include <freeradius-devel/eap/types.h>
61 uint8_t const *
data,
size_t data_len,
void *decode_ctx);
64 uint8_t const *
data,
size_t const attr_len,
size_t const data_len,
92 if ((
in[0] != 0x00) || (
in[1] != 0x00)) {
116 uint8_t const *
data,
size_t const attr_len,
size_t const data_len,
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;
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);
149 while ((
size_t)(end - p) >=
sizeof(
uint32_t)) {
151 size_t sim_at_len = p[1] *
sizeof(
uint32_t);
153 if (sim_at_len == 0) {
158 if ((p + sim_at_len) > end) {
159 fr_strerror_printf(
"%s: Invalid IV length, longer than remaining data", __FUNCTION__);
163 if (sim_at == FR_IV) {
164 if (
sim_iv_extract(&(packet_ctx->
iv[0]), p + 2, sim_at_len - 2) < 0)
return -1;
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__);
190 MEM(decr = talloc_zero_array(ctx,
uint8_t, attr_len));
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__);
208 if (!EVP_DecryptFinal_ex(evp_ctx, decr + decr_len, (
int *)&len)) {
209 fr_tls_strerror_printf(
"%s: Failed decrypting attribute", __FUNCTION__);
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);
227 if (
unlikely(attr_len != decr_len)) {
229 __FUNCTION__, attr_len, decr_len);
233 FR_PROTO_TRACE(
"decryption successful, got %zu bytes of cleartext", decr_len);
259 if (da->flags.length == 0) {
263 element_len = da->flags.length;
271 if (element_len == 1) {
278 if (element_len > len) {
287 if (len % element_len) {
289 __FUNCTION__, element_len, len);
294 return len / element_len;
320 if (!
parent->flags.length || (
parent->flags.length % 4)) {
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);
328 actual_len = attr_len - 2;
335 if (!actual_len)
return p -
data;
341 if (elements < 0)
return elements;
343 for (i = 0; i < elements; i++) {
345 if (ret < 0)
return ret;
370 uint8_t const *
data,
size_t const attr_len,
size_t data_len,
400 attr_len - 2, data_len - 2, decode_ctx);
401 if (decr_len < 0)
return -1;
414 while ((
size_t)(end - p) >=
sizeof(
uint32_t)) {
416 size_t sim_at_len = ((
size_t)p[1]) << 2;
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, (
size_t) (end - p));
430 if (sim_at_len == 0) {
431 fr_strerror_printf(
"%s: Malformed nested attribute %d: Length field 0", __FUNCTION__, sim_at);
441 if (sim_at == FR_PADDING) {
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);
463 for (i = 2; i < sim_at_len; i++)
zero |= p[i];
486 __FUNCTION__, sim_at);
494 if (!unknown_child)
goto error;
495 child = unknown_child;
502 if (ret < 0)
goto error;
526 uint8_t const *
data,
size_t const attr_len,
size_t const data_len,
589 if (attr_len < 2)
goto raw;
594 __FUNCTION__, res_len);
599 if (res_len > (attr_len - 2)) {
600 fr_strerror_printf(
"%s: RES Length field value (%d bits) > attribute value length (%zu bits)",
601 __FUNCTION__, res_len * 8, (attr_len - 2) * 8);
605 if ((res_len < 4) || (res_len > 16)) {
606 fr_strerror_printf(
"%s: RES Length field value must be between 32-128 bits, got %d bits",
607 __FUNCTION__, (res_len * 8));
634 if (attr_len < 2)
goto raw;
648 if (attr_len < 2)
goto raw;
649 if (
parent->flags.length && (attr_len !=
parent->flags.length)) {
652 "but value was %zu bytes", __FUNCTION__,
659 if (
parent->flags.is_unknown)
goto raw;
665 if (attr_len < prefix)
goto raw;
666 if (
parent->flags.length && (attr_len != (
parent->flags.length + prefix)))
goto wrong_len;
678 if (attr_len < 2)
goto raw;
695 __FUNCTION__,
parent->name);
699#ifdef STATIC_ANALYZER
700 if (!
parent->parent)
return -1;
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);
745 if (!
parent->flags.length) {
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);
832 uint8_t const *
data,
size_t data_len,
void *decode_ctx)
847 __FUNCTION__, data_len);
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);
860 if (sim_at_len == 0) {
861 fr_strerror_printf(
"%s: Malformed attribute %d: Length field 0", __FUNCTION__, sim_at);
883 FR_PROTO_TRACE(
"decode context changed %s -> %s", da->parent->name, da->name);
885 if (da->flags.array) {
890 if (ret < 0)
return ret;
910 uint8_t const *
data,
size_t data_len,
void *decode_ctx)
947 uint8_t const *end = p + data_len;
961 fr_strerror_printf(
"Packet data too small, expected at least 3 bytes got %zu bytes", data_len);
1018 test_ctx->
k_encr = talloc_memdup(test_ctx, k_encr, k_encr_len);
1029 static uint8_t k_encr[] = { 0x00, 0x01, 0x02, 0x03, 0x04 ,0x05, 0x06, 0x07,
1030 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
1033 if (!test_ctx)
return -1;
1046 static uint8_t k_encr[] = { 0x00, 0x01, 0x02, 0x03, 0x04 ,0x05, 0x06, 0x07,
1047 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
1050 if (!test_ctx)
return -1;
1062 static uint8_t k_encr[] = { 0x53, 0x6e, 0x5e, 0xbc, 0x44 ,0x65, 0x58, 0x2a,
1063 0xa6, 0xa8, 0xec, 0x99, 0x86, 0xeb, 0xb6, 0x20 };
1066 if (!test_ctx)
return -1;
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.
static fr_dict_attr_t * fr_dict_attr_unknown_raw_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr)
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
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.
#define AKA_SIM_IV_SIZE
Length of the IV used when processing AT_ENCR.
#define AKA_SIM_SKIPPABLE_MAX
The last non-skippable attribute.
bool have_iv
Whether we found the IV already.
uint8_t const * k_encr
The encryption key used for encrypting.
uint8_t iv[AKA_SIM_IV_SIZE]
From the current packet.
#define fr_aka_sim_flag_encrypted(_da)
EVP_CIPHER_CTX * aka_sim_crypto_cipher_ctx(void)
Allocate and reset a resumable EVP_CIPHER_CTX for each thread.
#define PAIR_DECODE_OOM
Fatal error - Out of memory.
#define PAIR_DECODE_FATAL_ERROR
Fatal error - Failed decoding the packet.
void fr_aka_sim_free(void)
int fr_aka_sim_init(void)
size_t fr_aka_sim_octets_prefix_len(fr_dict_attr_t const *da)
Return the number of bytes before the octets value.
size_t const fr_aka_sim_attr_sizes[FR_TYPE_MAX+1][2]
SIM AT on-the-wire format attribute sizes.
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.
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.
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.
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.
static int decode_test_ctx_sim(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict)
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.
fr_test_point_pair_decode_t aka_tp_decode
fr_test_point_pair_decode_t sim_tp_decode_rfc4186
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)
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.
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.
static int decode_test_ctx_sim_rfc4186(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict)
static int decode_test_ctx_aka(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict)
fr_test_point_pair_decode_t sim_tp_decode
static fr_aka_sim_ctx_t * test_ctx_init(TALLOC_CTX *ctx, uint8_t const *k_encr, size_t k_encr_len)
static int _test_ctx_free(UNUSED fr_aka_sim_ctx_t *ctx)
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.
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.
static const uint8_t * zero
@ 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.
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)
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)
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)
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.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
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.
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.
fr_pair_t * fr_pair_afrom_child_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr)
Create a new valuepair.
Stores an attribute, a value and various bits of other data.
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Entry point for pair decoders.
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.
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
#define FR_PROTO_TRACE(_fmt,...)
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
#define fr_strerror_const_push(_msg)
#define fr_strerror_const(_msg)
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
static size_t char ** out
#define fr_box_octets(_val, _len)