The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
vector.c
Go to the documentation of this file.
1/*
2 * This program 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 * $Id: f84f1e8c0201d0dadf05a5791d003adf05d25271 $
19 * @file src/lib/eap_aka_sim/vector.c
20 * @brief Retrieve or derive vectors for EAP-SIM.
21 *
22 * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23 *
24 * @copyright 2016 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
25 * @copyright 2016 The FreeRADIUS server project
26 */
27RCSID("$Id: f84f1e8c0201d0dadf05a5791d003adf05d25271 $")
28
29#include <freeradius-devel/eap/base.h>
30#include <freeradius-devel/sim/common.h>
31#include <freeradius-devel/sim/milenage.h>
32#include <freeradius-devel/sim/ts_34_108.h>
33#include <freeradius-devel/sim/comp128.h>
34#include <freeradius-devel/protocol/freeradius/freeradius.internal.sim.h>
35#include <freeradius-devel/util/rand.h>
36
37#include "base.h"
38#include "attrs.h"
39
40
41static int vector_opc_from_op(request_t *request, uint8_t const **out, uint8_t opc_buff[MILENAGE_OPC_SIZE],
43{
44 fr_pair_t *opc_vp;
45 fr_pair_t *op_vp;
46
47 opc_vp = fr_pair_find_by_da(list, NULL, attr_sim_opc);
48 if (opc_vp) {
49 if (opc_vp->vp_length != MILENAGE_OPC_SIZE) {
50 REDEBUG("control.%s has incorrect length, expected %d bytes got %zu bytes",
51 attr_sim_opc->name, MILENAGE_OPC_SIZE, opc_vp->vp_length);
52 return -1;
53 }
54 *out = opc_vp->vp_octets;
55 return 0;
56 }
57
58 op_vp = fr_pair_find_by_da(list, NULL, attr_sim_op);
59 if (op_vp) {
60 if (op_vp->vp_length != MILENAGE_OP_SIZE) {
61 REDEBUG("control.%s has incorrect length, expected %d bytes got %zu bytes",
62 attr_sim_op->name, MILENAGE_OP_SIZE, op_vp->vp_length);
63 return -1;
64 }
65 if (milenage_opc_generate(opc_buff, op_vp->vp_octets, ki) < 0) {
66 RPEDEBUG("Deriving OPc failed");
67 return -1;
68 }
69 *out = opc_buff;
70 return 0;
71 }
72
73 *out = NULL;
74 return 1;
75}
76
77static int vector_gsm_from_ki(request_t *request, fr_pair_list_t *vps, int idx, fr_aka_sim_keys_t *keys)
78{
79 fr_pair_t *ki_vp, *version_vp;
80 uint8_t opc_buff[MILENAGE_OPC_SIZE];
81 uint8_t const *opc_p = NULL;
82 uint32_t version;
83 unsigned int i;
84
85 /*
86 * Generate a new RAND value, and derive Kc and SRES from Ki
87 */
88 ki_vp = fr_pair_find_by_da(vps, NULL, attr_sim_ki);
89 if (!ki_vp) {
90 RDEBUG3("No control.%sfound, not generating triplets locally", attr_sim_ki->name);
91 return 1;
92 } else if (ki_vp->vp_length != MILENAGE_KI_SIZE) {
93 REDEBUG("control.%s has incorrect length, expected 16 bytes got %zu bytes",
94 attr_sim_ki->name, ki_vp->vp_length);
95 return -1;
96 }
97
98 /*
99 * Check to see if we have a Ki for the IMSI, this allows us to generate the rest
100 * of the triplets.
101 */
102 version_vp = fr_pair_find_by_da(vps, NULL, attr_sim_algo_version);
103 if (!version_vp) {
104 if (vector_opc_from_op(request, &opc_p, opc_buff, vps, ki_vp->vp_octets) < 0) return -1;
105 version = opc_p ? FR_SIM_ALGO_VERSION_VALUE_COMP128_4 : FR_SIM_ALGO_VERSION_VALUE_COMP128_3;
106 /*
107 * Version was explicitly specified, see if we can find the prerequisite
108 * attributes.
109 */
110 } else {
111 version = version_vp->vp_uint32;
112 if (version == FR_SIM_ALGO_VERSION_VALUE_COMP128_4) {
113 if (vector_opc_from_op(request, &opc_p, opc_buff, vps, ki_vp->vp_octets) < 0) return -1;
114 if (!opc_p) {
115 RPEDEBUG2("No control.%s or control.%s found, "
116 "can't run Milenage (COMP128-4)", attr_sim_op->name, attr_sim_opc->name);
117 return -1;
118 }
119 }
120 }
121
122 for (i = 0; i < AKA_SIM_VECTOR_GSM_RAND_SIZE; i += sizeof(uint32_t)) {
123 uint32_t rand = fr_rand();
124 memcpy(&keys->gsm.vector[idx].rand[i], &rand, sizeof(rand));
125 }
126
127 switch (version) {
128 case FR_SIM_ALGO_VERSION_VALUE_COMP128_1:
129 comp128v1(keys->gsm.vector[idx].sres,
130 keys->gsm.vector[idx].kc,
131 ki_vp->vp_octets,
132 keys->gsm.vector[idx].rand);
133 break;
134
135 case FR_SIM_ALGO_VERSION_VALUE_COMP128_2:
136 comp128v23(keys->gsm.vector[idx].sres,
137 keys->gsm.vector[idx].kc,
138 ki_vp->vp_octets,
139 keys->gsm.vector[idx].rand, true);
140 break;
141
142 case FR_SIM_ALGO_VERSION_VALUE_COMP128_3:
143 comp128v23(keys->gsm.vector[idx].sres,
144 keys->gsm.vector[idx].kc,
145 ki_vp->vp_octets,
146 keys->gsm.vector[idx].rand, false);
147 break;
148
149 case FR_SIM_ALGO_VERSION_VALUE_COMP128_4:
150 if (milenage_gsm_generate(keys->gsm.vector[idx].sres,
151 keys->gsm.vector[idx].kc,
152 opc_p,
153 ki_vp->vp_octets,
154 keys->gsm.vector[idx].rand) < 0) {
155 RPEDEBUG2("Failed deriving GSM triplet");
156 return -1;
157 }
158 break;
159
160 default:
161 REDEBUG("Unknown/unsupported algorithm %u", version);
162 return -1;
163 }
164
165 /*
166 * Store for completeness...
167 */
168 memcpy(keys->auc.ki, ki_vp->vp_octets, sizeof(keys->auc.ki));
169 if (opc_p) memcpy(keys->auc.opc, opc_p, sizeof(keys->auc.opc));
170 keys->vector_src = AKA_SIM_VECTOR_SRC_KI;
171
172 return 0;
173}
174
176 int idx, fr_aka_sim_keys_t *keys)
177{
178 fr_pair_t *rand = NULL, *sres = NULL, *kc = NULL;
179 fr_dcursor_t cursor;
180 int i;
181
182 for (i = 0, (kc = fr_pair_dcursor_by_da_init(&cursor, vps, attr_eap_aka_sim_kc));
183 (i < idx) && (kc = fr_dcursor_next(&cursor));
184 i++);
185 if (!kc) {
186 RDEBUG3("No control.%s[%i] attribute found, not using GSM triplets",
187 attr_eap_aka_sim_kc->name, idx);
188 return 1;
189 }
190 if (kc->vp_length != AKA_SIM_VECTOR_GSM_KC_SIZE) {
191 REDEBUG("control.%s[%i] is not " STRINGIFY(AKA_SIM_VECTOR_GSM_KC_SIZE) " bytes, got %zu bytes",
192 attr_eap_aka_sim_kc->name, idx, kc->vp_length);
193 return -1;
194 }
195
196 for (i = 0, (rand = fr_pair_dcursor_by_da_init(&cursor, vps, attr_eap_aka_sim_rand));
197 (i < idx) && (rand = fr_dcursor_next(&cursor));
198 i++);
199 if (!rand) {
200 RDEBUG3("No control.%s[%i] attribute found, not using GSM triplets",
201 attr_eap_aka_sim_rand->name, idx);
202 return 1;
203 }
204 if (rand->vp_length != AKA_SIM_VECTOR_GSM_RAND_SIZE) {
205 REDEBUG("control.RAND[%i] is not " STRINGIFY(SIM_RAND_SIZE) " bytes, got %zu bytes",
206 idx, rand->vp_length);
207 return -1;
208 }
209
210 for (i = 0, (sres = fr_pair_dcursor_by_da_init(&cursor, vps, attr_eap_aka_sim_sres));
211 (i < idx) && (sres = fr_dcursor_next(&cursor));
212 i++);
213 if (!sres) {
214 RDEBUG3("No control.%s[%i] attribute found, not using GSM triplets",
215 attr_eap_aka_sim_sres->name, idx);
216 return 1;
217 }
218 if (sres->vp_length != AKA_SIM_VECTOR_GSM_SRES_SIZE) {
219 REDEBUG("control.%s[%i] is not " STRINGIFY(AKA_SIM_VECTOR_GSM_SRES_SIZE) " bytes, got %zu bytes",
220 attr_eap_aka_sim_sres->name, idx, sres->vp_length);
221 return -1;
222 }
223
224 memcpy(keys->gsm.vector[idx].kc, kc->vp_strvalue, AKA_SIM_VECTOR_GSM_KC_SIZE);
225 memcpy(keys->gsm.vector[idx].rand, rand->vp_octets, AKA_SIM_VECTOR_GSM_RAND_SIZE);
226 memcpy(keys->gsm.vector[idx].sres, sres->vp_octets, AKA_SIM_VECTOR_GSM_SRES_SIZE);
227 keys->vector_src = AKA_SIM_VECTOR_SRC_TRIPLETS;
228
229 return 0;
230}
231
232/** Derive triplets from quintuplets
233 *
234 */
236 int idx, fr_aka_sim_keys_t *keys)
237{
238 fr_dcursor_t cursor;
239
240 fr_pair_t *ck = NULL, *ik = NULL, *rand = NULL, *xres = NULL;
241
242 int i;
243
244 /*
245 * Fetch CK
246 */
247 for (i = 0, (ck = fr_pair_dcursor_by_da_init(&cursor, vps, attr_eap_aka_sim_ck));
248 (i < idx) && (ck = fr_dcursor_next(&cursor));
249 i++);
250 if (!ck) {
251 RDEBUG3("No control.%s[%i] attribute found, not using quintuplet derivation",
252 attr_eap_aka_sim_ck->name, idx);
253 return 1;
254 }
255
256 /*
257 * Fetch IK
258 */
259 for (i = 0, (ik = fr_pair_dcursor_by_da_init(&cursor, vps, attr_eap_aka_sim_ik));
260 (i < idx) && (ik = fr_dcursor_next(&cursor));
261 i++);
262 if (!ik) {
263 RDEBUG3("No control.%s[%i] attribute found, not using quintuplet derivation",
264 attr_eap_aka_sim_ik->name, idx);
265 return 1;
266 }
267
268 /*
269 * Fetch RAND
270 */
271 for (i = 0, (rand = fr_pair_dcursor_by_da_init(&cursor, vps, attr_eap_aka_sim_rand));
272 (i < idx) && (rand = fr_dcursor_next(&cursor));
273 i++);
274 if (!rand) {
275 RDEBUG3("No control.%s[%i] attribute found, not using quintuplet derivation",
276 attr_eap_aka_sim_rand->name, idx);
277 return 1;
278 }
279
280 if (rand->vp_length != AKA_SIM_VECTOR_UMTS_RAND_SIZE) {
281 REDEBUG("control.%s[%i] incorrect length. Expected "
283 "got %zu bytes", attr_eap_aka_sim_rand->name, idx, rand->vp_length);
284 return -1;
285 }
286
287 /*
288 * Fetch XRES
289 */
290 for (i = 0, (xres = fr_pair_dcursor_by_da_init(&cursor, vps, attr_eap_aka_sim_xres));
291 (i < idx) && (xres = fr_dcursor_next(&cursor));
292 i++);
293 if (!xres) {
294 RDEBUG3("No control.%s[%i] attribute found, not using quintuplet derivation",
295 attr_eap_aka_sim_xres->name, idx);
296 return 1;
297 }
298
299 memcpy(keys->gsm.vector[idx].rand, rand->vp_octets, AKA_SIM_VECTOR_GSM_RAND_SIZE);
300
301 milenage_gsm_from_umts(keys->gsm.vector[idx].sres,
302 keys->gsm.vector[idx].kc,
303 ik->vp_octets,
304 ck->vp_octets,
305 xres->vp_octets);
306
307 keys->vector_src = AKA_SIM_VECTOR_SRC_QUINTUPLETS;
308
309 return 0;
310}
311
312/** Retrieve GSM triplets from sets of attributes.
313 *
314 * Hunt for a source of SIM triplets
315 *
316 * @param[in] request The current subrequest.
317 * @param[in] vps List to hunt for triplets in.
318 * @param[in] idx To write EAP-SIM triplets to.
319 * @param[in] keys EAP session keys.
320 * @param[in] src Forces triplets to be retrieved from a particular src
321 * and ensures if multiple triplets are being retrieved
322 * that they all come from the same src.
323 * @return
324 * - 1 Vector could not be retrieved from the specified src.
325 * - 0 Vector was retrieved OK and written to the specified index.
326 * - -1 Error retrieving vector from the specified src.
327 */
329 int idx, fr_aka_sim_keys_t *keys, fr_aka_sim_vector_src_t *src)
330{
331 int ret;
332
333 fr_assert(idx >= 0 && idx < 3);
334 fr_assert((keys->vector_type == AKA_SIM_VECTOR_NONE) || (keys->vector_type == AKA_SIM_VECTOR_GSM));
335
336 switch (*src) {
337 default:
339 ret = vector_gsm_from_ki(request, vps, idx, keys);
340 if (ret == 0) {
342 break;
343 }
344 if (ret < 0) return -1;
345 if (*src != AKA_SIM_VECTOR_SRC_AUTO) return 1;
347
349 ret = vector_gsm_from_triplets(request, vps, idx, keys);
350 if (ret == 0) {
352 break;
353 }
354 if (ret < 0) return -1;
355 if (*src != AKA_SIM_VECTOR_SRC_AUTO) return 1;
357
359 ret = vector_gsm_from_quintuplets(request, vps, idx, keys);
360 if (ret == 0) {
362 break;
363 }
364 if (ret < 0) return -1;
365 break;
366 }
367
368 if (ret == 1) {
369 RWDEBUG("Could not find or derive data for GSM vector[%i]", idx);
370 return 1;
371 }
372
373 if (RDEBUG_ENABLED2) {
374 RDEBUG2("GSM vector[%i]", idx);
375
376 RINDENT();
377 /*
378 * Don't change colon indent, matches other messages later...
379 */
380 RHEXDUMP_INLINE2(keys->gsm.vector[idx].kc, AKA_SIM_VECTOR_GSM_KC_SIZE,
381 "KC :");
382 RHEXDUMP_INLINE2(keys->gsm.vector[idx].rand, AKA_SIM_VECTOR_GSM_RAND_SIZE,
383 "RAND :");
384 RHEXDUMP_INLINE2(keys->gsm.vector[idx].sres, AKA_SIM_VECTOR_GSM_SRES_SIZE,
385 "SRES :");
386 REXDENT();
387 }
388
389 keys->vector_type = AKA_SIM_VECTOR_GSM;
390
391 return 0;
392}
393
395{
396 fr_pair_t *ki_vp, *amf_vp, *sqn_vp, *version_vp;
397
398 size_t ki_size, amf_size;
399 uint32_t version = FR_SIM_ALGO_VERSION_VALUE_MILENAGE;
400 unsigned int i;
401
402 /*
403 * Select the algorithm (default to Milenage)
404 */
405 version_vp = fr_pair_find_by_da(vps, NULL, attr_sim_algo_version);
406 if (version_vp) version = version_vp->vp_uint32;
407
408 /*
409 * Get expected input sizes
410 */
411 switch (version) {
412 case FR_SIM_ALGO_VERSION_VALUE_MILENAGE:
413 ki_size = MILENAGE_KI_SIZE;
414 amf_size = MILENAGE_AMF_SIZE;
415 break;
416
417 case FR_SIM_ALGO_VERSION_VALUE_TS_34_108_UMTS:
418 ki_size = TS_34_108_KI_SIZE;
419 amf_size = TS_34_108_AMF_SIZE;
420 break;
421
422 /*
423 * GSM algos
424 */
425 case FR_SIM_ALGO_VERSION_VALUE_COMP128_1:
426 case FR_SIM_ALGO_VERSION_VALUE_COMP128_2:
427 case FR_SIM_ALGO_VERSION_VALUE_COMP128_3:
428 case FR_SIM_ALGO_VERSION_VALUE_COMP128_4:
429 REDEBUG("COMP128-* algorithms cannot generate UMTS vectors");
430 return -1;
431
432 default:
433 REDEBUG("Unknown/unsupported algorithm %u", version);
434 return -1;
435 }
436
437 /*
438 * Find the Ki VP and check its length
439 */
440 ki_vp = fr_pair_find_by_da(vps, NULL, attr_sim_ki);
441 if (!ki_vp) {
442 RDEBUG3("No control.%s found, not generating quintuplets locally", attr_sim_ki->name);
443 return 1;
444 } else if (ki_vp->vp_length != ki_size) {
445 REDEBUG("control.%s has incorrect length, expected %zu bytes got %zu bytes",
446 attr_sim_ki->name, ki_size, ki_vp->vp_length);
447 return -1;
448 }
449
450 /*
451 * Find the Sequence Number VP or default to SQN = 2
452 */
453 sqn_vp = fr_pair_find_by_da(vps, NULL, attr_sim_sqn);
454 keys->sqn = sqn_vp ? sqn_vp->vp_uint64 : 2; /* 2 is the lowest valid SQN on our side */
455
456 /*
457 * Check if we have an AMF value
458 */
459 amf_vp = fr_pair_find_by_da(vps, NULL, attr_sim_amf);
460 if (amf_vp) {
461 if (amf_vp->vp_length != amf_size) {
462 REDEBUG("control.%s has incorrect length, expected %zu bytes got %zu bytes",
463 attr_sim_amf->name, amf_size, amf_vp->vp_length);
464 return -1;
465 }
466 }
467
468 /*
469 * Generate rand
470 */
471 for (i = 0; i < AKA_SIM_VECTOR_UMTS_RAND_SIZE; i += sizeof(uint32_t)) {
472 uint32_t rand = fr_rand();
473 memcpy(&keys->umts.vector.rand[i], &rand, sizeof(rand));
474 }
475
476 switch (version) {
477 case FR_SIM_ALGO_VERSION_VALUE_MILENAGE:
478 {
479 uint8_t amf_buff[MILENAGE_AMF_SIZE] = { 0x00, 0x00 };
480 uint8_t sqn_buff[MILENAGE_SQN_SIZE];
481 uint8_t opc_buff[MILENAGE_OPC_SIZE];
482 uint8_t const *opc_p;
483
484 if (vector_opc_from_op(request, &opc_p, opc_buff, vps, ki_vp->vp_octets) < 0) return -1;
485
486 uint48_to_buff(sqn_buff, keys->sqn);
487 if (amf_vp) memcpy(amf_buff, amf_vp->vp_octets, amf_size);
488
489 RDEBUG3("Milenage inputs");
490 RINDENT();
491 /*
492 * Don't change colon indent, matches other messages later...
493 */
494 RHEXDUMP_INLINE3(ki_vp->vp_octets, ki_size,
495 "Ki :");
496 RHEXDUMP_INLINE3(opc_p, sizeof(opc_buff),
497 "OPc :");
498 RHEXDUMP_INLINE3(sqn_buff, sizeof(sqn_buff),
499 "SQN :");
500 RHEXDUMP_INLINE3(amf_buff, sizeof(amf_buff),
501 "AMF :");
502 REXDENT();
503
504 if (milenage_umts_generate(keys->umts.vector.autn,
505 keys->umts.vector.ik,
506 keys->umts.vector.ck,
507 keys->umts.vector.ak,
508 keys->umts.vector.xres,
509 opc_p,
510 amf_buff,
511 ki_vp->vp_octets,
512 keys->sqn,
513 keys->umts.vector.rand) < 0) {
514 RPEDEBUG2("Failed deriving UMTS Quintuplet");
515 return -1;
516 }
517 keys->umts.vector.xres_len = MILENAGE_RES_SIZE;
518
519 /*
520 * Store the keys we used for possible AUTS
521 * validation later.
522 */
523 memcpy(keys->auc.ki, ki_vp->vp_octets, sizeof(keys->auc.ki));
524 memcpy(keys->auc.opc, opc_p, sizeof(keys->auc.opc));
525 keys->vector_src = AKA_SIM_VECTOR_SRC_KI;
526 }
527 return 0;
528
529 /*
530 * This is a dummy algorithm and should be used for testing
531 * purposes only. It offers no security and can be trivially
532 * broken and the original Ki retrieved.
533 */
534 case FR_SIM_ALGO_VERSION_VALUE_TS_34_108_UMTS:
535 {
536 uint8_t amf_buff[TS_34_108_AMF_SIZE] = { 0x00, 0x00 };
537 uint8_t sqn_buff[TS_34_108_SQN_SIZE];
538
539 uint48_to_buff(sqn_buff, keys->sqn);
540
541 if (amf_vp) memcpy(amf_buff, amf_vp->vp_octets, amf_size);
542
543 RDEBUG3("TS-34-108-UMTS inputs");
544 RINDENT();
545 /*
546 * Don't change colon indent, matches other messages later...
547 */
549 ki_vp->vp_octets, ki_size,
550 "Ki :");
552 sqn_buff, sizeof(sqn_buff),
553 "SQN :");
555 amf_buff, sizeof(amf_buff),
556 "AMF :");
557 REXDENT();
558
559 if (ts_34_108_umts_generate(keys->umts.vector.autn,
560 keys->umts.vector.ik,
561 keys->umts.vector.ck,
562 keys->umts.vector.ak,
563 keys->umts.vector.xres,
564 amf_buff,
565 ki_vp->vp_octets,
566 keys->sqn,
567 keys->umts.vector.rand) < 0) {
568 RPEDEBUG2("Failed deriving UMTS Quintuplet");
569 return -1;
570 }
571 keys->umts.vector.xres_len = TS_34_108_RES_SIZE;
572
573 /*
574 * Store the keys we used for possible AUTS
575 * validation later.
576 */
577 memcpy(keys->auc.ki, ki_vp->vp_octets, sizeof(keys->auc.ki));
578 keys->vector_src = AKA_SIM_VECTOR_SRC_KI;
579 }
580 return 0;
581
582 default:
583 fr_assert(0);
584 return -1;
585 }
586}
587
588/** Get one set of quintuplets from the request
589 *
590 */
592{
593 fr_pair_t *rand_vp = NULL, *xres_vp = NULL, *ck_vp = NULL, *ik_vp = NULL;
594 fr_pair_t *autn_vp = NULL, *sqn_vp = NULL, *ak_vp = NULL;
595
596 /*
597 * Fetch AUTN
598 */
599 autn_vp = fr_pair_find_by_da(vps, NULL, attr_eap_aka_sim_autn);
600 if (!autn_vp) {
601 RDEBUG3("No control.%s attribute found, not using UMTS quintuplets", attr_eap_aka_sim_autn->name);
602 return 1;
603 }
604
605 if (autn_vp->vp_length != AKA_SIM_VECTOR_UMTS_AUTN_SIZE) {
606 REDEBUG("control.%s incorrect length. Expected "
607 STRINGIFY(AKA_SIM_VECTOR_UMTS_AUTN_SIZE) " bytes, got %zu bytes",
608 attr_eap_aka_sim_autn->name, autn_vp->vp_length);
609 return -1;
610 }
611
612 /*
613 * Fetch CK
614 */
615 ck_vp = fr_pair_find_by_da(vps, NULL, attr_eap_aka_sim_ck);
616 if (!ck_vp) {
617 RDEBUG3("No control.%s attribute found, not using UMTS quintuplets", attr_eap_aka_sim_ck->name);
618 return 1;
619 }
620
621 if (ck_vp->vp_length != AKA_SIM_VECTOR_UMTS_CK_SIZE) {
622 REDEBUG("control.%s incorrect length. Expected "
623 STRINGIFY(EAP_AKA_XRES_MAX_SIZE) " bytes, got %zu bytes",
624 attr_eap_aka_sim_ck->name, ck_vp->vp_length);
625 return -1;
626 }
627
628 /*
629 * Fetch IK
630 */
631 ik_vp = fr_pair_find_by_da(vps, NULL, attr_eap_aka_sim_ik);
632 if (!ik_vp) {
633 RDEBUG3("No control.%s attribute found, not using UMTS quintuplets", attr_eap_aka_sim_ik->name);
634 return 1;
635 }
636
637 if (ik_vp->vp_length != AKA_SIM_VECTOR_UMTS_IK_SIZE) {
638 REDEBUG("control.%s incorrect length. Expected "
639 STRINGIFY(AKA_SIM_VECTOR_UMTS_IK_SIZE) " bytes, got %zu bytes",
640 attr_eap_aka_sim_ik->name, ik_vp->vp_length);
641 return -1;
642 }
643
644 /*
645 * Fetch RAND
646 */
647 rand_vp = fr_pair_find_by_da(vps, NULL, attr_eap_aka_sim_rand);
648 if (!rand_vp) {
649 RDEBUG3("No control.%s attribute found, not using quintuplet derivation", attr_eap_aka_sim_rand->name);
650 return 1;
651 }
652
653 if (rand_vp->vp_length != AKA_SIM_VECTOR_UMTS_RAND_SIZE) {
654 REDEBUG("control.%s incorrect length. Expected " STRINGIFY(AKA_SIM_VECTOR_UMTS_RAND_SIZE) " bytes, "
655 "got %zu bytes", attr_eap_aka_sim_rand->name, rand_vp->vp_length);
656 return -1;
657 }
658
659 /*
660 * Fetch XRES
661 */
662 xres_vp = fr_pair_find_by_da(vps, NULL, attr_eap_aka_sim_xres);
663 if (!xres_vp) {
664 RDEBUG3("No control.%s attribute found, not using UMTS quintuplets", attr_eap_aka_sim_xres->name);
665 return 1;
666 }
667
668 if (xres_vp->vp_length > AKA_SIM_VECTOR_UMTS_XRES_MAX_SIZE) {
669 REDEBUG("control.%s incorrect length. Expected < "
670 STRINGIFY(EAP_AKA_XRES_MAX_SIZE) " bytes, got %zu bytes",
671 attr_eap_aka_sim_xres->name, xres_vp->vp_length);
672 return -1;
673 }
674
675 /*
676 * Fetch (optional) AK
677 */
678 ak_vp = fr_pair_find_by_da(vps, NULL, attr_eap_aka_sim_ak);
679 if (ak_vp && (ak_vp->vp_length != MILENAGE_AK_SIZE)) {
680 REDEBUG("control.%s incorrect length. Expected "
681 STRINGIFY(MILENAGE_AK_SIZE) " bytes, got %zu bytes",
682 attr_eap_aka_sim_ak->name, ak_vp->vp_length);
683 return -1;
684 }
685
686 /*
687 * Fetch (optional) SQN
688 */
689 sqn_vp = fr_pair_find_by_da(vps, NULL, attr_sim_sqn);
690 if (sqn_vp && (sqn_vp->vp_length != MILENAGE_SQN_SIZE)) {
691 REDEBUG("control.%s incorrect length. Expected "
692 STRINGIFY(MILENAGE_SQN_SIZE) " bytes, got %zu bytes",
693 attr_sim_sqn->name, sqn_vp->vp_length);
694 return -1;
695 }
696
697 /*
698 * SQN = AUTN[0..5] ⊕ AK
699 * AK = AK
700 */
701 if (ak_vp && !sqn_vp) {
702 keys->sqn = uint48_from_buff(autn_vp->vp_octets) ^ uint48_from_buff(ak_vp->vp_octets);
703 memcpy(keys->umts.vector.ak, ak_vp->vp_octets, sizeof(keys->umts.vector.ak));
704 /*
705 * SQN = SQN
706 * AK = AUTN[0..5] ⊕ SQN
707 */
708 } else if (sqn_vp && !ak_vp) {
709 keys->sqn = sqn_vp->vp_uint64;
710 uint48_to_buff(keys->umts.vector.ak, uint48_from_buff(autn_vp->vp_octets) ^ sqn_vp->vp_uint64);
711 /*
712 * SQN = SQN
713 * AK = AK
714 */
715 } else if (sqn_vp && ak_vp) {
716 keys->sqn = sqn_vp->vp_uint64;
717 memcpy(keys->umts.vector.ak, ak_vp->vp_octets, sizeof(keys->umts.vector.ak));
718 /*
719 * SQN = AUTN[0..5]
720 * AK = 0x000000000000
721 */
722 } else {
723 keys->sqn = uint48_from_buff(autn_vp->vp_octets);
724 memset(keys->umts.vector.ak, 0, sizeof(keys->umts.vector.ak));
725 }
726
727 memcpy(keys->umts.vector.autn, autn_vp->vp_octets, AKA_SIM_VECTOR_UMTS_AUTN_SIZE);
728 memcpy(keys->umts.vector.ck, ck_vp->vp_octets, AKA_SIM_VECTOR_UMTS_CK_SIZE);
729 memcpy(keys->umts.vector.ik, ik_vp->vp_octets, AKA_SIM_VECTOR_UMTS_IK_SIZE);
730 memcpy(keys->umts.vector.rand, rand_vp->vp_octets, AKA_SIM_VECTOR_UMTS_RAND_SIZE);
731 memcpy(keys->umts.vector.xres, xres_vp->vp_octets, xres_vp->vp_length);
732 keys->umts.vector.xres_len = xres_vp->vp_length; /* xres is variable length */
733
734 keys->vector_src = AKA_SIM_VECTOR_SRC_QUINTUPLETS;
735
736 return 0;
737}
738
739/** Retrieve UMTS quintuplets from sets of attributes.
740 *
741 * Hunt for a source of UMTS quintuplets
742 *
743 * @param request The current request.
744 * @param vps List to hunt for triplets in.
745 * @param keys UMTS keys.
746 * @param src Forces quintuplets to be retrieved from a particular src.
747 *
748 * @return
749 * - 1 Vector could not be retrieved from the specified src.
750 * - 0 Vector was retrieved OK and written to the specified index.
751 * - -1 Error retrieving vector from the specified src.
752 */
755{
756 int ret;
757
758 fr_assert((keys->vector_type == AKA_SIM_VECTOR_NONE) || (keys->vector_type == AKA_SIM_VECTOR_UMTS));
759
760 switch (*src) {
761 default:
763 ret = vector_umts_from_ki(request, vps, keys);
764 if (ret == 0) {
766 break;
767 }
768 if (ret < 0) return -1;
769 if (*src != AKA_SIM_VECTOR_SRC_AUTO) return 1;
771
773 ret = vector_umts_from_quintuplets(request, vps, keys);
774 if (ret == 0) {
776 break;
777 }
778 if (ret < 0) return -1;
779 break;
780 }
781
782 if (ret == 1) {
783 RWDEBUG("Could not find or derive data for UMTS vector");
784 return 1;
785 }
786
787 if (RDEBUG_ENABLED2) {
788 RDEBUG2("UMTS vector");
789
790 RINDENT();
791 /*
792 * Don't change colon indent, matches other messages later...
793 */
794 RHEXDUMP_INLINE2(keys->umts.vector.autn, AKA_SIM_VECTOR_UMTS_AUTN_SIZE,
795 "AUTN :");
796 RHEXDUMP_INLINE2(keys->umts.vector.ck, AKA_SIM_VECTOR_UMTS_CK_SIZE,
797 "CK :");
798 RHEXDUMP_INLINE2(keys->umts.vector.ik, AKA_SIM_VECTOR_UMTS_IK_SIZE,
799 "IK :");
800 RHEXDUMP_INLINE2(keys->umts.vector.rand, AKA_SIM_VECTOR_UMTS_RAND_SIZE,
801 "RAND :");
802 RHEXDUMP_INLINE2(keys->umts.vector.xres, keys->umts.vector.xres_len,
803 "XRES :");
804 REXDENT();
805 }
806
807 keys->vector_type = AKA_SIM_VECTOR_UMTS;
808
809 return 0;
810}
811
812/** Populate a fr_aka_sim_keys_t structure from attributes in the session-state list
813 *
814 * @param[in] request The current request.
815 * @param[in] vps Session-state list
816 * @param[in] keys key structure to populate.
817 * @return
818 * - 1 if we do not have sufficient data.
819 * - 0 on success.
820 * - -1 on validation failure.
821 */
823{
824 fr_pair_t *counter_vp;
825 fr_pair_t *mk_vp;
826
827 /*
828 * This is the *old* counter value increment
829 * by 1 to get the *new* counter value
830 */
832 if (!counter_vp) {
833 RDEBUG2("No session-state.%s attribute found, can't calculate re-auth keys",
835 return 1;
836 }
837 counter_vp->vp_uint16++;
838
839 mk_vp = fr_pair_find_by_da(vps, NULL, attr_session_data);
840 if (!mk_vp) mk_vp = fr_pair_find_by_da(vps, NULL, attr_eap_aka_sim_mk);
841 if (!mk_vp) {
842 RDEBUG2("Neither session-state.%s or session-state.%s attributes found, "
843 "can't calculate re-auth keys", attr_session_data->name, attr_eap_aka_sim_mk->name);
844 return 1;
845 }
846
847 if (mk_vp->vp_length != AKA_SIM_MK_SIZE) {
848 REDEBUG("session-state.%s incorrect length. Expected %u bytes, got %zu bytes",
849 attr_eap_aka_sim_mk->name, AKA_SIM_MK_SIZE, mk_vp->vp_length);
850 return -1;
851 }
852
853 fr_aka_sim_crypto_keys_init_kdf_0_reauth(keys, mk_vp->vp_octets, counter_vp->vp_uint16);
854
855 keys->vector_type = AKA_SIM_VECTOR_UMTS_REAUTH_KDF_0_REAUTH; /* Didn't come from a vector */
856 keys->vector_src = AKA_SIM_VECTOR_SRC_REAUTH;
857
858 return 0;
859}
860
861/** Populate a fr_aka_sim_keys_t structure from attributes in the session-state list
862 *
863 * @param[in] request The current request.
864 * @param[in] vps Session-state list
865 * @param[in] keys key structure to populate.
866 * @return
867 * - 1 if we do not have sufficient data.
868 * - 0 on success.
869 * - -1 on validation failure.
870 */
872{
873 fr_pair_t *counter_vp;
874 fr_pair_t *mk_vp;
875
876 /*
877 * This is the *old* counter value increment
878 * by 1 to get the *new* counter value
879 */
881 if (!counter_vp) {
882 RDEBUG2("No session-state.%s attribute found, can't calculate re-auth keys",
884 return 1;
885 }
886 counter_vp->vp_uint16++;
887
888 mk_vp = fr_pair_find_by_da(vps, NULL, attr_session_data);
889 if (!mk_vp) mk_vp = fr_pair_find_by_da(vps, NULL, attr_eap_aka_sim_mk);
890 if (!mk_vp) {
891 RDEBUG2("Neither session-state.%s or session-sate:%s attributes found, "
892 "can't calculate re-auth keys", attr_session_data->name, attr_eap_aka_sim_mk->name);
893 return 1;
894 }
895
896 if (mk_vp->vp_length != AKA_PRIME_MK_REAUTH_SIZE) {
897 REDEBUG("session-state.%s incorrect length. Expected "
898 "%u bytes, got %zu bytes",
899 attr_eap_aka_sim_mk->name, AKA_PRIME_MK_REAUTH_SIZE, mk_vp->vp_length);
900 return -1;
901 }
902
903 fr_aka_sim_crypto_keys_init_umts_kdf_1_reauth(keys, mk_vp->vp_octets, counter_vp->vp_uint16);
904
905 keys->vector_type = AKA_SIM_VECTOR_UMTS_REAUTH_KDF_1_REAUTH; /* Didn't come from a vector */
906 keys->vector_src = AKA_SIM_VECTOR_SRC_REAUTH;
907
908 return 0;
909}
910
911/** Clear reauth data if reauthentication failed
912 *
913 * @param[in] keys key structure to clear.
914 */
916{
917 memset(&keys->reauth, 0, sizeof(keys->reauth));
918 keys->vector_src = 0;
919 keys->vector_type = 0;
920}
921
922/** Perform milenage AUTS validation and resynchronisation
923 *
924 * @param[out] new_sqn The new sequence number provided by the AUTS.
925 * @param[in] request The current request.
926 * @param[in] auts_vp The AUTS response.
927 * @param[in] keys UMTS keys.
928 * @return
929 * - 1 if we do not have sufficient data (lacking ki).
930 * - 0 on success.
931 * - -1 on validation failure.
932 */
934 request_t *request, fr_pair_t *auts_vp, fr_aka_sim_keys_t *keys)
935{
936 if (keys->vector_src != AKA_SIM_VECTOR_SRC_KI) {
937 RDEBUG2("Original vectors were not generated locally, cannot perform AUTS validation");
938 return 1;
939 }
940
941 if (auts_vp->vp_length != MILENAGE_AUTS_SIZE) {
942 REDEBUG("control.%s incorrect length. Expected "
943 STRINGIFY(MILENAGE_AUTS_SIZE) " bytes, got %zu bytes",
944 attr_eap_aka_sim_auts->name, auts_vp->vp_length);
945 return -1;
946 }
947
948 if (milenage_auts(new_sqn, keys->auc.opc, keys->auc.ki, keys->umts.vector.rand, auts_vp->vp_octets) < 0) {
949 REDEBUG("AUTS validation failed");
950 return -1;
951 }
952
953 RDEBUG2("AUTS validation success, new SQN %"PRIu64, *new_sqn);
954
955 return 0;
956}
#define RCSID(id)
Definition build.h:506
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:343
#define STRINGIFY(x)
Definition build.h:216
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
void comp128v1(uint8_t sres[static 4], uint8_t kc[static 8], uint8_t const ki[static 16], uint8_t const rand[static 16])
Calculate comp128v1 sres and kc from ki and rand.
Definition comp128.c:241
void comp128v23(uint8_t sres[static 4], uint8_t kc[static 8], uint8_t const ki[static 16], uint8_t const rand[static 16], bool v2)
Calculate comp128v2 or comp128v3 sres and kc from ki and rand.
Definition comp128.c:336
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition dcursor.h:288
#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
#define AKA_SIM_VECTOR_GSM_SRES_SIZE
Length of SRES in GSM triplet.
Definition base.h:66
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:952
uint64_t sqn
Sequence number.
Definition base.h:158
#define AKA_PRIME_MK_REAUTH_SIZE
The portion of the MK used for re-auth.
Definition base.h:57
fr_aka_sim_vector_src_t
Where to get EAP-SIM vectors from.
Definition base.h:99
@ AKA_SIM_VECTOR_SRC_REAUTH
Not a vector.
Definition base.h:105
@ AKA_SIM_VECTOR_SRC_AUTO
Discover where to get Triplets from automatically.
Definition base.h:100
@ AKA_SIM_VECTOR_SRC_QUINTUPLETS
Source of triplets is derived from EAP-AKA-* quintuplets.
Definition base.h:102
@ AKA_SIM_VECTOR_SRC_KI
Should generate triplets locally using a Ki.
Definition base.h:104
@ AKA_SIM_VECTOR_SRC_TRIPLETS
Source of triplets is EAP-SIM-* attributes.
Definition base.h:101
#define AKA_SIM_VECTOR_UMTS_XRES_MAX_SIZE
Definition base.h:74
#define AKA_SIM_VECTOR_UMTS_CK_SIZE
Definition base.h:70
#define AKA_SIM_MK_SIZE
Definition base.h:54
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:922
#define AKA_SIM_VECTOR_GSM_KC_SIZE
Length of Kc in GSM triplet.
Definition base.h:67
#define AKA_SIM_VECTOR_UMTS_IK_SIZE
Definition base.h:71
#define AKA_SIM_VECTOR_UMTS_AUTN_SIZE
Definition base.h:69
@ 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
Master key state struct for all SIMlike EAP protocols.
Definition base.h:148
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_counter
Definition base.c:67
HIDDEN fr_dict_attr_t const * attr_session_data
Definition base.c:102
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_ak
Definition base.c:59
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_mk
Definition base.c:86
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_auts
Definition base.c:62
HIDDEN fr_dict_attr_t const * attr_sim_algo_version
Definition base.c:110
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_xres
Definition base.c:101
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_sres
Definition base.c:98
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_ik
Definition base.c:75
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_autn
Definition base.c:61
HIDDEN fr_dict_attr_t const * attr_sim_opc
Definition base.c:114
HIDDEN fr_dict_attr_t const * attr_sim_ki
Definition base.c:112
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_kc
Definition base.c:80
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_ck
Definition base.c:65
HIDDEN fr_dict_attr_t const * attr_sim_sqn
Definition base.c:115
HIDDEN fr_dict_attr_t const * attr_sim_op
Definition base.c:113
HIDDEN fr_dict_attr_t const * attr_sim_amf
Definition base.c:111
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_rand
Definition attrs.h:39
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition log.h:455
#define RWDEBUG(fmt,...)
Definition log.h:373
#define RDEBUG3(fmt,...)
Definition log.h:355
#define RHEXDUMP_INLINE2(_data, _len, _fmt,...)
Definition log.h:697
#define RPEDEBUG(fmt,...)
Definition log.h:388
#define RHEXDUMP_INLINE3(_data, _len, _fmt,...)
Definition log.h:698
#define RPEDEBUG2(fmt,...)
Definition log.h:389
#define RINDENT()
Indent R* messages by one level.
Definition log.h:442
unsigned int uint32_t
unsigned char uint8_t
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
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
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
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
#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_OP_SIZE
Operator code (unique to the operator)
Definition milenage.h:27
#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
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
Definition pair.c:784
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:707
VQP attributes.
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
#define RDEBUG_ENABLED2()
#define RDEBUG2(fmt,...)
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition rand.c:104
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
int ts_34_108_umts_generate(uint8_t autn[TS_34_108_AUTN_SIZE], uint8_t ik[TS_34_108_IK_SIZE], uint8_t ck[TS_34_108_CK_SIZE], uint8_t ak[TS_34_108_AK_SIZE], uint8_t res[TS_34_108_RES_SIZE], uint8_t const amf[TS_34_108_AMF_SIZE], uint8_t const ki[TS_34_108_KI_SIZE], uint64_t sqn, uint8_t const rand[TS_34_108_RAND_SIZE])
Definition ts_34_108.c:40
#define TS_34_108_KI_SIZE
Subscriber key.
Definition ts_34_108.h:30
#define TS_34_108_SQN_SIZE
Sequence number.
Definition ts_34_108.h:33
#define TS_34_108_AMF_SIZE
Authentication management field.
Definition ts_34_108.h:32
#define TS_34_108_RES_SIZE
Definition ts_34_108.h:43
Master include file to access all functions and structures in the library.
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
Definition pair.h:639
static size_t char ** out
Definition value.h:1030
static int vector_umts_from_quintuplets(request_t *request, fr_pair_list_t *vps, fr_aka_sim_keys_t *keys)
Get one set of quintuplets from the request.
Definition vector.c:591
int fr_aka_sim_vector_gsm_umts_kdf_0_reauth_from_attrs(request_t *request, fr_pair_list_t *vps, fr_aka_sim_keys_t *keys)
Populate a fr_aka_sim_keys_t structure from attributes in the session-state list.
Definition vector.c:822
static int vector_umts_from_ki(request_t *request, fr_pair_list_t *vps, fr_aka_sim_keys_t *keys)
Definition vector.c:394
static int vector_opc_from_op(request_t *request, uint8_t const **out, uint8_t opc_buff[MILENAGE_OPC_SIZE], fr_pair_list_t *list, uint8_t const ki[MILENAGE_KI_SIZE])
Definition vector.c:41
void fr_aka_sim_vector_umts_reauth_clear(fr_aka_sim_keys_t *keys)
Clear reauth data if reauthentication failed.
Definition vector.c:915
static int vector_gsm_from_quintuplets(request_t *request, fr_pair_list_t *vps, int idx, fr_aka_sim_keys_t *keys)
Derive triplets from quintuplets.
Definition vector.c:235
int fr_aka_sim_vector_gsm_from_attrs(request_t *request, fr_pair_list_t *vps, int idx, fr_aka_sim_keys_t *keys, fr_aka_sim_vector_src_t *src)
Retrieve GSM triplets from sets of attributes.
Definition vector.c:328
static int vector_gsm_from_ki(request_t *request, fr_pair_list_t *vps, int idx, fr_aka_sim_keys_t *keys)
Definition vector.c:77
int fr_aka_sim_vector_umts_kdf_1_reauth_from_attrs(request_t *request, fr_pair_list_t *vps, fr_aka_sim_keys_t *keys)
Populate a fr_aka_sim_keys_t structure from attributes in the session-state list.
Definition vector.c:871
static int vector_gsm_from_triplets(request_t *request, fr_pair_list_t *vps, int idx, fr_aka_sim_keys_t *keys)
Definition vector.c:175
int fr_aka_sim_umts_resync_from_attrs(uint64_t *new_sqn, request_t *request, fr_pair_t *auts_vp, fr_aka_sim_keys_t *keys)
Perform milenage AUTS validation and resynchronisation.
Definition vector.c:933
int fr_aka_sim_vector_umts_from_attrs(request_t *request, fr_pair_list_t *vps, fr_aka_sim_keys_t *keys, fr_aka_sim_vector_src_t *src)
Retrieve UMTS quintuplets from sets of attributes.
Definition vector.c:753