Line data Source code
1 : /*
2 : * EAP-IKEv2 common routines
3 : * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
4 : *
5 : * This software may be distributed under the terms of the BSD license.
6 : * See README for more details.
7 : */
8 :
9 : #include "includes.h"
10 :
11 : #include "common.h"
12 : #include "eap_defs.h"
13 : #include "eap_common.h"
14 : #include "ikev2_common.h"
15 : #include "eap_ikev2_common.h"
16 :
17 :
18 10 : int eap_ikev2_derive_keymat(int prf, struct ikev2_keys *keys,
19 : const u8 *i_nonce, size_t i_nonce_len,
20 : const u8 *r_nonce, size_t r_nonce_len,
21 : u8 *keymat)
22 : {
23 : u8 *nonces;
24 : size_t nlen;
25 :
26 : /* KEYMAT = prf+(SK_d, Ni | Nr) */
27 10 : if (keys->SK_d == NULL || i_nonce == NULL || r_nonce == NULL)
28 0 : return -1;
29 :
30 10 : nlen = i_nonce_len + r_nonce_len;
31 10 : nonces = os_malloc(nlen);
32 10 : if (nonces == NULL)
33 0 : return -1;
34 10 : os_memcpy(nonces, i_nonce, i_nonce_len);
35 10 : os_memcpy(nonces + i_nonce_len, r_nonce, r_nonce_len);
36 :
37 10 : if (ikev2_prf_plus(prf, keys->SK_d, keys->SK_d_len, nonces, nlen,
38 : keymat, EAP_MSK_LEN + EAP_EMSK_LEN)) {
39 0 : os_free(nonces);
40 0 : return -1;
41 : }
42 10 : os_free(nonces);
43 :
44 10 : wpa_hexdump_key(MSG_DEBUG, "EAP-IKEV2: KEYMAT",
45 : keymat, EAP_MSK_LEN + EAP_EMSK_LEN);
46 :
47 10 : return 0;
48 : }
49 :
50 :
51 20 : struct wpabuf * eap_ikev2_build_frag_ack(u8 id, u8 code)
52 : {
53 : struct wpabuf *msg;
54 :
55 : #ifdef CCNS_PL
56 : msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 1, code, id);
57 : if (msg == NULL) {
58 : wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory "
59 : "for fragment ack");
60 : return NULL;
61 : }
62 : wpabuf_put_u8(msg, 0); /* Flags */
63 : #else /* CCNS_PL */
64 20 : msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 0, code, id);
65 20 : if (msg == NULL) {
66 0 : wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory "
67 : "for fragment ack");
68 0 : return NULL;
69 : }
70 : #endif /* CCNS_PL */
71 :
72 20 : wpa_printf(MSG_DEBUG, "EAP-IKEV2: Send fragment ack");
73 :
74 20 : return msg;
75 : }
76 :
77 :
78 18 : int eap_ikev2_validate_icv(int integ_alg, struct ikev2_keys *keys,
79 : int initiator, const struct wpabuf *msg,
80 : const u8 *pos, const u8 *end)
81 : {
82 : const struct ikev2_integ_alg *integ;
83 : size_t icv_len;
84 : u8 icv[IKEV2_MAX_HASH_LEN];
85 18 : const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
86 :
87 18 : integ = ikev2_get_integ(integ_alg);
88 18 : if (integ == NULL) {
89 0 : wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
90 : "transform / cannot validate ICV");
91 0 : return -1;
92 : }
93 18 : icv_len = integ->hash_len;
94 :
95 18 : if (end - pos < (int) icv_len) {
96 0 : wpa_printf(MSG_DEBUG, "EAP-IKEV2: Not enough room in the "
97 : "message for Integrity Checksum Data");
98 0 : return -1;
99 : }
100 :
101 18 : if (SK_a == NULL) {
102 0 : wpa_printf(MSG_DEBUG, "EAP-IKEV2: No SK_a for ICV validation");
103 0 : return -1;
104 : }
105 :
106 36 : if (ikev2_integ_hash(integ_alg, SK_a, keys->SK_integ_len,
107 18 : wpabuf_head(msg),
108 18 : wpabuf_len(msg) - icv_len, icv) < 0) {
109 0 : wpa_printf(MSG_INFO, "EAP-IKEV2: Could not calculate ICV");
110 0 : return -1;
111 : }
112 :
113 18 : if (os_memcmp(icv, end - icv_len, icv_len) != 0) {
114 0 : wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid ICV");
115 0 : wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Calculated ICV",
116 : icv, icv_len);
117 0 : wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Received ICV",
118 0 : end - icv_len, icv_len);
119 0 : return -1;
120 : }
121 :
122 18 : wpa_printf(MSG_DEBUG, "EAP-IKEV2: Valid Integrity Checksum Data in "
123 : "the received message");
124 :
125 18 : return icv_len;
126 : }
|