]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/wpa/src/eap_common/eap_ikev2_common.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / wpa / src / eap_common / eap_ikev2_common.c
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 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         if (keys->SK_d == NULL || i_nonce == NULL || r_nonce == NULL)
28                 return -1;
29
30         nlen = i_nonce_len + r_nonce_len;
31         nonces = os_malloc(nlen);
32         if (nonces == NULL)
33                 return -1;
34         os_memcpy(nonces, i_nonce, i_nonce_len);
35         os_memcpy(nonces + i_nonce_len, r_nonce, r_nonce_len);
36
37         if (ikev2_prf_plus(prf, keys->SK_d, keys->SK_d_len, nonces, nlen,
38                            keymat, EAP_MSK_LEN + EAP_EMSK_LEN)) {
39                 os_free(nonces);
40                 return -1;
41         }
42         os_free(nonces);
43
44         wpa_hexdump_key(MSG_DEBUG, "EAP-IKEV2: KEYMAT",
45                         keymat, EAP_MSK_LEN + EAP_EMSK_LEN);
46
47         return 0;
48 }
49
50
51 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         msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 0, code, id);
65         if (msg == NULL) {
66                 wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory "
67                            "for fragment ack");
68                 return NULL;
69         }
70 #endif /* CCNS_PL */
71
72         wpa_printf(MSG_DEBUG, "EAP-IKEV2: Send fragment ack");
73
74         return msg;
75 }
76
77
78 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         const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
86
87         integ = ikev2_get_integ(integ_alg);
88         if (integ == NULL) {
89                 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
90                            "transform / cannot validate ICV");
91                 return -1;
92         }
93         icv_len = integ->hash_len;
94
95         if (end - pos < (int) icv_len) {
96                 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Not enough room in the "
97                            "message for Integrity Checksum Data");
98                 return -1;
99         }
100
101         if (SK_a == NULL) {
102                 wpa_printf(MSG_DEBUG, "EAP-IKEV2: No SK_a for ICV validation");
103                 return -1;
104         }
105
106         if (ikev2_integ_hash(integ_alg, SK_a, keys->SK_integ_len,
107                              wpabuf_head(msg),
108                              wpabuf_len(msg) - icv_len, icv) < 0) {
109                 wpa_printf(MSG_INFO, "EAP-IKEV2: Could not calculate ICV");
110                 return -1;
111         }
112
113         if (os_memcmp(icv, end - icv_len, icv_len) != 0) {
114                 wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid ICV");
115                 wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Calculated ICV",
116                             icv, icv_len);
117                 wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Received ICV",
118                             end - icv_len, icv_len);
119                 return -1;
120         }
121
122         wpa_printf(MSG_DEBUG, "EAP-IKEV2: Valid Integrity Checksum Data in "
123                    "the received message");
124
125         return icv_len;
126 }