31RCSID(
"$Id: c30075f1cc8ca9a0bdc6621e1a1953ad0a098b8b $")
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");
208 md_ctx = EVP_MD_CTX_create();
209 if (!md_ctx || (EVP_MD_CTX_copy_ex(md_ctx, checkcode->
md_ctx) != 1)) {
210 fr_tls_strerror_printf(
"Failed copying checkcode digest");
211 if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
217 if (EVP_DigestFinal_ex(md_ctx,
buff, NULL) != 1) {
218 fr_tls_strerror_printf(
"Failed finalising checkcode digest");
219 EVP_MD_CTX_destroy(md_ctx);
223 EVP_MD_CTX_destroy(md_ctx);
247 while ((p + 2) < end) {
253 if (p[0] == FR_MAC) {
255 if ((p +
len) > end) {
309 EVP_MD
const *md,
uint8_t const *key,
size_t const key_len,
310 uint8_t const *hmac_extra,
size_t const hmac_extra_len)
312 EVP_MD_CTX *md_ctx = NULL;
315 uint8_t digest[SHA256_DIGEST_LENGTH];
316 size_t digest_len =
sizeof(digest);
333 if (
unlikely(!key) || (key_len == 0)) {
339 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, (
int)key_len);
341 fr_tls_strerror_printf(
"Failed creating HMAC signing key");
343 if (pkey) EVP_PKEY_free(pkey);
344 if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
348 md_ctx = EVP_MD_CTX_create();
350 fr_tls_strerror_printf(
"Failed creating HMAC ctx");
354 if (EVP_DigestSignInit(md_ctx, NULL, md, NULL, pkey) != 1) {
355 fr_tls_strerror_printf(
"Failed initialising digest");
365 eap_hdr.
id = eap_packet->
id;
366 packet_len = htons((
sizeof(eap_hdr) + eap_packet->
type.
length) & UINT16_MAX);
367 memcpy(&eap_hdr.
length, &packet_len,
sizeof(packet_len));
371 if (EVP_DigestSignUpdate(md_ctx, &eap_hdr,
sizeof(eap_hdr)) != 1) {
372 fr_tls_strerror_printf(
"Failed digesting EAP data");
384 uint8_t zero[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
394 if (EVP_DigestSignUpdate(md_ctx, p, mac - p) != 1) {
395 fr_tls_strerror_printf(
"Failed digesting packet data (before MAC)");
406 if (EVP_DigestSignUpdate(md_ctx,
zero,
sizeof(
zero)) != 1) {
407 fr_tls_strerror_printf(
"Failed digesting zeroed MAC");
429 if (EVP_DigestSignUpdate(md_ctx, p, end - p) != 1) {
430 fr_tls_strerror_printf(
"Failed digesting packet data");
443 if (EVP_DigestSignUpdate(md_ctx, hmac_extra, hmac_extra_len) != 1) {
444 fr_tls_strerror_printf(
"Failed digesting HMAC extra data");
449 if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1) {
450 fr_tls_strerror_printf(
"Failed finalising digest");
459 memcpy(
out, digest, 16);
462 EVP_MD_CTX_destroy(md_ctx);
501 sizeof(keys->gsm.nonce_mt) +
502 keys->gsm.version_list_len +
503 sizeof(keys->gsm.version_select)) <=
sizeof(buf)))
return -1;
518 memcpy(p, keys->gsm.nonce_mt,
sizeof(keys->gsm.nonce_mt));
519 p +=
sizeof(keys->gsm.nonce_mt);
521 memcpy(p, keys->gsm.version_list, keys->gsm.version_list_len);
522 p += keys->gsm.version_list_len;
524 memcpy(p, keys->gsm.version_select,
sizeof(keys->gsm.version_select));
525 p +=
sizeof(keys->gsm.version_select);
527 FR_PROTO_HEX_DUMP(buf, p - buf,
"Identity || n*Kc || NONCE_MT || Version List || Selected Version");
549 memcpy(keys->
k_encr, p, 16);
558 memcpy(keys->
msk, p, 64);
562 memcpy(keys->
emsk, p, 64);
602 sizeof(keys->umts.vector.ik) +
603 sizeof(keys->umts.vector.ck)) <=
sizeof(buf)))
return -1;
609 memcpy(p, keys->umts.vector.ik,
sizeof(keys->umts.vector.ik));
610 p +=
sizeof(keys->umts.vector.ik);
612 memcpy(p, keys->umts.vector.ck,
sizeof(keys->umts.vector.ck));
613 p +=
sizeof(keys->umts.vector.ck);
632 memcpy(keys->
k_encr, p, 16);
639 memcpy(keys->
msk, p, 64);
642 memcpy(keys->
emsk, p, 64);
671 size_t digest_len =
sizeof(digest);
676 uint8_t k[
sizeof(keys->umts.vector.ik) +
sizeof(keys->umts.vector.ck)];
683 EVP_MD_CTX *md_ctx = NULL;
697 sizeof(l1)) <=
sizeof(s)))
return -1;
712 memcpy(p, &l0,
sizeof(l0));
719 memcpy(p, &l1,
sizeof(l1));
730 memcpy(p, keys->umts.vector.ck,
sizeof(keys->umts.vector.ck));
731 p +=
sizeof(keys->umts.vector.ck);
732 memcpy(p, keys->umts.vector.ik,
sizeof(keys->umts.vector.ik));
736 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, k,
sizeof(k));
738 fr_tls_strerror_printf(
"Failed creating HMAC signing key");
740 if (pkey) EVP_PKEY_free(pkey);
741 if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
745 md_ctx = EVP_MD_CTX_create();
747 fr_tls_strerror_printf(
"Failed creating HMAC ctx");
751 if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
752 fr_tls_strerror_printf(
"Failed initialising digest");
756 if (EVP_DigestSignUpdate(md_ctx, s, s_len) != 1)
goto error;
757 if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1)
goto error;
765 EVP_MD_CTX_destroy(md_ctx);
801 uint8_t digest[SHA256_DIGEST_LENGTH];
803 EVP_MD_CTX *md_ctx = NULL;
805 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, (
int)key_len);
807 fr_tls_strerror_printf(
"Failed creating HMAC signing key");
809 if (pkey) EVP_PKEY_free(pkey);
810 if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
814 md_ctx = EVP_MD_CTX_create();
816 fr_tls_strerror_printf(
"Failed creating HMAC ctx");
820 if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
821 fr_tls_strerror_printf(
"Failed initialising digest");
826 size_t digest_len =
sizeof(digest);
831 if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1)
goto error;
832 if ((p !=
out) && EVP_DigestSignUpdate(md_ctx, digest,
sizeof(digest)) != 1)
goto error;
833 if (EVP_DigestSignUpdate(md_ctx,
in, in_len) != 1)
goto error;
834 if (EVP_DigestSignUpdate(md_ctx, &c,
sizeof(c)) != 1)
goto error;
835 if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1)
goto error;
838 if (copy > digest_len) copy = digest_len;
840 memcpy(p, digest, copy);
844 EVP_MD_CTX_destroy(md_ctx);
872#define KDF_1_S_STATIC "EAP-AKA'"
919 memcpy(keys->
k_encr, p, 16);
929 memcpy(keys->
msk, p,
sizeof(keys->
msk));
930 p +=
sizeof(keys->
msk);
932 memcpy(keys->
emsk, p,
sizeof(keys->
emsk));
959 keys->reauth.counter = counter;
965 memcpy(keys->reauth.nonce_s, (
uint8_t *)&nonce_s,
sizeof(keys->reauth.nonce_s));
989 keys->reauth.counter = counter;
995 memcpy(keys->reauth.nonce_s, (
uint8_t *)&nonce_s,
sizeof(keys->reauth.nonce_s));
1028 unsigned int len = 0;
1036 if (keys->reauth.counter == 0) {
1048 if (need >
sizeof(buf)) {
1049 fr_strerror_printf(
"Identity too long. PRF input is %zu bytes, input buffer is %zu bytes",
1061 memcpy(keys->
k_encr, p, 16);
1088 *p++ = ((keys->reauth.counter & 0xff00) >> 8);
1089 *p++ = (keys->reauth.counter & 0x00ff);
1094 memcpy(p, keys->reauth.nonce_s,
sizeof(keys->reauth.nonce_s));
1095 p +=
sizeof(keys->reauth.nonce_s);
1108 md_ctx = EVP_MD_CTX_create();
1110 fr_tls_strerror_printf(
"Failed creating MD ctx");
1112 EVP_MD_CTX_destroy(md_ctx);
1116 if (EVP_DigestInit_ex(md_ctx, EVP_sha1(), NULL) != 1) {
1117 fr_tls_strerror_printf(
"Failed initialising digest");
1121 if (EVP_DigestUpdate(md_ctx, buf, p - buf) != 1) {
1122 fr_tls_strerror_printf(
"Failed digesting crypto data");
1126 if (EVP_DigestFinal_ex(md_ctx, keys->reauth.xkey_prime, &
len) != 1) {
1127 fr_tls_strerror_printf(
"Failed finalising digest");
1131 EVP_MD_CTX_destroy(md_ctx);
1133 FR_PROTO_HEX_DUMP(keys->reauth.xkey_prime,
sizeof(keys->reauth.xkey_prime),
"xkey'");
1144 memcpy(keys->
msk, p, 64);
1148 memcpy(keys->
emsk, p, 64);
1170#define KDF_1_S_REAUTH_STATIC "EAP-AKA' re-auth"
1217 fr_dbuff_in_bytes(&dbuff, ((keys->reauth.counter & 0xff00) >> 8), (keys->reauth.counter & 0x00ff));
1225 "\"EAP-AKA' re-auth\" || Identity || counter || NONCE_S");
1262 switch (keys->vector_type) {
1273 for (i = 0; i < keys->gsm.num_vectors; i++) {
1311 "counter : %u", keys->reauth.counter);
1320 "counter : %u", keys->reauth.counter);
1332 switch (keys->vector_type) {
1361#ifdef TESTING_SIM_CRYPTO
1365#include <freeradius-devel/util/test/acutest.h>
1372 .identity_len =
sizeof(
"1244070100000001@eapsim.foo") - 1,
1377 .rand = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1378 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
1379 .sres = { 0xd1, 0xd2, 0xd3, 0xd4 },
1380 .kc = { 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7 }
1383 .rand = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1384 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f },
1385 .sres = { 0xe1, 0xe2, 0xe3, 0xe4 },
1386 .kc = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7 }
1389 .rand = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
1390 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f },
1391 .sres = { 0xf1, 0xf2, 0xf3, 0xf4 },
1392 .kc = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }
1395 .nonce_mt = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1396 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
1397 .version_list = { 0x00, 0x01 },
1398 .version_list_len = 2,
1399 .version_select = { 0x00, 0x01 },
1406 .
k_encr = { 0x53, 0x6e, 0x5e, 0xbc, 0x44, 0x65, 0x58, 0x2a,
1407 0xa6, 0xa8, 0xec, 0x99, 0x86, 0xeb, 0xb6, 0x20 },
1408 .k_aut = { 0x25, 0xaf, 0x19, 0x42, 0xef, 0xcb, 0xf4, 0xbc,
1409 0x72, 0xb3, 0x94, 0x34, 0x21, 0xf2, 0xa9, 0x74 },
1411 .msk = { 0x39, 0xd4, 0x5a, 0xea, 0xf4, 0xe3, 0x06, 0x01,
1412 0x98, 0x3e, 0x97, 0x2b, 0x6c, 0xfd, 0x46, 0xd1,
1413 0xc3, 0x63, 0x77, 0x33, 0x65, 0x69, 0x0d, 0x09,
1414 0xcd, 0x44, 0x97, 0x6b, 0x52, 0x5f, 0x47, 0xd3,
1415 0xa6, 0x0a, 0x98, 0x5e, 0x95, 0x5c, 0x53, 0xb0,
1416 0x90, 0xb2, 0xe4, 0xb7, 0x37, 0x19, 0x19, 0x6a,
1417 0x40, 0x25, 0x42, 0x96, 0x8f, 0xd1, 0x4a, 0x88,
1418 0x8f, 0x46, 0xb9, 0xa7, 0x88, 0x6e, 0x44, 0x88 },
1419 .emsk = { 0x59, 0x49, 0xea, 0xb0, 0xff, 0xf6, 0x9d, 0x52,
1420 0x31, 0x5c, 0x6c, 0x63, 0x4f, 0xd1, 0x4a, 0x7f,
1421 0x0d, 0x52, 0x02, 0x3d, 0x56, 0xf7, 0x96, 0x98,
1422 0xfa, 0x65, 0x96, 0xab, 0xee, 0xd4, 0xf9, 0x3f,
1423 0xbb, 0x48, 0xeb, 0x53, 0x4d, 0x98, 0x54, 0x14,
1424 0xce, 0xed, 0x0d, 0x9a, 0x8e, 0xd3, 0x3c, 0x38,
1425 0x7c, 0x9d, 0xfd, 0xab, 0x92, 0xff, 0xbd, 0xf2,
1426 0x40, 0xfc, 0xec, 0xf6, 0x5a, 0x2c, 0x93, 0xb9 }
1429static void test_eap_sim_kdf_0_gsm(
void)
1439 memcpy(&keys, &rfc4186_vector0_in,
sizeof(keys));
1458 .identity_len =
sizeof(
"0555444333222111") - 1,
1460 .sqn = 205964772668538,
1464 .rand = { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e,
1465 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 },
1466 .autn = { 0xbb, 0x52, 0xe9, 0x1c, 0x74, 0x7a, 0xc3, 0xab,
1467 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 },
1468 .ik = { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb,
1469 0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a },
1470 .ck = { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94,
1471 0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f },
1472 .xres = { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 },
1480 .
k_encr = { 0x18, 0xe8, 0xb2, 0x0b, 0xcd, 0xa7, 0x04, 0x86,
1481 0xfd, 0x59, 0x59, 0x58, 0x6a, 0x9e, 0x7c, 0x3d },
1482 .k_aut = { 0x18, 0xc0, 0x44, 0x07, 0x0e, 0x5e, 0x64, 0x2a,
1483 0x26, 0x43, 0x87, 0x6f, 0xf7, 0xa8, 0x38, 0x12 },
1485 .msk = { 0x35, 0x2f, 0xfa, 0xef, 0x2d, 0xf1, 0x20, 0xcb,
1486 0x22, 0x41, 0x0b, 0x9c, 0x0b, 0x70, 0x62, 0x3c,
1487 0xb5, 0xa3, 0x5b, 0xc9, 0xfc, 0xd6, 0xbc, 0xa0,
1488 0xfc, 0x33, 0x7b, 0x48, 0xb1, 0x76, 0x30, 0x89,
1489 0x0a, 0x03, 0x37, 0x5c, 0xfd, 0x1e, 0x64, 0xcb,
1490 0xd6, 0xbf, 0x83, 0x04, 0x37, 0x4d, 0xd2, 0xe1,
1491 0x39, 0xd6, 0x4e, 0xd1, 0xa6, 0xd6, 0x18, 0xff,
1492 0xef, 0xb0, 0x8c, 0x26, 0xa6, 0xbb, 0x35, 0x85 },
1493 .emsk = { 0x9e, 0x06, 0x59, 0xae, 0x03, 0x97, 0x7d, 0xcb,
1494 0xb1, 0xd6, 0x4d, 0x24, 0x05, 0xe1, 0x10, 0x82,
1495 0xa9, 0x1a, 0xdb, 0x9a, 0xc7, 0xf7, 0xbd, 0x0b,
1496 0x74, 0xa6, 0x1e, 0xc0, 0xe9, 0x80, 0xb3, 0x6f,
1497 0xa0, 0xc3, 0x98, 0x8b, 0x6e, 0x11, 0xef, 0x12,
1498 0x52, 0x8e, 0x38, 0x04, 0xb3, 0x2d, 0xf1, 0xbc,
1499 0x52, 0xf6, 0x24, 0x9f, 0xa9, 0x6d, 0xc9, 0x4c,
1500 0x94, 0xa3, 0xd9, 0xb1, 0x48, 0xf4, 0xf9, 0x96 }
1503static void test_eap_aka_kdf_0_umts(
void)
1513 memcpy(&keys, &rfc4187_vector0_in,
sizeof(keys));
1530 .
identity = (
uint8_t const *)
"Y24fNSrz8BP274jOJaF17WfxI8YO7QX00pMXk9XMMVOw7broaNhTczuFq53aEpOkk3L0dm@eapsim.foo",
1531 .identity_len =
sizeof(
"Y24fNSrz8BP274jOJaF17WfxI8YO7QX00pMXk9XMMVOw7broaNhTczuFq53aEpOkk3L0dm@eapsim.foo") - 1,
1535 .nonce_s = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1536 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }
1538 .mk = { 0xe5, 0x76, 0xd5, 0xca, 0x33, 0x2e, 0x99, 0x30,
1539 0x01, 0x8b, 0xf1, 0xba, 0xee, 0x27, 0x63, 0xc7,
1540 0x95, 0xb3, 0xc7, 0x12 },
1544 .
k_encr = { 0x53, 0x6e, 0x5e, 0xbc, 0x44, 0x65, 0x58, 0x2a,
1545 0xa6, 0xa8, 0xec, 0x99, 0x86, 0xeb, 0xb6, 0x20 },
1546 .k_aut = { 0x25, 0xaf, 0x19, 0x42, 0xef, 0xcb, 0xf4, 0xbc,
1547 0x72, 0xb3, 0x94, 0x34, 0x21, 0xf2, 0xa9, 0x74 },
1549 .msk = { 0x62, 0x63, 0xf6, 0x14, 0x97, 0x38, 0x95, 0xe1,
1550 0x33, 0x5f, 0x7e, 0x30, 0xcf, 0xf0, 0x28, 0xee,
1551 0x21, 0x76, 0xf5, 0x19, 0x00, 0x2c, 0x9a, 0xbe,
1552 0x73, 0x2f, 0xe0, 0xef, 0x00, 0xcf, 0x16, 0x7c,
1553 0x75, 0x6d, 0x9e, 0x4c, 0xed, 0x6d, 0x5e, 0xd6,
1554 0x40, 0xeb, 0x3f, 0xe3, 0x85, 0x65, 0xca, 0x07,
1555 0x6e, 0x7f, 0xb8, 0xa8, 0x17, 0xcf, 0xe8, 0xd9,
1556 0xad, 0xbc, 0xe4, 0x41, 0xd4, 0x7c, 0x4f, 0x5e },
1557 .emsk = { 0x3d, 0x8f, 0xf7, 0x86, 0x3a, 0x63, 0x0b, 0x2b,
1558 0x06, 0xe2, 0xcf, 0x20, 0x96, 0x84, 0xc1, 0x3f,
1559 0x6b, 0x82, 0xf9, 0x92, 0xf2, 0xb0, 0x6f, 0x1b,
1560 0x54, 0xbf, 0x51, 0xef, 0x23, 0x7f, 0x2a, 0x40,
1561 0x1e, 0xf5, 0xe0, 0xd7, 0xe0, 0x98, 0xa3, 0x4c,
1562 0x53, 0x3e, 0xae, 0xbf, 0x34, 0x57, 0x88, 0x54,
1563 0xb7, 0x72, 0x15, 0x26, 0x20, 0xa7, 0x77, 0xf0,
1564 0xe0, 0x34, 0x08, 0x84, 0xa2, 0x94, 0xfb, 0x73 }
1567static void test_eap_sim_kdf_0_reauth(
void)
1577 memcpy(&keys, &rfc4186_vector0_reauth_in,
sizeof(keys));
1595 .identity_len =
sizeof(
"0555444333222111") - 1,
1597 .network = (
uint8_t const *)
"WLAN",
1598 .network_len =
sizeof(
"WLAN") - 1,
1600 .sqn = 205964772668538,
1604 .rand = { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e,
1605 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 },
1606 .autn = { 0xbb, 0x52, 0xe9, 0x1c, 0x74, 0x7a, 0xc3, 0xab,
1607 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 },
1608 .ik = { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb,
1609 0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a },
1610 .ck = { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94,
1611 0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f },
1612 .xres = { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 },
1620 .
ik_prime = { 0x00, 0x93, 0x96, 0x2d, 0x0d, 0xd8, 0x4a, 0xa5,
1621 0x68, 0x4b, 0x04, 0x5c, 0x9e, 0xdf, 0xfa, 0x04 },
1622 .ck_prime = { 0xcc, 0xfc, 0x23, 0x0c, 0xa7, 0x4f, 0xcc, 0x96,
1623 0xc0, 0xa5, 0xd6, 0x11, 0x64, 0xf5, 0xa7, 0x6c },
1625 .k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1626 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1627 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1628 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1629 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1630 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1632 .k_re = { 0xcf, 0x83, 0xaa, 0x8b, 0xc7, 0xe0, 0xac, 0xed,
1633 0x89, 0x2a, 0xcc, 0x98, 0xe7, 0x6a, 0x9b, 0x20,
1634 0x95, 0xb5, 0x58, 0xc7, 0x79, 0x5c, 0x70, 0x94,
1635 0x71, 0x5c, 0xb3, 0x39, 0x3a, 0xa7, 0xd1, 0x7a },
1636 .msk = { 0x67, 0xc4, 0x2d, 0x9a, 0xa5, 0x6c, 0x1b, 0x79,
1637 0xe2, 0x95, 0xe3, 0x45, 0x9f, 0xc3, 0xd1, 0x87,
1638 0xd4, 0x2b, 0xe0, 0xbf, 0x81, 0x8d, 0x30, 0x70,
1639 0xe3, 0x62, 0xc5, 0xe9, 0x67, 0xa4, 0xd5, 0x44,
1640 0xe8, 0xec, 0xfe, 0x19, 0x35, 0x8a, 0xb3, 0x03,
1641 0x9a, 0xff, 0x03, 0xb7, 0xc9, 0x30, 0x58, 0x8c,
1642 0x05, 0x5b, 0xab, 0xee, 0x58, 0xa0, 0x26, 0x50,
1643 0xb0, 0x67, 0xec, 0x4e, 0x93, 0x47, 0xc7, 0x5a },
1644 .emsk = { 0xf8, 0x61, 0x70, 0x3c, 0xd7, 0x75, 0x59, 0x0e,
1645 0x16, 0xc7, 0x67, 0x9e, 0xa3, 0x87, 0x4a, 0xda,
1646 0x86, 0x63, 0x11, 0xde, 0x29, 0x07, 0x64, 0xd7,
1647 0x60, 0xcf, 0x76, 0xdf, 0x64, 0x7e, 0xa0, 0x1c,
1648 0x31, 0x3f, 0x69, 0x92, 0x4b, 0xdd, 0x76, 0x50,
1649 0xca, 0x9b, 0xac, 0x14, 0x1e, 0xa0, 0x75, 0xc4,
1650 0xef, 0x9e, 0x80, 0x29, 0xc0, 0xe2, 0x90, 0xcd,
1651 0xba, 0xd5, 0x63, 0x8b, 0x63, 0xbc, 0x23, 0xfb }
1654static void test_eap_aka_kdf_1_umts(
void)
1664 memcpy(&keys, &rfc5448_vector0_in,
sizeof(keys));
1680static void test_eap_aka_kdf_1_umts_external_prime(
void)
1692 memcpy(&keys, &rfc5448_vector0_in,
sizeof(keys));
1693 memset(keys.umts.vector.ck, 0xff,
sizeof(keys.umts.vector.ck));
1694 memset(keys.umts.vector.ik, 0xff,
sizeof(keys.umts.vector.ik));
1711static void test_eap_aka_derive_ck_ik(
void)
1722 memcpy(&keys, &rfc5448_vector0_in,
sizeof(keys));
1734 .identity_len =
sizeof(
"5555444333222111") - 1,
1736 .network = (
uint8_t const *)
"WLAN",
1737 .network_len =
sizeof(
"WLAN") - 1,
1741 .nonce_s = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1742 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }
1744 .k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1745 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1746 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1747 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1748 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1749 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1751 .k_re = { 0xcf, 0x83, 0xaa, 0x8b, 0xc7, 0xe0, 0xac, 0xed,
1752 0x89, 0x2a, 0xcc, 0x98, 0xe7, 0x6a, 0x9b, 0x20,
1753 0x95, 0xb5, 0x58, 0xc7, 0x79, 0x5c, 0x70, 0x94,
1754 0x71, 0x5c, 0xb3, 0x39, 0x3a, 0xa7, 0xd1, 0x7a }
1761 .
k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1762 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1763 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1764 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1765 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1766 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1768 .msk = { 0x28, 0xf2, 0xb9, 0x3a, 0x8e, 0xdc, 0x4a, 0x01,
1769 0xb6, 0x9d, 0x37, 0x8b, 0xa6, 0x8a, 0x77, 0xbb,
1770 0x01, 0x6c, 0x0f, 0xeb, 0xb7, 0x60, 0xdb, 0x98,
1771 0x57, 0x99, 0x64, 0x99, 0x00, 0x00, 0x6f, 0x97,
1772 0xa1, 0x76, 0x5c, 0x65, 0xf5, 0xd5, 0xbf, 0xde,
1773 0xe7, 0x61, 0xba, 0x42, 0x92, 0xe4, 0x51, 0xd1,
1774 0xa0, 0xc5, 0x7e, 0x76, 0xeb, 0x91, 0x3e, 0xe9,
1775 0x95, 0xf5, 0xce, 0x6e, 0xb7, 0x98, 0x91, 0x38 },
1776 .emsk = { 0xb9, 0x05, 0xa2, 0xf4, 0x67, 0xe0, 0xeb, 0x9a,
1777 0xfb, 0xa4, 0x59, 0xa7, 0xd8, 0xa7, 0xc8, 0x77,
1778 0xd5, 0xfa, 0x2e, 0x5e, 0xd3, 0x77, 0xf8, 0xc5,
1779 0x2f, 0xa4, 0x86, 0xad, 0xf5, 0x15, 0x5e, 0xb7,
1780 0x96, 0xac, 0xa9, 0x3e, 0xa3, 0xa9, 0x95, 0xe8,
1781 0xa2, 0x34, 0x36, 0x54, 0x5a, 0xf1, 0x57, 0x22,
1782 0xaa, 0x94, 0xb9, 0xfb, 0xd9, 0x06, 0x0c, 0x50,
1783 0xa3, 0x56, 0xcc, 0xb4, 0xc7, 0x10, 0x0e, 0x66 }
1786static void test_eap_aka_kdf_1_reauth(
void)
1796 memcpy(&keys, &rfc5448_vector0_reauth_in,
sizeof(keys));
1813 {
"test_eap_sim_kdf_0_gsm", test_eap_sim_kdf_0_gsm },
1818 {
"test_eap_aka_kdf_0_umts", test_eap_aka_kdf_0_umts },
1823 {
"test_eap_sim_kdf_0_reauth", test_eap_sim_kdf_0_reauth },
1828 {
"test_eap_aka_kdf_1_umts", test_eap_aka_kdf_1_umts },
1829 {
"test_eap_aka_kdf_1_umts_external_prime", test_eap_aka_kdf_1_umts_external_prime },
1830 {
"test_eap_aka_derive_ck_ik", test_eap_aka_derive_ck_ik },
1831 {
"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 request[4]
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
@ 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
#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.
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 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