31RCSID(
"$Id: da2bfc15756722407217dad6756401af957486b6 $")
36#include <freeradius-devel/protocol/eap/aka-sim/dictionary.h>
38#include <freeradius-devel/eap/types.h>
39#include <freeradius-devel/sim/common.h>
40#include <freeradius-devel/sim/milenage.h>
41#include <freeradius-devel/tls/base.h>
42#include <freeradius-devel/tls/strerror.h>
43#include <freeradius-devel/util/atexit.h>
44#include <freeradius-devel/util/proto.h>
45#include <freeradius-devel/util/rand.h>
46#include <freeradius-devel/util/sha1.h>
47#include <openssl/evp.h>
61 EVP_CIPHER_CTX_free(arg);
75 MEM(ctx = EVP_CIPHER_CTX_new());
100 if (checkcode->
md_ctx) EVP_MD_CTX_destroy(checkcode->
md_ctx);
122 (*checkcode)->md_ctx = EVP_MD_CTX_create();
123 if (!(*checkcode)->md_ctx) {
124 fr_tls_strerror_printf(
"Failed creating MD ctx");
126 TALLOC_FREE(*checkcode);
129 if (EVP_DigestInit_ex((*checkcode)->md_ctx, md, NULL) != 1) {
130 fr_tls_strerror_printf(
"Failed initialising MD ctx");
158 eap_hdr.
id = eap_packet->
id;
159 packet_len = htons((
sizeof(eap_hdr) + eap_packet->
type.
length) & UINT16_MAX);
160 memcpy(&eap_hdr.
length, &packet_len,
sizeof(packet_len));
163 FR_PROTO_HEX_DUMP((
void *)&eap_hdr,
sizeof(eap_hdr),
"Ingesting checkcode EAP header");
168 if (EVP_DigestUpdate(checkcode->
md_ctx, &eap_hdr,
sizeof(eap_hdr)) != 1) {
169 fr_tls_strerror_printf(
"Failed digesting EAP header");
179 fr_tls_strerror_printf(
"Failed digesting packet data");
201 len = (
size_t)EVP_MD_CTX_size((*checkcode).md_ctx);
203 if (EVP_DigestFinal_ex((*checkcode).md_ctx,
buff, NULL) != 1) {
204 fr_tls_strerror_printf(
"Failed finalising checkcode digest");
230 while ((p + 2) < end) {
236 if (p[0] == FR_MAC) {
238 if ((p + len) > end) {
239 fr_strerror_printf(
"Malformed AT_MAC: Length (%zu) exceeds buffer (%zu)", len, (
size_t) (end - p));
292 EVP_MD
const *md,
uint8_t const *key,
size_t const key_len,
293 uint8_t const *hmac_extra,
size_t const hmac_extra_len)
295 EVP_MD_CTX *md_ctx = NULL;
298 uint8_t digest[SHA256_DIGEST_LENGTH];
299 size_t digest_len =
sizeof(digest);
316 if (
unlikely(!key) || (key_len == 0)) {
322 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, key_len);
324 fr_tls_strerror_printf(
"Failed creating HMAC signing key");
326 if (pkey) EVP_PKEY_free(pkey);
327 if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
331 md_ctx = EVP_MD_CTX_create();
333 fr_tls_strerror_printf(
"Failed creating HMAC ctx");
337 if (EVP_DigestSignInit(md_ctx, NULL, md, NULL, pkey) != 1) {
338 fr_tls_strerror_printf(
"Failed initialising digest");
348 eap_hdr.
id = eap_packet->
id;
349 packet_len = htons((
sizeof(eap_hdr) + eap_packet->
type.
length) & UINT16_MAX);
350 memcpy(&eap_hdr.
length, &packet_len,
sizeof(packet_len));
354 if (EVP_DigestSignUpdate(md_ctx, &eap_hdr,
sizeof(eap_hdr)) != 1) {
355 fr_tls_strerror_printf(
"Failed digesting EAP data");
367 uint8_t zero[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
377 if (EVP_DigestSignUpdate(md_ctx, p, mac - p) != 1) {
378 fr_tls_strerror_printf(
"Failed digesting packet data (before MAC)");
389 if (EVP_DigestSignUpdate(md_ctx,
zero,
sizeof(
zero)) != 1) {
390 fr_tls_strerror_printf(
"Failed digesting zeroed MAC");
412 if (EVP_DigestSignUpdate(md_ctx, p, end - p) != 1) {
413 fr_tls_strerror_printf(
"Failed digesting packet data");
426 if (EVP_DigestSignUpdate(md_ctx, hmac_extra, hmac_extra_len) != 1) {
427 fr_tls_strerror_printf(
"Failed digesting HMAC extra data");
432 if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1) {
433 fr_tls_strerror_printf(
"Failed finalising digest");
442 memcpy(
out, digest, 16);
445 EVP_MD_CTX_destroy(md_ctx);
484 sizeof(keys->gsm.nonce_mt) +
485 keys->gsm.version_list_len +
486 sizeof(keys->gsm.version_select)) <=
sizeof(buf)))
return -1;
501 memcpy(p, keys->gsm.nonce_mt,
sizeof(keys->gsm.nonce_mt));
502 p +=
sizeof(keys->gsm.nonce_mt);
504 memcpy(p, keys->gsm.version_list, keys->gsm.version_list_len);
505 p += keys->gsm.version_list_len;
507 memcpy(p, keys->gsm.version_select,
sizeof(keys->gsm.version_select));
508 p +=
sizeof(keys->gsm.version_select);
510 FR_PROTO_HEX_DUMP(buf, p - buf,
"Identity || n*Kc || NONCE_MT || Version List || Selected Version");
532 memcpy(keys->
k_encr, p, 16);
541 memcpy(keys->
msk, p, 64);
545 memcpy(keys->
emsk, p, 64);
585 sizeof(keys->umts.vector.ik) +
586 sizeof(keys->umts.vector.ck)) <=
sizeof(buf)))
return -1;
592 memcpy(p, keys->umts.vector.ik,
sizeof(keys->umts.vector.ik));
593 p +=
sizeof(keys->umts.vector.ik);
595 memcpy(p, keys->umts.vector.ck,
sizeof(keys->umts.vector.ck));
596 p +=
sizeof(keys->umts.vector.ck);
615 memcpy(keys->
k_encr, p, 16);
622 memcpy(keys->
msk, p, 64);
625 memcpy(keys->
emsk, p, 64);
654 size_t digest_len =
sizeof(digest);
659 uint8_t k[
sizeof(keys->umts.vector.ik) +
sizeof(keys->umts.vector.ck)];
666 EVP_MD_CTX *md_ctx = NULL;
680 sizeof(l1)) <=
sizeof(s)))
return -1;
695 memcpy(p, &l0,
sizeof(l0));
702 memcpy(p, &l1,
sizeof(l1));
713 memcpy(p, keys->umts.vector.ck,
sizeof(keys->umts.vector.ck));
714 p +=
sizeof(keys->umts.vector.ck);
715 memcpy(p, keys->umts.vector.ik,
sizeof(keys->umts.vector.ik));
719 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, k,
sizeof(k));
721 fr_tls_strerror_printf(
"Failed creating HMAC signing key");
723 if (pkey) EVP_PKEY_free(pkey);
724 if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
728 md_ctx = EVP_MD_CTX_create();
730 fr_tls_strerror_printf(
"Failed creating HMAC ctx");
734 if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
735 fr_tls_strerror_printf(
"Failed initialising digest");
739 if (EVP_DigestSignUpdate(md_ctx, s, s_len) != 1)
goto error;
740 if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1)
goto error;
748 EVP_MD_CTX_destroy(md_ctx);
784 uint8_t digest[SHA256_DIGEST_LENGTH];
786 EVP_MD_CTX *md_ctx = NULL;
788 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, key_len);
790 fr_tls_strerror_printf(
"Failed creating HMAC signing key");
792 if (pkey) EVP_PKEY_free(pkey);
793 if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
797 md_ctx = EVP_MD_CTX_create();
799 fr_tls_strerror_printf(
"Failed creating HMAC ctx");
803 if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
804 fr_tls_strerror_printf(
"Failed initialising digest");
809 size_t digest_len =
sizeof(digest);
814 if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1)
goto error;
815 if ((p !=
out) && EVP_DigestSignUpdate(md_ctx, digest,
sizeof(digest)) != 1)
goto error;
816 if (EVP_DigestSignUpdate(md_ctx,
in, in_len) != 1)
goto error;
817 if (EVP_DigestSignUpdate(md_ctx, &c,
sizeof(c)) != 1)
goto error;
818 if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1)
goto error;
821 if (copy > digest_len) copy = digest_len;
823 memcpy(p, digest, copy);
827 EVP_MD_CTX_destroy(md_ctx);
855#define KDF_1_S_STATIC "EAP-AKA'"
896 memcpy(keys->
k_encr, p, 16);
906 memcpy(keys->
msk, p,
sizeof(keys->
msk));
907 p +=
sizeof(keys->
msk);
909 memcpy(keys->
emsk, p,
sizeof(keys->
emsk));
936 keys->reauth.counter = counter;
942 memcpy(keys->reauth.nonce_s, (
uint8_t *)&nonce_s,
sizeof(keys->reauth.nonce_s));
966 keys->reauth.counter = counter;
972 memcpy(keys->reauth.nonce_s, (
uint8_t *)&nonce_s,
sizeof(keys->reauth.nonce_s));
1005 unsigned int len = 0;
1013 if (keys->reauth.counter == 0) {
1025 if (need >
sizeof(buf)) {
1026 fr_strerror_printf(
"Identity too long. PRF input is %zu bytes, input buffer is %zu bytes",
1038 memcpy(keys->
k_encr, p, 16);
1065 *p++ = ((keys->reauth.counter & 0xff00) >> 8);
1066 *p++ = (keys->reauth.counter & 0x00ff);
1071 memcpy(p, keys->reauth.nonce_s,
sizeof(keys->reauth.nonce_s));
1072 p +=
sizeof(keys->reauth.nonce_s);
1085 md_ctx = EVP_MD_CTX_create();
1087 fr_tls_strerror_printf(
"Failed creating MD ctx");
1089 EVP_MD_CTX_destroy(md_ctx);
1093 if (EVP_DigestInit_ex(md_ctx, EVP_sha1(), NULL) != 1) {
1094 fr_tls_strerror_printf(
"Failed initialising digest");
1098 if (EVP_DigestUpdate(md_ctx, buf, p - buf) != 1) {
1099 fr_tls_strerror_printf(
"Failed digesting crypto data");
1103 if (EVP_DigestFinal_ex(md_ctx, keys->reauth.xkey_prime, &len) != 1) {
1104 fr_tls_strerror_printf(
"Failed finalising digest");
1108 EVP_MD_CTX_destroy(md_ctx);
1110 FR_PROTO_HEX_DUMP(keys->reauth.xkey_prime,
sizeof(keys->reauth.xkey_prime),
"xkey'");
1121 memcpy(keys->
msk, p, 64);
1125 memcpy(keys->
emsk, p, 64);
1147#define KDF_1_S_REAUTH_STATIC "EAP-AKA' re-auth"
1194 fr_dbuff_in_bytes(&dbuff, ((keys->reauth.counter & 0xff00) >> 8), (keys->reauth.counter & 0x00ff));
1202 "\"EAP-AKA' re-auth\" || Identity || counter || NONCE_S");
1239 switch (keys->vector_type) {
1250 for (i = 0; i < keys->gsm.num_vectors; i++) {
1288 "counter : %u", keys->reauth.counter);
1297 "counter : %u", keys->reauth.counter);
1309 switch (keys->vector_type) {
1338#ifdef TESTING_SIM_CRYPTO
1344#include <freeradius-devel/util/test/acutest.h>
1351 .identity_len =
sizeof(
"1244070100000001@eapsim.foo") - 1,
1356 .rand = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1357 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
1358 .sres = { 0xd1, 0xd2, 0xd3, 0xd4 },
1359 .kc = { 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7 }
1362 .rand = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1363 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f },
1364 .sres = { 0xe1, 0xe2, 0xe3, 0xe4 },
1365 .kc = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7 }
1368 .rand = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
1369 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f },
1370 .sres = { 0xf1, 0xf2, 0xf3, 0xf4 },
1371 .kc = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }
1374 .nonce_mt = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1375 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
1376 .version_list = { 0x00, 0x01 },
1377 .version_list_len = 2,
1378 .version_select = { 0x00, 0x01 },
1385 .
k_encr = { 0x53, 0x6e, 0x5e, 0xbc, 0x44, 0x65, 0x58, 0x2a,
1386 0xa6, 0xa8, 0xec, 0x99, 0x86, 0xeb, 0xb6, 0x20 },
1387 .k_aut = { 0x25, 0xaf, 0x19, 0x42, 0xef, 0xcb, 0xf4, 0xbc,
1388 0x72, 0xb3, 0x94, 0x34, 0x21, 0xf2, 0xa9, 0x74 },
1390 .msk = { 0x39, 0xd4, 0x5a, 0xea, 0xf4, 0xe3, 0x06, 0x01,
1391 0x98, 0x3e, 0x97, 0x2b, 0x6c, 0xfd, 0x46, 0xd1,
1392 0xc3, 0x63, 0x77, 0x33, 0x65, 0x69, 0x0d, 0x09,
1393 0xcd, 0x44, 0x97, 0x6b, 0x52, 0x5f, 0x47, 0xd3,
1394 0xa6, 0x0a, 0x98, 0x5e, 0x95, 0x5c, 0x53, 0xb0,
1395 0x90, 0xb2, 0xe4, 0xb7, 0x37, 0x19, 0x19, 0x6a,
1396 0x40, 0x25, 0x42, 0x96, 0x8f, 0xd1, 0x4a, 0x88,
1397 0x8f, 0x46, 0xb9, 0xa7, 0x88, 0x6e, 0x44, 0x88 },
1398 .emsk = { 0x59, 0x49, 0xea, 0xb0, 0xff, 0xf6, 0x9d, 0x52,
1399 0x31, 0x5c, 0x6c, 0x63, 0x4f, 0xd1, 0x4a, 0x7f,
1400 0x0d, 0x52, 0x02, 0x3d, 0x56, 0xf7, 0x96, 0x98,
1401 0xfa, 0x65, 0x96, 0xab, 0xee, 0xd4, 0xf9, 0x3f,
1402 0xbb, 0x48, 0xeb, 0x53, 0x4d, 0x98, 0x54, 0x14,
1403 0xce, 0xed, 0x0d, 0x9a, 0x8e, 0xd3, 0x3c, 0x38,
1404 0x7c, 0x9d, 0xfd, 0xab, 0x92, 0xff, 0xbd, 0xf2,
1405 0x40, 0xfc, 0xec, 0xf6, 0x5a, 0x2c, 0x93, 0xb9 }
1408static void test_eap_sim_kdf_0_gsm(
void)
1418 memcpy(&keys, &rfc4186_vector0_in,
sizeof(keys));
1437 .identity_len =
sizeof(
"0555444333222111") - 1,
1439 .sqn = 205964772668538,
1443 .rand = { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e,
1444 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 },
1445 .autn = { 0xbb, 0x52, 0xe9, 0x1c, 0x74, 0x7a, 0xc3, 0xab,
1446 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 },
1447 .ik = { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb,
1448 0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a },
1449 .ck = { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94,
1450 0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f },
1451 .xres = { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 },
1459 .
k_encr = { 0x18, 0xe8, 0xb2, 0x0b, 0xcd, 0xa7, 0x04, 0x86,
1460 0xfd, 0x59, 0x59, 0x58, 0x6a, 0x9e, 0x7c, 0x3d },
1461 .k_aut = { 0x18, 0xc0, 0x44, 0x07, 0x0e, 0x5e, 0x64, 0x2a,
1462 0x26, 0x43, 0x87, 0x6f, 0xf7, 0xa8, 0x38, 0x12 },
1464 .msk = { 0x35, 0x2f, 0xfa, 0xef, 0x2d, 0xf1, 0x20, 0xcb,
1465 0x22, 0x41, 0x0b, 0x9c, 0x0b, 0x70, 0x62, 0x3c,
1466 0xb5, 0xa3, 0x5b, 0xc9, 0xfc, 0xd6, 0xbc, 0xa0,
1467 0xfc, 0x33, 0x7b, 0x48, 0xb1, 0x76, 0x30, 0x89,
1468 0x0a, 0x03, 0x37, 0x5c, 0xfd, 0x1e, 0x64, 0xcb,
1469 0xd6, 0xbf, 0x83, 0x04, 0x37, 0x4d, 0xd2, 0xe1,
1470 0x39, 0xd6, 0x4e, 0xd1, 0xa6, 0xd6, 0x18, 0xff,
1471 0xef, 0xb0, 0x8c, 0x26, 0xa6, 0xbb, 0x35, 0x85 },
1472 .emsk = { 0x9e, 0x06, 0x59, 0xae, 0x03, 0x97, 0x7d, 0xcb,
1473 0xb1, 0xd6, 0x4d, 0x24, 0x05, 0xe1, 0x10, 0x82,
1474 0xa9, 0x1a, 0xdb, 0x9a, 0xc7, 0xf7, 0xbd, 0x0b,
1475 0x74, 0xa6, 0x1e, 0xc0, 0xe9, 0x80, 0xb3, 0x6f,
1476 0xa0, 0xc3, 0x98, 0x8b, 0x6e, 0x11, 0xef, 0x12,
1477 0x52, 0x8e, 0x38, 0x04, 0xb3, 0x2d, 0xf1, 0xbc,
1478 0x52, 0xf6, 0x24, 0x9f, 0xa9, 0x6d, 0xc9, 0x4c,
1479 0x94, 0xa3, 0xd9, 0xb1, 0x48, 0xf4, 0xf9, 0x96 }
1482static void test_eap_aka_kdf_0_umts(
void)
1492 memcpy(&keys, &rfc4187_vector0_in,
sizeof(keys));
1509 .
identity = (
uint8_t const *)
"Y24fNSrz8BP274jOJaF17WfxI8YO7QX00pMXk9XMMVOw7broaNhTczuFq53aEpOkk3L0dm@eapsim.foo",
1510 .identity_len =
sizeof(
"Y24fNSrz8BP274jOJaF17WfxI8YO7QX00pMXk9XMMVOw7broaNhTczuFq53aEpOkk3L0dm@eapsim.foo") - 1,
1514 .nonce_s = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1515 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }
1517 .mk = { 0xe5, 0x76, 0xd5, 0xca, 0x33, 0x2e, 0x99, 0x30,
1518 0x01, 0x8b, 0xf1, 0xba, 0xee, 0x27, 0x63, 0xc7,
1519 0x95, 0xb3, 0xc7, 0x12 },
1523 .
k_encr = { 0x53, 0x6e, 0x5e, 0xbc, 0x44, 0x65, 0x58, 0x2a,
1524 0xa6, 0xa8, 0xec, 0x99, 0x86, 0xeb, 0xb6, 0x20 },
1525 .k_aut = { 0x25, 0xaf, 0x19, 0x42, 0xef, 0xcb, 0xf4, 0xbc,
1526 0x72, 0xb3, 0x94, 0x34, 0x21, 0xf2, 0xa9, 0x74 },
1528 .msk = { 0x62, 0x63, 0xf6, 0x14, 0x97, 0x38, 0x95, 0xe1,
1529 0x33, 0x5f, 0x7e, 0x30, 0xcf, 0xf0, 0x28, 0xee,
1530 0x21, 0x76, 0xf5, 0x19, 0x00, 0x2c, 0x9a, 0xbe,
1531 0x73, 0x2f, 0xe0, 0xef, 0x00, 0xcf, 0x16, 0x7c,
1532 0x75, 0x6d, 0x9e, 0x4c, 0xed, 0x6d, 0x5e, 0xd6,
1533 0x40, 0xeb, 0x3f, 0xe3, 0x85, 0x65, 0xca, 0x07,
1534 0x6e, 0x7f, 0xb8, 0xa8, 0x17, 0xcf, 0xe8, 0xd9,
1535 0xad, 0xbc, 0xe4, 0x41, 0xd4, 0x7c, 0x4f, 0x5e },
1536 .emsk = { 0x3d, 0x8f, 0xf7, 0x86, 0x3a, 0x63, 0x0b, 0x2b,
1537 0x06, 0xe2, 0xcf, 0x20, 0x96, 0x84, 0xc1, 0x3f,
1538 0x6b, 0x82, 0xf9, 0x92, 0xf2, 0xb0, 0x6f, 0x1b,
1539 0x54, 0xbf, 0x51, 0xef, 0x23, 0x7f, 0x2a, 0x40,
1540 0x1e, 0xf5, 0xe0, 0xd7, 0xe0, 0x98, 0xa3, 0x4c,
1541 0x53, 0x3e, 0xae, 0xbf, 0x34, 0x57, 0x88, 0x54,
1542 0xb7, 0x72, 0x15, 0x26, 0x20, 0xa7, 0x77, 0xf0,
1543 0xe0, 0x34, 0x08, 0x84, 0xa2, 0x94, 0xfb, 0x73 }
1546static void test_eap_sim_kdf_0_reauth(
void)
1556 memcpy(&keys, &rfc4186_vector0_reauth_in,
sizeof(keys));
1574 .identity_len =
sizeof(
"0555444333222111") - 1,
1576 .network = (
uint8_t const *)
"WLAN",
1577 .network_len =
sizeof(
"WLAN") - 1,
1579 .sqn = 205964772668538,
1583 .rand = { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e,
1584 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 },
1585 .autn = { 0xbb, 0x52, 0xe9, 0x1c, 0x74, 0x7a, 0xc3, 0xab,
1586 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 },
1587 .ik = { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb,
1588 0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a },
1589 .ck = { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94,
1590 0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f },
1591 .xres = { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 },
1599 .
ik_prime = { 0x00, 0x93, 0x96, 0x2d, 0x0d, 0xd8, 0x4a, 0xa5,
1600 0x68, 0x4b, 0x04, 0x5c, 0x9e, 0xdf, 0xfa, 0x04 },
1601 .ck_prime = { 0xcc, 0xfc, 0x23, 0x0c, 0xa7, 0x4f, 0xcc, 0x96,
1602 0xc0, 0xa5, 0xd6, 0x11, 0x64, 0xf5, 0xa7, 0x6c },
1604 .k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1605 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1606 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1607 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1608 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1609 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1611 .k_re = { 0xcf, 0x83, 0xaa, 0x8b, 0xc7, 0xe0, 0xac, 0xed,
1612 0x89, 0x2a, 0xcc, 0x98, 0xe7, 0x6a, 0x9b, 0x20,
1613 0x95, 0xb5, 0x58, 0xc7, 0x79, 0x5c, 0x70, 0x94,
1614 0x71, 0x5c, 0xb3, 0x39, 0x3a, 0xa7, 0xd1, 0x7a },
1615 .msk = { 0x67, 0xc4, 0x2d, 0x9a, 0xa5, 0x6c, 0x1b, 0x79,
1616 0xe2, 0x95, 0xe3, 0x45, 0x9f, 0xc3, 0xd1, 0x87,
1617 0xd4, 0x2b, 0xe0, 0xbf, 0x81, 0x8d, 0x30, 0x70,
1618 0xe3, 0x62, 0xc5, 0xe9, 0x67, 0xa4, 0xd5, 0x44,
1619 0xe8, 0xec, 0xfe, 0x19, 0x35, 0x8a, 0xb3, 0x03,
1620 0x9a, 0xff, 0x03, 0xb7, 0xc9, 0x30, 0x58, 0x8c,
1621 0x05, 0x5b, 0xab, 0xee, 0x58, 0xa0, 0x26, 0x50,
1622 0xb0, 0x67, 0xec, 0x4e, 0x93, 0x47, 0xc7, 0x5a },
1623 .emsk = { 0xf8, 0x61, 0x70, 0x3c, 0xd7, 0x75, 0x59, 0x0e,
1624 0x16, 0xc7, 0x67, 0x9e, 0xa3, 0x87, 0x4a, 0xda,
1625 0x86, 0x63, 0x11, 0xde, 0x29, 0x07, 0x64, 0xd7,
1626 0x60, 0xcf, 0x76, 0xdf, 0x64, 0x7e, 0xa0, 0x1c,
1627 0x31, 0x3f, 0x69, 0x92, 0x4b, 0xdd, 0x76, 0x50,
1628 0xca, 0x9b, 0xac, 0x14, 0x1e, 0xa0, 0x75, 0xc4,
1629 0xef, 0x9e, 0x80, 0x29, 0xc0, 0xe2, 0x90, 0xcd,
1630 0xba, 0xd5, 0x63, 0x8b, 0x63, 0xbc, 0x23, 0xfb }
1633static void test_eap_aka_kdf_1_umts(
void)
1643 memcpy(&keys, &rfc5448_vector0_in,
sizeof(keys));
1659static void test_eap_aka_derive_ck_ik(
void)
1670 memcpy(&keys, &rfc5448_vector0_in,
sizeof(keys));
1682 .identity_len =
sizeof(
"5555444333222111") - 1,
1684 .network = (
uint8_t const *)
"WLAN",
1685 .network_len =
sizeof(
"WLAN") - 1,
1689 .nonce_s = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1690 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }
1692 .k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1693 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1694 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1695 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1696 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1697 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1699 .k_re = { 0xcf, 0x83, 0xaa, 0x8b, 0xc7, 0xe0, 0xac, 0xed,
1700 0x89, 0x2a, 0xcc, 0x98, 0xe7, 0x6a, 0x9b, 0x20,
1701 0x95, 0xb5, 0x58, 0xc7, 0x79, 0x5c, 0x70, 0x94,
1702 0x71, 0x5c, 0xb3, 0x39, 0x3a, 0xa7, 0xd1, 0x7a }
1709 .
k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1710 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1711 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1712 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1713 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1714 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1716 .msk = { 0x28, 0xf2, 0xb9, 0x3a, 0x8e, 0xdc, 0x4a, 0x01,
1717 0xb6, 0x9d, 0x37, 0x8b, 0xa6, 0x8a, 0x77, 0xbb,
1718 0x01, 0x6c, 0x0f, 0xeb, 0xb7, 0x60, 0xdb, 0x98,
1719 0x57, 0x99, 0x64, 0x99, 0x00, 0x00, 0x6f, 0x97,
1720 0xa1, 0x76, 0x5c, 0x65, 0xf5, 0xd5, 0xbf, 0xde,
1721 0xe7, 0x61, 0xba, 0x42, 0x92, 0xe4, 0x51, 0xd1,
1722 0xa0, 0xc5, 0x7e, 0x76, 0xeb, 0x91, 0x3e, 0xe9,
1723 0x95, 0xf5, 0xce, 0x6e, 0xb7, 0x98, 0x91, 0x38 },
1724 .emsk = { 0xb9, 0x05, 0xa2, 0xf4, 0x67, 0xe0, 0xeb, 0x9a,
1725 0xfb, 0xa4, 0x59, 0xa7, 0xd8, 0xa7, 0xc8, 0x77,
1726 0xd5, 0xfa, 0x2e, 0x5e, 0xd3, 0x77, 0xf8, 0xc5,
1727 0x2f, 0xa4, 0x86, 0xad, 0xf5, 0x15, 0x5e, 0xb7,
1728 0x96, 0xac, 0xa9, 0x3e, 0xa3, 0xa9, 0x95, 0xe8,
1729 0xa2, 0x34, 0x36, 0x54, 0x5a, 0xf1, 0x57, 0x22,
1730 0xaa, 0x94, 0xb9, 0xfb, 0xd9, 0x06, 0x0c, 0x50,
1731 0xa3, 0x56, 0xcc, 0xb4, 0xc7, 0x10, 0x0e, 0x66 }
1734static void test_eap_aka_kdf_1_reauth(
void)
1744 memcpy(&keys, &rfc5448_vector0_reauth_in,
sizeof(keys));
1761 {
"test_eap_sim_kdf_0_gsm", test_eap_sim_kdf_0_gsm },
1766 {
"test_eap_aka_kdf_0_umts", test_eap_aka_kdf_0_umts },
1771 {
"test_eap_sim_kdf_0_reauth", test_eap_sim_kdf_0_reauth },
1776 {
"test_eap_aka_kdf_1_umts", test_eap_aka_kdf_1_umts },
1777 {
"test_eap_aka_derive_ck_ik", test_eap_aka_derive_ck_ik },
1778 {
"test_eap_aka_kdf_1_reauth", test_eap_aka_kdf_1_reauth },
int fr_atexit_trigger(bool uctx_scope, fr_atexit_t func, void const *uctx)
Iterates through all thread local destructor lists, causing destructor to be triggered.
#define fr_atexit_thread_local(_name, _free, _uctx)
static uint8_t * uint48_to_buff(uint8_t out[static 6], uint64_t i)
Copy a 48bit value from a 64bit integer into a uint8_t buff in big endian byte order.
static uint64_t uint48_from_buff(uint8_t const in[6])
Convert a 48bit big endian value into a unsigned 64bit integer.
Structure to hold EAP data.
EAP-SIM/EAP-AKA Private crypto functions.
#define fr_dbuff_used(_dbuff_or_marker)
Return the number of bytes remaining between the start of the dbuff or marker and the current positio...
#define fr_dbuff_init(_out, _start, _len_or_end)
Initialise an dbuff for encoding or decoding.
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
#define fr_dbuff_out_memcpy(_out, _dbuff_or_marker, _outlen)
Copy exactly _outlen bytes from the dbuff.
#define fr_dbuff_in_bytes(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker.
#define fr_dbuff_in_memcpy(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into a dbuff or marker.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
When we need to create a base EAP packet.
uint8_t * identity
Identity from AT_IDENTITY.
#define AKA_SIM_VECTOR_UMTS_RAND_SIZE
#define AKA_SIM_VECTOR_GSM_RAND_SIZE
Length of RAND in GSM triplet.
uint8_t * network
Network name (EAP-AKA-Prime only).
void fr_aka_sim_fips186_2prf(uint8_t out[static 160], uint8_t mk[static 20])
Implement the FIPS-186-2 PRF to derive keying material from the MK.
#define AKA_SIM_VECTOR_GSM_SRES_SIZE
Length of SRES in GSM triplet.
uint8_t emsk[64]
Derived extended master session key.
size_t network_len
Length of the network name (EAP-AKA-Prime only).
#define AKA_SIM_NONCE_S_SIZE
Length of re-authentication nonce.
uint8_t ik_prime[AKA_SIM_VECTOR_UMTS_IK_SIZE]
Derived from IK, for AKA'.
uint64_t sqn
Sequence number.
#define AKA_SIM_MAC_SIZE
Length of MAC used to prevent packet modification.
#define AKA_PRIME_MK_REAUTH_SIZE
The portion of the MK used for re-auth.
#define AKA_SIM_SQN_AK_SIZE
#define AKA_SIM_K_RE_SIZE
Reauthentication key size.
#define EAP_AKA_AUTH_SIZE
#define AKA_SIM_VECTOR_UMTS_CK_SIZE
#define AKA_SIM_MAX_STRING_LENGTH
Maximum size of a SIM/AKA['] string ((4 * 255) - 4).
uint8_t ck_prime[AKA_SIM_VECTOR_UMTS_CK_SIZE]
Derived from CK, for AKA'.
size_t identity_len
Length of the identity.
#define EAP_AKA_PRIME_AUTH_SIZE
#define AKA_PRIME_MK_SIZE
uint8_t k_aut[32]
Derived authentication key.
#define AKA_SIM_VECTOR_GSM_KC_SIZE
Length of Kc in GSM triplet.
size_t k_aut_len
Length of k_aut. 16 for AKA/SIM, 32 for AKA'.
uint8_t k_re[AKA_SIM_K_RE_SIZE]
Derived reauthentication key for AKA'(kdf 1).
#define AKA_SIM_MAC_DIGEST_SIZE
Length of MAC used to prevent packet modification.
#define AKA_SIM_VECTOR_UMTS_IK_SIZE
uint8_t k_encr[16]
Derived encryption key.
#define AKA_SIM_VECTOR_UMTS_AUTN_SIZE
EVP_MD_CTX * md_ctx
Context to hold state of digest as we consume packets.
@ AKA_SIM_VECTOR_GSM
Vector is GSM triplets.
@ AKA_SIM_VECTOR_UMTS_REAUTH_KDF_1_REAUTH
@ AKA_SIM_VECTOR_UMTS
Vector is UMTS quintuplets.
@ AKA_SIM_VECTOR_UMTS_REAUTH_KDF_0_REAUTH
uint8_t mk[AKA_SIM_MK_MAX_SIZE]
Master key from session attributes.
uint8_t msk[64]
Derived master session key.
#define EAP_AKA_SIM_AUTH_SIZE
Stores our checkcode state.
Master key state struct for all SIMlike EAP protocols.
int fr_aka_sim_crypto_umts_kdf_0(fr_aka_sim_keys_t *keys)
Key Derivation Function as described in RFC4187 (EAP-AKA) section 7.
int fr_aka_sim_crypto_umts_kdf_1_reauth(fr_aka_sim_keys_t *keys)
Key Derivation Function (Fast-Reauthentication) as described in RFC 5448 (EAP-AKA') section 3....
ssize_t fr_aka_sim_crypto_sign_packet(uint8_t out[static AKA_SIM_MAC_DIGEST_SIZE], eap_packet_t *eap_packet, bool zero_mac, EVP_MD const *md, uint8_t const *key, size_t const key_len, uint8_t const *hmac_extra, size_t const hmac_extra_len)
Calculate the digest value for a packet.
static int aka_prime_prf(uint8_t *out, size_t outlen, uint8_t const *key, size_t key_len, uint8_t const *in, size_t in_len)
PRF as described in RFC 5448 (EAP-AKA') section 3.4.1.
void fr_aka_sim_crypto_keys_log(request_t *request, fr_aka_sim_keys_t *keys)
Dump the current state of all keys associated with the EAP SIM session.
void fr_aka_sim_crypto_keys_init_umts_kdf_1_reauth(fr_aka_sim_keys_t *keys, uint8_t const mk[static AKA_PRIME_MK_REAUTH_SIZE], uint16_t counter)
Initialise fr_aka_sim_keys_t with EAP-AKA['] reauthentication data.
int fr_aka_sim_crypto_kdf_0_reauth(fr_aka_sim_keys_t *keys)
Key Derivation Function (Fast-Reauthentication) as described in RFC4186/7 (EAP-SIM/AKA) section 7.
static int _evp_cipher_ctx_free_on_exit(void *arg)
void aka_sim_crypto_cipher_ctx_free(void)
Explicitly free all thread load cipher ctxs.
static int fr_aka_sim_find_mac(uint8_t const **out, uint8_t *data, size_t data_len)
Locate the start of the AT_MAC value in the buffer.
ssize_t fr_aka_sim_crypto_finalise_checkcode(TALLOC_CTX *ctx, uint8_t **out, fr_aka_sim_checkcode_t *checkcode)
Write out the final checkcode value.
int fr_aka_sim_crypto_gsm_kdf_0(fr_aka_sim_keys_t *keys)
Key Derivation Function as described in RFC4186 (EAP-SIM) section 7.
#define KDF_1_S_REAUTH_STATIC
void fr_aka_sim_crypto_keys_init_kdf_0_reauth(fr_aka_sim_keys_t *keys, uint8_t const mk[static AKA_SIM_MK_SIZE], uint16_t counter)
Initialise fr_aka_sim_keys_t with EAP-SIM reauthentication data.
static int _fr_aka_sim_crypto_free_checkcode(fr_aka_sim_checkcode_t *checkcode)
Free OpenSSL memory associated with our checkcode ctx.
int fr_aka_sim_crypto_umts_kdf_1(fr_aka_sim_keys_t *keys)
Key Derivation Function as described in RFC 5448 (EAP-AKA') section 3.3.
int fr_aka_sim_crypto_update_checkcode(fr_aka_sim_checkcode_t *checkcode, eap_packet_t *eap_packet)
Digest a packet, updating the checkcode.
static int ck_ik_prime_derive(fr_aka_sim_keys_t *keys)
Key Derivation Function (CK', IK') as specified in 3GPP.33.402.
static _Thread_local EVP_CIPHER_CTX * evp_chipher_ctx
Used for every non-persistent EVP_CIPHER operation in this library.
int fr_aka_sim_crypto_init_checkcode(TALLOC_CTX *ctx, fr_aka_sim_checkcode_t **checkcode, EVP_MD const *md)
Initialise checkcode message digest.
EVP_CIPHER_CTX * aka_sim_crypto_cipher_ctx(void)
Allocate and reset a resumable EVP_CIPHER_CTX for each thread.
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define RHEXDUMP_INLINE3(_data, _len, _fmt,...)
#define RINDENT()
Indent R* messages by one level.
static const uint8_t * zero
#define MILENAGE_SQN_SIZE
Sequence number.
uint32_t fr_rand(void)
Return a 32-bit random number.
void fr_sha1_init(fr_sha1_ctx *context)
void fr_sha1_final(uint8_t digest[static SHA1_DIGEST_LENGTH], fr_sha1_ctx *context)
void fr_sha1_update(fr_sha1_ctx *context, uint8_t const *in, size_t len)
static char buff[sizeof("18446744073709551615")+3]
Master include file to access all functions and structures in the library.
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
static size_t char ** out