The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
milenage.c
Go to the documentation of this file.
1 /**
2  * @file src/lib/sim/milenage.c
3  * @brief 3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208)
4  *
5  * This file implements an example authentication algorithm defined for 3GPP
6  * AKA. This can be used to implement a simple HLR/AuC into hlr_auc_gw to allow
7  * EAP-AKA to be tested properly with real USIM cards.
8  *
9  * This implementations assumes that the r1..r5 and c1..c5 constants defined in
10  * TS 35.206 are used, i.e., r1=64, r2=0, r3=32, r4=64, r5=96, c1=00..00,
11  * c2=00..01, c3=00..02, c4=00..04, c5=00..08. The block cipher is assumed to
12  * be AES (Rijndael).
13  *
14  * This software may be distributed under the terms of the BSD license.
15  * See README for more details.
16  *
17  * @copyright 2017 The FreeRADIUS server project
18  * @copyright 2006-2007 (j@w1.fi)
19  */
20 #include <stddef.h>
21 #include <string.h>
22 
23 #include <freeradius-devel/tls/strerror.h>
24 #include <freeradius-devel/util/proto.h>
25 #include <openssl/evp.h>
26 #include "common.h"
27 #include "milenage.h"
28 
29 #define MILENAGE_MAC_A_SIZE 8
30 #define MILENAGE_MAC_S_SIZE 8
31 
32 static inline int aes_128_encrypt_block(EVP_CIPHER_CTX *evp_ctx,
33  uint8_t const key[16], uint8_t const in[16], uint8_t out[16])
34 {
35  size_t len = 0;
36 
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");
39  return -1;
40  }
41 
42  /*
43  * By default OpenSSL will try and pad out a 16 byte
44  * plaintext to 32 bytes so that it's detectable that
45  * there was padding.
46  *
47  * In this case we know the length of the plaintext
48  * we're trying to recover, so we explicitly tell
49  * OpenSSL not to pad here, and not to expected padding
50  * when decrypting.
51  */
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");
56  return -1;
57  }
58 
59  EVP_CIPHER_CTX_reset(evp_ctx);
60 
61  return 0;
62 }
63 
64 /** milenage_f1 - Milenage f1 and f1* algorithms
65  *
66  * @param[in] opc 128-bit value derived from OP and K.
67  * @param[in] k 128-bit subscriber key.
68  * @param[in] rand 128-bit random challenge.
69  * @param[in] sqn 48-bit sequence number.
70  * @param[in] amf 16-bit authentication management field.
71  * @param[out] mac_a Buffer for MAC-A = 64-bit network authentication code, or NULL
72  * @param[out] mac_s Buffer for MAC-S = 64-bit resync authentication code, or NULL
73  * @return
74  * - 0 on success.
75  * - -1 on failure.
76  */
79  uint8_t const opc[MILENAGE_OPC_SIZE],
80  uint8_t const k[MILENAGE_KI_SIZE],
81  uint8_t const rand[MILENAGE_RAND_SIZE],
82  uint8_t const sqn[MILENAGE_SQN_SIZE],
83  uint8_t const amf[MILENAGE_AMF_SIZE])
84 {
85  uint8_t tmp1[16], tmp2[16], tmp3[16];
86  int i;
87  EVP_CIPHER_CTX *evp_ctx;
88 
89  /* tmp1 = TEMP = E_K(RAND XOR OP_C) */
90  for (i = 0; i < 16; i++) tmp1[i] = rand[i] ^ opc[i];
91 
92  evp_ctx = EVP_CIPHER_CTX_new();
93  if (!evp_ctx) {
94  fr_tls_strerror_printf("Failed allocating EVP context");
95  return -1;
96  }
97 
98  if (aes_128_encrypt_block(evp_ctx, k, tmp1, tmp1) < 0) {
99  error:
100  EVP_CIPHER_CTX_free(evp_ctx);
101  return -1;
102  }
103 
104  /* tmp2 = IN1 = SQN || AMF || SQN || AMF */
105  memcpy(tmp2, sqn, 6);
106  memcpy(tmp2 + 6, amf, 2);
107  memcpy(tmp2 + 8, tmp2, 8);
108 
109  /* OUT1 = E_K(TEMP XOR rot(IN1 XOR OP_C, r1) XOR c1) XOR OP_C */
110 
111  /*
112  * rotate (tmp2 XOR OP_C) by r1 (= 0x40 = 8 bytes)
113  */
114  for (i = 0; i < 16; i++) tmp3[(i + 8) % 16] = tmp2[i] ^ opc[i];
115 
116  /*
117  * XOR with TEMP = E_K(RAND XOR OP_C)
118  */
119  for (i = 0; i < 16; i++) tmp3[i] ^= tmp1[i];
120  /* XOR with c1 (= ..00, i.e., NOP) */
121 
122  /*
123  * f1 || f1* = E_K(tmp3) XOR OP_c
124  */
125  if (aes_128_encrypt_block(evp_ctx, k, tmp3, tmp1) < 0) goto error; /* Reuses existing key */
126 
127  for (i = 0; i < 16; i++) tmp1[i] ^= opc[i];
128 
129  if (mac_a) memcpy(mac_a, tmp1, 8); /* f1 */
130  if (mac_s) memcpy(mac_s, tmp1 + 8, 8); /* f1* */
131 
132  EVP_CIPHER_CTX_free(evp_ctx);
133 
134  return 0;
135 }
136 
137 /** milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms
138  *
139  * @param[out] res Buffer for RES = 64-bit signed response (f2), or NULL
140  * @param[out] ck Buffer for CK = 128-bit confidentiality key (f3), or NULL
141  * @param[out] ik Buffer for IK = 128-bit integrity key (f4), or NULL
142  * @param[out] ak Buffer for AK = 48-bit anonymity key (f5), or NULL
143  * @param[out] ak_resync Buffer for AK = 48-bit anonymity key (f5*), or NULL
144  * @param[in] opc 128-bit value derived from OP and K.
145  * @param[in] k 128-bit subscriber key
146  * @param[in] rand 128-bit random challenge
147  * @return
148  * - 0 on success.
149  * - -1 on failure.
150  */
155  uint8_t ak_resync[MILENAGE_AK_SIZE],
156  uint8_t const opc[MILENAGE_OPC_SIZE],
157  uint8_t const k[MILENAGE_KI_SIZE],
158  uint8_t const rand[MILENAGE_RAND_SIZE])
159 {
160  uint8_t tmp1[16], tmp2[16], tmp3[16];
161  int i;
162  EVP_CIPHER_CTX *evp_ctx;
163 
164  /* tmp2 = TEMP = E_K(RAND XOR OP_C) */
165  for (i = 0; i < 16; i++) tmp1[i] = rand[i] ^ opc[i];
166 
167  evp_ctx = EVP_CIPHER_CTX_new();
168  if (!evp_ctx) {
169  fr_tls_strerror_printf("Failed allocating EVP context");
170  return -1;
171  }
172 
173  if (aes_128_encrypt_block(evp_ctx, k, tmp1, tmp2) < 0) {
174  error:
175  EVP_CIPHER_CTX_free(evp_ctx);
176  return -1;
177  }
178 
179  /* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */
180  /* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */
181  /* OUT4 = E_K(rot(TEMP XOR OP_C, r4) XOR c4) XOR OP_C */
182  /* OUT5 = E_K(rot(TEMP XOR OP_C, r5) XOR c5) XOR OP_C */
183 
184  /* f2 and f5 */
185  /* rotate by r2 (= 0, i.e., NOP) */
186  for (i = 0; i < 16; i++) tmp1[i] = tmp2[i] ^ opc[i];
187  tmp1[15] ^= 1; /* XOR c2 (= ..01) */
188  /* f5 || f2 = E_K(tmp1) XOR OP_c */
189 
190  if (aes_128_encrypt_block(evp_ctx, k, tmp1, tmp3) < 0) goto error;
191 
192  for (i = 0; i < 16; i++) tmp3[i] ^= opc[i];
193  if (res) memcpy(res, tmp3 + 8, 8); /* f2 */
194  if (ak) memcpy(ak, tmp3, 6); /* f5 */
195 
196  /* f3 */
197  if (ck) {
198  /* rotate by r3 = 0x20 = 4 bytes */
199  for (i = 0; i < 16; i++) tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i];
200  tmp1[15] ^= 2; /* XOR c3 (= ..02) */
201 
202  if (aes_128_encrypt_block(evp_ctx, k, tmp1, ck) < 0) goto error;
203 
204  for (i = 0; i < 16; i++) ck[i] ^= opc[i];
205  }
206 
207  /* f4 */
208  if (ik) {
209  /* rotate by r4 = 0x40 = 8 bytes */
210  for (i = 0; i < 16; i++) tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i];
211  tmp1[15] ^= 4; /* XOR c4 (= ..04) */
212 
213  if (aes_128_encrypt_block(evp_ctx, k, tmp1, ik) < 0) goto error;
214 
215  for (i = 0; i < 16; i++) ik[i] ^= opc[i];
216  }
217 
218  /* f5* */
219  if (ak_resync) {
220  /* rotate by r5 = 0x60 = 12 bytes */
221  for (i = 0; i < 16; i++) tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i];
222  tmp1[15] ^= 8; /* XOR c5 (= ..08) */
223 
224  if (aes_128_encrypt_block(evp_ctx, k, tmp1, tmp1) < 0) goto error;
225 
226  for (i = 0; i < 6; i++) ak_resync[i] = tmp1[i] ^ opc[i];
227  }
228  EVP_CIPHER_CTX_free(evp_ctx);
229 
230  return 0;
231 }
232 
233 /** Derive OPc from OP and Ki
234  *
235  * @param[out] opc The derived Operator Code used as an input to other Milenage
236  * functions.
237  * @param[in] op Operator Code.
238  * @param[in] ki Subscriber key.
239  * @return
240  * - 0 on success.
241  * - -1 on failure.
242  */
244  uint8_t const op[MILENAGE_OP_SIZE],
245  uint8_t const ki[MILENAGE_KI_SIZE])
246 {
247  int ret;
249  EVP_CIPHER_CTX *evp_ctx;
250  size_t i;
251 
252  evp_ctx = EVP_CIPHER_CTX_new();
253  if (!evp_ctx) {
254  fr_tls_strerror_printf("Failed allocating EVP context");
255  return -1;
256  }
257  ret = aes_128_encrypt_block(evp_ctx, ki, op, tmp);
258  EVP_CIPHER_CTX_free(evp_ctx);
259  if (ret < 0) return ret;
260 
261  for (i = 0; i < sizeof(tmp); i++) opc[i] = op[i] ^ tmp[i];
262 
263  return 0;
264 }
265 
266 /** Generate AKA AUTN, IK, CK, RES
267  *
268  * @param[out] autn Buffer for AUTN = 128-bit authentication token.
269  * @param[out] ik Buffer for IK = 128-bit integrity key (f4), or NULL.
270  * @param[out] ck Buffer for CK = 128-bit confidentiality key (f3), or NULL.
271  * @param[out] ak Buffer for AK = 48-bit anonymity key (f5), or NULL
272  * @param[out] res Buffer for RES = 64-bit signed response (f2), or NULL.
273  * @param[in] opc 128-bit operator variant algorithm configuration field (encr.).
274  * @param[in] amf 16-bit authentication management field.
275  * @param[in] ki 128-bit subscriber key.
276  * @param[in] sqn 48-bit sequence number (host byte order).
277  * @param[in] rand 128-bit random challenge.
278  * @return
279  * - 0 on success.
280  * - -1 on failure.
281  */
287  uint8_t const opc[MILENAGE_OPC_SIZE],
288  uint8_t const amf[MILENAGE_AMF_SIZE],
289  uint8_t const ki[MILENAGE_KI_SIZE],
290  uint64_t sqn,
291  uint8_t const rand[MILENAGE_RAND_SIZE])
292 {
293  uint8_t mac_a[8], ak_buff[MILENAGE_AK_SIZE];
294  uint8_t sqn_buff[MILENAGE_SQN_SIZE];
295  uint8_t *p = autn;
296  size_t i;
297 
298  if ((milenage_f1(mac_a, NULL, opc, ki, rand,
299  uint48_to_buff(sqn_buff, sqn), amf) < 0) ||
300  (milenage_f2345(res, ik, ck, ak_buff, NULL, opc, ki, rand) < 0)) return -1;
301 
302  /*
303  * AUTN = (SQN ^ AK) || AMF || MAC_A
304  */
305  for (i = 0; i < sizeof(sqn_buff); i++) *p++ = sqn_buff[i] ^ ak_buff[i];
306  memcpy(p, amf, MILENAGE_AMF_SIZE);
307  p += MILENAGE_AMF_SIZE;
308  memcpy(p, mac_a, sizeof(mac_a));
309 
310  /*
311  * Output the anonymity key if required
312  */
313  if (ak) memcpy(ak, ak_buff, sizeof(ak_buff));
314 
315  return 0;
316 }
317 
318 /** Milenage AUTS validation
319  *
320  * @param[out] sqn SQN = 48-bit sequence number (host byte order).
321  * @param[in] opc 128-bit operator variant algorithm configuration field (encr.).
322  * @param[in] ki 128-bit subscriber key.
323  * @param[in] rand 128-bit random challenge.
324  * @param[in] auts 112-bit authentication token from client.
325  * @return
326  * - 0 on success with sqn filled.
327  * - -1 on failure.
328  */
329 int milenage_auts(uint64_t *sqn,
330  uint8_t const opc[MILENAGE_OPC_SIZE],
331  uint8_t const ki[MILENAGE_KI_SIZE],
332  uint8_t const rand[MILENAGE_RAND_SIZE],
333  uint8_t const auts[MILENAGE_AUTS_SIZE])
334 {
335  uint8_t amf[MILENAGE_AMF_SIZE] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
337  uint8_t sqn_buff[MILENAGE_SQN_SIZE];
338  size_t i;
339 
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];
342 
343  if (milenage_f1(NULL, mac_s, opc, ki, rand, sqn_buff, amf) || CRYPTO_memcmp(mac_s, auts + 6, 8) != 0) return -1;
344 
345  *sqn = uint48_from_buff(sqn_buff);
346 
347  return 0;
348 }
349 
350 /** Generate GSM-Milenage (3GPP TS 55.205) authentication triplet from a quintuplet
351  *
352  * @param[out] sres Buffer for SRES = 32-bit SRES.
353  * @param[out] kc 64-bit Kc.
354  * @param[in] ik 128-bit integrity.
355  * @param[in] ck Confidentiality key.
356  * @param[in] res 64-bit signed response.
357  */
360  uint8_t const ik[MILENAGE_IK_SIZE],
361  uint8_t const ck[MILENAGE_CK_SIZE],
362  uint8_t const res[MILENAGE_RES_SIZE])
363 {
364  int i;
365 
366  for (i = 0; i < 8; i++) kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8];
367 
368 #ifdef GSM_MILENAGE_ALT_SRES
369  memcpy(sres, res, 4);
370 #else /* GSM_MILENAGE_ALT_SRES */
371  for (i = 0; i < 4; i++) sres[i] = res[i] ^ res[i + 4];
372 #endif /* GSM_MILENAGE_ALT_SRES */
373 }
374 
375 /** Generate GSM-Milenage (3GPP TS 55.205) authentication triplet
376  *
377  * @param[out] sres Buffer for SRES = 32-bit SRES.
378  * @param[out] kc 64-bit Kc.
379  * @param[in] opc 128-bit operator variant algorithm configuration field (encr.).
380  * @param[in] ki 128-bit subscriber key.
381  * @param[in] rand 128-bit random challenge.
382  * @return
383  * - 0 on success.
384  * - -1 on failure.
385  */
388  uint8_t const opc[MILENAGE_OPC_SIZE],
389  uint8_t const ki[MILENAGE_KI_SIZE],
390  uint8_t const rand[MILENAGE_RAND_SIZE])
391 {
393 
394  if (milenage_f2345(res, ik, ck, NULL, NULL, opc, ki, rand)) return -1;
395 
396  milenage_gsm_from_umts(sres, kc, ik, ck, res);
397 
398  return 0;
399 }
400 
401 /** Milenage check
402  *
403  * @param[out] ik Buffer for IK = 128-bit integrity key (f4), or NULL.
404  * @param[out] ck Buffer for CK = 128-bit confidentiality key (f3), or NULL.
405  * @param[out] res Buffer for RES = 64-bit signed response (f2), or NULL.
406  * @param[in] auts 112-bit buffer for AUTS.
407  * @param[in] opc 128-bit operator variant algorithm configuration field (encr.).
408  * @param[in] ki 128-bit subscriber key.
409  * @param[in] sqn 48-bit sequence number.
410  * @param[in] rand 128-bit random challenge.
411  * @param[in] autn 128-bit authentication token.
412  * @return
413  * - 0 on success.
414  * - -1 on failure.
415  * - -2 on synchronization failure
416  */
421  uint8_t const opc[MILENAGE_OPC_SIZE],
422  uint8_t const ki[MILENAGE_KI_SIZE],
423  uint64_t sqn,
424  uint8_t const rand[MILENAGE_RAND_SIZE],
425  uint8_t const autn[MILENAGE_AUTN_SIZE])
426 {
427 
429  uint8_t sqn_buff[MILENAGE_SQN_SIZE];
430  const uint8_t *amf;
431  size_t i;
432 
433  uint48_to_buff(sqn_buff, sqn);
434 
435  FR_PROTO_HEX_DUMP(autn, MILENAGE_AUTN_SIZE, "AUTN");
436  FR_PROTO_HEX_DUMP(rand, MILENAGE_RAND_SIZE, "RAND");
437 
438  if (milenage_f2345(res, ck, ik, ak, NULL, opc, ki, rand)) return -1;
439 
444 
445  /* AUTN = (SQN ^ AK) || AMF || MAC */
446  for (i = 0; i < 6; i++) rx_sqn[i] = autn[i] ^ ak[i];
447  FR_PROTO_HEX_DUMP(rx_sqn, MILENAGE_SQN_SIZE, "SQN");
448 
449  if (CRYPTO_memcmp(rx_sqn, sqn_buff, sizeof(rx_sqn)) <= 0) {
450  uint8_t auts_amf[MILENAGE_AMF_SIZE] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
451 
452  if (milenage_f2345(NULL, NULL, NULL, NULL, ak, opc, ki, rand)) return -1;
453 
454  FR_PROTO_HEX_DUMP(ak, sizeof(ak), "AK*");
455  for (i = 0; i < 6; i++) auts[i] = sqn_buff[i] ^ ak[i];
456 
457  if (milenage_f1(NULL, auts + 6, opc, ki, rand, sqn_buff, auts_amf) < 0) return -1;
458  FR_PROTO_HEX_DUMP(auts, 14, "AUTS");
459  return -2;
460  }
461 
462  amf = autn + 6;
464  if (milenage_f1(mac_a, NULL, opc, ki, rand, rx_sqn, amf) < 0) return -1;
465 
466  FR_PROTO_HEX_DUMP(mac_a, MILENAGE_MAC_A_SIZE, "MAC_A");
467 
468  if (CRYPTO_memcmp(mac_a, autn + 8, 8) != 0) {
469  FR_PROTO_HEX_DUMP(autn + 8, 8, "Received MAC_A");
470  fr_strerror_const("MAC mismatch");
471  return -1;
472  }
473 
474  return 0;
475 }
476 
477 #ifdef TESTING_MILENAGE
478 /*
479  * cc milenage.c -g3 -Wall -DHAVE_DLFCN_H -DTESTING_MILENAGE -DWITH_TLS -I../../../../ -I../../../ -I ../base/ -I /usr/local/opt/openssl/include/ -include ../include/build.h -L /usr/local/opt/openssl/lib/ -l ssl -l crypto -l talloc -L ../../../../../build/lib/local/.libs/ -lfreeradius-server -lfreeradius-tls -lfreeradius-util -o test_milenage && ./test_milenage
480  */
481 #include <freeradius-devel/util/acutest.h>
482 
483 void test_set_1(void)
484 {
485  /*
486  * Inputs
487  */
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 };
498 
499  /*
500  * Outputs
501  */
502  uint8_t opc_out[MILENAGE_OPC_SIZE];
503  uint8_t mac_a_out[MILENAGE_MAC_A_SIZE];
504  uint8_t mac_s_out[MILENAGE_MAC_S_SIZE];
505  uint8_t res_out[MILENAGE_RES_SIZE];
506  uint8_t ck_out[MILENAGE_CK_SIZE];
507  uint8_t ik_out[MILENAGE_IK_SIZE];
508  uint8_t ak_out[MILENAGE_AK_SIZE];
509  uint8_t ak_resync_out[MILENAGE_AK_SIZE];
510 
511  /* function 1 */
512  uint8_t mac_a[] = { 0x4a, 0x9f, 0xfa, 0xc3, 0x54, 0xdf, 0xaf, 0xb3 };
513  /* function 1* */
514  uint8_t mac_s[] = { 0x01, 0xcf, 0xaf, 0x9e, 0xc4, 0xe8, 0x71, 0xe9 };
515  /* function 2 */
516  uint8_t res[] = { 0xa5, 0x42, 0x11, 0xd5, 0xe3, 0xba, 0x50, 0xbf };
517  /* function 3 */
518  uint8_t ck[] = { 0xb4, 0x0b, 0xa9, 0xa3, 0xc5, 0x8b, 0x2a, 0x05,
519  0xbb, 0xf0, 0xd9, 0x87, 0xb2, 0x1b, 0xf8, 0xcb };
520  /* function 4 */
521  uint8_t ik[] = { 0xf7, 0x69, 0xbc, 0xd7, 0x51, 0x04, 0x46, 0x04,
522  0x12, 0x76, 0x72, 0x71, 0x1c, 0x6d, 0x34, 0x41 };
523  /* function 5 */
524  uint8_t ak[] = { 0xaa, 0x68, 0x9c, 0x64, 0x83, 0x70 };
525  /* function 5* */
526  uint8_t ak_resync[] = { 0x45, 0x1e, 0x8b, 0xec, 0xa4, 0x3b };
527 
528  int ret = 0;
529 
530 /*
531  fr_debug_lvl = 4;
532 */
533  ret = milenage_opc_generate(opc_out, op, ki);
534  TEST_CHECK(ret == 0);
535 
536  FR_PROTO_HEX_DUMP(opc_out, sizeof(opc_out), "opc");
537 
538  TEST_CHECK(memcmp(opc_out, opc, sizeof(opc_out)) == 0);
539 
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;
542 
543  FR_PROTO_HEX_DUMP(mac_a, sizeof(mac_a_out), "mac_a");
544  FR_PROTO_HEX_DUMP(mac_s, sizeof(mac_s_out), "mac_s");
545  FR_PROTO_HEX_DUMP(ik_out, sizeof(ik_out), "ik");
546  FR_PROTO_HEX_DUMP(ck_out, sizeof(ck_out), "ck");
547  FR_PROTO_HEX_DUMP(res_out, sizeof(res_out), "res");
548  FR_PROTO_HEX_DUMP(ak_out, sizeof(ak_out), "ak");
549  FR_PROTO_HEX_DUMP(ak_resync_out, sizeof(ak_resync_out), "ak_resync");
550 
551  TEST_CHECK(ret == 0);
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);
559 }
560 
561 void test_set_19(void)
562 {
563  /*
564  * Inputs
565  */
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 };
576 
577  /*
578  * Outputs
579  */
580  uint8_t opc_out[MILENAGE_OPC_SIZE];
581  uint8_t mac_a_out[MILENAGE_MAC_A_SIZE];
582  uint8_t mac_s_out[MILENAGE_MAC_S_SIZE];
583  uint8_t res_out[MILENAGE_RES_SIZE];
584  uint8_t ck_out[MILENAGE_CK_SIZE];
585  uint8_t ik_out[MILENAGE_IK_SIZE];
586  uint8_t ak_out[MILENAGE_AK_SIZE];
587  uint8_t ak_resync_out[MILENAGE_AK_SIZE];
588 
589  /* function 1 */
590  uint8_t mac_a[] = { 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 };
591  /* function 1* */
592  uint8_t mac_s[] = { 0x62, 0xda, 0xe3, 0x85, 0x3f, 0x3a, 0xf9, 0xd2 };
593  /* function 2 */
594  uint8_t res[] = { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 };
595  /* function 3 */
596  uint8_t ck[] = { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94,
597  0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f };
598  /* function 4 */
599  uint8_t ik[] = { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb,
600  0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a };
601  /* function 5 */
602  uint8_t ak[] = { 0xad, 0xa1, 0x5a, 0xeb, 0x7b, 0xb8 };
603  /* function 5* */
604  uint8_t ak_resync[] = { 0xd4, 0x61, 0xbc, 0x15, 0x47, 0x5d };
605 
606  int ret = 0;
607 
608 /*
609  fr_debug_lvl = 4;
610 */
611 
612  ret = milenage_opc_generate(opc_out, op, ki);
613  TEST_CHECK(ret == 0);
614 
615  FR_PROTO_HEX_DUMP(opc_out, sizeof(opc_out), "opc");
616 
617  TEST_CHECK(memcmp(opc_out, opc, sizeof(opc_out)) == 0);
618 
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;
621 
622  FR_PROTO_HEX_DUMP(mac_a, sizeof(mac_a_out), "mac_a");
623  FR_PROTO_HEX_DUMP(mac_s, sizeof(mac_s_out), "mac_s");
624  FR_PROTO_HEX_DUMP(ik_out, sizeof(ik_out), "ik");
625  FR_PROTO_HEX_DUMP(ck_out, sizeof(ck_out), "ck");
626  FR_PROTO_HEX_DUMP(res_out, sizeof(res_out), "res");
627  FR_PROTO_HEX_DUMP(ak_out, sizeof(ak_out), "ak");
628  FR_PROTO_HEX_DUMP(ak_resync_out, sizeof(ak_resync_out), "ak_resync");
629 
630  TEST_CHECK(ret == 0);
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);
638 }
639 
640 TEST_LIST = {
641  { "test_set_1", test_set_1 },
642  { "test_set_19", test_set_19 },
643  { NULL }
644 };
645 #endif
#define TEST_CHECK(cond)
Definition: acutest.h:85
#define TEST_LIST
Definition: acutest.h:62
#define unlikely(_x)
Definition: build.h:378
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.
Definition: common.h:37
static uint64_t uint48_from_buff(uint8_t const in[6])
Convert a 48bit big endian value into a unsigned 64bit integer.
Definition: common.h:52
static fr_slen_t in
Definition: dict.h:645
unsigned char uint8_t
Definition: merged_model.c:30
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.
Definition: milenage.c:282
#define MILENAGE_MAC_A_SIZE
Definition: milenage.c:29
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])
Definition: milenage.c:32
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.
Definition: milenage.c:417
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.
Definition: milenage.c:329
#define MILENAGE_MAC_S_SIZE
Definition: milenage.c:30
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.
Definition: milenage.c:358
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.
Definition: milenage.c:386
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
Definition: milenage.c:77
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.
Definition: milenage.c:243
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
Definition: milenage.c:151
3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208)
#define MILENAGE_AK_SIZE
Anonymisation key.
Definition: milenage.h:36
#define MILENAGE_SQN_SIZE
Sequence number.
Definition: milenage.h:30
#define MILENAGE_AMF_SIZE
Authentication management field.
Definition: milenage.h:29
#define MILENAGE_KI_SIZE
Subscriber key.
Definition: milenage.h:26
#define MILENAGE_RAND_SIZE
Random challenge.
Definition: milenage.h:31
#define MILENAGE_AUTN_SIZE
Network authentication key.
Definition: milenage.h:37
#define MILENAGE_SRES_SIZE
Definition: milenage.h:46
#define MILENAGE_CK_SIZE
Ciphering key.
Definition: milenage.h:39
#define MILENAGE_OP_SIZE
Operator code (unique to the operator)
Definition: milenage.h:27
#define MILENAGE_IK_SIZE
Integrity key.
Definition: milenage.h:38
#define MILENAGE_KC_SIZE
Definition: milenage.h:47
#define MILENAGE_AUTS_SIZE
Definition: milenage.h:41
#define MILENAGE_OPC_SIZE
Derived operator code (unique to the operator and subscriber).
Definition: milenage.h:28
#define MILENAGE_RES_SIZE
Definition: milenage.h:40
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
Definition: proto.h:41
#define fr_strerror_const(_msg)
Definition: strerror.h:223
static size_t char ** out
Definition: value.h:984