The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
crypto.c
Go to the documentation of this file.
1 /*
2  * This program is is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * @file src/lib/eap_aka_sim/crypto.c
19  * @brief Calculate keys from GSM vectors.
20  *
21  * The development of the original EAP/SIM support was funded by Internet Foundation
22  * Austria (http://www.nic.at/ipa). The original EAP-SIM PRF functions were written
23  * by Michael Richardson <mcr@sandelman.ottawa.on.ca>, but these have since been
24  * replaced.
25  *
26  * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
27  *
28  * @copyright 2003-2018 The FreeRADIUS server project
29  * @copyright 2016-2018 Network RADIUS (legal@networkradius.com)
30  */
31 RCSID("$Id: 946594c6041f5f3b5eba06aff53110e09ce06074 $")
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 
36 #include <freeradius-devel/protocol/eap/aka-sim/dictionary.h>
37 
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>
48 
49 #include "base.h"
50 #include "attrs.h"
51 #include "crypto_priv.h"
52 
53 /** Used for every non-persistent EVP_CIPHER operation in this library
54  *
55  * Avoids memory churn allocating and freeing the ctx for each operation.
56  */
57 static _Thread_local EVP_CIPHER_CTX *evp_chipher_ctx;
58 
59 static int _evp_cipher_ctx_free_on_exit(void *arg)
60 {
61  EVP_CIPHER_CTX_free(arg);
62  return 0;
63 }
64 
65 /** Allocate and reset a resumable EVP_CIPHER_CTX for each thread
66  *
67  * No two crypto operations ever occur simultaneously in the same thread,
68  * so it's fine to use a single context that persists for all operations.
69  */
70 EVP_CIPHER_CTX *aka_sim_crypto_cipher_ctx(void)
71 {
72  if (unlikely(!evp_chipher_ctx)) {
73  EVP_CIPHER_CTX *ctx;
74 
75  MEM(ctx = EVP_CIPHER_CTX_new());
77  } else {
78  EVP_CIPHER_CTX_reset(evp_chipher_ctx);
79  }
80 
81  return evp_chipher_ctx;
82 }
83 
84 /** Explicitly free all thread load cipher ctxs
85  *
86  */
88 {
90  evp_chipher_ctx = NULL;
91 }
92 
93 /** Free OpenSSL memory associated with our checkcode ctx
94  *
95  * @param[in] checkcode to free.
96  * @return 0
97  */
99 {
100  if (checkcode->md_ctx) EVP_MD_CTX_destroy(checkcode->md_ctx);
101  return 0;
102 }
103 
104 /** Initialise checkcode message digest
105  *
106  * @param[in] ctx to allocate checkcode structure in.
107  * @param[out] checkcode a new checkcode structure.
108  * @param[in] md to use when calculating the checkcode,
109  * either EVP_sha1(), or EVP_sha256().
110  * @return
111  * - 0 on success.
112  * - -1 on failure.
113  */
114 int fr_aka_sim_crypto_init_checkcode(TALLOC_CTX *ctx, fr_aka_sim_checkcode_t **checkcode, EVP_MD const *md)
115 {
116  *checkcode = talloc_zero(ctx, fr_aka_sim_checkcode_t);
117  if (!*checkcode) {
118  fr_strerror_const("Out of memory");
119  return -1;
120  }
121 
122  (*checkcode)->md_ctx = EVP_MD_CTX_create();
123  if (!(*checkcode)->md_ctx) {
124  fr_tls_strerror_printf("Failed creating MD ctx");
125  error:
126  TALLOC_FREE(*checkcode);
127  return -1;
128  }
129  if (EVP_DigestInit_ex((*checkcode)->md_ctx, md, NULL) != 1) {
130  fr_tls_strerror_printf("Failed initialising MD ctx");
131  goto error;
132  }
133 
134  talloc_set_destructor(*checkcode, _fr_aka_sim_crypto_free_checkcode);
135 
136  return 0;
137 }
138 
139 /** Digest a packet, updating the checkcode
140  *
141  * Call #fr_aka_sim_crypto_finalise_checkcode to obtain the final checkcode value.
142  *
143  * @param[in,out] checkcode if *checkcode is NULL, a new checkcode structure
144  * will be allocated and the message digest context
145  * will be initialised before the provided
146  * eap_packet is fed into the digest.
147  * @param[in] eap_packet to digest.
148  * @return
149  * - 0 on success.
150  * - -1 on failure.
151  */
153 {
154  uint16_t packet_len;
155  eap_packet_raw_t eap_hdr;
156 
157  eap_hdr.code = eap_packet->code;
158  eap_hdr.id = eap_packet->id;
159  packet_len = htons((sizeof(eap_hdr) + eap_packet->type.length) & UINT16_MAX); /* EAP Header + Method + SIM data */
160  memcpy(&eap_hdr.length, &packet_len, sizeof(packet_len));
161  eap_hdr.data[0] = eap_packet->type.num;
162 
163  FR_PROTO_HEX_DUMP((void *)&eap_hdr, sizeof(eap_hdr), "Ingesting checkcode EAP header");
164 
165  /*
166  * Digest the header
167  */
168  if (EVP_DigestUpdate(checkcode->md_ctx, &eap_hdr, sizeof(eap_hdr)) != 1) {
169  fr_tls_strerror_printf("Failed digesting EAP header");
170  return -1;
171  }
172 
173  FR_PROTO_HEX_DUMP((void *)eap_packet->type.data, eap_packet->type.length, "Ingesting checkcode EAP data");
174 
175  /*
176  * Digest the packet
177  */
178  if (EVP_DigestUpdate(checkcode->md_ctx, eap_packet->type.data, eap_packet->type.length) != 1) {
179  fr_tls_strerror_printf("Failed digesting packet data");
180  return -1;
181  }
182 
183  return 0;
184 }
185 
186 /** Write out the final checkcode value
187  *
188  * @param[in] ctx ctx to allocate buffer containing the checkcode.
189  * @param[out] out talloced buffer containing the checkcode.
190  * bytes if MD was SHA1, or 32 bytes if MD was SHA256.
191  * @param[in,out] checkcode structure to get final digest from and to tree.
192  * @return
193  * - <= 0 on failure.
194  * - > 0 the number of bytes written to out.
195  */
197 {
198  size_t len;
199  uint8_t *buff;
200 
201  len = (size_t)EVP_MD_CTX_size((*checkcode).md_ctx);
202  MEM(buff = talloc_array(ctx, uint8_t, len));
203  if (EVP_DigestFinal_ex((*checkcode).md_ctx, buff, NULL) != 1) {
204  fr_tls_strerror_printf("Failed finalising checkcode digest");
205  return -1;
206  }
207  *out = buff;
208 
209  return (size_t)len;
210 }
211 
212 /** Locate the start of the AT_MAC value in the buffer
213  *
214  * @param[out] out The start of the digest portion of the AT_MAC attribute.
215  * @param[in] data to search for the AT_MAC in.
216  * @param[in] data_len size of the data.
217  * @return
218  * - 1 if we couldn't find a MAC.
219  * - 0 if we found and zeroed out the mac field.
220  * - -1 if the field was malformed.
221  */
222 static int fr_aka_sim_find_mac(uint8_t const **out, uint8_t *data, size_t data_len)
223 {
224  uint8_t *p = data, *end = p + data_len;
225  size_t len;
226 
227  *out = NULL;
228 
229  p += 3; /* Skip header */
230  while ((p + 2) < end) {
231  if (p[0] == FR_MAC) {
232  len = p[1] << 2;
233  if ((p + len) > end) {
234  fr_strerror_printf("Malformed AT_MAC: Length (%zu) exceeds buffer (%zu)", len, end - p);
235  return -1;
236  }
237 
238  if (len != AKA_SIM_MAC_SIZE) {
239  fr_strerror_printf("Malformed AT_MAC: Length (%zu) incorrect (%u)",
240  len, AKA_SIM_MAC_SIZE);
241  return -1;
242  }
243  *out = p + 4;
244 
245  return 0;
246  }
247  p += p[1] << 2; /* Advance */
248  }
249 
250  fr_strerror_const("No MAC attribute found");
251 
252  return 1;
253 }
254 
255 /** Calculate the digest value for a packet
256  *
257  * Run a digest over a fake EAP header, the entire SIM packet and any extra HMAC data,
258  * writing a truncated (16 byte) digest value to out.
259  *
260  * @note The 16 byte digest field in the packet must have either been zeroed out before
261  * this function is called (as it is when encoding data), or zero_mac must be set
262  * to true.
263  *
264  * @note This function uses the EVP_* signing functions. Do not be tempted to swap them
265  * for the HMAC functions, as the EVP interface may be hardware accelerated but
266  * the HMAC interface is purely a software implementation.
267  *
268  * @param[out] out Where to write the digest.
269  * @param[in] eap_packet to extract header values from.
270  * @param[in] zero_mac Assume the mac field is not zeroed (i.e. received packet)
271  * and skip it during mac calculation feeding in 16 zeroed
272  * bytes in its place.
273  * @param[in] md to use to create the HMAC.
274  * @param[in] key to use to sign the packet.
275  * @param[in] key_len Length of the key.
276  * @param[in] hmac_extra data to concatenate with the packet when calculating the HMAC
277  * (may be NULL).
278  * @param[in] hmac_extra_len Length of hmac_extra (may be zero).
279  * @return
280  * - < 0 on failure.
281  * - 0 if there's no MAC attribute to verify.
282  * - > 0 the number of bytes written to out.
283  */
285  eap_packet_t *eap_packet, bool zero_mac,
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)
288 {
289  EVP_MD_CTX *md_ctx = NULL;
290  EVP_PKEY *pkey;
291 
292  uint8_t digest[SHA256_DIGEST_LENGTH];
293  size_t digest_len = sizeof(digest);
294  uint8_t const *mac;
295  uint8_t *p = eap_packet->type.data, *end = p + eap_packet->type.length;
296 
297  eap_packet_raw_t eap_hdr;
298  uint16_t packet_len;
299 
300  if (unlikely(!eap_packet)) {
301  fr_strerror_const("Invalid argument: eap_packet is NULL");
302  return -1;
303  }
304 
305  if (unlikely(!md)) {
306  fr_strerror_const("Invalid argument: md is NULL");
307  return -1;
308  }
309 
310  if (unlikely(!key) || (key_len == 0)) {
311  fr_strerror_const("Invalid argument: key is NULL");
312  return -1;
313  }
314 
315  FR_PROTO_HEX_DUMP(key, key_len, "MAC key");
316  pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, key_len);
317  if (!pkey) {
318  fr_tls_strerror_printf("Failed creating HMAC signing key");
319  error:
320  if (pkey) EVP_PKEY_free(pkey);
321  if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
322  return -1;
323  }
324 
325  md_ctx = EVP_MD_CTX_create();
326  if (!md_ctx) {
327  fr_tls_strerror_printf("Failed creating HMAC ctx");
328  goto error;
329  }
330 
331  if (EVP_DigestSignInit(md_ctx, NULL, md, NULL, pkey) != 1) {
332  fr_tls_strerror_printf("Failed initialising digest");
333  goto error;
334  }
335 
336  /*
337  * The HMAC has to be over the entire packet, which
338  * we don't get access too. So we create a fake EAP
339  * header now, and feed that into the HMAC function.
340  */
341  eap_hdr.code = eap_packet->code;
342  eap_hdr.id = eap_packet->id;
343  packet_len = htons((sizeof(eap_hdr) + eap_packet->type.length) & UINT16_MAX); /* EAP Header + Method + SIM data */
344  memcpy(&eap_hdr.length, &packet_len, sizeof(packet_len));
345  eap_hdr.data[0] = eap_packet->type.num;
346 
347  FR_PROTO_HEX_DUMP((uint8_t *)&eap_hdr, sizeof(eap_hdr), "MAC digest input (eap header)");
348  if (EVP_DigestSignUpdate(md_ctx, &eap_hdr, sizeof(eap_hdr)) != 1) {
349  fr_tls_strerror_printf("Failed digesting EAP data");
350  goto error;
351  }
352 
353  /*
354  * Digest the packet up to the AT_MAC, value, then
355  * digest 16 bytes of zero.
356  */
357  if (zero_mac) {
358  switch (fr_aka_sim_find_mac(&mac, p, end - p)) {
359  case 0:
360  {
361  uint8_t zero[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
363 
364  FR_PROTO_HEX_DUMP(p, mac - p, "MAC digest input");
365 
366  /*
367  * Digest everything up to the hash
368  * part of the AT_MAC, including
369  * AT_MAC header and reserved bytes.
370  */
371  if (EVP_DigestSignUpdate(md_ctx, p, mac - p) != 1) {
372  fr_tls_strerror_printf("Failed digesting packet data (before MAC)");
373  goto error;
374  }
375  p += mac - p;
376 
377 
378  FR_PROTO_HEX_DUMP(zero, sizeof(zero), "MAC digest input");
379  /*
380  * Feed in 16 bytes of zeroes to
381  * simulated the zeroed out Mac.
382  */
383  if (EVP_DigestSignUpdate(md_ctx, zero, sizeof(zero)) != 1) {
384  fr_tls_strerror_printf("Failed digesting zeroed MAC");
385  goto error;
386  }
387  p += sizeof(zero);
388  }
389  break;
390 
391  case 1:
392  return 0;
393 
394  case -1:
395  fr_assert(0); /* Should have been checked by encoder or decoder */
396  goto error;
397  }
398  }
399 
400  if (p < end) {
401  FR_PROTO_HEX_DUMP(p, (end - p), "MAC digest input");
402 
403  /*
404  * Digest the rest of the packet.
405  */
406  if (EVP_DigestSignUpdate(md_ctx, p, end - p) != 1) {
407  fr_tls_strerror_printf("Failed digesting packet data");
408  goto error;
409  }
410  }
411 
412  /*
413  * Digest any HMAC concatenated data
414  *
415  * Some subtypes require the HMAC to be calculated over
416  * a concatenation of packet data, and something extra...
417  */
418  if (hmac_extra) {
419  FR_PROTO_HEX_DUMP(hmac_extra, hmac_extra_len, "MAC digest input (extra)");
420  if (EVP_DigestSignUpdate(md_ctx, hmac_extra, hmac_extra_len) != 1) {
421  fr_tls_strerror_printf("Failed digesting HMAC extra data");
422  goto error;
423  }
424  }
425 
426  if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1) {
427  fr_tls_strerror_printf("Failed finalising digest");
428  goto error;
429  }
430 
431  FR_PROTO_HEX_DUMP(digest, digest_len, "MAC");
432 
433  /*
434  * Truncate by four bytes.
435  */
436  memcpy(out, digest, 16);
437 
438  EVP_PKEY_free(pkey);
439  EVP_MD_CTX_destroy(md_ctx);
440 
441  return 16; /* AT_MAC (1), LEN (1), RESERVED (2) */
442 }
443 
444 /** Key Derivation Function as described in RFC4186 (EAP-SIM) section 7
445  *
446  @verbatim
447  MK = SHA1(Identity|n*Kc| NONCE_MT| Version List| Selected Version)
448  FK = PRF(MK)
449  K_encr = FK[0..127]
450  K_aut = FK[128..255]
451  MSK = FK[256..767]
452  EMSK = FK[768..1279]
453  @endverbatim
454  * @note expects keys to contain a AKA_SIM_VECTOR_GSM.
455  *
456  * @param[in,out] keys Contains the authentication vectors and the buffers
457  * to store the result of the derivation.
458  * @return
459  * - 0 on success.
460  * - -1 on failure.
461  */
463 {
465  uint8_t fk[160];
466 
467  uint8_t buf[AKA_SIM_MAX_STRING_LENGTH + sizeof(keys->gsm.nonce_mt) + 2 + sizeof(keys->gsm.version_select)];
468  uint8_t *p;
469 
470  if (!fr_cond_assert(keys->vector_type == AKA_SIM_VECTOR_GSM)) return -1;
471 
472  /*
473  * Our stack buffer should be large enough in
474  * all cases.
475  */
476  if (!fr_cond_assert((keys->identity_len +
478  sizeof(keys->gsm.nonce_mt) +
479  keys->gsm.version_list_len +
480  sizeof(keys->gsm.version_select)) <= sizeof(buf))) return -1;
481 
482  p = buf;
483  memcpy(p, keys->identity, keys->identity_len);
484  p += keys->identity_len;
485 
486  memcpy(p, keys->gsm.vector[0].kc, AKA_SIM_VECTOR_GSM_KC_SIZE);
488 
489  memcpy(p, keys->gsm.vector[1].kc, AKA_SIM_VECTOR_GSM_KC_SIZE);
491 
492  memcpy(p, keys->gsm.vector[2].kc, AKA_SIM_VECTOR_GSM_KC_SIZE);
494 
495  memcpy(p, keys->gsm.nonce_mt, sizeof(keys->gsm.nonce_mt));
496  p += sizeof(keys->gsm.nonce_mt);
497 
498  memcpy(p, keys->gsm.version_list, keys->gsm.version_list_len);
499  p += keys->gsm.version_list_len;
500 
501  memcpy(p, keys->gsm.version_select, sizeof(keys->gsm.version_select));
502  p += sizeof(keys->gsm.version_select);
503 
504  FR_PROTO_HEX_DUMP(buf, p - buf, "Identity || n*Kc || NONCE_MT || Version List || Selected Version");
505 
506  /*
507  * Do the master key first
508  */
510  fr_sha1_update(&context, buf, p - buf);
511  fr_sha1_final(keys->mk, &context);
512  keys->mk_len = AKA_SIM_MK_SIZE;
513 
514  FR_PROTO_HEX_DUMP(keys->mk, keys->mk_len, "Master key");
515 
516  /*
517  * Now use the PRF to expand it, generated
518  * k_aut, k_encr, MSK and EMSK.
519  */
520  fr_aka_sim_fips186_2prf(fk, keys->mk);
521 
522  /*
523  * Split up the result
524  */
525  p = fk;
526  memcpy(keys->k_encr, p, 16); /* 128 bits for encryption */
527  p += 16;
528  FR_PROTO_HEX_DUMP(keys->k_encr, sizeof(keys->k_encr), "K_encr");
529 
530  memcpy(keys->k_aut, p, EAP_AKA_SIM_AUTH_SIZE); /* 128 bits for auth */
533  FR_PROTO_HEX_DUMP(keys->k_aut, keys->k_aut_len, "K_aut");
534 
535  memcpy(keys->msk, p, 64); /* 64 bytes for Master Session Key */
536  p += 64;
537  FR_PROTO_HEX_DUMP(keys->msk, sizeof(keys->msk), "K_msk");
538 
539  memcpy(keys->emsk, p, 64); /* 64 bytes for Extended Master Session Key */
540  FR_PROTO_HEX_DUMP(keys->emsk, sizeof(keys->emsk), "K_emsk");
541 
542  return 0;
543 }
544 
545 /** Key Derivation Function as described in RFC4187 (EAP-AKA) section 7
546  *
547  * @note expects keys to contain a AKA_SIM_VECTOR_UMTS.
548  *
549  @verbatim
550  MK = SHA1(Identity|IK|CK)
551  FK = PRF(MK)
552  K_encr = FK[0..127]
553  K_aut = FK[128..255]
554  MSK = FK[256..767]
555  EMSK = FK[768..1279]
556  @endverbatim
557  *
558  * @param[in,out] keys Contains the authentication vectors and the buffers
559  * to store the result of the derivation.
560  * @return
561  * - 0 on success.
562  * - -1 on failure.
563  */
565 {
567  uint8_t fk[160];
568  uint8_t buf[AKA_SIM_MAX_STRING_LENGTH + sizeof(keys->umts.vector.ik) + sizeof(keys->umts.vector.ck)];
569  uint8_t *p;
570  size_t blen;
571 
572  if (!fr_cond_assert(keys->vector_type == AKA_SIM_VECTOR_UMTS)) return - 1;
573 
574  /*
575  * Our stack buffer should be large enough in
576  * all cases.
577  */
578  if (!fr_cond_assert((keys->identity_len +
579  sizeof(keys->umts.vector.ik) +
580  sizeof(keys->umts.vector.ck)) <= sizeof(buf))) return -1;
581 
582  p = buf;
583  memcpy(p, keys->identity, keys->identity_len);
584  p += keys->identity_len;
585 
586  memcpy(p, keys->umts.vector.ik, sizeof(keys->umts.vector.ik));
587  p += sizeof(keys->umts.vector.ik);
588 
589  memcpy(p, keys->umts.vector.ck, sizeof(keys->umts.vector.ck));
590  p += sizeof(keys->umts.vector.ck);
591 
592  blen = p - buf;
593 
594  /* do the master key first */
596  fr_sha1_update(&context, buf, blen);
597  fr_sha1_final(keys->mk, &context);
598  keys->mk_len = AKA_SIM_MK_SIZE;
599 
600  /*
601  * now use the PRF to expand it, generated k_aut, k_encr,
602  * MSK and EMSK.
603  */
604  fr_aka_sim_fips186_2prf(fk, keys->mk);
605 
606  /* split up the result */
607  p = fk;
608 
609  memcpy(keys->k_encr, p, 16); /* 128 bits for encryption */
610  p += 16;
611 
612  memcpy(keys->k_aut, p, EAP_AKA_AUTH_SIZE); /* 128 bits for auth */
613  p += EAP_AKA_AUTH_SIZE;
615 
616  memcpy(keys->msk, p, 64); /* 64 bytes for Master Session Key */
617  p += 64;
618 
619  memcpy(keys->emsk, p, 64); /* 64 bytes for Extended Master Session Key */
620 
621  return 0;
622 }
623 
624 /** Key Derivation Function (CK', IK') as specified in 3GPP.33.402
625  *
626  @verbatim
627  CK' || IK' = HMAC-SHA-256(Key, S)
628  S = FC || P0 || L0 || P1 || L1 || ... || Pn || Ln
629  Key = CK || IK
630  FC = 0x20
631  P0 = access network identity (3GPP TS 24.302)
632  L0 = length of access network identity (2 octets, big endian)
633  P1 = SQN xor AK (if AK is not used, AK is treated as 000..0
634  L1 = 0x00 0x06
635  @endverbatim
636  *
637  * @note expects keys to contain a AKA_SIM_VECTOR_UMTS.
638  *
639  * @param[in,out] keys Contains the authentication vectors and the buffers
640  * to store the result of the derivation.
641  * @return
642  * - 0 on success.
643  * - -1 on failure.
644  */
646 {
647  uint8_t digest[sizeof(keys->ik_prime) + sizeof(keys->ck_prime)];
648  size_t digest_len = sizeof(digest);
649 
650  uint8_t sqn_ak_buff[MILENAGE_SQN_SIZE];
651  uint16_t l0, l1;
652 
653  uint8_t k[sizeof(keys->umts.vector.ik) + sizeof(keys->umts.vector.ck)];
654  uint8_t s[sizeof(uint8_t) + AKA_SIM_MAX_STRING_LENGTH + sizeof(l0) + AKA_SIM_SQN_AK_SIZE + sizeof(l1)];
655 
656  uint8_t *p = s;
657 
658  size_t s_len;
659  EVP_PKEY *pkey;
660  EVP_MD_CTX *md_ctx = NULL;
661 
662  if (!fr_cond_assert(keys->vector_type == AKA_SIM_VECTOR_UMTS)) return -1;
663 
664  uint48_to_buff(sqn_ak_buff, keys->sqn ^ uint48_from_buff(keys->umts.vector.ak));
665 
666  /*
667  * Our stack buffer should be large enough in
668  * all cases.
669  */
670  if (!fr_cond_assert((sizeof(uint8_t) +
671  keys->network_len +
672  sizeof(l0) +
674  sizeof(l1)) <= sizeof(s))) return -1;
675 
676  FR_PROTO_HEX_DUMP(keys->network, keys->network_len, "Network");
677  FR_PROTO_HEX_DUMP(keys->umts.vector.ck, sizeof(keys->umts.vector.ck), "CK");
678  FR_PROTO_HEX_DUMP(keys->umts.vector.ik, sizeof(keys->umts.vector.ik), "IK");
679  FR_PROTO_HEX_DUMP(sqn_ak_buff, AKA_SIM_SQN_AK_SIZE, "SQN ⊕ AK");
680 
681  /*
682  * FC || P0 || L0 || P1 || L1 || ... || Pn || Ln
683  */
684  *p++ = 0x20;
685  memcpy(p, keys->network, keys->network_len);
686  p += keys->network_len;
687 
688  l0 = htons((uint16_t)keys->network_len);
689  memcpy(p, &l0, sizeof(l0));
690  p += sizeof(l0);
691 
692  memcpy(p, sqn_ak_buff, AKA_SIM_SQN_AK_SIZE);
693  p += AKA_SIM_SQN_AK_SIZE;
694 
695  l1 = htons(AKA_SIM_SQN_AK_SIZE);
696  memcpy(p, &l1, sizeof(l1));
697  p += sizeof(l1);
698 
699  s_len = p - s;
700 
701  FR_PROTO_HEX_DUMP(s, s_len, "FC || P0 || L0 || P1 || L1 || ... || Pn || Ln");
702 
703  /*
704  * CK || IK
705  */
706  p = k;
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));
710 
711  FR_PROTO_HEX_DUMP(k, sizeof(k), "CK || IK");
712 
713  pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, k, sizeof(k));
714  if (!pkey) {
715  fr_tls_strerror_printf("Failed creating HMAC signing key");
716  error:
717  if (pkey) EVP_PKEY_free(pkey);
718  if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
719  return -1;
720  }
721 
722  md_ctx = EVP_MD_CTX_create();
723  if (!md_ctx) {
724  fr_tls_strerror_printf("Failed creating HMAC ctx");
725  goto error;
726  }
727 
728  if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
729  fr_tls_strerror_printf("Failed initialising digest");
730  goto error;
731  }
732 
733  if (EVP_DigestSignUpdate(md_ctx, s, s_len) != 1) goto error;
734  if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1) goto error;
735 
736  memcpy(keys->ik_prime, digest, sizeof(keys->ik_prime));
737  memcpy(keys->ck_prime, digest + sizeof(keys->ik_prime), sizeof(keys->ck_prime));
738 
739  FR_PROTO_HEX_DUMP(keys->ck_prime, sizeof(keys->ck_prime), "CK'");
740  FR_PROTO_HEX_DUMP(keys->ik_prime, sizeof(keys->ik_prime), "IK'");
741 
742  EVP_MD_CTX_destroy(md_ctx);
743  EVP_PKEY_free(pkey);
744 
745  return 0;
746 }
747 
748 /** PRF as described in RFC 5448 (EAP-AKA') section 3.4.1
749  *
750  @verbatim
751  PRF'(K,S) = T1 | T2 | T3 | T4 | ...
752 
753  where:
754  T1 = HMAC-SHA-256 (K, S | 0x01)
755  T2 = HMAC-SHA-256 (K, T1 | S | 0x02)
756  T3 = HMAC-SHA-256 (K, T2 | S | 0x03)
757  T4 = HMAC-SHA-256 (K, T3 | S | 0x04)
758  ...
759  @endverbatim
760  *
761  * PRF' produces as many bits of output as is needed.
762  *
763  * @param[out] out Where to write the output of the PRF.
764  * @param[in] outlen how many bytes need to be generated.
765  * @param[in] key for the PRF (K).
766  * @param[in] key_len Length of key data.
767  * @param[in] in Data to feed into the PRF (S).
768  * @param[in] in_len Length of input data.
769  * @return
770  * - 0 on success.
771  * - -1 on failure.
772  */
773 static int aka_prime_prf(uint8_t *out, size_t outlen,
774  uint8_t const *key, size_t key_len, uint8_t const *in, size_t in_len)
775 {
776  uint8_t *p = out, *end = p + outlen;
777  uint8_t c = 0;
778  uint8_t digest[SHA256_DIGEST_LENGTH];
779  EVP_PKEY *pkey;
780  EVP_MD_CTX *md_ctx = NULL;
781 
782  pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, key_len);
783  if (!pkey) {
784  fr_tls_strerror_printf("Failed creating HMAC signing key");
785  error:
786  if (pkey) EVP_PKEY_free(pkey);
787  if (md_ctx) EVP_MD_CTX_destroy(md_ctx);
788  return -1;
789  }
790 
791  md_ctx = EVP_MD_CTX_create();
792  if (!md_ctx) {
793  fr_tls_strerror_printf("Failed creating HMAC ctx");
794  goto error;
795  }
796 
797  if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
798  fr_tls_strerror_printf("Failed initialising digest");
799  goto error;
800  }
801 
802  while (p < end) {
803  size_t digest_len = sizeof(digest);
804  size_t copy;
805 
806  c++;
807 
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;/* Ingest last round */
810  if (EVP_DigestSignUpdate(md_ctx, in, in_len) != 1) goto error; /* Ingest s */
811  if (EVP_DigestSignUpdate(md_ctx, &c, sizeof(c)) != 1) goto error; /* Ingest round number */
812  if (EVP_DigestSignFinal(md_ctx, digest, &digest_len) != 1) goto error; /* Output T(i) */
813 
814  copy = end - p;
815  if (copy > digest_len) copy = digest_len;
816 
817  memcpy(p, digest, copy);
818  p += copy;
819  }
820 
821  EVP_MD_CTX_destroy(md_ctx);
822  EVP_PKEY_free(pkey);
823 
824  return 0;
825 }
826 
827 /** Key Derivation Function as described in RFC 5448 (EAP-AKA') section 3.3
828  *
829  @verbatim
830  MK = PRF'(IK'|CK',"EAP-AKA'"|Identity)
831  K_encr = MK[0..127]
832  K_aut = MK[128..383]
833  K_re = MK[384..639]
834  MSK = MK[640..1151]
835  EMSK = MK[1152..1663]
836  @endverbatim
837  *
838  * @note expects keys to contain a AKA_SIM_VECTOR_UMTS.
839  *
840  * @param[in,out] keys Contains the authentication vectors and the buffers
841  * to store the result of the derivation.
842  * @return
843  * - 0 on success.
844  * - -1 on failure.
845  */
847 {
848  uint8_t k[sizeof(keys->ck_prime) + sizeof(keys->ik_prime)];
849 #define KDF_1_S_STATIC "EAP-AKA'"
851  uint8_t *p = s;
852  size_t s_len;
853 
854  ck_ik_prime_derive(keys);
855 
856  if (!fr_cond_assert(keys->vector_type == AKA_SIM_VECTOR_UMTS)) return -1;
857 
858  /*
859  * build s, a concatenation of EAP-AKA' and Identity
860  */
861  if (!fr_cond_assert((sizeof(KDF_1_S_STATIC) - 1) + keys->identity_len <= sizeof(s))) return -1;
862 
863  memcpy(p, KDF_1_S_STATIC, sizeof(KDF_1_S_STATIC) - 1);
864  p += sizeof(KDF_1_S_STATIC) - 1;
865 
866  memcpy(p, keys->identity, keys->identity_len);
867  p += keys->identity_len;
868 
869  s_len = p - s;
870 
871  /*
872  * build k, a concatenation of IK' and CK'
873  */
874  p = k;
875  memcpy(p, keys->ck_prime, sizeof(keys->ck_prime));
876  p += sizeof(keys->ck_prime);
877 
878  memcpy(p, keys->ik_prime, sizeof(keys->ik_prime));
879 
880  /*
881  * Feed into PRF
882  */
883  keys->mk_len = AKA_PRIME_MK_SIZE;
884  if (aka_prime_prf(keys->mk, keys->mk_len, k, sizeof(k), s, s_len) < 0) return -1;
885 
886  /*
887  * Split the PRF output into separate keys
888  */
889  p = keys->mk;
890  memcpy(keys->k_encr, p, 16); /* 128 bits for encryption */
891  p += 16;
892 
893  memcpy(keys->k_aut, p, EAP_AKA_PRIME_AUTH_SIZE); /* 256 bits for aut */
896 
897  memcpy(keys->k_re, p, AKA_SIM_K_RE_SIZE); /* 256 bits for reauthentication key */
898  p += AKA_SIM_K_RE_SIZE;
899 
900  memcpy(keys->msk, p, sizeof(keys->msk)); /* 64 bytes for Master Session Key */
901  p += sizeof(keys->msk);
902 
903  memcpy(keys->emsk, p, sizeof(keys->emsk)); /* 64 bytes for Extended Master Session Key */
904 
905  return 0;
906 }
907 
908 
909 /** Initialise fr_aka_sim_keys_t with EAP-SIM reauthentication data
910  *
911  * Generates a new nonce_s and copies the mk and counter values into the fr_aka_sim_keys_t.
912  *
913  * @param[out] keys structure to populate.
914  * @param[in] mk from original authentication.
915  * @param[in] counter re-authentication counter.
916  */
918  uint8_t const mk[static AKA_SIM_MK_SIZE], uint16_t counter)
919 {
920  uint32_t nonce_s[4];
921 
922  static_assert(sizeof(keys->mk) >= AKA_SIM_MK_SIZE, "mk buffer is too small");
923 
924  /*
925  * Copy in master key
926  */
927  keys->mk_len = AKA_SIM_MK_SIZE;
928  memcpy(keys->mk, mk, keys->mk_len);
929 
930  keys->reauth.counter = counter;
931 
932  nonce_s[0] = fr_rand();
933  nonce_s[1] = fr_rand();
934  nonce_s[2] = fr_rand();
935  nonce_s[3] = fr_rand();
936  memcpy(keys->reauth.nonce_s, (uint8_t *)&nonce_s, sizeof(keys->reauth.nonce_s));
937 }
938 
939 /** Initialise fr_aka_sim_keys_t with EAP-AKA['] reauthentication data
940  *
941  * Generates a new nonce_s and copies the mk and counter values into the fr_aka_sim_keys_t.
942  *
943  * @param[out] keys structure to populate.
944  * @param[in] mk from original authentication.
945  * @param[in] counter re-authentication counter.
946  */
948  uint8_t const mk[static AKA_PRIME_MK_REAUTH_SIZE], uint16_t counter)
949 {
950  uint32_t nonce_s[4];
951 
952  static_assert(sizeof(keys->mk) >= AKA_PRIME_MK_REAUTH_SIZE, "mk buffer is too small");
953 
954  /*
955  * Copy in master key
956  */
958  memcpy(keys->mk, mk, keys->mk_len);
959 
960  keys->reauth.counter = counter;
961 
962  nonce_s[0] = fr_rand();
963  nonce_s[1] = fr_rand();
964  nonce_s[2] = fr_rand();
965  nonce_s[3] = fr_rand();
966  memcpy(keys->reauth.nonce_s, (uint8_t *)&nonce_s, sizeof(keys->reauth.nonce_s));
967 }
968 
969 /** Key Derivation Function (Fast-Reauthentication) as described in RFC4186/7 (EAP-SIM/AKA) section 7
970  *
971  @verbatim
972  XKEY' = SHA1(Identity|counter|NONCE_S|MK)
973  FK = PRF(XKEY')
974  MSK = FK[0..511]
975  EMSK = FK[512..1023]
976  @endverbatim
977  *
978  * Derives new MSK, EMSK, k_aut, k_encr
979  *
980  * Use #fr_aka_sim_crypto_keys_init_kdf_0_reauth to populate the #fr_aka_sim_keys_t structure.
981  *
982  * @note expects keys to contain a populated mk, none_s and counter values.
983  *
984  * @param[in,out] keys Contains the authentication vectors and the buffers
985  * to store the result of the derivation.
986  * @return
987  * - 0 on success.
988  * - -1 on failure.
989  */
991 {
992  EVP_MD_CTX *md_ctx;
993  uint8_t fk[160];
994 
995  uint8_t buf[384];
996  uint8_t *p;
997 
998  size_t need;
999  unsigned int len = 0;
1000 
1001  /*
1002  * RFC 4187 Section 5.1
1003  * ...
1004  * "On full authentication, both the server and
1005  * the peer initialize the counter to one."
1006  */
1007  if (keys->reauth.counter == 0) {
1008  fr_strerror_const("Re-authentication counter not initialised, must be >= 1");
1009  return -1;
1010  }
1011 
1012  if (keys->mk_len != AKA_SIM_MK_SIZE) {
1013  fr_strerror_printf("Master key is incorrect length, expected %u, got %zu", AKA_SIM_MK_SIZE,
1014  keys->mk_len);
1015  return -1;
1016  }
1017 
1018  need = keys->identity_len + sizeof(uint16_t) + AKA_SIM_NONCE_S_SIZE + keys->mk_len;
1019  if (need > sizeof(buf)) {
1020  fr_strerror_printf("Identity too long. PRF input is %zu bytes, input buffer is %zu bytes",
1021  need, sizeof(buf));
1022  return -1;
1023  }
1024 
1025  /*
1026  * Re-derive k_aut and k_encr from the original Master Key
1027  * These keys stay the same over multiple re-auth attempts.
1028  */
1029  fr_aka_sim_fips186_2prf(fk, keys->mk);
1030 
1031  p = fk;
1032  memcpy(keys->k_encr, p, 16); /* 128 bits for encryption */
1033  p += 16;
1034  FR_PROTO_HEX_DUMP(keys->k_encr, sizeof(keys->k_encr), "K_encr");
1035 
1036  memcpy(keys->k_aut, p, EAP_AKA_SIM_AUTH_SIZE); /* 128 bits for auth */
1037 
1039  FR_PROTO_HEX_DUMP(keys->k_aut, keys->k_aut_len, "K_aut");
1040 
1041  /*
1042  * Derive a new MSK and EMSK
1043  *
1044  * New PRF input is:
1045  * XKEY' = SHA1(Identity|counter|NONCE_S| MK)
1046  */
1047 
1048  /*
1049  * Identity
1050  */
1051  p = buf;
1052  memcpy(p, keys->identity, keys->identity_len);
1053  p += keys->identity_len;
1054  FR_PROTO_HEX_DUMP(keys->identity, keys->identity_len, "identity");
1055 
1056  /*
1057  * Counter
1058  */
1059  *p++ = ((keys->reauth.counter & 0xff00) >> 8);
1060  *p++ = (keys->reauth.counter & 0x00ff);
1061 
1062  /*
1063  * nonce_s
1064  */
1065  memcpy(p, keys->reauth.nonce_s, sizeof(keys->reauth.nonce_s));
1066  p += sizeof(keys->reauth.nonce_s);
1067 
1068  /*
1069  * Master key
1070  */
1071  memcpy(p, keys->mk, keys->mk_len);
1072  p += keys->mk_len;
1073 
1074  FR_PROTO_HEX_DUMP(buf, p - buf, "Identity || counter || NONCE_S || MK");
1075 
1076  /*
1077  * Digest re-auth key with SHA1
1078  */
1079  md_ctx = EVP_MD_CTX_create();
1080  if (!md_ctx) {
1081  fr_tls_strerror_printf("Failed creating MD ctx");
1082  error:
1083  EVP_MD_CTX_destroy(md_ctx);
1084  return -1;
1085  }
1086 
1087  if (EVP_DigestInit_ex(md_ctx, EVP_sha1(), NULL) != 1) {
1088  fr_tls_strerror_printf("Failed initialising digest");
1089  goto error;
1090  }
1091 
1092  if (EVP_DigestUpdate(md_ctx, buf, p - buf) != 1) {
1093  fr_tls_strerror_printf("Failed digesting crypto data");
1094  goto error;
1095  }
1096 
1097  if (EVP_DigestFinal_ex(md_ctx, keys->reauth.xkey_prime, &len) != 1) {
1098  fr_tls_strerror_printf("Failed finalising digest");
1099  goto error;
1100  }
1101 
1102  EVP_MD_CTX_destroy(md_ctx);
1103 
1104  FR_PROTO_HEX_DUMP(keys->reauth.xkey_prime, sizeof(keys->reauth.xkey_prime), "xkey'");
1105 
1106  /*
1107  * Expand XKEY' with PRF
1108  */
1109  fr_aka_sim_fips186_2prf(fk, keys->reauth.xkey_prime);
1110 
1111  /*
1112  * Split up the result
1113  */
1114  p = fk;
1115  memcpy(keys->msk, p, 64); /* 64 bytes for Master Session Key */
1116  p += 64;
1117  FR_PROTO_HEX_DUMP(keys->msk, sizeof(keys->msk), "K_msk");
1118 
1119  memcpy(keys->emsk, p, 64); /* 64 bytes for Extended Master Session Key */
1120  FR_PROTO_HEX_DUMP(keys->emsk, sizeof(keys->emsk), "K_emsk");
1121 
1122  return 0;
1123 }
1124 
1125 /** Key Derivation Function (Fast-Reauthentication) as described in RFC 5448 (EAP-AKA') section 3.3
1126  *
1127  @verbatim
1128  MK = PRF'(K_re,"EAP-AKA' re-auth"|Identity|counter|NONCE_S)
1129  MSK = MK[0..511]
1130  EMSK = MK[512..1023]
1131  @endverbatim
1132  *
1133  * @param[in,out] keys Contains the authentication vectors and the buffers
1134  * to store the result of the derivation.
1135  * @return
1136  * - 0 on success.
1137  * - -1 on failure.
1138  */
1140 {
1141 #define KDF_1_S_REAUTH_STATIC "EAP-AKA' re-auth"
1144  fr_dbuff_t dbuff;
1145 
1146  if (!fr_cond_assert(((sizeof(KDF_1_S_REAUTH_STATIC) - 1) +
1147  keys->identity_len +
1148  sizeof(uint16_t) +
1149  AKA_SIM_NONCE_S_SIZE) <= sizeof(s))) return -1;
1150 
1151  fr_dbuff_init(&dbuff, keys->mk, keys->mk_len);
1152 
1153  /*
1154  * k_encr - Taken from original MK
1155  */
1156  fr_dbuff_out_memcpy(keys->k_encr, &dbuff, sizeof(keys->k_encr));
1157  FR_PROTO_HEX_DUMP(keys->k_encr, sizeof(keys->k_encr), "K_encr");
1158 
1159  /*
1160  * k_aut - Taken from original MK
1161  */
1164  FR_PROTO_HEX_DUMP(keys->k_aut, keys->k_aut_len, "K_aut");
1165 
1166  /*
1167  * k_re - Taken from original MK
1168  */
1169  fr_dbuff_out_memcpy(keys->k_re, &dbuff, AKA_SIM_K_RE_SIZE);
1170  FR_PROTO_HEX_DUMP(keys->k_aut, AKA_SIM_K_RE_SIZE, "K_re");
1171 
1172  fr_dbuff_init(&dbuff, s, sizeof(s)); /* dbuff now points to s */
1173 
1174  /*
1175  * "EAP-AKA' re-auth"
1176  */
1178 
1179  /*
1180  * Identity
1181  */
1182  fr_dbuff_in_memcpy(&dbuff, keys->identity, keys->identity_len);
1183  FR_PROTO_HEX_DUMP(keys->identity, keys->identity_len, "identity");
1184 
1185  /*
1186  * Counter
1187  */
1188  fr_dbuff_in_bytes(&dbuff, ((keys->reauth.counter & 0xff00) >> 8), (keys->reauth.counter & 0x00ff));
1189 
1190  /*
1191  * nonce_s
1192  */
1193  fr_dbuff_in_memcpy(&dbuff, keys->reauth.nonce_s, sizeof(keys->reauth.nonce_s));
1194 
1196  "\"EAP-AKA' re-auth\" || Identity || counter || NONCE_S");
1197 
1198  /*
1199  * Feed into PRF
1200  *
1201  * Note, we don't update the mk in the keys structure
1202  * as the original MK needs to be written into session
1203  * store, it doesn't change between re-authentication
1204  * rounds.
1205  */
1206  if (aka_prime_prf(mk, sizeof(mk), keys->k_re, sizeof(keys->k_re),
1207  fr_dbuff_start(&dbuff), fr_dbuff_used(&dbuff)) < 0) return -1;
1208  FR_PROTO_HEX_DUMP(mk, sizeof(mk), "mk");
1209 
1210  fr_dbuff_init(&dbuff, mk, sizeof(mk)); /* dbuff now points to mk */
1211 
1212  fr_dbuff_out_memcpy(keys->msk, &dbuff, sizeof(keys->msk)); /* 64 bytes for msk */
1213  FR_PROTO_HEX_DUMP(keys->msk, sizeof(keys->msk), "K_msk");
1214 
1215  fr_dbuff_out_memcpy(keys->emsk, &dbuff, sizeof(keys->emsk)); /* 64 bytes for Extended Master Session Key */
1216  FR_PROTO_HEX_DUMP(keys->emsk, sizeof(keys->emsk), "K_emsk");
1217 
1218  return 0;
1219 }
1220 
1221 /** Dump the current state of all keys associated with the EAP SIM session
1222  *
1223  * @param[in] request The current request.
1224  * @param[in] keys SIM keys associated with the session.
1225  */
1227 {
1228  RDEBUG3("KDF inputs");
1229 
1230  RINDENT();
1231  RHEXDUMP_INLINE3(keys->identity, keys->identity_len,
1232  "Identity :");
1233  switch (keys->vector_type) {
1234  case AKA_SIM_VECTOR_GSM:
1235  {
1236  unsigned int i;
1237 
1238  RHEXDUMP_INLINE3(keys->gsm.nonce_mt, sizeof(keys->gsm.nonce_mt),
1239  "nonce_mt :");
1240 
1241  RHEXDUMP_INLINE3(keys->gsm.version_list, keys->gsm.version_list_len,
1242  "version_list :");
1243 
1244  for (i = 0; i < keys->gsm.num_vectors; i++) {
1245  RHEXDUMP_INLINE3(keys->gsm.vector[i].rand, AKA_SIM_VECTOR_GSM_RAND_SIZE,
1246  "[%i] RAND :", i);
1247  RHEXDUMP_INLINE3(keys->gsm.vector[i].sres, AKA_SIM_VECTOR_GSM_SRES_SIZE,
1248  "[%i] SRES :", i);
1249  RHEXDUMP_INLINE3(keys->gsm.vector[i].kc, AKA_SIM_VECTOR_GSM_KC_SIZE,
1250  "[%i] KC :", i);
1251  }
1252  }
1253  break;
1254 
1255  case AKA_SIM_VECTOR_UMTS:
1256  RHEXDUMP_INLINE3(keys->umts.vector.autn, AKA_SIM_VECTOR_UMTS_AUTN_SIZE,
1257  "AUTN :");
1258 
1259  RHEXDUMP_INLINE3(keys->umts.vector.ck, AKA_SIM_VECTOR_UMTS_CK_SIZE,
1260  "CK :");
1261 
1262  RHEXDUMP_INLINE3(keys->umts.vector.ik, AKA_SIM_VECTOR_UMTS_IK_SIZE,
1263  "IK :");
1264 
1265  RHEXDUMP_INLINE3(keys->umts.vector.rand, AKA_SIM_VECTOR_UMTS_RAND_SIZE,
1266  "RAND :");
1267 
1268  RHEXDUMP_INLINE3(keys->umts.vector.xres, keys->umts.vector.xres_len,
1269  "XRES :");
1270 
1272  "CK' :");
1273 
1275  "IK' :");
1276  break;
1277 
1279  RHEXDUMP_INLINE3(keys->mk, keys->mk_len,
1280  "MK :");
1281  RDEBUG3(
1282  "counter : %u", keys->reauth.counter);
1283  RHEXDUMP_INLINE3(keys->reauth.nonce_s, sizeof(keys->reauth.nonce_s),
1284  "nonce_s :");
1285  break;
1286 
1288  RHEXDUMP_INLINE3(keys->mk, keys->mk_len,
1289  "MK :");
1290  RDEBUG3(
1291  "counter : %u", keys->reauth.counter);
1292  RHEXDUMP_INLINE3(keys->reauth.nonce_s, sizeof(keys->reauth.nonce_s),
1293  "nonce_s :");
1294  break;
1295 
1296  case AKA_SIM_VECTOR_NONE:
1297  break;
1298  }
1299  REXDENT();
1300 
1301  RDEBUG3("Intermediary keys");
1302  RINDENT();
1303  switch (keys->vector_type) {
1305  RHEXDUMP_INLINE3(keys->reauth.xkey_prime, sizeof(keys->reauth.xkey_prime),
1306  "XKEY' :");
1307  break;
1308 
1309  default:
1310  break;
1311  }
1312  REXDENT();
1313 
1314  RDEBUG3("PRF output");
1315  RINDENT();
1316  RHEXDUMP_INLINE3(keys->mk, keys->mk_len,
1317  "MK :");
1318  RHEXDUMP_INLINE3(keys->k_re, sizeof(keys->k_re),
1319  "k_re :");
1320  RHEXDUMP_INLINE3(keys->k_aut, keys->k_aut_len,
1321  "k_aut :");
1322  RHEXDUMP_INLINE3(keys->k_encr, sizeof(keys->k_encr),
1323  "k_encr :");
1324  RHEXDUMP_INLINE3(keys->msk, sizeof(keys->msk),
1325  "MSK :");
1326  RHEXDUMP_INLINE3(keys->emsk, sizeof(keys->emsk),
1327  "EMSK :");
1328  REXDENT();
1329 }
1330 
1331 
1332 #ifdef TESTING_SIM_CRYPTO
1333 /*
1334  * cc crypto.c fips186prf.c -g3 -Wall -DHAVE_DLFCN_H -DTESTING_SIM_CRYPTO -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_sim_crypto && ./test_sim_crypto
1335  */
1336 #include <stddef.h>
1337 #include <stdbool.h>
1338 #include <freeradius-devel/util/acutest.h>
1339 
1340 /*
1341  * EAP-SIM (RFC4186) GSM authentication vectors
1342  */
1343 static fr_aka_sim_keys_t const rfc4186_vector0_in = {
1344  .identity = (uint8_t const *)"1244070100000001@eapsim.foo",
1345  .identity_len = sizeof("1244070100000001@eapsim.foo") - 1,
1346 
1347  .gsm = {
1348  .vector = {
1349  {
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 }
1354  },
1355  {
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 }
1360  },
1361  {
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 }
1366  }
1367  },
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 },
1373  .num_vectors = 3
1374  },
1375  .vector_type = AKA_SIM_VECTOR_GSM
1376 };
1377 
1378 static fr_aka_sim_keys_t const rfc4186_vector0_out = {
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 },
1383  .k_aut_len = 16,
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 }
1400 };
1401 
1402 static void test_eap_sim_kdf_0_gsm(void)
1403 {
1404  fr_aka_sim_keys_t keys;
1405  int ret;
1406 
1407 /*
1408  fr_debug_lvl = 4;
1409  printf("\n");
1410 */
1411 
1412  memcpy(&keys, &rfc4186_vector0_in, sizeof(keys));
1413 
1414  ret = fr_aka_sim_crypto_gsm_kdf_0(&keys);
1415  TEST_CHECK(ret == 0);
1416 
1417  TEST_CHECK(memcmp(&rfc4186_vector0_out.k_encr, keys.k_encr, sizeof(keys.k_encr)) == 0);
1418  TEST_CHECK(rfc4186_vector0_out.k_aut_len == keys.k_aut_len);
1419  TEST_CHECK(memcmp(&rfc4186_vector0_out.k_aut, keys.k_aut, keys.k_aut_len) == 0);
1420  TEST_CHECK(memcmp(&rfc4186_vector0_out.msk, keys.msk, sizeof(keys.msk)) == 0);
1421  TEST_CHECK(memcmp(&rfc4186_vector0_out.emsk, keys.emsk, sizeof(keys.emsk)) == 0);
1422 }
1423 
1424 /*
1425  * UMTS authentication vectors
1426  *
1427  * Test vector from 18 from 3GPP TS 35.208 V9 (the same used by EAP-AKA')
1428  */
1429 static fr_aka_sim_keys_t const rfc4187_vector0_in = {
1430  .identity = (uint8_t const *)"0555444333222111",
1431  .identity_len = sizeof("0555444333222111") - 1,
1432 
1433  .sqn = 205964772668538,
1434 
1435  .umts = {
1436  .vector = {
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 },
1446  .xres_len = 8
1447  }
1448  },
1449  .vector_type = AKA_SIM_VECTOR_UMTS
1450 };
1451 
1452 static fr_aka_sim_keys_t const rfc4187_vector0_out = {
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 },
1457  .k_aut_len = 16,
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 }
1474 };
1475 
1476 static void test_eap_aka_kdf_0_umts(void)
1477 {
1478  fr_aka_sim_keys_t keys;
1479  int ret;
1480 
1481 /*
1482  fr_debug_lvl = 4;
1483  printf("\n");
1484 */
1485 
1486  memcpy(&keys, &rfc4187_vector0_in, sizeof(keys));
1487 
1488  ret = fr_aka_sim_crypto_umts_kdf_0(&keys);
1489  TEST_CHECK(ret == 0);
1490 
1491  TEST_CHECK(memcmp(&rfc4187_vector0_out.k_encr, keys.k_encr, sizeof(keys.k_encr)) == 0);
1492  TEST_CHECK(rfc4187_vector0_out.k_aut_len == keys.k_aut_len);
1493 
1494  TEST_CHECK(memcmp(&rfc4187_vector0_out.k_aut, keys.k_aut, keys.k_aut_len) == 0);
1495  TEST_CHECK(memcmp(&rfc4187_vector0_out.msk, keys.msk, sizeof(keys.msk)) == 0);
1496  TEST_CHECK(memcmp(&rfc4187_vector0_out.emsk, keys.emsk, sizeof(keys.emsk)) == 0);
1497 }
1498 
1499 /*
1500  * EAP-SIM (RFC4186) GSM re-authentication vectors
1501  */
1502 static fr_aka_sim_keys_t const rfc4186_vector0_reauth_in = {
1503  .identity = (uint8_t const *)"Y24fNSrz8BP274jOJaF17WfxI8YO7QX00pMXk9XMMVOw7broaNhTczuFq53aEpOkk3L0dm@eapsim.foo",
1504  .identity_len = sizeof("Y24fNSrz8BP274jOJaF17WfxI8YO7QX00pMXk9XMMVOw7broaNhTczuFq53aEpOkk3L0dm@eapsim.foo") - 1,
1505 
1506  .reauth = {
1507  .counter = 1,
1508  .nonce_s = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1509  0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }
1510  },
1511  .mk = { 0xe5, 0x76, 0xd5, 0xca, 0x33, 0x2e, 0x99, 0x30,
1512  0x01, 0x8b, 0xf1, 0xba, 0xee, 0x27, 0x63, 0xc7,
1513  0x95, 0xb3, 0xc7, 0x12 },
1514 };
1515 
1516 static fr_aka_sim_keys_t const rfc4186_vector0_reauth_out = {
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 },
1521  .k_aut_len = 16,
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 }
1538 };
1539 
1540 static void test_eap_sim_kdf_0_reauth(void)
1541 {
1542  fr_aka_sim_keys_t keys;
1543  int ret;
1544 
1545 /*
1546  fr_debug_lvl = 4;
1547  printf("\n");
1548 */
1549 
1550  memcpy(&keys, &rfc4186_vector0_reauth_in, sizeof(keys));
1551 
1552  ret = fr_aka_sim_crypto_kdf_0_reauth(&keys);
1553  TEST_CHECK(ret == 0);
1554 
1555  TEST_CHECK(memcmp(&rfc4186_vector0_reauth_out.k_encr, keys.k_encr, sizeof(keys.k_encr)) == 0);
1556  TEST_CHECK(rfc4186_vector0_reauth_out.k_aut_len == keys.k_aut_len);
1557  TEST_CHECK(memcmp(&rfc4186_vector0_reauth_out.k_aut, keys.k_aut, keys.k_aut_len) == 0);
1558  TEST_CHECK(memcmp(&rfc4186_vector0_reauth_out.msk, keys.msk, sizeof(keys.msk)) == 0);
1559  TEST_CHECK(memcmp(&rfc4186_vector0_reauth_out.emsk, keys.emsk, sizeof(keys.emsk)) == 0);
1560 }
1561 
1562 
1563 /*
1564  * EAP-AKA' (RFC5448) UMTS authentication vectors
1565  */
1566 static fr_aka_sim_keys_t const rfc5448_vector0_in = {
1567  .identity = (uint8_t const *)"0555444333222111",
1568  .identity_len = sizeof("0555444333222111") - 1,
1569 
1570  .network = (uint8_t const *)"WLAN",
1571  .network_len = sizeof("WLAN") - 1,
1572 
1573  .sqn = 205964772668538,
1574 
1575  .umts = {
1576  .vector = {
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 },
1586  .xres_len = 8
1587  }
1588  },
1589  .vector_type = AKA_SIM_VECTOR_UMTS
1590 };
1591 
1592 static fr_aka_sim_keys_t const rfc5448_vector0_out = {
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 },
1597 
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 },
1604  .k_aut_len = 32,
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 }
1625 };
1626 
1627 static void test_eap_aka_kdf_1_umts(void)
1628 {
1629  fr_aka_sim_keys_t keys;
1630  int ret;
1631 
1632 /*
1633  fr_debug_lvl = 4;
1634  printf("\n");
1635 */
1636 
1637  memcpy(&keys, &rfc5448_vector0_in, sizeof(keys));
1638 
1639  memcpy(keys.ck_prime, rfc5448_vector0_out.ck_prime, sizeof(keys.ck_prime));
1640  memcpy(keys.ik_prime, rfc5448_vector0_out.ik_prime, sizeof(keys.ik_prime));
1641 
1642  ret = fr_aka_sim_crypto_umts_kdf_1(&keys);
1643  TEST_CHECK(ret == 0);
1644 
1645  TEST_CHECK(memcmp(&rfc5448_vector0_out.k_encr, keys.k_encr, sizeof(keys.k_encr)) == 0);
1646  TEST_CHECK(rfc5448_vector0_out.k_aut_len == keys.k_aut_len);
1647  TEST_CHECK(memcmp(&rfc5448_vector0_out.k_aut, keys.k_aut, keys.k_aut_len) == 0);
1648  TEST_CHECK(memcmp(&rfc5448_vector0_out.k_re, keys.k_re, sizeof(keys.k_re)) == 0);
1649  TEST_CHECK(memcmp(&rfc5448_vector0_out.msk, keys.msk, sizeof(keys.msk)) == 0);
1650  TEST_CHECK(memcmp(&rfc5448_vector0_out.emsk, keys.emsk, sizeof(keys.emsk)) == 0);
1651 }
1652 
1653 static void test_eap_aka_derive_ck_ik(void)
1654 {
1655 
1656  fr_aka_sim_keys_t keys;
1657  int ret;
1658 
1659 /*
1660  fr_debug_lvl = 4;
1661  printf("\n");
1662 */
1663 
1664  memcpy(&keys, &rfc5448_vector0_in, sizeof(keys));
1665  ret = ck_ik_prime_derive(&keys);
1666  TEST_CHECK(ret == 0);
1667  TEST_CHECK(memcmp(&rfc5448_vector0_out.ck_prime, keys.ck_prime, sizeof(keys.ck_prime)) == 0);
1668  TEST_CHECK(memcmp(&rfc5448_vector0_out.ik_prime, keys.ik_prime, sizeof(keys.ik_prime)) == 0);
1669 }
1670 
1671 /*
1672  * EAP-AKA' (RFC5448) UMTS authentication vectors
1673  */
1674 static fr_aka_sim_keys_t const rfc5448_vector0_reauth_in = {
1675  .identity = (uint8_t const *)"5555444333222111",
1676  .identity_len = sizeof("5555444333222111") - 1,
1677 
1678  .network = (uint8_t const *)"WLAN",
1679  .network_len = sizeof("WLAN") - 1,
1680 
1681  .reauth = {
1682  .counter = 1,
1683  .nonce_s = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
1684  0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }
1685  },
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 },
1692  .k_aut_len = 32,
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 }
1697 };
1698 
1699 /*
1700  * Not tested against external source (yet)
1701  */
1702 static fr_aka_sim_keys_t const rfc5448_vector0_reauth_out = {
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 },
1709  .k_aut_len = 32,
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 }
1726 };
1727 
1728 static void test_eap_aka_kdf_1_reauth(void)
1729 {
1730  fr_aka_sim_keys_t keys;
1731  int ret;
1732 
1733 /*
1734  fr_debug_lvl = 4;
1735  printf("\n");
1736 */
1737 
1738  memcpy(&keys, &rfc5448_vector0_reauth_in, sizeof(keys));
1739 
1741  TEST_CHECK(ret == 0);
1742 
1743  TEST_CHECK(memcmp(&rfc5448_vector0_reauth_out.k_encr, keys.k_encr, sizeof(keys.k_encr)) == 0);
1744  TEST_CHECK(rfc5448_vector0_reauth_out.k_aut_len == keys.k_aut_len);
1745  TEST_CHECK(memcmp(&rfc5448_vector0_reauth_out.k_aut, keys.k_aut, keys.k_aut_len) == 0);
1746  TEST_CHECK(memcmp(&rfc5448_vector0_reauth_out.msk, keys.msk, sizeof(keys.msk)) == 0);
1747  TEST_CHECK(memcmp(&rfc5448_vector0_reauth_out.emsk, keys.emsk, sizeof(keys.emsk)) == 0);
1748 }
1749 
1750 
1751 TEST_LIST = {
1752  /*
1753  * EAP-SIM
1754  */
1755  { "test_eap_sim_kdf_0_gsm", test_eap_sim_kdf_0_gsm },
1756 
1757  /*
1758  * EAP-AKA
1759  */
1760  { "test_eap_aka_kdf_0_umts", test_eap_aka_kdf_0_umts },
1761 
1762  /*
1763  * EAP-SIM/EAP-AKA
1764  */
1765  { "test_eap_sim_kdf_0_reauth", test_eap_sim_kdf_0_reauth },
1766 
1767  /*
1768  * EAP-AKA'
1769  */
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 },
1773 
1774 
1775  { NULL }
1776 };
1777 #endif
1778 
#define TEST_CHECK(cond)
Definition: acutest.h:85
#define TEST_LIST
Definition: acutest.h:62
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.
Definition: atexit.c:331
#define fr_atexit_thread_local(_name, _free, _uctx)
Definition: atexit.h:221
static int context
Definition: radmin.c:71
#define RCSID(id)
Definition: build.h:444
#define static_assert
For systems with an old version libc, define static_assert.
Definition: build.h:35
#define unlikely(_x)
Definition: build.h:378
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
eap_type_data_t type
Definition: compose.h:39
eap_code_t code
Definition: compose.h:36
uint8_t id
Definition: compose.h:37
Structure to hold EAP data.
Definition: compose.h:35
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...
Definition: dbuff.h:762
#define fr_dbuff_init(_out, _start, _len_or_end)
Initialise an dbuff for encoding or decoding.
Definition: dbuff.h:354
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition: dbuff.h:893
#define fr_dbuff_out_memcpy(_out, _dbuff_or_marker, _outlen)
Copy exactly _outlen bytes from the dbuff.
Definition: dbuff.h:1724
#define fr_dbuff_in_bytes(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker.
Definition: dbuff.h:1460
#define fr_dbuff_in_memcpy(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into a dbuff or marker.
Definition: dbuff.h:1345
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:137
static fr_slen_t in
Definition: dict.h:645
eap_type_t num
Definition: types.h:110
uint8_t data[1]
Definition: types.h:125
size_t length
Definition: types.h:111
uint8_t code
Definition: types.h:122
uint8_t * data
Definition: types.h:112
uint8_t length[2]
Definition: types.h:124
uint8_t id
Definition: types.h:123
Structure to represent packet format of eap on wire
Definition: types.h:121
uint8_t * identity
Identity from AT_IDENTITY.
Definition: base.h:152
#define AKA_SIM_VECTOR_UMTS_RAND_SIZE
Definition: base.h:73
#define AKA_SIM_VECTOR_GSM_RAND_SIZE
Length of RAND in GSM triplet.
Definition: base.h:65
uint8_t * network
Network name (EAP-AKA-Prime only).
Definition: base.h:155
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.
Definition: fips186prf.c:91
size_t mk_len
Definition: base.h:212
#define AKA_SIM_VECTOR_GSM_SRES_SIZE
Length of SRES in GSM triplet.
Definition: base.h:66
uint8_t emsk[64]
Derived extended master session key.
Definition: base.h:228
size_t network_len
Length of the network name (EAP-AKA-Prime only).
Definition: base.h:156
#define AKA_SIM_NONCE_S_SIZE
Length of re-authentication nonce.
Definition: base.h:46
uint8_t ik_prime[AKA_SIM_VECTOR_UMTS_IK_SIZE]
Derived from IK, for AKA'.
Definition: base.h:219
uint64_t sqn
Sequence number.
Definition: base.h:158
#define AKA_SIM_MAC_SIZE
Length of MAC used to prevent packet modification.
Definition: base.h:43
#define AKA_PRIME_MK_REAUTH_SIZE
The portion of the MK used for re-auth.
Definition: base.h:57
#define AKA_SIM_SQN_AK_SIZE
Definition: base.h:45
#define AKA_SIM_K_RE_SIZE
Reauthentication key size.
Definition: base.h:61
#define EAP_AKA_AUTH_SIZE
Definition: base.h:84
#define AKA_SIM_VECTOR_UMTS_CK_SIZE
Definition: base.h:70
#define AKA_SIM_MAX_STRING_LENGTH
Maximum size of a SIM/AKA['] string ((4 * 255) - 4).
Definition: base.h:40
uint8_t ck_prime[AKA_SIM_VECTOR_UMTS_CK_SIZE]
Derived from CK, for AKA'.
Definition: base.h:218
size_t identity_len
Length of the identity.
Definition: base.h:153
#define EAP_AKA_PRIME_AUTH_SIZE
Definition: base.h:85
#define AKA_PRIME_MK_SIZE
Definition: base.h:55
#define AKA_SIM_MK_SIZE
Definition: base.h:54
uint8_t k_aut[32]
Derived authentication key.
Definition: base.h:224
#define AKA_SIM_VECTOR_GSM_KC_SIZE
Length of Kc in GSM triplet.
Definition: base.h:67
size_t k_aut_len
Length of k_aut. 16 for AKA/SIM, 32 for AKA'.
Definition: base.h:225
uint8_t k_re[AKA_SIM_K_RE_SIZE]
Derived reauthentication key for AKA'(kdf 1).
Definition: base.h:213
#define AKA_SIM_MAC_DIGEST_SIZE
Length of MAC used to prevent packet modification.
Definition: base.h:42
#define AKA_SIM_VECTOR_UMTS_IK_SIZE
Definition: base.h:71
uint8_t k_encr[16]
Derived encryption key.
Definition: base.h:226
#define AKA_SIM_VECTOR_UMTS_AUTN_SIZE
Definition: base.h:69
EVP_MD_CTX * md_ctx
Context to hold state of digest as we consume packets.
Definition: base.h:141
@ AKA_SIM_VECTOR_GSM
Vector is GSM triplets.
Definition: base.h:91
@ AKA_SIM_VECTOR_UMTS_REAUTH_KDF_1_REAUTH
Definition: base.h:94
@ AKA_SIM_VECTOR_UMTS
Vector is UMTS quintuplets.
Definition: base.h:92
@ AKA_SIM_VECTOR_UMTS_REAUTH_KDF_0_REAUTH
Definition: base.h:93
@ AKA_SIM_VECTOR_NONE
Definition: base.h:90
uint8_t mk[AKA_SIM_MK_MAX_SIZE]
Master key from session attributes.
Definition: base.h:211
uint8_t msk[64]
Derived master session key.
Definition: base.h:227
#define EAP_AKA_SIM_AUTH_SIZE
Definition: base.h:79
Stores our checkcode state.
Definition: base.h:140
Master key state struct for all SIMlike EAP protocols.
Definition: base.h:148
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.
Definition: crypto.c:564
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....
Definition: crypto.c:1139
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.
Definition: crypto.c:284
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.
Definition: crypto.c:773
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.
Definition: crypto.c:1226
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.
Definition: crypto.c:947
#define KDF_1_S_STATIC
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.
Definition: crypto.c:990
static int _evp_cipher_ctx_free_on_exit(void *arg)
Definition: crypto.c:59
void aka_sim_crypto_cipher_ctx_free(void)
Explicitly free all thread load cipher ctxs.
Definition: crypto.c:87
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.
Definition: crypto.c:222
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.
Definition: crypto.c:196
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.
Definition: crypto.c:462
#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.
Definition: crypto.c:917
static int _fr_aka_sim_crypto_free_checkcode(fr_aka_sim_checkcode_t *checkcode)
Free OpenSSL memory associated with our checkcode ctx.
Definition: crypto.c:98
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.
Definition: crypto.c:846
int fr_aka_sim_crypto_update_checkcode(fr_aka_sim_checkcode_t *checkcode, eap_packet_t *eap_packet)
Digest a packet, updating the checkcode.
Definition: crypto.c:152
static int ck_ik_prime_derive(fr_aka_sim_keys_t *keys)
Key Derivation Function (CK', IK') as specified in 3GPP.33.402.
Definition: crypto.c:645
static _Thread_local EVP_CIPHER_CTX * evp_chipher_ctx
Used for every non-persistent EVP_CIPHER operation in this library.
Definition: crypto.c:57
EVP_CIPHER_CTX * aka_sim_crypto_cipher_ctx(void)
Allocate and reset a resumable EVP_CIPHER_CTX for each thread.
Definition: crypto.c:70
int fr_aka_sim_crypto_init_checkcode(TALLOC_CTX *ctx, fr_aka_sim_checkcode_t **checkcode, EVP_MD const *md)
Initialise checkcode message digest.
Definition: crypto.c:114
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition: log.h:443
#define RDEBUG3(fmt,...)
Definition: log.h:343
#define RHEXDUMP_INLINE3(_data, _len, _fmt,...)
Definition: log.h:686
#define RINDENT()
Indent R* messages by one level.
Definition: log.h:430
static const uint8_t * zero
Definition: md4.c:365
unsigned short uint16_t
Definition: merged_model.c:31
unsigned int uint32_t
Definition: merged_model.c:33
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
unsigned long int size_t
Definition: merged_model.c:25
#define MILENAGE_SQN_SIZE
Sequence number.
Definition: milenage.h:30
VQP attributes.
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition: rand.c:106
void fr_sha1_init(fr_sha1_ctx *context)
Definition: sha1.c:93
void fr_sha1_final(uint8_t digest[static SHA1_DIGEST_LENGTH], fr_sha1_ctx *context)
Definition: sha1.c:141
void fr_sha1_update(fr_sha1_ctx *context, uint8_t const *in, size_t len)
Definition: sha1.c:105
static char buff[sizeof("18446744073709551615")+3]
Definition: size_tests.c:41
if(!subtype_vp) goto fail
fr_assert(0)
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,...)
Definition: proto.h:41
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_const(_msg)
Definition: strerror.h:223
static fr_slen_t data
Definition: value.h:1259
static size_t char ** out
Definition: value.h:984