28RCSID(
"$Id: 119d3fa11c8dca11f91fe5fed0c8b381c2a7ca4b $")
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);
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);
150 while ((
size_t)(end - p) >=
sizeof(
uint32_t)) {
152 size_t sim_at_len = p[1] *
sizeof(
uint32_t);
154 if (sim_at_len == 0) {
159 if ((p + sim_at_len) > end) {
160 fr_strerror_printf(
"%s: Invalid IV length, longer than remaining data", __FUNCTION__);
164 if (sim_at == FR_IV) {
185 fr_tls_strerror_printf(
"%s: Failed setting decryption parameters", __FUNCTION__);
191 MEM(decr = talloc_zero_array(ctx,
uint8_t, attr_len));
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__);
209 if (!EVP_DecryptFinal_ex(evp_ctx, decr + decr_len, &
len)) {
210 fr_tls_strerror_printf(
"%s: Failed decrypting attribute", __FUNCTION__);
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);
228 if (
unlikely(attr_len != decr_len)) {
230 __FUNCTION__, attr_len, decr_len);
234 FR_PROTO_TRACE(
"decryption successful, got %zu bytes of cleartext", decr_len);
260 if (da->flags.length == 0) {
264 element_len = da->flags.length;
272 if (element_len == 1) {
279 if (element_len >
len) {
288 if (
len % element_len) {
290 __FUNCTION__, element_len,
len);
295 return len / element_len;
321 if (!
parent->flags.length || (
parent->flags.length % 4)) {
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);
329 actual_len = attr_len - 2;
336 if (!actual_len)
return p -
data;
342 if (elements < 0)
return elements;
344 for (i = 0; i < elements; i++) {
346 if (ret < 0)
return ret;
371 uint8_t const *
data,
size_t const attr_len,
size_t data_len,
401 attr_len - 2, data_len - 2, decode_ctx);
402 if (decr_len < 0)
return -1;
415 while ((
size_t)(end - p) >=
sizeof(
uint32_t)) {
417 size_t sim_at_len = ((
size_t)p[1]) << 2;
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));
431 if (sim_at_len == 0) {
432 fr_strerror_printf(
"%s: Malformed nested attribute %d: Length field 0", __FUNCTION__, sim_at);
442 if (sim_at == FR_PADDING) {
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);
464 for (i = 2; i < sim_at_len; i++)
zero |= p[i];
487 __FUNCTION__, sim_at);
495 if (!unknown_child)
goto error;
496 child = unknown_child;
503 if (ret < 0)
goto error;
527 uint8_t const *
data,
size_t const attr_len,
size_t const data_len,
590 if (attr_len < 2)
goto raw;
595 __FUNCTION__, res_len);
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);
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));
635 if (attr_len < 2)
goto raw;
649 if (attr_len < 2)
goto raw;
650 if (
parent->flags.length && (attr_len !=
parent->flags.length)) {
653 "but value was %zu bytes", __FUNCTION__,
660 if (
parent->flags.is_unknown)
goto raw;
666 if (attr_len < prefix)
goto raw;
667 if (
parent->flags.length && (attr_len != (
parent->flags.length + prefix)))
goto wrong_len;
679 if (attr_len < 2)
goto raw;
696 __FUNCTION__,
parent->name);
700#ifdef STATIC_ANALYZER
701 if (!
parent->parent)
return -1;
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);
746 if (!
parent->flags.length) {
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);
833 uint8_t const *
data,
size_t data_len,
void *decode_ctx)
848 __FUNCTION__, data_len);
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);
861 if (sim_at_len == 0) {
862 fr_strerror_printf(
"%s: Malformed attribute %d: Length field 0", __FUNCTION__, sim_at);
884 FR_PROTO_TRACE(
"decode context changed %s -> %s", da->parent->name, da->name);
886 if (da->flags.array) {
891 if (ret < 0)
return ret;
911 uint8_t const *
data,
size_t data_len,
void *decode_ctx)
948 uint8_t const *end = p + data_len;
962 fr_strerror_printf(
"Packet data too small, expected at least 3 bytes got %zu bytes", data_len);
1031 static uint8_t k_encr[] = { 0x00, 0x01, 0x02, 0x03, 0x04 ,0x05, 0x06, 0x07,
1032 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
1049 static uint8_t k_encr[] = { 0x00, 0x01, 0x02, 0x03, 0x04 ,0x05, 0x06, 0x07,
1050 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
1066 static uint8_t k_encr[] = { 0x53, 0x6e, 0x5e, 0xbc, 0x44 ,0x65, 0x58, 0x2a,
1067 0xa6, 0xa8, 0xec, 0x99, 0x86, 0xeb, 0xb6, 0x20 };
static int packet_ctx
the tests pass only the address of packet_ctx
fr_dict_attr_t const * root_da
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.
static fr_aka_sim_attr_flags_encrypt_t fr_aka_sim_flag_encrypted(fr_dict_attr_t const *da)
#define AKA_SIM_IV_SIZE
Length of the IV used when processing AT_ENCR.
#define AKA_SIM_SKIPPABLE_MAX
The last non-skippable attribute.
#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.
EVP_CIPHER_CTX * aka_sim_crypto_cipher_ctx(void)
Allocate and reset a resumable EVP_CIPHER_CTX for each thread.
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.
fr_test_point_pair_decode_t aka_tp_decode
fr_test_point_pair_decode_t sim_tp_decode_rfc4186
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.
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)
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 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)
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.
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 decode_test_ctx_sim(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict, UNUSED fr_dict_attr_t const *root_da)
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 *da, uint8_t const *data, size_t data_len)
Create a "raw" pair from malformed 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.
static fr_radius_bio_verify_t test_ctx(void)
Make a verify context which allows Access-Request and Access-Accept.
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 fr_sbuff_err_t char size_t fr_sbuff_t * in
static fr_sbuff_err_t char ** out
static fr_sbuff_err_t char size_t * len
#define fr_box_octets(_val, _len)