31 RCSID(
"$Id: 946594c6041f5f3b5eba06aff53110e09ce06074 $")
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) {
231 if (p[0] == FR_MAC) {
233 if ((p + len) > end) {
234 fr_strerror_printf(
"Malformed AT_MAC: Length (%zu) exceeds buffer (%zu)", len, end - p);
286 EVP_MD
const *md,
uint8_t const *key,
size_t const key_len,
287 uint8_t const *hmac_extra,
size_t const hmac_extra_len)
289 EVP_MD_CTX *md_ctx = NULL;
292 uint8_t digest[SHA256_DIGEST_LENGTH];
293 size_t digest_len =
sizeof(digest);
310 if (
unlikely(!key) || (key_len == 0)) {
316 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, key_len);
318 fr_tls_strerror_printf(
"Failed creating HMAC signing key");
320 if (pkey) EVP_PKEY_free(pkey);
321 if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
325 md_ctx = EVP_MD_CTX_create();
327 fr_tls_strerror_printf(
"Failed creating HMAC ctx");
331 if (EVP_DigestSignInit(md_ctx, NULL, md, NULL, pkey) != 1) {
332 fr_tls_strerror_printf(
"Failed initialising digest");
342 eap_hdr.
id = eap_packet->
id;
343 packet_len = htons((
sizeof(eap_hdr) + eap_packet->
type.
length) & UINT16_MAX);
344 memcpy(&eap_hdr.
length, &packet_len,
sizeof(packet_len));
348 if (EVP_DigestSignUpdate(md_ctx, &eap_hdr,
sizeof(eap_hdr)) != 1) {
349 fr_tls_strerror_printf(
"Failed digesting EAP data");
361 uint8_t zero[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
371 if (EVP_DigestSignUpdate(md_ctx, p, mac - p) != 1) {
372 fr_tls_strerror_printf(
"Failed digesting packet data (before MAC)");
383 if (EVP_DigestSignUpdate(md_ctx,
zero,
sizeof(
zero)) != 1) {
384 fr_tls_strerror_printf(
"Failed digesting zeroed MAC");
406 if (EVP_DigestSignUpdate(md_ctx, p, end - p) != 1) {
407 fr_tls_strerror_printf(
"Failed digesting packet data");
420 if (EVP_DigestSignUpdate(md_ctx, hmac_extra, hmac_extra_len) != 1) {
421 fr_tls_strerror_printf(
"Failed digesting HMAC extra data");
426 if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1) {
427 fr_tls_strerror_printf(
"Failed finalising digest");
436 memcpy(
out, digest, 16);
439 EVP_MD_CTX_destroy(md_ctx);
478 sizeof(keys->gsm.nonce_mt) +
479 keys->gsm.version_list_len +
480 sizeof(keys->gsm.version_select)) <=
sizeof(buf)))
return -1;
495 memcpy(p, keys->gsm.nonce_mt,
sizeof(keys->gsm.nonce_mt));
496 p +=
sizeof(keys->gsm.nonce_mt);
498 memcpy(p, keys->gsm.version_list, keys->gsm.version_list_len);
499 p += keys->gsm.version_list_len;
501 memcpy(p, keys->gsm.version_select,
sizeof(keys->gsm.version_select));
502 p +=
sizeof(keys->gsm.version_select);
504 FR_PROTO_HEX_DUMP(buf, p - buf,
"Identity || n*Kc || NONCE_MT || Version List || Selected Version");
526 memcpy(keys->
k_encr, p, 16);
535 memcpy(keys->
msk, p, 64);
539 memcpy(keys->
emsk, p, 64);
579 sizeof(keys->umts.vector.ik) +
580 sizeof(keys->umts.vector.ck)) <=
sizeof(buf)))
return -1;
586 memcpy(p, keys->umts.vector.ik,
sizeof(keys->umts.vector.ik));
587 p +=
sizeof(keys->umts.vector.ik);
589 memcpy(p, keys->umts.vector.ck,
sizeof(keys->umts.vector.ck));
590 p +=
sizeof(keys->umts.vector.ck);
609 memcpy(keys->
k_encr, p, 16);
616 memcpy(keys->
msk, p, 64);
619 memcpy(keys->
emsk, p, 64);
648 size_t digest_len =
sizeof(digest);
653 uint8_t k[
sizeof(keys->umts.vector.ik) +
sizeof(keys->umts.vector.ck)];
660 EVP_MD_CTX *md_ctx = NULL;
674 sizeof(l1)) <=
sizeof(s)))
return -1;
689 memcpy(p, &l0,
sizeof(l0));
696 memcpy(p, &l1,
sizeof(l1));
707 memcpy(p, keys->umts.vector.ck,
sizeof(keys->umts.vector.ck));
708 p +=
sizeof(keys->umts.vector.ck);
709 memcpy(p, keys->umts.vector.ik,
sizeof(keys->umts.vector.ik));
713 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, k,
sizeof(k));
715 fr_tls_strerror_printf(
"Failed creating HMAC signing key");
717 if (pkey) EVP_PKEY_free(pkey);
718 if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
722 md_ctx = EVP_MD_CTX_create();
724 fr_tls_strerror_printf(
"Failed creating HMAC ctx");
728 if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
729 fr_tls_strerror_printf(
"Failed initialising digest");
733 if (EVP_DigestSignUpdate(md_ctx, s, s_len) != 1)
goto error;
734 if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1)
goto error;
742 EVP_MD_CTX_destroy(md_ctx);
778 uint8_t digest[SHA256_DIGEST_LENGTH];
780 EVP_MD_CTX *md_ctx = NULL;
782 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, key_len);
784 fr_tls_strerror_printf(
"Failed creating HMAC signing key");
786 if (pkey) EVP_PKEY_free(pkey);
787 if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
791 md_ctx = EVP_MD_CTX_create();
793 fr_tls_strerror_printf(
"Failed creating HMAC ctx");
797 if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
798 fr_tls_strerror_printf(
"Failed initialising digest");
803 size_t digest_len =
sizeof(digest);
808 if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1)
goto error;
809 if ((p !=
out) && EVP_DigestSignUpdate(md_ctx, digest,
sizeof(digest)) != 1)
goto error;
810 if (EVP_DigestSignUpdate(md_ctx,
in, in_len) != 1)
goto error;
811 if (EVP_DigestSignUpdate(md_ctx, &c,
sizeof(c)) != 1)
goto error;
812 if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1)
goto error;
815 if (copy > digest_len) copy = digest_len;
817 memcpy(p, digest, copy);
821 EVP_MD_CTX_destroy(md_ctx);
849 #define KDF_1_S_STATIC "EAP-AKA'"
890 memcpy(keys->
k_encr, p, 16);
900 memcpy(keys->
msk, p,
sizeof(keys->
msk));
901 p +=
sizeof(keys->
msk);
903 memcpy(keys->
emsk, p,
sizeof(keys->
emsk));
930 keys->reauth.counter = counter;
936 memcpy(keys->reauth.nonce_s, (
uint8_t *)&nonce_s,
sizeof(keys->reauth.nonce_s));
960 keys->reauth.counter = counter;
966 memcpy(keys->reauth.nonce_s, (
uint8_t *)&nonce_s,
sizeof(keys->reauth.nonce_s));
999 unsigned int len = 0;
1007 if (keys->reauth.counter == 0) {
1019 if (need >
sizeof(buf)) {
1020 fr_strerror_printf(
"Identity too long. PRF input is %zu bytes, input buffer is %zu bytes",
1032 memcpy(keys->
k_encr, p, 16);
1059 *p++ = ((keys->reauth.counter & 0xff00) >> 8);
1060 *p++ = (keys->reauth.counter & 0x00ff);
1065 memcpy(p, keys->reauth.nonce_s,
sizeof(keys->reauth.nonce_s));
1066 p +=
sizeof(keys->reauth.nonce_s);
1079 md_ctx = EVP_MD_CTX_create();
1081 fr_tls_strerror_printf(
"Failed creating MD ctx");
1083 EVP_MD_CTX_destroy(md_ctx);
1087 if (EVP_DigestInit_ex(md_ctx, EVP_sha1(), NULL) != 1) {
1088 fr_tls_strerror_printf(
"Failed initialising digest");
1092 if (EVP_DigestUpdate(md_ctx, buf, p - buf) != 1) {
1093 fr_tls_strerror_printf(
"Failed digesting crypto data");
1097 if (EVP_DigestFinal_ex(md_ctx, keys->reauth.xkey_prime, &len) != 1) {
1098 fr_tls_strerror_printf(
"Failed finalising digest");
1102 EVP_MD_CTX_destroy(md_ctx);
1104 FR_PROTO_HEX_DUMP(keys->reauth.xkey_prime,
sizeof(keys->reauth.xkey_prime),
"xkey'");
1115 memcpy(keys->
msk, p, 64);
1119 memcpy(keys->
emsk, p, 64);
1141 #define KDF_1_S_REAUTH_STATIC "EAP-AKA' re-auth"
1188 fr_dbuff_in_bytes(&dbuff, ((keys->reauth.counter & 0xff00) >> 8), (keys->reauth.counter & 0x00ff));
1196 "\"EAP-AKA' re-auth\" || Identity || counter || NONCE_S");
1233 switch (keys->vector_type) {
1244 for (i = 0; i < keys->gsm.num_vectors; i++) {
1282 "counter : %u", keys->reauth.counter);
1291 "counter : %u", keys->reauth.counter);
1303 switch (keys->vector_type) {
1332 #ifdef TESTING_SIM_CRYPTO
1337 #include <stdbool.h>
1338 #include <freeradius-devel/util/acutest.h>
1345 .identity_len =
sizeof(
"1244070100000001@eapsim.foo") - 1,
1350 .rand = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1351 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
1352 .sres = { 0xd1, 0xd2, 0xd3, 0xd4 },
1353 .kc = { 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7 }
1356 .rand = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1357 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f },
1358 .sres = { 0xe1, 0xe2, 0xe3, 0xe4 },
1359 .kc = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7 }
1362 .rand = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
1363 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f },
1364 .sres = { 0xf1, 0xf2, 0xf3, 0xf4 },
1365 .kc = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }
1368 .nonce_mt = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1369 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
1370 .version_list = { 0x00, 0x01 },
1371 .version_list_len = 2,
1372 .version_select = { 0x00, 0x01 },
1379 .
k_encr = { 0x53, 0x6e, 0x5e, 0xbc, 0x44, 0x65, 0x58, 0x2a,
1380 0xa6, 0xa8, 0xec, 0x99, 0x86, 0xeb, 0xb6, 0x20 },
1381 .k_aut = { 0x25, 0xaf, 0x19, 0x42, 0xef, 0xcb, 0xf4, 0xbc,
1382 0x72, 0xb3, 0x94, 0x34, 0x21, 0xf2, 0xa9, 0x74 },
1384 .msk = { 0x39, 0xd4, 0x5a, 0xea, 0xf4, 0xe3, 0x06, 0x01,
1385 0x98, 0x3e, 0x97, 0x2b, 0x6c, 0xfd, 0x46, 0xd1,
1386 0xc3, 0x63, 0x77, 0x33, 0x65, 0x69, 0x0d, 0x09,
1387 0xcd, 0x44, 0x97, 0x6b, 0x52, 0x5f, 0x47, 0xd3,
1388 0xa6, 0x0a, 0x98, 0x5e, 0x95, 0x5c, 0x53, 0xb0,
1389 0x90, 0xb2, 0xe4, 0xb7, 0x37, 0x19, 0x19, 0x6a,
1390 0x40, 0x25, 0x42, 0x96, 0x8f, 0xd1, 0x4a, 0x88,
1391 0x8f, 0x46, 0xb9, 0xa7, 0x88, 0x6e, 0x44, 0x88 },
1392 .emsk = { 0x59, 0x49, 0xea, 0xb0, 0xff, 0xf6, 0x9d, 0x52,
1393 0x31, 0x5c, 0x6c, 0x63, 0x4f, 0xd1, 0x4a, 0x7f,
1394 0x0d, 0x52, 0x02, 0x3d, 0x56, 0xf7, 0x96, 0x98,
1395 0xfa, 0x65, 0x96, 0xab, 0xee, 0xd4, 0xf9, 0x3f,
1396 0xbb, 0x48, 0xeb, 0x53, 0x4d, 0x98, 0x54, 0x14,
1397 0xce, 0xed, 0x0d, 0x9a, 0x8e, 0xd3, 0x3c, 0x38,
1398 0x7c, 0x9d, 0xfd, 0xab, 0x92, 0xff, 0xbd, 0xf2,
1399 0x40, 0xfc, 0xec, 0xf6, 0x5a, 0x2c, 0x93, 0xb9 }
1402 static void test_eap_sim_kdf_0_gsm(
void)
1412 memcpy(&keys, &rfc4186_vector0_in,
sizeof(keys));
1431 .identity_len =
sizeof(
"0555444333222111") - 1,
1433 .sqn = 205964772668538,
1437 .rand = { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e,
1438 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 },
1439 .autn = { 0xbb, 0x52, 0xe9, 0x1c, 0x74, 0x7a, 0xc3, 0xab,
1440 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 },
1441 .ik = { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb,
1442 0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a },
1443 .ck = { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94,
1444 0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f },
1445 .xres = { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 },
1453 .
k_encr = { 0x18, 0xe8, 0xb2, 0x0b, 0xcd, 0xa7, 0x04, 0x86,
1454 0xfd, 0x59, 0x59, 0x58, 0x6a, 0x9e, 0x7c, 0x3d },
1455 .k_aut = { 0x18, 0xc0, 0x44, 0x07, 0x0e, 0x5e, 0x64, 0x2a,
1456 0x26, 0x43, 0x87, 0x6f, 0xf7, 0xa8, 0x38, 0x12 },
1458 .msk = { 0x35, 0x2f, 0xfa, 0xef, 0x2d, 0xf1, 0x20, 0xcb,
1459 0x22, 0x41, 0x0b, 0x9c, 0x0b, 0x70, 0x62, 0x3c,
1460 0xb5, 0xa3, 0x5b, 0xc9, 0xfc, 0xd6, 0xbc, 0xa0,
1461 0xfc, 0x33, 0x7b, 0x48, 0xb1, 0x76, 0x30, 0x89,
1462 0x0a, 0x03, 0x37, 0x5c, 0xfd, 0x1e, 0x64, 0xcb,
1463 0xd6, 0xbf, 0x83, 0x04, 0x37, 0x4d, 0xd2, 0xe1,
1464 0x39, 0xd6, 0x4e, 0xd1, 0xa6, 0xd6, 0x18, 0xff,
1465 0xef, 0xb0, 0x8c, 0x26, 0xa6, 0xbb, 0x35, 0x85 },
1466 .emsk = { 0x9e, 0x06, 0x59, 0xae, 0x03, 0x97, 0x7d, 0xcb,
1467 0xb1, 0xd6, 0x4d, 0x24, 0x05, 0xe1, 0x10, 0x82,
1468 0xa9, 0x1a, 0xdb, 0x9a, 0xc7, 0xf7, 0xbd, 0x0b,
1469 0x74, 0xa6, 0x1e, 0xc0, 0xe9, 0x80, 0xb3, 0x6f,
1470 0xa0, 0xc3, 0x98, 0x8b, 0x6e, 0x11, 0xef, 0x12,
1471 0x52, 0x8e, 0x38, 0x04, 0xb3, 0x2d, 0xf1, 0xbc,
1472 0x52, 0xf6, 0x24, 0x9f, 0xa9, 0x6d, 0xc9, 0x4c,
1473 0x94, 0xa3, 0xd9, 0xb1, 0x48, 0xf4, 0xf9, 0x96 }
1476 static void test_eap_aka_kdf_0_umts(
void)
1486 memcpy(&keys, &rfc4187_vector0_in,
sizeof(keys));
1503 .
identity = (
uint8_t const *)
"Y24fNSrz8BP274jOJaF17WfxI8YO7QX00pMXk9XMMVOw7broaNhTczuFq53aEpOkk3L0dm@eapsim.foo",
1504 .identity_len =
sizeof(
"Y24fNSrz8BP274jOJaF17WfxI8YO7QX00pMXk9XMMVOw7broaNhTczuFq53aEpOkk3L0dm@eapsim.foo") - 1,
1508 .nonce_s = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1509 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }
1511 .mk = { 0xe5, 0x76, 0xd5, 0xca, 0x33, 0x2e, 0x99, 0x30,
1512 0x01, 0x8b, 0xf1, 0xba, 0xee, 0x27, 0x63, 0xc7,
1513 0x95, 0xb3, 0xc7, 0x12 },
1517 .
k_encr = { 0x53, 0x6e, 0x5e, 0xbc, 0x44, 0x65, 0x58, 0x2a,
1518 0xa6, 0xa8, 0xec, 0x99, 0x86, 0xeb, 0xb6, 0x20 },
1519 .k_aut = { 0x25, 0xaf, 0x19, 0x42, 0xef, 0xcb, 0xf4, 0xbc,
1520 0x72, 0xb3, 0x94, 0x34, 0x21, 0xf2, 0xa9, 0x74 },
1522 .msk = { 0x62, 0x63, 0xf6, 0x14, 0x97, 0x38, 0x95, 0xe1,
1523 0x33, 0x5f, 0x7e, 0x30, 0xcf, 0xf0, 0x28, 0xee,
1524 0x21, 0x76, 0xf5, 0x19, 0x00, 0x2c, 0x9a, 0xbe,
1525 0x73, 0x2f, 0xe0, 0xef, 0x00, 0xcf, 0x16, 0x7c,
1526 0x75, 0x6d, 0x9e, 0x4c, 0xed, 0x6d, 0x5e, 0xd6,
1527 0x40, 0xeb, 0x3f, 0xe3, 0x85, 0x65, 0xca, 0x07,
1528 0x6e, 0x7f, 0xb8, 0xa8, 0x17, 0xcf, 0xe8, 0xd9,
1529 0xad, 0xbc, 0xe4, 0x41, 0xd4, 0x7c, 0x4f, 0x5e },
1530 .emsk = { 0x3d, 0x8f, 0xf7, 0x86, 0x3a, 0x63, 0x0b, 0x2b,
1531 0x06, 0xe2, 0xcf, 0x20, 0x96, 0x84, 0xc1, 0x3f,
1532 0x6b, 0x82, 0xf9, 0x92, 0xf2, 0xb0, 0x6f, 0x1b,
1533 0x54, 0xbf, 0x51, 0xef, 0x23, 0x7f, 0x2a, 0x40,
1534 0x1e, 0xf5, 0xe0, 0xd7, 0xe0, 0x98, 0xa3, 0x4c,
1535 0x53, 0x3e, 0xae, 0xbf, 0x34, 0x57, 0x88, 0x54,
1536 0xb7, 0x72, 0x15, 0x26, 0x20, 0xa7, 0x77, 0xf0,
1537 0xe0, 0x34, 0x08, 0x84, 0xa2, 0x94, 0xfb, 0x73 }
1540 static void test_eap_sim_kdf_0_reauth(
void)
1550 memcpy(&keys, &rfc4186_vector0_reauth_in,
sizeof(keys));
1568 .identity_len =
sizeof(
"0555444333222111") - 1,
1570 .network = (
uint8_t const *)
"WLAN",
1571 .network_len =
sizeof(
"WLAN") - 1,
1573 .sqn = 205964772668538,
1577 .rand = { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e,
1578 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 },
1579 .autn = { 0xbb, 0x52, 0xe9, 0x1c, 0x74, 0x7a, 0xc3, 0xab,
1580 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 },
1581 .ik = { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb,
1582 0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a },
1583 .ck = { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94,
1584 0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f },
1585 .xres = { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 },
1593 .
ik_prime = { 0x00, 0x93, 0x96, 0x2d, 0x0d, 0xd8, 0x4a, 0xa5,
1594 0x68, 0x4b, 0x04, 0x5c, 0x9e, 0xdf, 0xfa, 0x04 },
1595 .ck_prime = { 0xcc, 0xfc, 0x23, 0x0c, 0xa7, 0x4f, 0xcc, 0x96,
1596 0xc0, 0xa5, 0xd6, 0x11, 0x64, 0xf5, 0xa7, 0x6c },
1598 .k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1599 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1600 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1601 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1602 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1603 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1605 .k_re = { 0xcf, 0x83, 0xaa, 0x8b, 0xc7, 0xe0, 0xac, 0xed,
1606 0x89, 0x2a, 0xcc, 0x98, 0xe7, 0x6a, 0x9b, 0x20,
1607 0x95, 0xb5, 0x58, 0xc7, 0x79, 0x5c, 0x70, 0x94,
1608 0x71, 0x5c, 0xb3, 0x39, 0x3a, 0xa7, 0xd1, 0x7a },
1609 .msk = { 0x67, 0xc4, 0x2d, 0x9a, 0xa5, 0x6c, 0x1b, 0x79,
1610 0xe2, 0x95, 0xe3, 0x45, 0x9f, 0xc3, 0xd1, 0x87,
1611 0xd4, 0x2b, 0xe0, 0xbf, 0x81, 0x8d, 0x30, 0x70,
1612 0xe3, 0x62, 0xc5, 0xe9, 0x67, 0xa4, 0xd5, 0x44,
1613 0xe8, 0xec, 0xfe, 0x19, 0x35, 0x8a, 0xb3, 0x03,
1614 0x9a, 0xff, 0x03, 0xb7, 0xc9, 0x30, 0x58, 0x8c,
1615 0x05, 0x5b, 0xab, 0xee, 0x58, 0xa0, 0x26, 0x50,
1616 0xb0, 0x67, 0xec, 0x4e, 0x93, 0x47, 0xc7, 0x5a },
1617 .emsk = { 0xf8, 0x61, 0x70, 0x3c, 0xd7, 0x75, 0x59, 0x0e,
1618 0x16, 0xc7, 0x67, 0x9e, 0xa3, 0x87, 0x4a, 0xda,
1619 0x86, 0x63, 0x11, 0xde, 0x29, 0x07, 0x64, 0xd7,
1620 0x60, 0xcf, 0x76, 0xdf, 0x64, 0x7e, 0xa0, 0x1c,
1621 0x31, 0x3f, 0x69, 0x92, 0x4b, 0xdd, 0x76, 0x50,
1622 0xca, 0x9b, 0xac, 0x14, 0x1e, 0xa0, 0x75, 0xc4,
1623 0xef, 0x9e, 0x80, 0x29, 0xc0, 0xe2, 0x90, 0xcd,
1624 0xba, 0xd5, 0x63, 0x8b, 0x63, 0xbc, 0x23, 0xfb }
1627 static void test_eap_aka_kdf_1_umts(
void)
1637 memcpy(&keys, &rfc5448_vector0_in,
sizeof(keys));
1653 static void test_eap_aka_derive_ck_ik(
void)
1664 memcpy(&keys, &rfc5448_vector0_in,
sizeof(keys));
1676 .identity_len =
sizeof(
"5555444333222111") - 1,
1678 .network = (
uint8_t const *)
"WLAN",
1679 .network_len =
sizeof(
"WLAN") - 1,
1683 .nonce_s = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1684 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }
1686 .k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1687 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1688 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1689 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1690 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1691 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1693 .k_re = { 0xcf, 0x83, 0xaa, 0x8b, 0xc7, 0xe0, 0xac, 0xed,
1694 0x89, 0x2a, 0xcc, 0x98, 0xe7, 0x6a, 0x9b, 0x20,
1695 0x95, 0xb5, 0x58, 0xc7, 0x79, 0x5c, 0x70, 0x94,
1696 0x71, 0x5c, 0xb3, 0x39, 0x3a, 0xa7, 0xd1, 0x7a }
1703 .
k_encr = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
1704 0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
1705 .k_aut = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
1706 0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
1707 0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
1708 0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
1710 .msk = { 0x28, 0xf2, 0xb9, 0x3a, 0x8e, 0xdc, 0x4a, 0x01,
1711 0xb6, 0x9d, 0x37, 0x8b, 0xa6, 0x8a, 0x77, 0xbb,
1712 0x01, 0x6c, 0x0f, 0xeb, 0xb7, 0x60, 0xdb, 0x98,
1713 0x57, 0x99, 0x64, 0x99, 0x00, 0x00, 0x6f, 0x97,
1714 0xa1, 0x76, 0x5c, 0x65, 0xf5, 0xd5, 0xbf, 0xde,
1715 0xe7, 0x61, 0xba, 0x42, 0x92, 0xe4, 0x51, 0xd1,
1716 0xa0, 0xc5, 0x7e, 0x76, 0xeb, 0x91, 0x3e, 0xe9,
1717 0x95, 0xf5, 0xce, 0x6e, 0xb7, 0x98, 0x91, 0x38 },
1718 .emsk = { 0xb9, 0x05, 0xa2, 0xf4, 0x67, 0xe0, 0xeb, 0x9a,
1719 0xfb, 0xa4, 0x59, 0xa7, 0xd8, 0xa7, 0xc8, 0x77,
1720 0xd5, 0xfa, 0x2e, 0x5e, 0xd3, 0x77, 0xf8, 0xc5,
1721 0x2f, 0xa4, 0x86, 0xad, 0xf5, 0x15, 0x5e, 0xb7,
1722 0x96, 0xac, 0xa9, 0x3e, 0xa3, 0xa9, 0x95, 0xe8,
1723 0xa2, 0x34, 0x36, 0x54, 0x5a, 0xf1, 0x57, 0x22,
1724 0xaa, 0x94, 0xb9, 0xfb, 0xd9, 0x06, 0x0c, 0x50,
1725 0xa3, 0x56, 0xcc, 0xb4, 0xc7, 0x10, 0x0e, 0x66 }
1728 static void test_eap_aka_kdf_1_reauth(
void)
1738 memcpy(&keys, &rfc5448_vector0_reauth_in,
sizeof(keys));
1755 {
"test_eap_sim_kdf_0_gsm", test_eap_sim_kdf_0_gsm },
1760 {
"test_eap_aka_kdf_0_umts", test_eap_aka_kdf_0_umts },
1765 {
"test_eap_sim_kdf_0_reauth", test_eap_sim_kdf_0_reauth },
1770 {
"test_eap_aka_kdf_1_umts", test_eap_aka_kdf_1_umts },
1771 {
"test_eap_aka_derive_ck_ik", test_eap_aka_derive_ck_ik },
1772 {
"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)
#define static_assert
For systems with an old version libc, define static_assert.
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.
Structure to represent packet format of eap on wire
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.
EVP_CIPHER_CTX * aka_sim_crypto_cipher_ctx(void)
Allocate and reset a resumable EVP_CIPHER_CTX for each thread.
int fr_aka_sim_crypto_init_checkcode(TALLOC_CTX *ctx, fr_aka_sim_checkcode_t **checkcode, EVP_MD const *md)
Initialise checkcode message digest.
#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]
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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