Branch data 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 : 2 : 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 [ + - ][ + - ]: 2 : if (keys->SK_d == NULL || i_nonce == NULL || r_nonce == NULL)
[ - + ]
28 : 0 : return -1;
29 : :
30 : 2 : nlen = i_nonce_len + r_nonce_len;
31 : 2 : nonces = os_malloc(nlen);
32 [ - + ]: 2 : if (nonces == NULL)
33 : 0 : return -1;
34 : 2 : os_memcpy(nonces, i_nonce, i_nonce_len);
35 : 2 : os_memcpy(nonces + i_nonce_len, r_nonce, r_nonce_len);
36 : :
37 [ - + ]: 2 : 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 : 2 : os_free(nonces);
43 : :
44 : 2 : wpa_hexdump_key(MSG_DEBUG, "EAP-IKEV2: KEYMAT",
45 : : keymat, EAP_MSK_LEN + EAP_EMSK_LEN);
46 : :
47 : 2 : return 0;
48 : : }
49 : :
50 : :
51 : 0 : 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 : 0 : msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 0, code, id);
65 [ # # ]: 0 : 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 : 0 : wpa_printf(MSG_DEBUG, "EAP-IKEV2: Send fragment ack");
73 : :
74 : 0 : return msg;
75 : : }
76 : :
77 : :
78 : 2 : 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 [ + - ]: 2 : const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
86 : :
87 : 2 : integ = ikev2_get_integ(integ_alg);
88 [ - + ]: 2 : if (integ == NULL) {
89 : 0 : wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
90 : : "transform / cannot validate ICV");
91 : 0 : return -1;
92 : : }
93 : 2 : icv_len = integ->hash_len;
94 : :
95 [ - + ]: 2 : 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 [ - + ]: 2 : 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 [ - + ]: 2 : if (ikev2_integ_hash(integ_alg, SK_a, keys->SK_integ_len,
107 : 2 : wpabuf_head(msg),
108 : 2 : 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 [ - + ]: 2 : 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 : 2 : wpa_printf(MSG_DEBUG, "EAP-IKEV2: Valid Integrity Checksum Data in "
123 : : "the received message");
124 : :
125 : 2 : return icv_len;
126 : : }
|