1/* 2 * 3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208) 3 * Copyright (c) 2006-2007 <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 * 8 * This file implements an example authentication algorithm defined for 3GPP 9 * AKA. This can be used to implement a simple HLR/AuC into hlr_auc_gw to allow 10 * EAP-AKA to be tested properly with real USIM cards. 11 * 12 * This implementations assumes that the r1..r5 and c1..c5 constants defined in 13 * TS 35.206 are used, i.e., r1=64, r2=0, r3=32, r4=64, r5=96, c1=00..00, 14 * c2=00..01, c3=00..02, c4=00..04, c5=00..08. The block cipher is assumed to 15 * be AES (Rijndael). 16 */ 17 18#include "includes.h" 19 20#include "common.h" 21#include "crypto/aes_wrap.h" 22#include "milenage.h" 23 24 25/** 26 * milenage_f1 - Milenage f1 and f1* algorithms 27 * @opc: OPc = 128-bit value derived from OP and K 28 * @k: K = 128-bit subscriber key 29 * @_rand: RAND = 128-bit random challenge 30 * @sqn: SQN = 48-bit sequence number 31 * @amf: AMF = 16-bit authentication management field 32 * @mac_a: Buffer for MAC-A = 64-bit network authentication code, or %NULL 33 * @mac_s: Buffer for MAC-S = 64-bit resync authentication code, or %NULL 34 * Returns: 0 on success, -1 on failure 35 */ 36int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand, 37 const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s) 38{ 39 u8 tmp1[16], tmp2[16], tmp3[16]; 40 int i; 41 42 /* tmp1 = TEMP = E_K(RAND XOR OP_C) */ 43 for (i = 0; i < 16; i++) 44 tmp1[i] = _rand[i] ^ opc[i]; 45 if (aes_128_encrypt_block(k, tmp1, tmp1)) 46 return -1; 47 48 /* tmp2 = IN1 = SQN || AMF || SQN || AMF */ 49 os_memcpy(tmp2, sqn, 6); 50 os_memcpy(tmp2 + 6, amf, 2); 51 os_memcpy(tmp2 + 8, tmp2, 8); 52 53 /* OUT1 = E_K(TEMP XOR rot(IN1 XOR OP_C, r1) XOR c1) XOR OP_C */ 54 55 /* rotate (tmp2 XOR OP_C) by r1 (= 0x40 = 8 bytes) */ 56 for (i = 0; i < 16; i++) 57 tmp3[(i + 8) % 16] = tmp2[i] ^ opc[i]; 58 /* XOR with TEMP = E_K(RAND XOR OP_C) */ 59 for (i = 0; i < 16; i++) 60 tmp3[i] ^= tmp1[i]; 61 /* XOR with c1 (= ..00, i.e., NOP) */ 62 63 /* f1 || f1* = E_K(tmp3) XOR OP_c */ 64 if (aes_128_encrypt_block(k, tmp3, tmp1)) 65 return -1; 66 for (i = 0; i < 16; i++) 67 tmp1[i] ^= opc[i]; 68 if (mac_a) 69 os_memcpy(mac_a, tmp1, 8); /* f1 */ 70 if (mac_s) 71 os_memcpy(mac_s, tmp1 + 8, 8); /* f1* */ 72 return 0; 73} 74 75 76/** 77 * milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms 78 * @opc: OPc = 128-bit value derived from OP and K 79 * @k: K = 128-bit subscriber key 80 * @_rand: RAND = 128-bit random challenge 81 * @res: Buffer for RES = 64-bit signed response (f2), or %NULL 82 * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL 83 * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL 84 * @ak: Buffer for AK = 48-bit anonymity key (f5), or %NULL 85 * @akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL 86 * Returns: 0 on success, -1 on failure 87 */ 88int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand, 89 u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar) 90{ 91 u8 tmp1[16], tmp2[16], tmp3[16]; 92 int i; 93 94 /* tmp2 = TEMP = E_K(RAND XOR OP_C) */ 95 for (i = 0; i < 16; i++) 96 tmp1[i] = _rand[i] ^ opc[i]; 97 if (aes_128_encrypt_block(k, tmp1, tmp2)) 98 return -1; 99 100 /* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */ 101 /* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */ 102 /* OUT4 = E_K(rot(TEMP XOR OP_C, r4) XOR c4) XOR OP_C */ 103 /* OUT5 = E_K(rot(TEMP XOR OP_C, r5) XOR c5) XOR OP_C */ 104 105 /* f2 and f5 */ 106 /* rotate by r2 (= 0, i.e., NOP) */ 107 for (i = 0; i < 16; i++) 108 tmp1[i] = tmp2[i] ^ opc[i]; 109 tmp1[15] ^= 1; /* XOR c2 (= ..01) */ 110 /* f5 || f2 = E_K(tmp1) XOR OP_c */ 111 if (aes_128_encrypt_block(k, tmp1, tmp3)) 112 return -1; 113 for (i = 0; i < 16; i++) 114 tmp3[i] ^= opc[i]; 115 if (res) 116 os_memcpy(res, tmp3 + 8, 8); /* f2 */ 117 if (ak) 118 os_memcpy(ak, tmp3, 6); /* f5 */ 119 120 /* f3 */ 121 if (ck) { 122 /* rotate by r3 = 0x20 = 4 bytes */ 123 for (i = 0; i < 16; i++) 124 tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i]; 125 tmp1[15] ^= 2; /* XOR c3 (= ..02) */ 126 if (aes_128_encrypt_block(k, tmp1, ck)) 127 return -1; 128 for (i = 0; i < 16; i++) 129 ck[i] ^= opc[i]; 130 } 131 132 /* f4 */ 133 if (ik) { 134 /* rotate by r4 = 0x40 = 8 bytes */ 135 for (i = 0; i < 16; i++) 136 tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i]; 137 tmp1[15] ^= 4; /* XOR c4 (= ..04) */ 138 if (aes_128_encrypt_block(k, tmp1, ik)) 139 return -1; 140 for (i = 0; i < 16; i++) 141 ik[i] ^= opc[i]; 142 } 143 144 /* f5* */ 145 if (akstar) { 146 /* rotate by r5 = 0x60 = 12 bytes */ 147 for (i = 0; i < 16; i++) 148 tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i]; 149 tmp1[15] ^= 8; /* XOR c5 (= ..08) */ 150 if (aes_128_encrypt_block(k, tmp1, tmp1)) 151 return -1; 152 for (i = 0; i < 6; i++) 153 akstar[i] = tmp1[i] ^ opc[i]; 154 } 155 156 return 0; 157} 158 159 160/** 161 * milenage_generate - Generate AKA AUTN,IK,CK,RES 162 * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) 163 * @amf: AMF = 16-bit authentication management field 164 * @k: K = 128-bit subscriber key 165 * @sqn: SQN = 48-bit sequence number 166 * @_rand: RAND = 128-bit random challenge 167 * @autn: Buffer for AUTN = 128-bit authentication token 168 * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL 169 * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL 170 * @res: Buffer for RES = 64-bit signed response (f2), or %NULL 171 * @res_len: Max length for res; set to used length or 0 on failure 172 */ 173void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k, 174 const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik, 175 u8 *ck, u8 *res, size_t *res_len) 176{ 177 int i; 178 u8 mac_a[8], ak[6]; 179 180 if (*res_len < 8) { 181 *res_len = 0; 182 return; 183 } 184 if (milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) || 185 milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) { 186 *res_len = 0; 187 return; 188 } 189 *res_len = 8; 190 191 /* AUTN = (SQN ^ AK) || AMF || MAC */ 192 for (i = 0; i < 6; i++) 193 autn[i] = sqn[i] ^ ak[i]; 194 os_memcpy(autn + 6, amf, 2); 195 os_memcpy(autn + 8, mac_a, 8); 196} 197 198 199/** 200 * milenage_auts - Milenage AUTS validation 201 * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) 202 * @k: K = 128-bit subscriber key 203 * @_rand: RAND = 128-bit random challenge 204 * @auts: AUTS = 112-bit authentication token from client 205 * @sqn: Buffer for SQN = 48-bit sequence number 206 * Returns: 0 = success (sqn filled), -1 on failure 207 */ 208int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts, 209 u8 *sqn) 210{ 211 u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ 212 u8 ak[6], mac_s[8]; 213 int i; 214 215 if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak)) 216 return -1; 217 for (i = 0; i < 6; i++) 218 sqn[i] = auts[i] ^ ak[i]; 219 if (milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) || 220 memcmp(mac_s, auts + 6, 8) != 0) 221 return -1; 222 return 0; 223} 224 225 226/** 227 * gsm_milenage - Generate GSM-Milenage (3GPP TS 55.205) authentication triplet 228 * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) 229 * @k: K = 128-bit subscriber key 230 * @_rand: RAND = 128-bit random challenge 231 * @sres: Buffer for SRES = 32-bit SRES 232 * @kc: Buffer for Kc = 64-bit Kc 233 * Returns: 0 on success, -1 on failure 234 */ 235int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc) 236{ 237 u8 res[8], ck[16], ik[16]; 238 int i; 239 240 if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL)) 241 return -1; 242 243 for (i = 0; i < 8; i++) 244 kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8]; 245 246#ifdef GSM_MILENAGE_ALT_SRES 247 os_memcpy(sres, res, 4); 248#else /* GSM_MILENAGE_ALT_SRES */ 249 for (i = 0; i < 4; i++) 250 sres[i] = res[i] ^ res[i + 4]; 251#endif /* GSM_MILENAGE_ALT_SRES */ 252 return 0; 253} 254 255 256/** 257 * milenage_generate - Generate AKA AUTN,IK,CK,RES 258 * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) 259 * @k: K = 128-bit subscriber key 260 * @sqn: SQN = 48-bit sequence number 261 * @_rand: RAND = 128-bit random challenge 262 * @autn: AUTN = 128-bit authentication token 263 * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL 264 * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL 265 * @res: Buffer for RES = 64-bit signed response (f2), or %NULL 266 * @res_len: Variable that will be set to RES length 267 * @auts: 112-bit buffer for AUTS 268 * Returns: 0 on success, -1 on failure, or -2 on synchronization failure 269 */ 270int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand, 271 const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len, 272 u8 *auts) 273{ 274 int i; 275 u8 mac_a[8], ak[6], rx_sqn[6]; 276 const u8 *amf; 277 278 wpa_hexdump(MSG_DEBUG, "Milenage: AUTN", autn, 16); 279 wpa_hexdump(MSG_DEBUG, "Milenage: RAND", _rand, 16); 280 281 if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) 282 return -1; 283 284 *res_len = 8; 285 wpa_hexdump_key(MSG_DEBUG, "Milenage: RES", res, *res_len); 286 wpa_hexdump_key(MSG_DEBUG, "Milenage: CK", ck, 16); 287 wpa_hexdump_key(MSG_DEBUG, "Milenage: IK", ik, 16); 288 wpa_hexdump_key(MSG_DEBUG, "Milenage: AK", ak, 6); 289 290 /* AUTN = (SQN ^ AK) || AMF || MAC */ 291 for (i = 0; i < 6; i++) 292 rx_sqn[i] = autn[i] ^ ak[i]; 293 wpa_hexdump(MSG_DEBUG, "Milenage: SQN", rx_sqn, 6); 294 295 if (os_memcmp(rx_sqn, sqn, 6) <= 0) { 296 u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ 297 if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak)) 298 return -1; 299 wpa_hexdump_key(MSG_DEBUG, "Milenage: AK*", ak, 6); 300 for (i = 0; i < 6; i++) 301 auts[i] = sqn[i] ^ ak[i]; 302 if (milenage_f1(opc, k, _rand, sqn, auts_amf, NULL, auts + 6)) 303 return -1; 304 wpa_hexdump(MSG_DEBUG, "Milenage: AUTS", auts, 14); 305 return -2; 306 } 307 308 amf = autn + 6; 309 wpa_hexdump(MSG_DEBUG, "Milenage: AMF", amf, 2); 310 if (milenage_f1(opc, k, _rand, rx_sqn, amf, mac_a, NULL)) 311 return -1; 312 313 wpa_hexdump(MSG_DEBUG, "Milenage: MAC_A", mac_a, 8); 314 315 if (os_memcmp(mac_a, autn + 8, 8) != 0) { 316 wpa_printf(MSG_DEBUG, "Milenage: MAC mismatch"); 317 wpa_hexdump(MSG_DEBUG, "Milenage: Received MAC_A", 318 autn + 8, 8); 319 return -1; 320 } 321 322 return 0; 323} 324