23 #include <freeradius-devel/tls/strerror.h>
24 #include <freeradius-devel/util/proto.h>
25 #include <openssl/evp.h>
29 #define MILENAGE_MAC_A_SIZE 8
30 #define MILENAGE_MAC_S_SIZE 8
37 if (
unlikely(EVP_EncryptInit_ex(evp_ctx, EVP_aes_128_ecb(), NULL, key, NULL) != 1)) {
38 fr_tls_strerror_printf(
"Failed initialising AES-128-ECB context");
52 EVP_CIPHER_CTX_set_padding(evp_ctx, 0);
53 if (
unlikely(EVP_EncryptUpdate(evp_ctx,
out, (
int *)&len,
in, 16) != 1) ||
54 unlikely(EVP_EncryptFinal_ex(evp_ctx,
out + len, (
int *)&len) != 1)) {
55 fr_tls_strerror_printf(
"Failed encrypting data");
59 EVP_CIPHER_CTX_reset(evp_ctx);
85 uint8_t tmp1[16], tmp2[16], tmp3[16];
87 EVP_CIPHER_CTX *evp_ctx;
90 for (i = 0; i < 16; i++) tmp1[i] = rand[i] ^ opc[i];
92 evp_ctx = EVP_CIPHER_CTX_new();
94 fr_tls_strerror_printf(
"Failed allocating EVP context");
100 EVP_CIPHER_CTX_free(evp_ctx);
105 memcpy(tmp2, sqn, 6);
106 memcpy(tmp2 + 6, amf, 2);
107 memcpy(tmp2 + 8, tmp2, 8);
114 for (i = 0; i < 16; i++) tmp3[(i + 8) % 16] = tmp2[i] ^ opc[i];
119 for (i = 0; i < 16; i++) tmp3[i] ^= tmp1[i];
127 for (i = 0; i < 16; i++) tmp1[i] ^= opc[i];
129 if (mac_a) memcpy(mac_a, tmp1, 8);
130 if (mac_s) memcpy(mac_s, tmp1 + 8, 8);
132 EVP_CIPHER_CTX_free(evp_ctx);
160 uint8_t tmp1[16], tmp2[16], tmp3[16];
162 EVP_CIPHER_CTX *evp_ctx;
165 for (i = 0; i < 16; i++) tmp1[i] = rand[i] ^ opc[i];
167 evp_ctx = EVP_CIPHER_CTX_new();
169 fr_tls_strerror_printf(
"Failed allocating EVP context");
175 EVP_CIPHER_CTX_free(evp_ctx);
186 for (i = 0; i < 16; i++) tmp1[i] = tmp2[i] ^ opc[i];
192 for (i = 0; i < 16; i++) tmp3[i] ^= opc[i];
193 if (res) memcpy(res, tmp3 + 8, 8);
194 if (ak) memcpy(ak, tmp3, 6);
199 for (i = 0; i < 16; i++) tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i];
204 for (i = 0; i < 16; i++) ck[i] ^= opc[i];
210 for (i = 0; i < 16; i++) tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i];
215 for (i = 0; i < 16; i++) ik[i] ^= opc[i];
221 for (i = 0; i < 16; i++) tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i];
226 for (i = 0; i < 6; i++) ak_resync[i] = tmp1[i] ^ opc[i];
228 EVP_CIPHER_CTX_free(evp_ctx);
249 EVP_CIPHER_CTX *evp_ctx;
252 evp_ctx = EVP_CIPHER_CTX_new();
254 fr_tls_strerror_printf(
"Failed allocating EVP context");
258 EVP_CIPHER_CTX_free(evp_ctx);
259 if (ret < 0)
return ret;
261 for (i = 0; i <
sizeof(tmp); i++) opc[i] = op[i] ^ tmp[i];
300 (
milenage_f2345(res, ik, ck, ak_buff, NULL, opc, ki, rand) < 0))
return -1;
305 for (i = 0; i <
sizeof(sqn_buff); i++) *p++ = sqn_buff[i] ^ ak_buff[i];
308 memcpy(p, mac_a,
sizeof(mac_a));
313 if (ak) memcpy(ak, ak_buff,
sizeof(ak_buff));
340 if (
milenage_f2345(NULL, NULL, NULL, NULL, ak, opc, ki, rand))
return -1;
341 for (i = 0; i <
sizeof(sqn_buff); i++) sqn_buff[i] = auts[i] ^ ak[i];
343 if (
milenage_f1(NULL, mac_s, opc, ki, rand, sqn_buff, amf) || CRYPTO_memcmp(mac_s, auts + 6, 8) != 0)
return -1;
366 for (i = 0; i < 8; i++) kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8];
368 #ifdef GSM_MILENAGE_ALT_SRES
369 memcpy(sres, res, 4);
371 for (i = 0; i < 4; i++) sres[i] = res[i] ^ res[i + 4];
394 if (
milenage_f2345(res, ik, ck, NULL, NULL, opc, ki, rand))
return -1;
438 if (
milenage_f2345(res, ck, ik, ak, NULL, opc, ki, rand))
return -1;
446 for (i = 0; i < 6; i++) rx_sqn[i] = autn[i] ^ ak[i];
449 if (CRYPTO_memcmp(rx_sqn, sqn_buff,
sizeof(rx_sqn)) <= 0) {
452 if (
milenage_f2345(NULL, NULL, NULL, NULL, ak, opc, ki, rand))
return -1;
455 for (i = 0; i < 6; i++) auts[i] = sqn_buff[i] ^ ak[i];
457 if (
milenage_f1(NULL, auts + 6, opc, ki, rand, sqn_buff, auts_amf) < 0)
return -1;
464 if (
milenage_f1(mac_a, NULL, opc, ki, rand, rx_sqn, amf) < 0)
return -1;
468 if (CRYPTO_memcmp(mac_a, autn + 8, 8) != 0) {
477 #ifdef TESTING_MILENAGE
481 #include <freeradius-devel/util/acutest.h>
483 void test_set_1(
void)
488 uint8_t ki[] = { 0x46, 0x5b, 0x5c, 0xe8, 0xb1, 0x99, 0xb4, 0x9f,
489 0xaa, 0x5f, 0x0a, 0x2e, 0xe2, 0x38, 0xa6, 0xbc };
490 uint8_t rand[] = { 0x23, 0x55, 0x3c, 0xbe, 0x96, 0x37, 0xa8, 0x9d,
491 0x21, 0x8a, 0xe6, 0x4d, 0xae, 0x47, 0xbf, 0x35 };
492 uint8_t sqn[] = { 0xff, 0x9b, 0xb4, 0xd0, 0xb6, 0x07 };
493 uint8_t amf[] = { 0xb9, 0xb9 };
494 uint8_t op[] = { 0xcd, 0xc2, 0x02, 0xd5, 0x12, 0x3e, 0x20, 0xf6,
495 0x2b, 0x6d, 0x67, 0x6a, 0xc7, 0x2c, 0xb3, 0x18 };
496 uint8_t opc[] = { 0xcd, 0x63, 0xcb, 0x71, 0x95, 0x4a, 0x9f, 0x4e,
497 0x48, 0xa5, 0x99, 0x4e, 0x37, 0xa0, 0x2b, 0xaf };
512 uint8_t mac_a[] = { 0x4a, 0x9f, 0xfa, 0xc3, 0x54, 0xdf, 0xaf, 0xb3 };
514 uint8_t mac_s[] = { 0x01, 0xcf, 0xaf, 0x9e, 0xc4, 0xe8, 0x71, 0xe9 };
516 uint8_t res[] = { 0xa5, 0x42, 0x11, 0xd5, 0xe3, 0xba, 0x50, 0xbf };
518 uint8_t ck[] = { 0xb4, 0x0b, 0xa9, 0xa3, 0xc5, 0x8b, 0x2a, 0x05,
519 0xbb, 0xf0, 0xd9, 0x87, 0xb2, 0x1b, 0xf8, 0xcb };
521 uint8_t ik[] = { 0xf7, 0x69, 0xbc, 0xd7, 0x51, 0x04, 0x46, 0x04,
522 0x12, 0x76, 0x72, 0x71, 0x1c, 0x6d, 0x34, 0x41 };
524 uint8_t ak[] = { 0xaa, 0x68, 0x9c, 0x64, 0x83, 0x70 };
526 uint8_t ak_resync[] = { 0x45, 0x1e, 0x8b, 0xec, 0xa4, 0x3b };
538 TEST_CHECK(memcmp(opc_out, opc,
sizeof(opc_out)) == 0);
540 if ((
milenage_f1(mac_a_out, mac_s_out, opc, ki, rand, sqn, amf) < 0) ||
541 (
milenage_f2345(res_out, ik_out, ck_out, ak_out, ak_resync_out, opc, ki, rand) < 0)) ret = -1;
552 TEST_CHECK(memcmp(mac_a_out, mac_a,
sizeof(mac_a_out)) == 0);
553 TEST_CHECK(memcmp(mac_s_out, mac_s,
sizeof(mac_s_out)) == 0);
554 TEST_CHECK(memcmp(res_out, res,
sizeof(res_out)) == 0);
555 TEST_CHECK(memcmp(ck_out, ck,
sizeof(ck_out)) == 0);
556 TEST_CHECK(memcmp(ik_out, ik,
sizeof(ik_out)) == 0);
557 TEST_CHECK(memcmp(ak_out, ak,
sizeof(ak_out)) == 0);
558 TEST_CHECK(memcmp(ak_resync, ak_resync,
sizeof(ak_resync_out)) == 0);
561 void test_set_19(
void)
566 uint8_t ki[] = { 0x51, 0x22, 0x25, 0x02, 0x14, 0xc3, 0x3e, 0x72,
567 0x3a, 0x5d, 0xd5, 0x23, 0xfc, 0x14, 0x5f, 0xc0 };
568 uint8_t rand[] = { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e,
569 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 };
570 uint8_t sqn[] = { 0x16, 0xf3, 0xb3, 0xf7, 0x0f, 0xc2 };
571 uint8_t amf[] = { 0xc3, 0xab };
572 uint8_t op[] = { 0xc9, 0xe8, 0x76, 0x32, 0x86, 0xb5, 0xb9, 0xff,
573 0xbd, 0xf5, 0x6e, 0x12, 0x97, 0xd0, 0x88, 0x7b };
574 uint8_t opc[] = { 0x98, 0x1d, 0x46, 0x4c, 0x7c, 0x52, 0xeb, 0x6e,
575 0x50, 0x36, 0x23, 0x49, 0x84, 0xad, 0x0b, 0xcf };
590 uint8_t mac_a[] = { 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 };
592 uint8_t mac_s[] = { 0x62, 0xda, 0xe3, 0x85, 0x3f, 0x3a, 0xf9, 0xd2 };
594 uint8_t res[] = { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 };
596 uint8_t ck[] = { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94,
597 0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f };
599 uint8_t ik[] = { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb,
600 0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a };
602 uint8_t ak[] = { 0xad, 0xa1, 0x5a, 0xeb, 0x7b, 0xb8 };
604 uint8_t ak_resync[] = { 0xd4, 0x61, 0xbc, 0x15, 0x47, 0x5d };
617 TEST_CHECK(memcmp(opc_out, opc,
sizeof(opc_out)) == 0);
619 if ((
milenage_f1(mac_a_out, mac_s_out, opc, ki, rand, sqn, amf) < 0) ||
620 (
milenage_f2345(res_out, ik_out, ck_out, ak_out, ak_resync_out, opc, ki, rand) < 0)) ret = -1;
631 TEST_CHECK(memcmp(mac_a_out, mac_a,
sizeof(mac_a_out)) == 0);
632 TEST_CHECK(memcmp(mac_s_out, mac_s,
sizeof(mac_s_out)) == 0);
633 TEST_CHECK(memcmp(res_out, res,
sizeof(res_out)) == 0);
634 TEST_CHECK(memcmp(ck_out, ck,
sizeof(ck_out)) == 0);
635 TEST_CHECK(memcmp(ik_out, ik,
sizeof(ik_out)) == 0);
636 TEST_CHECK(memcmp(ak_out, ak,
sizeof(ak_out)) == 0);
637 TEST_CHECK(memcmp(ak_resync, ak_resync,
sizeof(ak_resync_out)) == 0);
641 {
"test_set_1", test_set_1 },
642 {
"test_set_19", test_set_19 },
Common code used by multiple SIM algorithms.
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.
int milenage_umts_generate(uint8_t autn[MILENAGE_AUTN_SIZE], uint8_t ik[MILENAGE_IK_SIZE], uint8_t ck[MILENAGE_CK_SIZE], uint8_t ak[MILENAGE_AK_SIZE], uint8_t res[MILENAGE_RES_SIZE], uint8_t const opc[MILENAGE_OPC_SIZE], uint8_t const amf[MILENAGE_AMF_SIZE], uint8_t const ki[MILENAGE_KI_SIZE], uint64_t sqn, uint8_t const rand[MILENAGE_RAND_SIZE])
Generate AKA AUTN, IK, CK, RES.
#define MILENAGE_MAC_A_SIZE
static int aes_128_encrypt_block(EVP_CIPHER_CTX *evp_ctx, uint8_t const key[16], uint8_t const in[16], uint8_t out[16])
int milenage_check(uint8_t ik[MILENAGE_IK_SIZE], uint8_t ck[MILENAGE_CK_SIZE], uint8_t res[MILENAGE_RES_SIZE], uint8_t auts[MILENAGE_AUTS_SIZE], uint8_t const opc[MILENAGE_OPC_SIZE], uint8_t const ki[MILENAGE_KI_SIZE], uint64_t sqn, uint8_t const rand[MILENAGE_RAND_SIZE], uint8_t const autn[MILENAGE_AUTN_SIZE])
Milenage check.
int milenage_auts(uint64_t *sqn, uint8_t const opc[MILENAGE_OPC_SIZE], uint8_t const ki[MILENAGE_KI_SIZE], uint8_t const rand[MILENAGE_RAND_SIZE], uint8_t const auts[MILENAGE_AUTS_SIZE])
Milenage AUTS validation.
#define MILENAGE_MAC_S_SIZE
void milenage_gsm_from_umts(uint8_t sres[MILENAGE_SRES_SIZE], uint8_t kc[MILENAGE_KC_SIZE], uint8_t const ik[MILENAGE_IK_SIZE], uint8_t const ck[MILENAGE_CK_SIZE], uint8_t const res[MILENAGE_RES_SIZE])
Generate GSM-Milenage (3GPP TS 55.205) authentication triplet from a quintuplet.
int milenage_gsm_generate(uint8_t sres[MILENAGE_SRES_SIZE], uint8_t kc[MILENAGE_KC_SIZE], uint8_t const opc[MILENAGE_OPC_SIZE], uint8_t const ki[MILENAGE_KI_SIZE], uint8_t const rand[MILENAGE_RAND_SIZE])
Generate GSM-Milenage (3GPP TS 55.205) authentication triplet.
static int milenage_f1(uint8_t mac_a[MILENAGE_MAC_A_SIZE], uint8_t mac_s[MILENAGE_MAC_S_SIZE], uint8_t const opc[MILENAGE_OPC_SIZE], uint8_t const k[MILENAGE_KI_SIZE], uint8_t const rand[MILENAGE_RAND_SIZE], uint8_t const sqn[MILENAGE_SQN_SIZE], uint8_t const amf[MILENAGE_AMF_SIZE])
milenage_f1 - Milenage f1 and f1* algorithms
int milenage_opc_generate(uint8_t opc[MILENAGE_OPC_SIZE], uint8_t const op[MILENAGE_OP_SIZE], uint8_t const ki[MILENAGE_KI_SIZE])
Derive OPc from OP and Ki.
static int milenage_f2345(uint8_t res[MILENAGE_RES_SIZE], uint8_t ik[MILENAGE_IK_SIZE], uint8_t ck[MILENAGE_CK_SIZE], uint8_t ak[MILENAGE_AK_SIZE], uint8_t ak_resync[MILENAGE_AK_SIZE], uint8_t const opc[MILENAGE_OPC_SIZE], uint8_t const k[MILENAGE_KI_SIZE], uint8_t const rand[MILENAGE_RAND_SIZE])
milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms
3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208)
#define MILENAGE_AK_SIZE
Anonymisation key.
#define MILENAGE_SQN_SIZE
Sequence number.
#define MILENAGE_AMF_SIZE
Authentication management field.
#define MILENAGE_KI_SIZE
Subscriber key.
#define MILENAGE_RAND_SIZE
Random challenge.
#define MILENAGE_AUTN_SIZE
Network authentication key.
#define MILENAGE_SRES_SIZE
#define MILENAGE_CK_SIZE
Ciphering key.
#define MILENAGE_OP_SIZE
Operator code (unique to the operator)
#define MILENAGE_IK_SIZE
Integrity key.
#define MILENAGE_AUTS_SIZE
#define MILENAGE_OPC_SIZE
Derived operator code (unique to the operator and subscriber).
#define MILENAGE_RES_SIZE
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
#define fr_strerror_const(_msg)
static size_t char ** out