31RCSID(
"$Id: 989c90614b8d8f5359a4447bf32deab27a33e8a9 $")
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/rand.h>
45#include <freeradius-devel/util/sha1.h>
46#include <openssl/evp.h>
60 EVP_CIPHER_CTX_free(arg);
74 MEM(ctx = EVP_CIPHER_CTX_new());
99 if (checkcode->
md_ctx) EVP_MD_CTX_destroy(checkcode->
md_ctx);
121 (*checkcode)->md_ctx = EVP_MD_CTX_create();
122 if (!(*checkcode)->md_ctx) {
123 fr_tls_strerror_printf(
"Failed creating MD ctx");
125 TALLOC_FREE(*checkcode);
128 if (EVP_DigestInit_ex((*checkcode)->md_ctx, md, NULL) != 1) {
129 fr_tls_strerror_printf(
"Failed initialising MD ctx");
157 eap_hdr.
id = eap_packet->
id;
158 packet_len = htons((
sizeof(eap_hdr) + eap_packet->
type.
length) & UINT16_MAX);
159 memcpy(&eap_hdr.
length, &packet_len,
sizeof(packet_len));
162 FR_PROTO_HEX_DUMP((
void *)&eap_hdr,
sizeof(eap_hdr),
"Ingesting checkcode EAP header");
167 if (EVP_DigestUpdate(checkcode->
md_ctx, &eap_hdr,
sizeof(eap_hdr)) != 1) {
168 fr_tls_strerror_printf(
"Failed digesting EAP header");
178 fr_tls_strerror_printf(
"Failed digesting packet data");
200 len = (
size_t)EVP_MD_CTX_size((*checkcode).md_ctx);
202 if (EVP_DigestFinal_ex((*checkcode).md_ctx,
buff, NULL) != 1) {
203 fr_tls_strerror_printf(
"Failed finalising checkcode digest");
229 while ((p + 2) < end) {
235 if (p[0] == FR_MAC) {
237 if ((p + len) > end) {
238 fr_strerror_printf(
"Malformed AT_MAC: Length (%zu) exceeds buffer (%zu)", len, (
size_t) (end - p));
291 EVP_MD
const *md,
uint8_t const *key,
size_t const key_len,
292 uint8_t const *hmac_extra,
size_t const hmac_extra_len)
294 EVP_MD_CTX *md_ctx = NULL;
297 uint8_t digest[SHA256_DIGEST_LENGTH];
298 size_t digest_len =
sizeof(digest);
315 if (
unlikely(!key) || (key_len == 0)) {
321 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, key_len);
323 fr_tls_strerror_printf(
"Failed creating HMAC signing key");
325 if (pkey) EVP_PKEY_free(pkey);
326 if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
330 md_ctx = EVP_MD_CTX_create();
332 fr_tls_strerror_printf(
"Failed creating HMAC ctx");
336 if (EVP_DigestSignInit(md_ctx, NULL, md, NULL, pkey) != 1) {
337 fr_tls_strerror_printf(
"Failed initialising digest");
347 eap_hdr.
id = eap_packet->
id;
348 packet_len = htons((
sizeof(eap_hdr) + eap_packet->
type.
length) & UINT16_MAX);
349 memcpy(&eap_hdr.
length, &packet_len,
sizeof(packet_len));
353 if (EVP_DigestSignUpdate(md_ctx, &eap_hdr,
sizeof(eap_hdr)) != 1) {
354 fr_tls_strerror_printf(
"Failed digesting EAP data");
366 uint8_t zero[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
376 if (EVP_DigestSignUpdate(md_ctx, p, mac - p) != 1) {
377 fr_tls_strerror_printf(
"Failed digesting packet data (before MAC)");
388 if (EVP_DigestSignUpdate(md_ctx,
zero,
sizeof(
zero)) != 1) {
389 fr_tls_strerror_printf(
"Failed digesting zeroed MAC");
411 if (EVP_DigestSignUpdate(md_ctx, p, end - p) != 1) {
412 fr_tls_strerror_printf(
"Failed digesting packet data");
425 if (EVP_DigestSignUpdate(md_ctx, hmac_extra, hmac_extra_len) != 1) {
426 fr_tls_strerror_printf(
"Failed digesting HMAC extra data");
431 if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1) {
432 fr_tls_strerror_printf(
"Failed finalising digest");
441 memcpy(
out, digest, 16);
444 EVP_MD_CTX_destroy(md_ctx);
483 sizeof(keys->gsm.nonce_mt) +
484 keys->gsm.version_list_len +
485 sizeof(keys->gsm.version_select)) <=
sizeof(buf)))
return -1;
500 memcpy(p, keys->gsm.nonce_mt,
sizeof(keys->gsm.nonce_mt));
501 p +=
sizeof(keys->gsm.nonce_mt);
503 memcpy(p, keys->gsm.version_list, keys->gsm.version_list_len);
504 p += keys->gsm.version_list_len;
506 memcpy(p, keys->gsm.version_select,
sizeof(keys->gsm.version_select));
507 p +=
sizeof(keys->gsm.version_select);
509 FR_PROTO_HEX_DUMP(buf, p - buf,
"Identity || n*Kc || NONCE_MT || Version List || Selected Version");
531 memcpy(keys->
k_encr, p, 16);
540 memcpy(keys->
msk, p, 64);
544 memcpy(keys->
emsk, p, 64);
584 sizeof(keys->umts.vector.ik) +
585 sizeof(keys->umts.vector.ck)) <=
sizeof(buf)))
return -1;
591 memcpy(p, keys->umts.vector.ik,
sizeof(keys->umts.vector.ik));
592 p +=
sizeof(keys->umts.vector.ik);
594 memcpy(p, keys->umts.vector.ck,
sizeof(keys->umts.vector.ck));
595 p +=
sizeof(keys->umts.vector.ck);
614 memcpy(keys->
k_encr, p, 16);
621 memcpy(keys->
msk, p, 64);
624 memcpy(keys->
emsk, p, 64);
653 size_t digest_len =
sizeof(digest);
658 uint8_t k[
sizeof(keys->umts.vector.ik) +
sizeof(keys->umts.vector.ck)];
665 EVP_MD_CTX *md_ctx = NULL;
679 sizeof(l1)) <=
sizeof(s)))
return -1;
694 memcpy(p, &l0,
sizeof(l0));
701 memcpy(p, &l1,
sizeof(l1));
712 memcpy(p, keys->umts.vector.ck,
sizeof(keys->umts.vector.ck));
713 p +=
sizeof(keys->umts.vector.ck);
714 memcpy(p, keys->umts.vector.ik,
sizeof(keys->umts.vector.ik));
718 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, k,
sizeof(k));
720 fr_tls_strerror_printf(
"Failed creating HMAC signing key");
722 if (pkey) EVP_PKEY_free(pkey);
723 if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
727 md_ctx = EVP_MD_CTX_create();
729 fr_tls_strerror_printf(
"Failed creating HMAC ctx");
733 if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
734 fr_tls_strerror_printf(
"Failed initialising digest");
738 if (EVP_DigestSignUpdate(md_ctx, s, s_len) != 1)
goto error;
739 if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1)
goto error;
747 EVP_MD_CTX_destroy(md_ctx);
783 uint8_t digest[SHA256_DIGEST_LENGTH];
785 EVP_MD_CTX *md_ctx = NULL;
787 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, key_len);
789 fr_tls_strerror_printf(
"Failed creating HMAC signing key");
791 if (pkey) EVP_PKEY_free(pkey);
792 if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
796 md_ctx = EVP_MD_CTX_create();
798 fr_tls_strerror_printf(
"Failed creating HMAC ctx");
802 if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
803 fr_tls_strerror_printf(
"Failed initialising digest");
808 size_t digest_len =
sizeof(digest);
813 if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1)
goto error;
814 if ((p !=
out) && EVP_DigestSignUpdate(md_ctx, digest,
sizeof(digest)) != 1)
goto error;
815 if (EVP_DigestSignUpdate(md_ctx,
in, in_len) != 1)
goto error;
816 if (EVP_DigestSignUpdate(md_ctx, &c,
sizeof(c)) != 1)
goto error;
817 if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1)
goto error;
820 if (copy > digest_len) copy = digest_len;
822 memcpy(p, digest, copy);
826 EVP_MD_CTX_destroy(md_ctx);
854#define KDF_1_S_STATIC "EAP-AKA'"
895 memcpy(keys->
k_encr, p, 16);
905 memcpy(keys->
msk, p,
sizeof(keys->
msk));
906 p +=
sizeof(keys->
msk);
908 memcpy(keys->
emsk, p,
sizeof(keys->
emsk));
935 keys->reauth.counter = counter;
941 memcpy(keys->reauth.nonce_s, (
uint8_t *)&nonce_s,
sizeof(keys->reauth.nonce_s));
965 keys->reauth.counter = counter;
971 memcpy(keys->reauth.nonce_s, (
uint8_t *)&nonce_s,
sizeof(keys->reauth.nonce_s));
1004 unsigned int len = 0;
1012 if (keys->reauth.counter == 0) {
1024 if (need >
sizeof(buf)) {
1025 fr_strerror_printf(
"Identity too long. PRF input is %zu bytes, input buffer is %zu bytes",
1037 memcpy(keys->
k_encr, p, 16);
1064 *p++ = ((keys->reauth.counter & 0xff00) >> 8);
1065 *p++ = (keys->reauth.counter & 0x00ff);
1070 memcpy(p, keys->reauth.nonce_s,
sizeof(keys->reauth.nonce_s));
1071 p +=
sizeof(keys->reauth.nonce_s);
1084 md_ctx = EVP_MD_CTX_create();
1086 fr_tls_strerror_printf(
"Failed creating MD ctx");
1088 EVP_MD_CTX_destroy(md_ctx);
1092 if (EVP_DigestInit_ex(md_ctx, EVP_sha1(), NULL) != 1) {
1093 fr_tls_strerror_printf(
"Failed initialising digest");
1097 if (EVP_DigestUpdate(md_ctx, buf, p - buf) != 1) {
1098 fr_tls_strerror_printf(
"Failed digesting crypto data");
1102 if (EVP_DigestFinal_ex(md_ctx, keys->reauth.xkey_prime, &len) != 1) {
1103 fr_tls_strerror_printf(
"Failed finalising digest");
1107 EVP_MD_CTX_destroy(md_ctx);
1109 FR_PROTO_HEX_DUMP(keys->reauth.xkey_prime,
sizeof(keys->reauth.xkey_prime),
"xkey'");
1120 memcpy(keys->
msk, p, 64);
1124 memcpy(keys->
emsk, p, 64);
1146#define KDF_1_S_REAUTH_STATIC "EAP-AKA' re-auth"
1193 fr_dbuff_in_bytes(&dbuff, ((keys->reauth.counter & 0xff00) >> 8), (keys->reauth.counter & 0x00ff));
1201 "\"EAP-AKA' re-auth\" || Identity || counter || NONCE_S");
1238 switch (keys->vector_type) {
1249 for (i = 0; i < keys->gsm.num_vectors; i++) {
1287 "counter : %u", keys->reauth.counter);
1296 "counter : %u", keys->reauth.counter);
1308 switch (keys->vector_type) {
1337#ifdef TESTING_SIM_CRYPTO
1341#include <freeradius-devel/util/test/acutest.h>
1348 .identity_len =
sizeof(
"1244070100000001@eapsim.foo") - 1,
1353 .rand = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1354 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
1355 .sres = { 0xd1, 0xd2, 0xd3, 0xd4 },
1356 .kc = { 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7 }
1359 .rand = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1360 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f },
1361 .sres = { 0xe1, 0xe2, 0xe3, 0xe4 },
1362 .kc = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7 }
1365 .rand = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
1366 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f },
1367 .sres = { 0xf1, 0xf2, 0xf3, 0xf4 },
1368 .kc = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }
1371 .nonce_mt = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1372 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
1373 .version_list = { 0x00, 0x01 },
1374 .version_list_len = 2,
1375 .version_select = { 0x00, 0x01 },
1382 .
k_encr = { 0x53, 0x6e, 0x5e, 0xbc, 0x44, 0x65, 0x58, 0x2a,
1383 0xa6, 0xa8, 0xec, 0x99, 0x86, 0xeb, 0xb6, 0x20 },
1384 .k_aut = { 0x25, 0xaf, 0x19, 0x42, 0xef, 0xcb, 0xf4, 0xbc,
1385 0x72, 0xb3, 0x94, 0x34, 0x21, 0xf2, 0xa9, 0x74 },
1387 .msk = { 0x39, 0xd4, 0x5a, 0xea, 0xf4, 0xe3, 0x06, 0x01,
1388 0x98, 0x3e, 0x97, 0x2b, 0x6c, 0xfd, 0x46, 0xd1,
1389 0xc3, 0x63, 0x77, 0x33, 0x65, 0x69, 0x0d, 0x09,
1390 0xcd, 0x44, 0x97, 0x6b, 0x52, 0x5f, 0x47, 0xd3,
1391 0xa6, 0x0a, 0x98, 0x5e, 0x95, 0x5c, 0x53, 0xb0,
1392 0x90, 0xb2, 0xe4, 0xb7, 0x37, 0x19, 0x19, 0x6a,
1393 0x40, 0x25, 0x42, 0x96, 0x8f, 0xd1, 0x4a, 0x88,
1394 0x8f, 0x46, 0xb9, 0xa7, 0x88, 0x6e, 0x44, 0x88 },
1395 .emsk = { 0x59, 0x49, 0xea, 0xb0, 0xff, 0xf6, 0x9d, 0x52,
1396 0x31, 0x5c, 0x6c, 0x63, 0x4f, 0xd1, 0x4a, 0x7f,
1397 0x0d, 0x52, 0x02, 0x3d, 0x56, 0xf7, 0x96, 0x98,
1398 0xfa, 0x65, 0x96, 0xab, 0xee, 0xd4, 0xf9, 0x3f,
1399 0xbb, 0x48, 0xeb, 0x53, 0x4d, 0x98, 0x54, 0x14,
1400 0xce, 0xed, 0x0d, 0x9a, 0x8e, 0xd3, 0x3c, 0x38,
1401 0x7c, 0x9d, 0xfd, 0xab, 0x92, 0xff, 0xbd, 0xf2,
1402 0x40, 0xfc, 0xec, 0xf6, 0x5a, 0x2c, 0x93, 0xb9 }
1405static void test_eap_sim_kdf_0_gsm(
void)
1415 memcpy(&keys, &rfc4186_vector0_in,
sizeof(keys));
1434 .identity_len =
sizeof(
"0555444333222111") - 1,
1436 .sqn = 205964772668538,
1440 .rand = { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e,
1441 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 },
1442 .autn = { 0xbb, 0x52, 0xe9, 0x1c, 0x74, 0x7a, 0xc3, 0xab,
1443 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 },
1444 .ik = { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb,
1445 0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a },
1446 .ck = { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94,
1447 0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f },
1448 .xres = { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 },
1456 .
k_encr = { 0x18, 0xe8, 0xb2, 0x0b, 0xcd, 0xa7, 0x04, 0x86,
1457 0xfd, 0x59, 0x59, 0x58, 0x6a, 0x9e, 0x7c, 0x3d },
1458 .k_aut = { 0x18, 0xc0, 0x44, 0x07, 0x0e, 0x5e, 0x64, 0x2a,
1459 0x26, 0x43, 0x87, 0x6f, 0xf7, 0xa8, 0x38, 0x12 },
1461 .msk = { 0x35, 0x2f, 0xfa, 0xef, 0x2d, 0xf1, 0x20, 0xcb,
1462 0x22, 0x41, 0x0b, 0x9c, 0x0b, 0x70, 0x62, 0x3c,
1463 0xb5, 0xa3, 0x5b, 0xc9, 0xfc, 0xd6, 0xbc, 0xa0,
1464 0xfc, 0x33, 0x7b, 0x48, 0xb1, 0x76, 0x30, 0x89,
1465 0x0a, 0x03, 0x37, 0x5c, 0xfd, 0x1e, 0x64, 0xcb,
1466 0xd6, 0xbf, 0x83, 0x04, 0x37, 0x4d, 0xd2, 0xe1,
1467 0x39, 0xd6, 0x4e, 0xd1, 0xa6, 0xd6, 0x18, 0xff,
1468 0xef, 0xb0, 0x8c, 0x26, 0xa6, 0xbb, 0x35, 0x85 },
1469 .emsk = { 0x9e, 0x06, 0x59, 0xae, 0x03, 0x97, 0x7d, 0xcb,
1470 0xb1, 0xd6, 0x4d, 0x24, 0x05, 0xe1, 0x10, 0x82,
1471 0xa9, 0x1a, 0xdb, 0x9a, 0xc7, 0xf7, 0xbd, 0x0b,
1472 0x74, 0xa6, 0x1e, 0xc0, 0xe9, 0x80, 0xb3, 0x6f,
1473 0xa0, 0xc3, 0x98, 0x8b, 0x6e, 0x11, 0xef, 0x12,
1474 0x52, 0x8e, 0x38, 0x04, 0xb3, 0x2d, 0xf1, 0xbc,
1475 0x52, 0xf6, 0x24, 0x9f, 0xa9, 0x6d, 0xc9, 0x4c,
1476 0x94, 0xa3, 0xd9, 0xb1, 0x48, 0xf4, 0xf9, 0x96 }
1479static void test_eap_aka_kdf_0_umts(
void)
1489 memcpy(&keys, &rfc4187_vector0_in,
sizeof(keys));
1506 .
identity = (
uint8_t const *)
"Y24fNSrz8BP274jOJaF17WfxI8YO7QX00pMXk9XMMVOw7broaNhTczuFq53aEpOkk3L0dm@eapsim.foo",
1507 .identity_len =
sizeof(
"Y24fNSrz8BP274jOJaF17WfxI8YO7QX00pMXk9XMMVOw7broaNhTczuFq53aEpOkk3L0dm@eapsim.foo") - 1,
1511 .nonce_s = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1512 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }
1514 .mk = { 0xe5, 0x76, 0xd5, 0xca, 0x33, 0x2e, 0x99, 0x30,
1515 0x01, 0x8b, 0xf1, 0xba, 0xee, 0x27, 0x63, 0xc7,
1516 0x95, 0xb3, 0xc7, 0x12 },
1520 .
k_encr = { 0x53, 0x6e, 0x5e, 0xbc, 0x44, 0x65, 0x58, 0x2a,
1521 0xa6, 0xa8, 0xec, 0x99, 0x86, 0xeb, 0xb6, 0x20 },
1522 .k_aut = { 0x25, 0xaf, 0x19, 0x42, 0xef, 0xcb, 0xf4, 0xbc,
1523 0x72, 0xb3, 0x94, 0x34, 0x21, 0xf2, 0xa9, 0x74 },
1525 .msk = { 0x62, 0x63, 0xf6, 0x14, 0x97, 0x38, 0x95, 0xe1,
1526 0x33, 0x5f, 0x7e, 0x30, 0xcf, 0xf0, 0x28, 0xee,
1527 0x21, 0x76, 0xf5, 0x19, 0x00, 0x2c, 0x9a, 0xbe,
1528 0x73, 0x2f, 0xe0, 0xef, 0x00, 0xcf, 0x16, 0x7c,
1529 0x75, 0x6d, 0x9e, 0x4c, 0xed, 0x6d, 0x5e, 0xd6,
1530 0x40, 0xeb, 0x3f, 0xe3, 0x85, 0x65, 0xca, 0x07,
1531 0x6e, 0x7f, 0xb8, 0xa8, 0x17, 0xcf, 0xe8, 0xd9,
1532 0xad, 0xbc, 0xe4, 0x41, 0xd4, 0x7c, 0x4f, 0x5e },
1533 .emsk = { 0x3d, 0x8f, 0xf7, 0x86, 0x3a, 0x63, 0x0b, 0x2b,
1534 0x06, 0xe2, 0xcf, 0x20, 0x96, 0x84, 0xc1, 0x3f,
1535 0x6b, 0x82, 0xf9, 0x92, 0xf2, 0xb0, 0x6f, 0x1b,
1536 0x54, 0xbf, 0x51, 0xef, 0x23, 0x7f, 0x2a, 0x40,
1537 0x1e, 0xf5, 0xe0, 0xd7, 0xe0, 0x98, 0xa3, 0x4c,
1538 0x53, 0x3e, 0xae, 0xbf, 0x34, 0x57, 0x88, 0x54,
1539 0xb7, 0x72, 0x15, 0x26, 0x20, 0xa7, 0x77, 0xf0,
1540 0xe0, 0x34, 0x08, 0x84, 0xa2, 0x94, 0xfb, 0x73 }
1543static void test_eap_sim_kdf_0_reauth(
void)
1553 memcpy(&keys, &rfc4186_vector0_reauth_in,
sizeof(keys));
1571 .identity_len =
sizeof(
"0555444333222111") - 1,
1573 .network = (
uint8_t const *)
"WLAN",
1574 .network_len =
sizeof(
"WLAN") - 1,
1576 .sqn = 205964772668538,
1580 .rand = { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e,
1581 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 },
1582 .autn = { 0xbb, 0x52, 0xe9, 0x1c, 0x74, 0x7a, 0xc3, 0xab,
1583 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 },
1584 .ik = { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb,
1585 0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a },
1586 .ck = { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94,
1587 0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f },
1588 .xres = { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 },
1596 .
ik_prime = { 0x00, 0x93, 0x96, 0x2d, 0x0d, 0xd8, 0x4a, 0xa5,
1597 0x68, 0x4b, 0x04, 0x5c, 0x9e, 0xdf, 0xfa, 0x04 },
1598 .ck_prime = { 0xcc, 0xfc, 0x23, 0x0c, 0xa7, 0x4f, 0xcc, 0x96,
1599 0xc0, 0xa5, 0xd6, 0x11, 0x64, 0xf5, 0xa7, 0x6c },
1601 .k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1602 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1603 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1604 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1605 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1606 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1608 .k_re = { 0xcf, 0x83, 0xaa, 0x8b, 0xc7, 0xe0, 0xac, 0xed,
1609 0x89, 0x2a, 0xcc, 0x98, 0xe7, 0x6a, 0x9b, 0x20,
1610 0x95, 0xb5, 0x58, 0xc7, 0x79, 0x5c, 0x70, 0x94,
1611 0x71, 0x5c, 0xb3, 0x39, 0x3a, 0xa7, 0xd1, 0x7a },
1612 .msk = { 0x67, 0xc4, 0x2d, 0x9a, 0xa5, 0x6c, 0x1b, 0x79,
1613 0xe2, 0x95, 0xe3, 0x45, 0x9f, 0xc3, 0xd1, 0x87,
1614 0xd4, 0x2b, 0xe0, 0xbf, 0x81, 0x8d, 0x30, 0x70,
1615 0xe3, 0x62, 0xc5, 0xe9, 0x67, 0xa4, 0xd5, 0x44,
1616 0xe8, 0xec, 0xfe, 0x19, 0x35, 0x8a, 0xb3, 0x03,
1617 0x9a, 0xff, 0x03, 0xb7, 0xc9, 0x30, 0x58, 0x8c,
1618 0x05, 0x5b, 0xab, 0xee, 0x58, 0xa0, 0x26, 0x50,
1619 0xb0, 0x67, 0xec, 0x4e, 0x93, 0x47, 0xc7, 0x5a },
1620 .emsk = { 0xf8, 0x61, 0x70, 0x3c, 0xd7, 0x75, 0x59, 0x0e,
1621 0x16, 0xc7, 0x67, 0x9e, 0xa3, 0x87, 0x4a, 0xda,
1622 0x86, 0x63, 0x11, 0xde, 0x29, 0x07, 0x64, 0xd7,
1623 0x60, 0xcf, 0x76, 0xdf, 0x64, 0x7e, 0xa0, 0x1c,
1624 0x31, 0x3f, 0x69, 0x92, 0x4b, 0xdd, 0x76, 0x50,
1625 0xca, 0x9b, 0xac, 0x14, 0x1e, 0xa0, 0x75, 0xc4,
1626 0xef, 0x9e, 0x80, 0x29, 0xc0, 0xe2, 0x90, 0xcd,
1627 0xba, 0xd5, 0x63, 0x8b, 0x63, 0xbc, 0x23, 0xfb }
1630static void test_eap_aka_kdf_1_umts(
void)
1640 memcpy(&keys, &rfc5448_vector0_in,
sizeof(keys));
1656static void test_eap_aka_derive_ck_ik(
void)
1667 memcpy(&keys, &rfc5448_vector0_in,
sizeof(keys));
1679 .identity_len =
sizeof(
"5555444333222111") - 1,
1681 .network = (
uint8_t const *)
"WLAN",
1682 .network_len =
sizeof(
"WLAN") - 1,
1686 .nonce_s = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1687 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }
1689 .k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1690 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1691 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1692 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1693 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1694 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1696 .k_re = { 0xcf, 0x83, 0xaa, 0x8b, 0xc7, 0xe0, 0xac, 0xed,
1697 0x89, 0x2a, 0xcc, 0x98, 0xe7, 0x6a, 0x9b, 0x20,
1698 0x95, 0xb5, 0x58, 0xc7, 0x79, 0x5c, 0x70, 0x94,
1699 0x71, 0x5c, 0xb3, 0x39, 0x3a, 0xa7, 0xd1, 0x7a }
1706 .
k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1707 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1708 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1709 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1710 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1711 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1713 .msk = { 0x28, 0xf2, 0xb9, 0x3a, 0x8e, 0xdc, 0x4a, 0x01,
1714 0xb6, 0x9d, 0x37, 0x8b, 0xa6, 0x8a, 0x77, 0xbb,
1715 0x01, 0x6c, 0x0f, 0xeb, 0xb7, 0x60, 0xdb, 0x98,
1716 0x57, 0x99, 0x64, 0x99, 0x00, 0x00, 0x6f, 0x97,
1717 0xa1, 0x76, 0x5c, 0x65, 0xf5, 0xd5, 0xbf, 0xde,
1718 0xe7, 0x61, 0xba, 0x42, 0x92, 0xe4, 0x51, 0xd1,
1719 0xa0, 0xc5, 0x7e, 0x76, 0xeb, 0x91, 0x3e, 0xe9,
1720 0x95, 0xf5, 0xce, 0x6e, 0xb7, 0x98, 0x91, 0x38 },
1721 .emsk = { 0xb9, 0x05, 0xa2, 0xf4, 0x67, 0xe0, 0xeb, 0x9a,
1722 0xfb, 0xa4, 0x59, 0xa7, 0xd8, 0xa7, 0xc8, 0x77,
1723 0xd5, 0xfa, 0x2e, 0x5e, 0xd3, 0x77, 0xf8, 0xc5,
1724 0x2f, 0xa4, 0x86, 0xad, 0xf5, 0x15, 0x5e, 0xb7,
1725 0x96, 0xac, 0xa9, 0x3e, 0xa3, 0xa9, 0x95, 0xe8,
1726 0xa2, 0x34, 0x36, 0x54, 0x5a, 0xf1, 0x57, 0x22,
1727 0xaa, 0x94, 0xb9, 0xfb, 0xd9, 0x06, 0x0c, 0x50,
1728 0xa3, 0x56, 0xcc, 0xb4, 0xc7, 0x10, 0x0e, 0x66 }
1731static void test_eap_aka_kdf_1_reauth(
void)
1741 memcpy(&keys, &rfc5448_vector0_reauth_in,
sizeof(keys));
1758 {
"test_eap_sim_kdf_0_gsm", test_eap_sim_kdf_0_gsm },
1763 {
"test_eap_aka_kdf_0_umts", test_eap_aka_kdf_0_umts },
1768 {
"test_eap_sim_kdf_0_reauth", test_eap_sim_kdf_0_reauth },
1773 {
"test_eap_aka_kdf_1_umts", test_eap_aka_kdf_1_umts },
1774 {
"test_eap_aka_derive_ck_ik", test_eap_aka_derive_ck_ik },
1775 {
"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