31RCSID(
"$Id: 9d643b0bd01abe501866917371ecbfc80af7848f $")
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'"
901 memcpy(keys->
k_encr, p, 16);
911 memcpy(keys->
msk, p,
sizeof(keys->
msk));
912 p +=
sizeof(keys->
msk);
914 memcpy(keys->
emsk, p,
sizeof(keys->
emsk));
941 keys->reauth.counter = counter;
947 memcpy(keys->reauth.nonce_s, (
uint8_t *)&nonce_s,
sizeof(keys->reauth.nonce_s));
971 keys->reauth.counter = counter;
977 memcpy(keys->reauth.nonce_s, (
uint8_t *)&nonce_s,
sizeof(keys->reauth.nonce_s));
1010 unsigned int len = 0;
1018 if (keys->reauth.counter == 0) {
1030 if (need >
sizeof(buf)) {
1031 fr_strerror_printf(
"Identity too long. PRF input is %zu bytes, input buffer is %zu bytes",
1043 memcpy(keys->
k_encr, p, 16);
1070 *p++ = ((keys->reauth.counter & 0xff00) >> 8);
1071 *p++ = (keys->reauth.counter & 0x00ff);
1076 memcpy(p, keys->reauth.nonce_s,
sizeof(keys->reauth.nonce_s));
1077 p +=
sizeof(keys->reauth.nonce_s);
1090 md_ctx = EVP_MD_CTX_create();
1092 fr_tls_strerror_printf(
"Failed creating MD ctx");
1094 EVP_MD_CTX_destroy(md_ctx);
1098 if (EVP_DigestInit_ex(md_ctx, EVP_sha1(), NULL) != 1) {
1099 fr_tls_strerror_printf(
"Failed initialising digest");
1103 if (EVP_DigestUpdate(md_ctx, buf, p - buf) != 1) {
1104 fr_tls_strerror_printf(
"Failed digesting crypto data");
1108 if (EVP_DigestFinal_ex(md_ctx, keys->reauth.xkey_prime, &len) != 1) {
1109 fr_tls_strerror_printf(
"Failed finalising digest");
1113 EVP_MD_CTX_destroy(md_ctx);
1115 FR_PROTO_HEX_DUMP(keys->reauth.xkey_prime,
sizeof(keys->reauth.xkey_prime),
"xkey'");
1126 memcpy(keys->
msk, p, 64);
1130 memcpy(keys->
emsk, p, 64);
1152#define KDF_1_S_REAUTH_STATIC "EAP-AKA' re-auth"
1199 fr_dbuff_in_bytes(&dbuff, ((keys->reauth.counter & 0xff00) >> 8), (keys->reauth.counter & 0x00ff));
1207 "\"EAP-AKA' re-auth\" || Identity || counter || NONCE_S");
1244 switch (keys->vector_type) {
1255 for (i = 0; i < keys->gsm.num_vectors; i++) {
1293 "counter : %u", keys->reauth.counter);
1302 "counter : %u", keys->reauth.counter);
1314 switch (keys->vector_type) {
1343#ifdef TESTING_SIM_CRYPTO
1347#include <freeradius-devel/util/test/acutest.h>
1354 .identity_len =
sizeof(
"1244070100000001@eapsim.foo") - 1,
1359 .rand = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1360 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
1361 .sres = { 0xd1, 0xd2, 0xd3, 0xd4 },
1362 .kc = { 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7 }
1365 .rand = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1366 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f },
1367 .sres = { 0xe1, 0xe2, 0xe3, 0xe4 },
1368 .kc = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7 }
1371 .rand = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
1372 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f },
1373 .sres = { 0xf1, 0xf2, 0xf3, 0xf4 },
1374 .kc = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }
1377 .nonce_mt = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1378 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
1379 .version_list = { 0x00, 0x01 },
1380 .version_list_len = 2,
1381 .version_select = { 0x00, 0x01 },
1388 .
k_encr = { 0x53, 0x6e, 0x5e, 0xbc, 0x44, 0x65, 0x58, 0x2a,
1389 0xa6, 0xa8, 0xec, 0x99, 0x86, 0xeb, 0xb6, 0x20 },
1390 .k_aut = { 0x25, 0xaf, 0x19, 0x42, 0xef, 0xcb, 0xf4, 0xbc,
1391 0x72, 0xb3, 0x94, 0x34, 0x21, 0xf2, 0xa9, 0x74 },
1393 .msk = { 0x39, 0xd4, 0x5a, 0xea, 0xf4, 0xe3, 0x06, 0x01,
1394 0x98, 0x3e, 0x97, 0x2b, 0x6c, 0xfd, 0x46, 0xd1,
1395 0xc3, 0x63, 0x77, 0x33, 0x65, 0x69, 0x0d, 0x09,
1396 0xcd, 0x44, 0x97, 0x6b, 0x52, 0x5f, 0x47, 0xd3,
1397 0xa6, 0x0a, 0x98, 0x5e, 0x95, 0x5c, 0x53, 0xb0,
1398 0x90, 0xb2, 0xe4, 0xb7, 0x37, 0x19, 0x19, 0x6a,
1399 0x40, 0x25, 0x42, 0x96, 0x8f, 0xd1, 0x4a, 0x88,
1400 0x8f, 0x46, 0xb9, 0xa7, 0x88, 0x6e, 0x44, 0x88 },
1401 .emsk = { 0x59, 0x49, 0xea, 0xb0, 0xff, 0xf6, 0x9d, 0x52,
1402 0x31, 0x5c, 0x6c, 0x63, 0x4f, 0xd1, 0x4a, 0x7f,
1403 0x0d, 0x52, 0x02, 0x3d, 0x56, 0xf7, 0x96, 0x98,
1404 0xfa, 0x65, 0x96, 0xab, 0xee, 0xd4, 0xf9, 0x3f,
1405 0xbb, 0x48, 0xeb, 0x53, 0x4d, 0x98, 0x54, 0x14,
1406 0xce, 0xed, 0x0d, 0x9a, 0x8e, 0xd3, 0x3c, 0x38,
1407 0x7c, 0x9d, 0xfd, 0xab, 0x92, 0xff, 0xbd, 0xf2,
1408 0x40, 0xfc, 0xec, 0xf6, 0x5a, 0x2c, 0x93, 0xb9 }
1411static void test_eap_sim_kdf_0_gsm(
void)
1421 memcpy(&keys, &rfc4186_vector0_in,
sizeof(keys));
1440 .identity_len =
sizeof(
"0555444333222111") - 1,
1442 .sqn = 205964772668538,
1446 .rand = { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e,
1447 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 },
1448 .autn = { 0xbb, 0x52, 0xe9, 0x1c, 0x74, 0x7a, 0xc3, 0xab,
1449 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 },
1450 .ik = { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb,
1451 0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a },
1452 .ck = { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94,
1453 0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f },
1454 .xres = { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 },
1462 .
k_encr = { 0x18, 0xe8, 0xb2, 0x0b, 0xcd, 0xa7, 0x04, 0x86,
1463 0xfd, 0x59, 0x59, 0x58, 0x6a, 0x9e, 0x7c, 0x3d },
1464 .k_aut = { 0x18, 0xc0, 0x44, 0x07, 0x0e, 0x5e, 0x64, 0x2a,
1465 0x26, 0x43, 0x87, 0x6f, 0xf7, 0xa8, 0x38, 0x12 },
1467 .msk = { 0x35, 0x2f, 0xfa, 0xef, 0x2d, 0xf1, 0x20, 0xcb,
1468 0x22, 0x41, 0x0b, 0x9c, 0x0b, 0x70, 0x62, 0x3c,
1469 0xb5, 0xa3, 0x5b, 0xc9, 0xfc, 0xd6, 0xbc, 0xa0,
1470 0xfc, 0x33, 0x7b, 0x48, 0xb1, 0x76, 0x30, 0x89,
1471 0x0a, 0x03, 0x37, 0x5c, 0xfd, 0x1e, 0x64, 0xcb,
1472 0xd6, 0xbf, 0x83, 0x04, 0x37, 0x4d, 0xd2, 0xe1,
1473 0x39, 0xd6, 0x4e, 0xd1, 0xa6, 0xd6, 0x18, 0xff,
1474 0xef, 0xb0, 0x8c, 0x26, 0xa6, 0xbb, 0x35, 0x85 },
1475 .emsk = { 0x9e, 0x06, 0x59, 0xae, 0x03, 0x97, 0x7d, 0xcb,
1476 0xb1, 0xd6, 0x4d, 0x24, 0x05, 0xe1, 0x10, 0x82,
1477 0xa9, 0x1a, 0xdb, 0x9a, 0xc7, 0xf7, 0xbd, 0x0b,
1478 0x74, 0xa6, 0x1e, 0xc0, 0xe9, 0x80, 0xb3, 0x6f,
1479 0xa0, 0xc3, 0x98, 0x8b, 0x6e, 0x11, 0xef, 0x12,
1480 0x52, 0x8e, 0x38, 0x04, 0xb3, 0x2d, 0xf1, 0xbc,
1481 0x52, 0xf6, 0x24, 0x9f, 0xa9, 0x6d, 0xc9, 0x4c,
1482 0x94, 0xa3, 0xd9, 0xb1, 0x48, 0xf4, 0xf9, 0x96 }
1485static void test_eap_aka_kdf_0_umts(
void)
1495 memcpy(&keys, &rfc4187_vector0_in,
sizeof(keys));
1512 .
identity = (
uint8_t const *)
"Y24fNSrz8BP274jOJaF17WfxI8YO7QX00pMXk9XMMVOw7broaNhTczuFq53aEpOkk3L0dm@eapsim.foo",
1513 .identity_len =
sizeof(
"Y24fNSrz8BP274jOJaF17WfxI8YO7QX00pMXk9XMMVOw7broaNhTczuFq53aEpOkk3L0dm@eapsim.foo") - 1,
1517 .nonce_s = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1518 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }
1520 .mk = { 0xe5, 0x76, 0xd5, 0xca, 0x33, 0x2e, 0x99, 0x30,
1521 0x01, 0x8b, 0xf1, 0xba, 0xee, 0x27, 0x63, 0xc7,
1522 0x95, 0xb3, 0xc7, 0x12 },
1526 .
k_encr = { 0x53, 0x6e, 0x5e, 0xbc, 0x44, 0x65, 0x58, 0x2a,
1527 0xa6, 0xa8, 0xec, 0x99, 0x86, 0xeb, 0xb6, 0x20 },
1528 .k_aut = { 0x25, 0xaf, 0x19, 0x42, 0xef, 0xcb, 0xf4, 0xbc,
1529 0x72, 0xb3, 0x94, 0x34, 0x21, 0xf2, 0xa9, 0x74 },
1531 .msk = { 0x62, 0x63, 0xf6, 0x14, 0x97, 0x38, 0x95, 0xe1,
1532 0x33, 0x5f, 0x7e, 0x30, 0xcf, 0xf0, 0x28, 0xee,
1533 0x21, 0x76, 0xf5, 0x19, 0x00, 0x2c, 0x9a, 0xbe,
1534 0x73, 0x2f, 0xe0, 0xef, 0x00, 0xcf, 0x16, 0x7c,
1535 0x75, 0x6d, 0x9e, 0x4c, 0xed, 0x6d, 0x5e, 0xd6,
1536 0x40, 0xeb, 0x3f, 0xe3, 0x85, 0x65, 0xca, 0x07,
1537 0x6e, 0x7f, 0xb8, 0xa8, 0x17, 0xcf, 0xe8, 0xd9,
1538 0xad, 0xbc, 0xe4, 0x41, 0xd4, 0x7c, 0x4f, 0x5e },
1539 .emsk = { 0x3d, 0x8f, 0xf7, 0x86, 0x3a, 0x63, 0x0b, 0x2b,
1540 0x06, 0xe2, 0xcf, 0x20, 0x96, 0x84, 0xc1, 0x3f,
1541 0x6b, 0x82, 0xf9, 0x92, 0xf2, 0xb0, 0x6f, 0x1b,
1542 0x54, 0xbf, 0x51, 0xef, 0x23, 0x7f, 0x2a, 0x40,
1543 0x1e, 0xf5, 0xe0, 0xd7, 0xe0, 0x98, 0xa3, 0x4c,
1544 0x53, 0x3e, 0xae, 0xbf, 0x34, 0x57, 0x88, 0x54,
1545 0xb7, 0x72, 0x15, 0x26, 0x20, 0xa7, 0x77, 0xf0,
1546 0xe0, 0x34, 0x08, 0x84, 0xa2, 0x94, 0xfb, 0x73 }
1549static void test_eap_sim_kdf_0_reauth(
void)
1559 memcpy(&keys, &rfc4186_vector0_reauth_in,
sizeof(keys));
1577 .identity_len =
sizeof(
"0555444333222111") - 1,
1579 .network = (
uint8_t const *)
"WLAN",
1580 .network_len =
sizeof(
"WLAN") - 1,
1582 .sqn = 205964772668538,
1586 .rand = { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e,
1587 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 },
1588 .autn = { 0xbb, 0x52, 0xe9, 0x1c, 0x74, 0x7a, 0xc3, 0xab,
1589 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 },
1590 .ik = { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb,
1591 0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a },
1592 .ck = { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94,
1593 0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f },
1594 .xres = { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 },
1602 .
ik_prime = { 0x00, 0x93, 0x96, 0x2d, 0x0d, 0xd8, 0x4a, 0xa5,
1603 0x68, 0x4b, 0x04, 0x5c, 0x9e, 0xdf, 0xfa, 0x04 },
1604 .ck_prime = { 0xcc, 0xfc, 0x23, 0x0c, 0xa7, 0x4f, 0xcc, 0x96,
1605 0xc0, 0xa5, 0xd6, 0x11, 0x64, 0xf5, 0xa7, 0x6c },
1607 .k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1608 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1609 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1610 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1611 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1612 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1614 .k_re = { 0xcf, 0x83, 0xaa, 0x8b, 0xc7, 0xe0, 0xac, 0xed,
1615 0x89, 0x2a, 0xcc, 0x98, 0xe7, 0x6a, 0x9b, 0x20,
1616 0x95, 0xb5, 0x58, 0xc7, 0x79, 0x5c, 0x70, 0x94,
1617 0x71, 0x5c, 0xb3, 0x39, 0x3a, 0xa7, 0xd1, 0x7a },
1618 .msk = { 0x67, 0xc4, 0x2d, 0x9a, 0xa5, 0x6c, 0x1b, 0x79,
1619 0xe2, 0x95, 0xe3, 0x45, 0x9f, 0xc3, 0xd1, 0x87,
1620 0xd4, 0x2b, 0xe0, 0xbf, 0x81, 0x8d, 0x30, 0x70,
1621 0xe3, 0x62, 0xc5, 0xe9, 0x67, 0xa4, 0xd5, 0x44,
1622 0xe8, 0xec, 0xfe, 0x19, 0x35, 0x8a, 0xb3, 0x03,
1623 0x9a, 0xff, 0x03, 0xb7, 0xc9, 0x30, 0x58, 0x8c,
1624 0x05, 0x5b, 0xab, 0xee, 0x58, 0xa0, 0x26, 0x50,
1625 0xb0, 0x67, 0xec, 0x4e, 0x93, 0x47, 0xc7, 0x5a },
1626 .emsk = { 0xf8, 0x61, 0x70, 0x3c, 0xd7, 0x75, 0x59, 0x0e,
1627 0x16, 0xc7, 0x67, 0x9e, 0xa3, 0x87, 0x4a, 0xda,
1628 0x86, 0x63, 0x11, 0xde, 0x29, 0x07, 0x64, 0xd7,
1629 0x60, 0xcf, 0x76, 0xdf, 0x64, 0x7e, 0xa0, 0x1c,
1630 0x31, 0x3f, 0x69, 0x92, 0x4b, 0xdd, 0x76, 0x50,
1631 0xca, 0x9b, 0xac, 0x14, 0x1e, 0xa0, 0x75, 0xc4,
1632 0xef, 0x9e, 0x80, 0x29, 0xc0, 0xe2, 0x90, 0xcd,
1633 0xba, 0xd5, 0x63, 0x8b, 0x63, 0xbc, 0x23, 0xfb }
1636static void test_eap_aka_kdf_1_umts(
void)
1646 memcpy(&keys, &rfc5448_vector0_in,
sizeof(keys));
1662static void test_eap_aka_kdf_1_umts_external_prime(
void)
1674 memcpy(&keys, &rfc5448_vector0_in,
sizeof(keys));
1675 memset(keys.umts.vector.ck, 0xff,
sizeof(keys.umts.vector.ck));
1676 memset(keys.umts.vector.ik, 0xff,
sizeof(keys.umts.vector.ik));
1693static void test_eap_aka_derive_ck_ik(
void)
1704 memcpy(&keys, &rfc5448_vector0_in,
sizeof(keys));
1716 .identity_len =
sizeof(
"5555444333222111") - 1,
1718 .network = (
uint8_t const *)
"WLAN",
1719 .network_len =
sizeof(
"WLAN") - 1,
1723 .nonce_s = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1724 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }
1726 .k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1727 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1728 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1729 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1730 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1731 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1733 .k_re = { 0xcf, 0x83, 0xaa, 0x8b, 0xc7, 0xe0, 0xac, 0xed,
1734 0x89, 0x2a, 0xcc, 0x98, 0xe7, 0x6a, 0x9b, 0x20,
1735 0x95, 0xb5, 0x58, 0xc7, 0x79, 0x5c, 0x70, 0x94,
1736 0x71, 0x5c, 0xb3, 0x39, 0x3a, 0xa7, 0xd1, 0x7a }
1743 .
k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1744 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1745 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1746 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1747 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1748 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1750 .msk = { 0x28, 0xf2, 0xb9, 0x3a, 0x8e, 0xdc, 0x4a, 0x01,
1751 0xb6, 0x9d, 0x37, 0x8b, 0xa6, 0x8a, 0x77, 0xbb,
1752 0x01, 0x6c, 0x0f, 0xeb, 0xb7, 0x60, 0xdb, 0x98,
1753 0x57, 0x99, 0x64, 0x99, 0x00, 0x00, 0x6f, 0x97,
1754 0xa1, 0x76, 0x5c, 0x65, 0xf5, 0xd5, 0xbf, 0xde,
1755 0xe7, 0x61, 0xba, 0x42, 0x92, 0xe4, 0x51, 0xd1,
1756 0xa0, 0xc5, 0x7e, 0x76, 0xeb, 0x91, 0x3e, 0xe9,
1757 0x95, 0xf5, 0xce, 0x6e, 0xb7, 0x98, 0x91, 0x38 },
1758 .emsk = { 0xb9, 0x05, 0xa2, 0xf4, 0x67, 0xe0, 0xeb, 0x9a,
1759 0xfb, 0xa4, 0x59, 0xa7, 0xd8, 0xa7, 0xc8, 0x77,
1760 0xd5, 0xfa, 0x2e, 0x5e, 0xd3, 0x77, 0xf8, 0xc5,
1761 0x2f, 0xa4, 0x86, 0xad, 0xf5, 0x15, 0x5e, 0xb7,
1762 0x96, 0xac, 0xa9, 0x3e, 0xa3, 0xa9, 0x95, 0xe8,
1763 0xa2, 0x34, 0x36, 0x54, 0x5a, 0xf1, 0x57, 0x22,
1764 0xaa, 0x94, 0xb9, 0xfb, 0xd9, 0x06, 0x0c, 0x50,
1765 0xa3, 0x56, 0xcc, 0xb4, 0xc7, 0x10, 0x0e, 0x66 }
1768static void test_eap_aka_kdf_1_reauth(
void)
1778 memcpy(&keys, &rfc5448_vector0_reauth_in,
sizeof(keys));
1795 {
"test_eap_sim_kdf_0_gsm", test_eap_sim_kdf_0_gsm },
1800 {
"test_eap_aka_kdf_0_umts", test_eap_aka_kdf_0_umts },
1805 {
"test_eap_sim_kdf_0_reauth", test_eap_sim_kdf_0_reauth },
1810 {
"test_eap_aka_kdf_1_umts", test_eap_aka_kdf_1_umts },
1811 {
"test_eap_aka_kdf_1_umts_external_prime", test_eap_aka_kdf_1_umts_external_prime },
1812 {
"test_eap_aka_derive_ck_ik", test_eap_aka_derive_ck_ik },
1813 {
"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)
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
bool ck_ik_prime_provided
CK'/IK' were supplied directly (e.g.
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 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.
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