2 * Copyright (C) 2006 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 /* The EAP-AKA method uses it's own simple parser for processing EAP-AKA
20 * payloads, as the IKEv2 parser is not suitable for that job. There are
21 * two simple methods for parsing payloads, read_header() and read_attribute().
22 * Every EAP-AKA payload consists of a header and a list of attributes. Those
23 * functions mentioned read the data and return the type of the found
24 * attribute/EAP-AKA-type. For generating a EAP-AKA message, we have a
25 * build_aka_payload(), which builds the whole message from a variable
26 * argument list containing its attributes.
27 * The processing of messages is split up in various functions:
28 * - peer_process() - General processing multiplexer for the peer
29 * - peer_process_challenge() - Specific AKA-Challenge processor
30 * - peer_process_notification() - Processing of AKA-Notification
31 * - server_process() - General processing multiplexer for the server
32 * - peer_process_challenge() - Processing of a received Challenge response
33 * - peer_process_synchronize() - Process a sequence number synchronization
34 * - server_initiate() - Initiation method for the server, calls
35 * - server_initiate_challenge() - Initiation of AKA-Challenge
49 #include <crypto/hashers/hasher.h>
51 /* Use test vectors specified in S.S0055
52 #define TEST_VECTORS */
54 #define RAND_LENGTH 16
64 #define AUTN_LENGTH (SQN_LENGTH + AMF_LENGTH + MAC_LENGTH)
65 #define AUTS_LENGTH (SQN_LENGTH + MAC_LENGTH)
66 #define PAYLOAD_LENGTH 64
69 #define EMSK_LENGTH 64
70 #define KAUTH_LENGTH 16
71 #define KENCR_LENGTH 16
72 #define AT_MAC_LENGTH 16
82 typedef enum aka_subtype_t aka_subtype_t
;
83 typedef enum aka_attribute_t aka_attribute_t
;
86 * Subtypes of AKA messages
90 AKA_AUTHENTICATION_REJECT
= 2,
91 AKA_SYNCHRONIZATION_FAILURE
= 4,
93 AKA_NOTIFICATION
= 12,
94 AKA_REAUTHENTICATION
= 13,
95 AKA_CLIENT_ERROR
= 14,
99 * Attribute types in AKA messages
101 enum aka_attribute_t
{
102 /** defines the end of attribute list */
110 AT_PERMANENT_ID_REQ
= 10,
112 AT_NOTIFICATION
= 12,
115 AT_VERSION_LIST
= 15,
116 AT_SELECTED_VERSION
= 16,
117 AT_FULLAUTH_ID_REQ
= 17,
119 AT_COUNTER_TOO_SMALL
= 20,
121 AT_CLIENT_ERROR_CODE
= 22,
124 AT_NEXT_PSEUDONYM
= 132,
125 AT_NEXT_REAUTH_ID
= 133,
130 ENUM_BEGIN(aka_subtype_names
, AKA_CHALLENGE
, AKA_IDENTITY
,
132 "AKA_AUTHENTICATION_REJECT",
134 "AKA_SYNCHRONIZATION_FAILURE",
136 ENUM_NEXT(aka_subtype_names
, AKA_NOTIFICATION
, AKA_CLIENT_ERROR
, AKA_IDENTITY
,
138 "AKA_REAUTHENTICATION",
140 ENUM_END(aka_subtype_names
, AKA_CLIENT_ERROR
);
143 ENUM_BEGIN(aka_attribute_names
, AT_END
, AT_CLIENT_ERROR_CODE
,
155 "AT_PERMANENT_ID_REQ",
161 "AT_SELECTED_VERSION",
162 "AT_FULLAUTH_ID_REQ",
165 "AT_COUNTER_TOO_SMALL",
167 "AT_CLIENT_ERROR_CODE");
168 ENUM_NEXT(aka_attribute_names
, AT_IV
, AT_RESULT_IND
, AT_CLIENT_ERROR_CODE
,
176 ENUM_END(aka_attribute_names
, AT_RESULT_IND
);
179 typedef struct private_eap_aka_t private_eap_aka_t
;
182 * Private data of an eap_aka_t object.
184 struct private_eap_aka_t
{
187 * Public authenticator_t interface.
194 identification_t
*server
;
199 identification_t
*peer
;
207 * MAC function used in EAP-AKA
212 * pseudo random function used in EAP-aka
217 * Special keyed SHA1 hasher used in EAP-AKA, implemented as PRF
227 * Key for EAP encryption
242 * Expected result from client XRES
247 * Shared secret K from ipsec.conf (padded)
252 * random value RAND generated by server
257 /** Family key, as proposed in S.S0055 */
258 static u_int8_t fmk_buf
[] = {0x41, 0x48, 0x41, 0x47};
259 static chunk_t fmk
= chunk_from_buf(fmk_buf
);
261 /** Authentication management field */
262 static u_int8_t amf_buf
[] = {0x00, 0x01};
263 static chunk_t amf
= chunk_from_buf(amf_buf
);
265 /** AT_CLIENT_ERROR_CODE AKA attribute */
266 static u_int8_t client_error_code_buf
[] = {0, 0};
267 static chunk_t client_error_code
= chunk_from_buf(client_error_code_buf
);
269 /** previously used sqn by peer, next one must be greater */
270 static u_int8_t peer_sqn_buf
[6];
271 static chunk_t peer_sqn
= chunk_from_buf(peer_sqn_buf
);
273 /** set SQN to the current time */
274 static void update_sqn(u_int8_t
*sqn
, time_t offset
)
277 gettimeofday(&time
, NULL
);
278 /* set sqb_sqn to an integer containing seconds followed by most
279 * significant useconds */
280 time
.tv_sec
= htonl(time
.tv_sec
+ offset
);
281 /* usec's are never larger than 0x000f423f, so we shift the 12 first bits */
283 time
.tv_usec
= htonl(time
.tv_usec
);
284 memcpy(sqn
, &time
.tv_sec
, 4);
285 memcpy(sqn
+ 4, &time
.tv_usec
, 2);
288 /** initialize peers SQN to the current system time at startup */
289 static void __attribute__ ((constructor
))init_sqn(void)
291 update_sqn(peer_sqn_buf
, 0);
295 * Binary represnation of the polynom T^160 + T^5 + T^3 + T^2 + 1
297 static u_int8_t g
[] = {
298 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300 0x00, 0x00, 0x00, 0x00, 0x2d
304 * Predefined random bits from the RAND Corporation book
306 static u_int8_t a
[] = {
307 0x9d, 0xe9, 0xc9, 0xc8, 0xef, 0xd5, 0x78, 0x11,
308 0x48, 0x23, 0x14, 0x01, 0x90, 0x1f, 0x2d, 0x49,
309 0x3f, 0x4c, 0x63, 0x65
313 * Predefined random bits from the RAND Corporation book
315 static u_int8_t b
[] = {
316 0x75, 0xef, 0xd1, 0x5c, 0x4b, 0x8f, 0x8f, 0x51,
317 0x4e, 0xf3, 0xbc, 0xc3, 0x79, 0x4a, 0x76, 0x5e,
318 0x7e, 0xec, 0x45, 0xe0
322 * Multiplicate two mpz_t with bits interpreted as polynoms.
324 static void mpz_mul_poly(mpz_t r
, mpz_t a
, mpz_t b
)
327 int current
= 0, shifted
= 0, shift
;
330 mpz_init_set_ui(rm
, 0);
331 /* scan through a, for each found bit: */
332 while ((current
= mpz_scan1(a
, current
)) != ULONG_MAX
)
334 /* XOR shifted b into r */
335 shift
= current
- shifted
;
336 mpz_mul_2exp(bm
, bm
, shift
);
348 * Calculate the sum of a + b interpreted as polynoms.
350 static void mpz_add_poly(mpz_t res
, mpz_t a
, mpz_t b
)
352 /* addition of polynominals is just the XOR */
357 * Calculate the remainder of a/b interpreted as polynoms.
359 static void mpz_mod_poly(mpz_t r
, mpz_t a
, mpz_t b
)
365 int a_bit
, b_bit
, diff
;
371 a_bit
= mpz_sizeinbase(a
, 2);
372 b_bit
= mpz_sizeinbase(b
, 2);
374 /* don't do anything if b > a */
377 /* shift b left to align up most signaficant "1" to a:
381 mpz_mul_2exp(bm
, b
, a_bit
- b_bit
);
384 /* XOR b into a, this kills the most significant "1":
388 /* find the next most significant "1" in a, and align up b:
392 diff
= a_bit
- mpz_sizeinbase(am
, 2);
393 mpz_div_2exp(bm
, bm
, diff
);
396 while (b_bit
<= mpz_sizeinbase(bm
, 2));
397 /* While b is not shifted to its original value */
399 /* after another iteration:
401 * which is the polynomial modulo
410 * Step 4 of the various fx() functions:
411 * Polynomial whiten calculations
413 static void step4(private_eap_aka_t
*this, u_int8_t x
[])
415 mpz_t xm
, am
, bm
, gm
;
422 mpz_import(xm
, HASH_SIZE_SHA1
, 1, 1, 1, 0, x
);
423 mpz_import(am
, sizeof(a
), 1, 1, 1, 0, a
);
424 mpz_import(bm
, sizeof(b
), 1, 1, 1, 0, b
);
425 mpz_import(gm
, sizeof(g
), 1, 1, 1, 0, g
);
427 mpz_mul_poly(xm
, am
, xm
);
428 mpz_add_poly(xm
, bm
, xm
);
429 mpz_mod_poly(xm
, xm
, gm
);
431 mpz_export(x
, NULL
, 1, HASH_SIZE_SHA1
, 1, 0, xm
);
440 * Step 3 of the various fx() functions:
441 * XOR the key into the SHA1 IV
443 static void step3(private_eap_aka_t
*this,
444 chunk_t k
, chunk_t payload
, u_int8_t h
[])
448 if (payload
.len
< sizeof(buf
))
450 /* pad c with zeros */
451 memset(buf
, 0, sizeof(buf
));
452 memcpy(buf
, payload
.ptr
, payload
.len
);
454 payload
.len
= sizeof(buf
);
458 /* not more than 512 bits can be G()-ed */
459 payload
.len
= sizeof(buf
);
462 /* use the keyed hasher to build the hash */
463 this->keyed_prf
->set_key(this->keyed_prf
, k
);
464 this->keyed_prf
->get_bytes(this->keyed_prf
, payload
, h
);
468 * Calculation function for f2(), f3(), f4()
470 static void fx(private_eap_aka_t
*this,
471 u_int8_t f
, chunk_t k
, chunk_t rand
, u_int8_t out
[])
473 chunk_t payload
= chunk_alloca(PAYLOAD_LENGTH
);
474 u_int8_t h
[HASH_SIZE_SHA1
];
477 for (i
= 0; i
< 2; i
++)
479 memset(payload
.ptr
, 0x5c, payload
.len
);
480 payload
.ptr
[11] ^= f
;
481 memxor(payload
.ptr
+ 12, fmk
.ptr
, fmk
.len
);
482 memxor(payload
.ptr
+ 24, rand
.ptr
, rand
.len
);
485 payload
.ptr
[19] ^= i
;
486 payload
.ptr
[35] ^= i
;
487 payload
.ptr
[51] ^= i
;
489 step3(this, k
, payload
, h
);
491 memcpy(out
+ i
* 8, h
, 8);
496 * Calculation function of f1() and f1star()
498 static void f1x(private_eap_aka_t
*this,
499 u_int8_t f
, chunk_t k
, chunk_t rand
, chunk_t sqn
,
500 chunk_t amf
, u_int8_t mac
[])
502 /* generate MAC = f1(FMK, SQN, RAND, AMF)
503 * K is loaded into hashers IV; FMK, RAND, SQN, AMF are XORed in a 512-bit
504 * payload which gets hashed
506 chunk_t payload
= chunk_alloca(PAYLOAD_LENGTH
);
507 u_int8_t h
[HASH_SIZE_SHA1
];
509 memset(payload
.ptr
, 0x5c, PAYLOAD_LENGTH
);
510 payload
.ptr
[11] ^= f
;
511 memxor(payload
.ptr
+ 12, fmk
.ptr
, fmk
.len
);
512 memxor(payload
.ptr
+ 16, rand
.ptr
, rand
.len
);
513 memxor(payload
.ptr
+ 34, sqn
.ptr
, sqn
.len
);
514 memxor(payload
.ptr
+ 42, amf
.ptr
, amf
.len
);
516 step3(this, k
, payload
, h
);
518 memcpy(mac
, h
, MAC_LENGTH
);
522 * Calculation function of f5() and f5star()
524 static void f5x(private_eap_aka_t
*this,
525 u_int8_t f
, chunk_t k
, chunk_t rand
, u_int8_t ak
[])
527 chunk_t payload
= chunk_alloca(PAYLOAD_LENGTH
);
528 u_int8_t h
[HASH_SIZE_SHA1
];
530 memset(payload
.ptr
, 0x5c, payload
.len
);
531 payload
.ptr
[11] ^= f
;
532 memxor(payload
.ptr
+ 12, fmk
.ptr
, fmk
.len
);
533 memxor(payload
.ptr
+ 16, rand
.ptr
, rand
.len
);
535 step3(this, k
, payload
, h
);
537 memcpy(ak
, h
, AK_LENGTH
);
541 * Calculate the MAC from a RAND, SQN, AMF value using K
543 static void f1(private_eap_aka_t
*this, chunk_t k
, chunk_t rand
, chunk_t sqn
,
544 chunk_t amf
, u_int8_t mac
[])
546 f1x(this, F1
, k
, rand
, sqn
, amf
, mac
);
547 DBG3(DBG_IKE
, "MAC %b", mac
, MAC_LENGTH
);
551 * Calculate the MACS from a RAND, SQN, AMF value using K
553 static void f1star(private_eap_aka_t
*this, chunk_t k
, chunk_t rand
,
554 chunk_t sqn
, chunk_t amf
, u_int8_t macs
[])
556 f1x(this, F1STAR
, k
, rand
, sqn
, amf
, macs
);
557 DBG3(DBG_IKE
, "MACS %b", macs
, MAC_LENGTH
);
561 * Calculate RES from RAND using K
563 static void f2(private_eap_aka_t
*this, chunk_t k
, chunk_t rand
, u_int8_t res
[])
565 fx(this, F2
, k
, rand
, res
);
566 DBG3(DBG_IKE
, "RES %b", res
, RES_LENGTH
);
570 * Calculate CK from RAND using K
572 static void f3(private_eap_aka_t
*this, chunk_t k
, chunk_t rand
, u_int8_t ck
[])
574 fx(this, F3
, k
, rand
, ck
);
575 DBG3(DBG_IKE
, "CK %b", ck
, CK_LENGTH
);
579 * Calculate IK from RAND using K
581 static void f4(private_eap_aka_t
*this, chunk_t k
, chunk_t rand
, u_int8_t ik
[])
583 fx(this, F4
, k
, rand
, ik
);
584 DBG3(DBG_IKE
, "IK %b", ik
, IK_LENGTH
);
588 * Calculate AK from a RAND using K
590 static void f5(private_eap_aka_t
*this, chunk_t k
, chunk_t rand
, u_int8_t ak
[])
592 f5x(this, F5
, k
, rand
, ak
);
593 DBG3(DBG_IKE
, "AK %b", ak
, AK_LENGTH
);
597 * Calculate AKS from a RAND using K
599 static void f5star(private_eap_aka_t
*this, chunk_t k
, chunk_t rand
, u_int8_t aks
[])
601 f5x(this, F5STAR
, k
, rand
, aks
);
602 DBG3(DBG_IKE
, "AKS %b", aks
, AK_LENGTH
);
606 * derive the keys needed for EAP_AKA
608 static bool derive_keys(private_eap_aka_t
*this, identification_t
*id
)
610 chunk_t ck
, ik
, mk
, identity
, tmp
;
612 ck
= chunk_alloca(CK_LENGTH
);
613 ik
= chunk_alloca(IK_LENGTH
);
614 mk
= chunk_alloca(MK_LENGTH
);
615 identity
= id
->get_encoding(id
);
617 /* MK = SHA1( Identity | IK | CK ) */
618 f3(this, this->k
, this->rand
, ck
.ptr
);
619 f4(this, this->k
, this->rand
, ik
.ptr
);
620 DBG3(DBG_IKE
, "Identity %B", &identity
);
621 tmp
= chunk_cata("ccc", identity
, ik
, ck
);
622 DBG3(DBG_IKE
, "Identity|IK|CK %B", &tmp
);
623 this->sha1
->get_hash(this->sha1
, tmp
, mk
.ptr
);
625 /* K_encr | K_auth | MSK | EMSK = prf(0) | prf(0)
626 * FIPS PRF has 320 bit block size, we need 160 byte for keys
627 * => run prf four times */
628 this->prf
->set_key(this->prf
, mk
);
629 tmp
= chunk_alloca(this->prf
->get_block_size(this->prf
) * 4);
630 this->prf
->get_bytes(this->prf
, chunk_empty
, tmp
.ptr
);
631 this->prf
->get_bytes(this->prf
, chunk_empty
, tmp
.ptr
+ tmp
.len
/ 4 * 1);
632 this->prf
->get_bytes(this->prf
, chunk_empty
, tmp
.ptr
+ tmp
.len
/ 4 * 2);
633 this->prf
->get_bytes(this->prf
, chunk_empty
, tmp
.ptr
+ tmp
.len
/ 4 * 3);
634 chunk_free(&this->k_encr
);
635 chunk_free(&this->k_auth
);
636 chunk_free(&this->msk
);
637 chunk_free(&this->emsk
);
638 chunk_split(tmp
, "aaaa", 16, &this->k_encr
, 16, &this->k_auth
,
639 64, &this->msk
, 64, &this->emsk
);
640 DBG3(DBG_IKE
, "MK %B", &mk
);
641 DBG3(DBG_IKE
, "PRF res %B", &tmp
);
642 DBG3(DBG_IKE
, "K_encr %B", &this->k_encr
);
643 DBG3(DBG_IKE
, "K_auth %B", &this->k_auth
);
644 DBG3(DBG_IKE
, "MSK %B", &this->msk
);
645 DBG3(DBG_IKE
, "EMSK %B", &this->emsk
);
650 * Get a shared key from ipsec.secrets.
651 * We use the standard keys as used in preshared key authentication. As
652 * these keys have an undefined length, we:
653 * - strip them if they are longer
654 * - fill them up with '\0' if they are shorter
656 static status_t
load_key(identification_t
*me
, identification_t
*other
, chunk_t
*k
)
658 shared_key_t
*shared
;
661 shared
= charon
->credentials
->get_shared(charon
->credentials
, SHARED_EAP
,
667 key
= shared
->get_key(shared
);
669 *k
= chunk_alloc(K_LENGTH
);
670 memset(k
->ptr
, '\0', k
->len
);
671 memcpy(k
->ptr
, key
.ptr
, min(key
.len
, k
->len
));
672 shared
->destroy(shared
);
677 * skip EAP_AKA header in message and returns its AKA subtype
679 static aka_subtype_t
read_header(chunk_t
*message
)
683 if (message
->len
< 8)
685 *message
= chunk_empty
;
688 type
= *(message
->ptr
+ 5);
689 *message
= chunk_skip(*message
, 8);
694 * read the next attribute from the chunk data
696 static aka_attribute_t
read_attribute(chunk_t
*data
, chunk_t
*attr_data
)
698 aka_attribute_t attribute
;
701 DBG3(DBG_IKE
, "reading attribute from %B", data
);
707 /* read attribute and length */
708 attribute
= *data
->ptr
++;
709 length
= *data
->ptr
++ * 4 - 2;
711 DBG3(DBG_IKE
, "found attribute %N with length %d",
712 aka_attribute_names
, attribute
, length
);
713 if (length
> data
->len
)
717 /* apply attribute value to attr_data */
718 attr_data
->len
= length
;
719 attr_data
->ptr
= data
->ptr
;
720 /* update data to point to next attribute */
721 *data
= chunk_skip(*data
, length
);
726 * Build an AKA payload from different attributes.
727 * The variable argument takes an aka_attribute_t
728 * followed by its data in a chunk.
730 static eap_payload_t
*build_aka_payload(private_eap_aka_t
*this, eap_code_t code
,
731 u_int8_t identifier
, aka_subtype_t type
, ...)
733 chunk_t message
= chunk_alloca(512); /* is enought for all current messages */
734 chunk_t pos
= message
;
735 eap_payload_t
*payload
;
737 aka_attribute_t attr
;
738 u_int8_t
*mac_pos
= NULL
;
740 /* write EAP header, skip length bytes */
742 *pos
.ptr
++ = identifier
;
745 /* write AKA header with type and subtype, null reserved bytes */
746 *pos
.ptr
++ = EAP_AKA
;
752 va_start(args
, type
);
753 while ((attr
= va_arg(args
, aka_attribute_t
)) != AT_END
)
755 chunk_t data
= va_arg(args
, chunk_t
);
757 DBG3(DBG_IKE
, "building %N %B", aka_attribute_names
, attr
, &data
);
759 /* write attribute header */
767 /* attribute length in 4byte words */
768 *pos
.ptr
= data
.len
/4 + 1;
769 pos
= chunk_skip(pos
, 1);
770 /* RES length in bits */
771 *(u_int16_t
*)pos
.ptr
= htons(data
.len
* 8);
772 pos
= chunk_skip(pos
, sizeof(u_int16_t
));
773 memcpy(pos
.ptr
, data
.ptr
, data
.len
);
774 pos
= chunk_skip(pos
, data
.len
);
780 *pos
.ptr
++ = data
.len
/4 + 1; pos
.len
--;
781 *pos
.ptr
++ = 0; pos
.len
--;
782 *pos
.ptr
++ = 0; pos
.len
--;
783 memcpy(pos
.ptr
, data
.ptr
, data
.len
);
784 pos
= chunk_skip(pos
, data
.len
);
789 *pos
.ptr
++ = 5; pos
.len
--;
790 *pos
.ptr
++ = 0; pos
.len
--;
791 *pos
.ptr
++ = 0; pos
.len
--;
793 /* MAC is calculated over message including zeroed AT_MAC attribute */
794 memset(mac_pos
, 0, AT_MAC_LENGTH
);
795 pos
.ptr
+= AT_MAC_LENGTH
;
796 pos
.len
-= AT_MAC_LENGTH
;
801 /* length is data length in 4-bytes + 1 for header */
802 *pos
.ptr
= data
.len
/4 + 1;
803 pos
= chunk_skip(pos
, 1);
804 memcpy(pos
.ptr
, data
.ptr
, data
.len
);
805 pos
= chunk_skip(pos
, data
.len
);
811 /* calculate message length, write into header */
812 message
.len
= pos
.ptr
- message
.ptr
;
813 *(u_int16_t
*)(message
.ptr
+ 2) = htons(message
.len
);
815 /* create MAC if AT_MAC attribte was included */
818 this->signer
->set_key(this->signer
, this->k_auth
);
819 DBG3(DBG_IKE
, "AT_MAC signature of %B", &message
);
820 DBG3(DBG_IKE
, "using key %B", &this->k_auth
);
821 this->signer
->get_signature(this->signer
, message
, mac_pos
);
822 DBG3(DBG_IKE
, "is %b", mac_pos
, AT_MAC_LENGTH
);
825 /* payload constructor takes data with some bytes skipped */
826 payload
= eap_payload_create_data(message
);
828 DBG3(DBG_IKE
, "created EAP message %B", &message
);
833 * generate a new non-zero identifier
835 static u_char
get_identifier()
846 * Initiate a AKA-Challenge using SQN
848 static status_t
server_initiate_challenge(private_eap_aka_t
*this, chunk_t sqn
,
852 chunk_t mac
, ak
, autn
;
854 mac
= chunk_alloca(MAC_LENGTH
);
855 ak
= chunk_alloca(AK_LENGTH
);
856 chunk_free(&this->rand
);
857 chunk_free(&this->xres
);
860 * we use a registered RNG, not f0() proposed in S.S0055
862 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
865 DBG1(DBG_IKE
, "generating RAND for EAP-AKA authentication failed");
868 rng
->allocate_bytes(rng
, RAND_LENGTH
, &this->rand
);
872 /* Test vector for RAND */
873 u_int8_t test_rand
[] = {
874 0x4b,0x05,0x2b,0x20,0xe2,0xa0,0x6c,0x8f,
875 0xf7,0x00,0xda,0x51,0x2b,0x4e,0x11,0x1e,
877 memcpy(this->rand
.ptr
, test_rand
, this->rand
.len
);
878 # endif /* TEST_VECTORS */
880 /* Get the shared key K: */
881 if (load_key(this->server
, this->peer
, &this->k
) != SUCCESS
)
883 DBG1(DBG_IKE
, "no shared key found for IDs '%D' - '%D' to authenticate "
884 "with EAP-AKA", this->server
, this->peer
);
889 /* Test vector for K */
890 u_int8_t test_k
[] = {
891 0xad,0x1b,0x5a,0x15,0x9b,0xe8,0x6b,0x2c,
892 0xa6,0x6c,0x7a,0xe4,0x0b,0xba,0x9b,0x9d,
894 memcpy(this->k
.ptr
, test_k
, this->k
.len
);
895 # endif /* TEST_VECTORS */
898 f1(this, this->k
, this->rand
, sqn
, amf
, mac
.ptr
);
901 f5(this, this->k
, this->rand
, ak
.ptr
);
903 /* precalculate XRES as expected from client */
904 this->xres
= chunk_alloc(RES_LENGTH
);
905 f2(this, this->k
, this->rand
, this->xres
.ptr
);
907 /* calculate AUTN = (SQN xor AK) || AMF || MAC */
908 autn
= chunk_cata("ccc", sqn
, amf
, mac
);
909 memxor(autn
.ptr
, ak
.ptr
, ak
.len
);
910 DBG3(DBG_IKE
, "AUTN %B", &autn
);
913 /* derive K_encr, K_auth, MSK, EMSK */
914 derive_keys(this, this->peer
);
917 *out
= build_aka_payload(this, EAP_REQUEST
, get_identifier(), AKA_CHALLENGE
,
918 AT_RAND
, this->rand
, AT_AUTN
, autn
, AT_MAC
,
919 chunk_empty
, AT_END
);
924 * Implementation of eap_method_t.initiate for an EAP_AKA server
926 static status_t
server_initiate(private_eap_aka_t
*this, eap_payload_t
**out
)
928 chunk_t sqn
= chunk_alloca(SQN_LENGTH
);
930 /* we use an offset of 3 minutes to tolerate clock inaccuracy
931 * without the need to synchronize sequence numbers */
932 update_sqn(sqn
.ptr
, 180);
935 /* Test vector for SQN */
936 u_int8_t test_sqn
[] = {0x00,0x00,0x00,0x00,0x00,0x01};
937 memcpy(sqn
.ptr
, test_sqn
, sqn
.len
);
938 # endif /* TEST_VECTORS */
940 return server_initiate_challenge(this, sqn
, out
);
943 static status_t
server_process_synchronize(private_eap_aka_t
*this,
944 eap_payload_t
*in
, eap_payload_t
**out
)
946 chunk_t attr
, auts
= chunk_empty
, pos
, message
, macs
, xmacs
, sqn
, aks
, amf
;
949 message
= in
->get_data(in
);
953 /* iterate over attributes */
956 aka_attribute_t attribute
= read_attribute(&pos
, &attr
);
965 if (attribute
>= 0 && attribute
<= 127)
967 DBG1(DBG_IKE
, "found non skippable attribute %N",
968 aka_attribute_names
, attribute
);
971 DBG1(DBG_IKE
, "ignoring skippable attribute %N",
972 aka_attribute_names
, attribute
);
978 if (auts
.len
!= AUTS_LENGTH
)
980 DBG1(DBG_IKE
, "synchronization request didn't contain useable AUTS");
984 chunk_split(auts
, "mm", SQN_LENGTH
, &sqn
, MAC_LENGTH
, &macs
);
985 aks
= chunk_alloca(AK_LENGTH
);
986 f5star(this, this->k
, this->rand
, aks
.ptr
);
987 /* decrypt serial number by XORing AKS */
988 memxor(sqn
.ptr
, aks
.ptr
, aks
.len
);
991 xmacs
= chunk_alloca(MAC_LENGTH
);
992 amf
= chunk_alloca(AMF_LENGTH
);
993 /* an AMF of zero is used for MACS calculation */
994 memset(amf
.ptr
, 0, amf
.len
);
995 f1star(this, this->k
, this->rand
, sqn
, amf
, xmacs
.ptr
);
996 if (!chunk_equals(macs
, xmacs
))
998 DBG1(DBG_IKE
, "received MACS does not match XMACS");
999 DBG3(DBG_IKE
, "MACS %B XMACS %B", &macs
, &xmacs
);
1003 /* retry the challenge with the received SQN + 1*/
1004 for (i
= SQN_LENGTH
- 1; i
>= 0; i
--)
1006 if (++sqn
.ptr
[i
] != 0)
1011 return server_initiate_challenge(this, sqn
, out
);
1015 * process an AKA_Challenge response
1017 static status_t
server_process_challenge(private_eap_aka_t
*this, eap_payload_t
*in
)
1019 chunk_t attr
, res
= chunk_empty
, at_mac
= chunk_empty
, pos
, message
;
1021 message
= in
->get_data(in
);
1025 /* iterate over attributes */
1028 aka_attribute_t attribute
= read_attribute(&pos
, &attr
);
1035 if (attr
.len
== 2 + RES_LENGTH
&&
1036 *(u_int16_t
*)attr
.ptr
== htons(RES_LENGTH
* 8))
1038 res
= chunk_skip(attr
, 2);
1043 attr
= chunk_skip(attr
, 2);
1044 at_mac
= chunk_clonea(attr
);
1045 /* zero MAC in message for MAC verification */
1046 memset(attr
.ptr
, 0, attr
.len
);
1049 if (attribute
>= 0 && attribute
<= 127)
1051 DBG1(DBG_IKE
, "found non skippable attribute %N",
1052 aka_attribute_names
, attribute
);
1055 DBG1(DBG_IKE
, "ignoring skippable attribute %N",
1056 aka_attribute_names
, attribute
);
1062 /* verify EAP message MAC AT_MAC */
1064 this->signer
->set_key(this->signer
, this->k_auth
);
1065 DBG3(DBG_IKE
, "verifying AT_MAC signature of %B", &message
);
1066 DBG3(DBG_IKE
, "using key %B", &this->k_auth
);
1067 if (!this->signer
->verify_signature(this->signer
, message
, at_mac
))
1069 DBG1(DBG_IKE
, "MAC in AT_MAC attribute verification failed");
1074 /* compare received RES against stored precalculated XRES */
1075 if (!chunk_equals(res
, this->xres
))
1077 DBG1(DBG_IKE
, "received RES does not match XRES");
1078 DBG3(DBG_IKE
, "RES %Bb XRES %B", &res
, &this->xres
);
1085 * Implementation of eap_method_t.process for EAP_AKA servers
1087 static status_t
server_process(private_eap_aka_t
*this,
1088 eap_payload_t
*in
, eap_payload_t
**out
)
1093 message
= in
->get_data(in
);
1094 type
= read_header(&message
);
1096 DBG3(DBG_IKE
, "received EAP message %B", &message
);
1102 return server_process_challenge(this, in
);
1104 case AKA_AUTHENTICATION_REJECT
:
1105 case AKA_CLIENT_ERROR
:
1107 DBG1(DBG_IKE
, "received %N, authentication failed",
1108 aka_subtype_names
, type
);
1111 case AKA_SYNCHRONIZATION_FAILURE
:
1113 DBG1(DBG_IKE
, "received %N, retrying with received SQN",
1114 aka_subtype_names
, type
);
1115 return server_process_synchronize(this, in
, out
);
1118 DBG1(DBG_IKE
, "received unknown AKA subtype %N, authentication failed",
1119 aka_subtype_names
, type
);
1125 * Process an incoming AKA-Challenge client side
1127 static status_t
peer_process_challenge(private_eap_aka_t
*this,
1128 eap_payload_t
*in
, eap_payload_t
**out
)
1130 chunk_t attr
= chunk_empty
;
1131 chunk_t autn
= chunk_empty
, at_mac
= chunk_empty
;
1132 chunk_t ak
, sqn
, sqn_ak
, mac
, xmac
, res
, amf
, message
, pos
;
1133 u_int8_t identifier
;
1135 ak
= chunk_alloca(AK_LENGTH
);
1136 xmac
= chunk_alloca(MAC_LENGTH
);
1137 res
= chunk_alloca(RES_LENGTH
);
1138 chunk_free(&this->rand
);
1140 message
= in
->get_data(in
);
1143 identifier
= in
->get_identifier(in
);
1145 DBG3(DBG_IKE
, "reading attributes from %B", &pos
);
1147 /* iterate over attributes */
1150 aka_attribute_t attribute
= read_attribute(&pos
, &attr
);
1156 this->rand
= chunk_clone(chunk_skip(attr
, 2));
1159 autn
= chunk_skip(attr
, 2);
1162 attr
= chunk_skip(attr
, 2);
1163 at_mac
= chunk_clonea(attr
);
1164 /* set MAC in message to zero for own MAC verification */
1165 memset(attr
.ptr
, 0, attr
.len
);
1168 if (attribute
>= 0 && attribute
<= 127)
1170 /* non skippable attribute, abort */
1171 *out
= build_aka_payload(this, EAP_RESPONSE
, identifier
, AKA_CLIENT_ERROR
,
1172 AT_CLIENT_ERROR_CODE
, client_error_code
, AT_END
);
1173 DBG1(DBG_IKE
, "found non skippable attribute %N, sending %N %d",
1174 aka_attribute_names
, attribute
,
1175 aka_attribute_names
, AT_CLIENT_ERROR_CODE
, 0);
1178 DBG1(DBG_IKE
, "ignoring skippable attribute %N",
1179 aka_attribute_names
, attribute
);
1185 if (this->rand
.len
!= RAND_LENGTH
|| autn
.len
!= AUTN_LENGTH
)
1187 /* required attributes wrong/not found, abort */
1188 *out
= build_aka_payload(this, EAP_RESPONSE
, identifier
, AKA_CLIENT_ERROR
,
1189 AT_CLIENT_ERROR_CODE
, client_error_code
, AT_END
);
1190 DBG1(DBG_IKE
, "could not find valid RAND/AUTN attribute, sending %N %d",
1191 aka_attribute_names
, AT_CLIENT_ERROR_CODE
, 0);
1195 DBG3(DBG_IKE
, "using autn %B", &autn
);
1196 /* split up AUTN = SQN xor AK | AMF | MAC */
1197 chunk_split(autn
, "mmm", SQN_LENGTH
, &sqn_ak
, AMF_LENGTH
, &amf
, MAC_LENGTH
, &mac
);
1199 /* Get the shared key K: */
1200 chunk_free(&this->k
);
1201 if (load_key(this->peer
, this->server
, &this->k
) != SUCCESS
)
1203 *out
= build_aka_payload(this, EAP_RESPONSE
, identifier
,
1204 AKA_AUTHENTICATION_REJECT
, AT_END
);
1205 DBG3(DBG_IKE
, "no shared key found for IDs '%D' - '%D' to authenticate "
1206 "with EAP-AKA, sending %N", this->peer
, this->server
,
1207 aka_subtype_names
, AKA_AUTHENTICATION_REJECT
);
1210 DBG3(DBG_IKE
, "using K %B", &this->k
);
1211 # ifdef TEST_VECTORS
1212 /* Test vector for K */
1213 u_int8_t test_k
[] = {
1214 0xad,0x1b,0x5a,0x15,0x9b,0xe8,0x6b,0x2c,
1215 0xa6,0x6c,0x7a,0xe4,0x0b,0xba,0x9b,0x9d,
1217 memcpy(this->k
.ptr
, test_k
, this->k
.len
);
1218 # endif /* TEST_VECTORS */
1220 /* calculate anonymity key AK */
1221 f5(this, this->k
, this->rand
, ak
.ptr
);
1222 DBG3(DBG_IKE
, "using rand %B", &this->rand
);
1223 DBG3(DBG_IKE
, "using ak %B", &ak
);
1224 /* XOR AK into SQN to decrypt it */
1226 sqn
= chunk_clonea(sqn_ak
);
1228 DBG3(DBG_IKE
, "using ak xor sqn %B", &sqn_ak
);
1229 memxor(sqn
.ptr
, ak
.ptr
, sqn
.len
);
1230 DBG3(DBG_IKE
, "using sqn %B", &sqn
);
1232 /* calculate expected MAC and compare against received one */
1233 f1(this, this->k
, this->rand
, sqn
, amf
, xmac
.ptr
);
1234 if (!chunk_equals(mac
, xmac
))
1236 *out
= build_aka_payload(this, EAP_RESPONSE
, identifier
,
1237 AKA_AUTHENTICATION_REJECT
, AT_END
);
1238 DBG1(DBG_IKE
, "received MAC does not match XMAC, sending %N",
1239 aka_subtype_names
, AKA_AUTHENTICATION_REJECT
);
1240 DBG3(DBG_IKE
, "MAC %B\nXMAC %B", &mac
, &xmac
);
1245 if (memcmp(peer_sqn
.ptr
, sqn
.ptr
, sqn
.len
) >= 0)
1247 /* sequence number invalid. send AUTS */
1248 chunk_t auts
, macs
, aks
, amf
;
1250 macs
= chunk_alloca(MAC_LENGTH
);
1251 aks
= chunk_alloca(AK_LENGTH
);
1252 amf
= chunk_alloca(AMF_LENGTH
);
1254 /* AMF is set to zero in AKA_SYNCHRONIZATION_FAILURE */
1255 memset(amf
.ptr
, 0, amf
.len
);
1256 /* AKS = f5*(RAND) */
1257 f5star(this, this->k
, this->rand
, aks
.ptr
);
1258 /* MACS = f1*(RAND) */
1259 f1star(this, this->k
, this->rand
, peer_sqn
, amf
, macs
.ptr
);
1260 /* AUTS = SQN xor AKS | MACS */
1261 memxor(aks
.ptr
, peer_sqn
.ptr
, aks
.len
);
1262 auts
= chunk_cata("cc", aks
, macs
);
1264 *out
= build_aka_payload(this, EAP_RESPONSE
, identifier
,
1265 AKA_SYNCHRONIZATION_FAILURE
,
1266 AT_AUTS
, auts
, AT_END
);
1267 DBG1(DBG_IKE
, "received SQN invalid, sending %N",
1268 aka_subtype_names
, AKA_SYNCHRONIZATION_FAILURE
);
1269 DBG3(DBG_IKE
, "received SQN %B\ncurrent SQN %B", &sqn
, &peer_sqn
);
1272 #endif /* SEQ_CHECK */
1274 /* derive K_encr, K_auth, MSK, EMSK */
1275 derive_keys(this, this->peer
);
1277 /* verify EAP message MAC AT_MAC */
1278 DBG3(DBG_IKE
, "verifying AT_MAC signature of %B", &message
);
1279 DBG3(DBG_IKE
, "using key %B", &this->k_auth
);
1280 this->signer
->set_key(this->signer
, this->k_auth
);
1281 if (!this->signer
->verify_signature(this->signer
, message
, at_mac
))
1283 *out
= build_aka_payload(this, EAP_RESPONSE
, identifier
, AKA_CLIENT_ERROR
,
1284 AT_CLIENT_ERROR_CODE
, client_error_code
, AT_END
);
1285 DBG1(DBG_IKE
, "MAC in AT_MAC attribute verification "
1286 "failed, sending %N %d", aka_attribute_names
,
1287 AT_CLIENT_ERROR_CODE
, 0);
1291 /* update stored SQN to the received one */
1292 memcpy(peer_sqn
.ptr
, sqn
.ptr
, sqn
.len
);
1295 f2(this, this->k
, this->rand
, res
.ptr
);
1297 /* build response */
1298 *out
= build_aka_payload(this, EAP_RESPONSE
, identifier
, AKA_CHALLENGE
,
1299 AT_RES
, res
, AT_MAC
, chunk_empty
, AT_END
);
1304 * Process an incoming AKA-Notification as client
1306 static status_t
peer_process_notification(private_eap_aka_t
*this,
1307 eap_payload_t
*in
, eap_payload_t
**out
)
1309 chunk_t message
, pos
, attr
;
1310 u_int8_t identifier
;
1312 message
= in
->get_data(in
);
1315 identifier
= in
->get_identifier(in
);
1317 DBG3(DBG_IKE
, "reading attributes from %B", &pos
);
1319 /* iterate over attributes */
1322 aka_attribute_t attribute
= read_attribute(&pos
, &attr
);
1327 case AT_NOTIFICATION
:
1333 DBG1(DBG_IKE
, "received invalid AKA notification, ignored");
1336 code
= ntohs(*(u_int16_t
*)attr
.ptr
);
1340 DBG1(DBG_IKE
, "received AKA notification 'general "
1341 "failure after authentication' (%d)", code
);
1344 DBG1(DBG_IKE
, "received AKA notification 'general "
1345 "failure' (%d)", code
);
1348 DBG1(DBG_IKE
, "received AKA notification 'successfully "
1349 "authenticated' (%d)", code
);
1352 DBG1(DBG_IKE
, "received AKA notification 'access "
1353 "temporarily denied' (%d)", code
);
1356 DBG1(DBG_IKE
, "received AKA notification 'not "
1357 "subscribed to service' (%d)", code
);
1360 DBG1(DBG_IKE
, "received AKA notification code %d, "
1366 if (attribute
>= 0 && attribute
<= 127)
1368 DBG1(DBG_IKE
, "ignoring non-skippable attribute %N in %N",
1369 aka_attribute_names
, attribute
, aka_subtype_names
,
1374 DBG1(DBG_IKE
, "ignoring skippable attribute %N",
1375 aka_attribute_names
, attribute
);
1385 * Implementation of eap_method_t.process for an EAP_AKA peer
1387 static status_t
peer_process(private_eap_aka_t
*this,
1388 eap_payload_t
*in
, eap_payload_t
**out
)
1392 u_int8_t identifier
;
1394 message
= in
->get_data(in
);
1395 type
= read_header(&message
);
1396 identifier
= in
->get_identifier(in
);
1398 DBG3(DBG_IKE
, "received EAP message %B", &message
);
1404 return peer_process_challenge(this, in
, out
);
1406 case AKA_NOTIFICATION
:
1408 return peer_process_notification(this, in
, out
);
1412 *out
= build_aka_payload(this, EAP_RESPONSE
, identifier
, AKA_CLIENT_ERROR
,
1413 AT_CLIENT_ERROR_CODE
, client_error_code
, AT_END
);
1414 DBG1(DBG_IKE
, "received unsupported %N request, sending %N %d",
1415 aka_subtype_names
, type
,
1416 aka_attribute_names
, AT_CLIENT_ERROR_CODE
, 0);
1423 * Implementation of eap_method_t.initiate for an EAP AKA peer
1425 static status_t
peer_initiate(private_eap_aka_t
*this, eap_payload_t
**out
)
1427 /* peer never initiates */
1432 * Implementation of eap_method_t.get_type.
1434 static eap_type_t
get_type(private_eap_aka_t
*this, u_int32_t
*vendor
)
1441 * Implementation of eap_method_t.get_msk.
1443 static status_t
get_msk(private_eap_aka_t
*this, chunk_t
*msk
)
1454 * Implementation of eap_method_t.is_mutual.
1456 static bool is_mutual(private_eap_aka_t
*this)
1462 * Implementation of eap_method_t.destroy.
1464 static void destroy(private_eap_aka_t
*this)
1466 this->server
->destroy(this->server
);
1467 this->peer
->destroy(this->peer
);
1468 DESTROY_IF(this->sha1
);
1469 DESTROY_IF(this->signer
);
1470 DESTROY_IF(this->prf
);
1471 DESTROY_IF(this->keyed_prf
);
1472 chunk_free(&this->k_encr
);
1473 chunk_free(&this->k_auth
);
1474 chunk_free(&this->msk
);
1475 chunk_free(&this->emsk
);
1476 chunk_free(&this->xres
);
1477 chunk_free(&this->k
);
1478 chunk_free(&this->rand
);
1483 * generic constructor used by client & server
1485 static private_eap_aka_t
*eap_aka_create_generic(identification_t
*server
,
1486 identification_t
*peer
)
1488 private_eap_aka_t
*this = malloc_thing(private_eap_aka_t
);
1490 this->public.eap_method_interface
.initiate
= NULL
;
1491 this->public.eap_method_interface
.process
= NULL
;
1492 this->public.eap_method_interface
.get_type
= (eap_type_t(*)(eap_method_t
*,u_int32_t
*))get_type
;
1493 this->public.eap_method_interface
.is_mutual
= (bool(*)(eap_method_t
*))is_mutual
;
1494 this->public.eap_method_interface
.get_msk
= (status_t(*)(eap_method_t
*,chunk_t
*))get_msk
;
1495 this->public.eap_method_interface
.destroy
= (void(*)(eap_method_t
*))destroy
;
1498 this->server
= server
->clone(server
);
1499 this->peer
= peer
->clone(peer
);
1500 this->k_encr
= chunk_empty
;
1501 this->k_auth
= chunk_empty
;
1502 this->msk
= chunk_empty
;
1503 this->emsk
= chunk_empty
;
1504 this->xres
= chunk_empty
;
1505 this->k
= chunk_empty
;
1506 this->rand
= chunk_empty
;
1508 this->sha1
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
1509 this->signer
= lib
->crypto
->create_signer(lib
->crypto
, AUTH_HMAC_SHA1_128
);
1510 this->prf
= lib
->crypto
->create_prf(lib
->crypto
, PRF_FIPS_SHA1_160
);
1511 this->keyed_prf
= lib
->crypto
->create_prf(lib
->crypto
, PRF_KEYED_SHA1
);
1513 if (!this->sha1
|| !this->signer
|| !this->prf
|| !this->keyed_prf
)
1515 DBG1(DBG_IKE
, "unable to initiate EAP-AKA, FIPS-PRF/SHA1 not supported");
1516 DESTROY_IF(this->sha1
);
1517 DESTROY_IF(this->signer
);
1518 DESTROY_IF(this->prf
);
1519 DESTROY_IF(this->keyed_prf
);
1527 * Described in header.
1529 eap_aka_t
*eap_aka_create_server(identification_t
*server
, identification_t
*peer
)
1531 private_eap_aka_t
*this = eap_aka_create_generic(server
, peer
);
1535 this->public.eap_method_interface
.initiate
= (status_t(*)(eap_method_t
*,eap_payload_t
**))server_initiate
;
1536 this->public.eap_method_interface
.process
= (status_t(*)(eap_method_t
*,eap_payload_t
*,eap_payload_t
**))server_process
;
1538 return (eap_aka_t
*)this;
1542 * Described in header.
1544 eap_aka_t
*eap_aka_create_peer(identification_t
*server
, identification_t
*peer
)
1546 private_eap_aka_t
*this = eap_aka_create_generic(server
, peer
);
1550 this->public.eap_method_interface
.initiate
= (status_t(*)(eap_method_t
*,eap_payload_t
**))peer_initiate
;
1551 this->public.eap_method_interface
.process
= (status_t(*)(eap_method_t
*,eap_payload_t
*,eap_payload_t
**))peer_process
;
1553 return (eap_aka_t
*)this;