]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa/src/ap/wpa_auth_kay.c
MFV r359401: OpenBSM: import ee79d73e8df5: auditreduce: add a zone filter
[FreeBSD/FreeBSD.git] / contrib / wpa / src / ap / wpa_auth_kay.c
1 /*
2  * IEEE 802.1X-2010 KaY Interface
3  * Copyright (c) 2019, The Linux Foundation
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "utils/includes.h"
10
11 #include "utils/common.h"
12 #include "pae/ieee802_1x_key.h"
13 #include "pae/ieee802_1x_kay.h"
14 #include "hostapd.h"
15 #include "sta_info.h"
16 #include "wpa_auth_kay.h"
17 #include "ieee802_1x.h"
18
19
20 #define DEFAULT_KEY_LEN         16
21 /* secure Connectivity Association Key Name (CKN) */
22 #define DEFAULT_CKN_LEN         16
23
24
25 static int hapd_macsec_init(void *priv, struct macsec_init_params *params)
26 {
27         struct hostapd_data *hapd = priv;
28
29         if (!hapd->driver->macsec_init)
30                 return -1;
31         return hapd->driver->macsec_init(hapd->drv_priv, params);
32 }
33
34
35 static int hapd_macsec_deinit(void *priv)
36 {
37         struct hostapd_data *hapd = priv;
38
39         if (!hapd->driver->macsec_deinit)
40                 return -1;
41         return hapd->driver->macsec_deinit(hapd->drv_priv);
42 }
43
44
45 static int hapd_macsec_get_capability(void *priv, enum macsec_cap *cap)
46 {
47         struct hostapd_data *hapd = priv;
48
49         if (!hapd->driver->macsec_get_capability)
50                 return -1;
51         return hapd->driver->macsec_get_capability(hapd->drv_priv, cap);
52 }
53
54
55 static int hapd_enable_protect_frames(void *priv, Boolean enabled)
56 {
57         struct hostapd_data *hapd = priv;
58
59         if (!hapd->driver->enable_protect_frames)
60                 return -1;
61         return hapd->driver->enable_protect_frames(hapd->drv_priv, enabled);
62 }
63
64
65 static int hapd_enable_encrypt(void *priv, Boolean enabled)
66 {
67         struct hostapd_data *hapd = priv;
68
69         if (!hapd->driver->enable_encrypt)
70                 return -1;
71         return hapd->driver->enable_encrypt(hapd->drv_priv, enabled);
72 }
73
74
75 static int hapd_set_replay_protect(void *priv, Boolean enabled, u32 window)
76 {
77         struct hostapd_data *hapd = priv;
78
79         if (!hapd->driver->set_replay_protect)
80                 return -1;
81         return hapd->driver->set_replay_protect(hapd->drv_priv, enabled,
82                                                  window);
83 }
84
85
86 static int hapd_set_current_cipher_suite(void *priv, u64 cs)
87 {
88         struct hostapd_data *hapd = priv;
89
90         if (!hapd->driver->set_current_cipher_suite)
91                 return -1;
92         return hapd->driver->set_current_cipher_suite(hapd->drv_priv, cs);
93 }
94
95
96 static int hapd_enable_controlled_port(void *priv, Boolean enabled)
97 {
98         struct hostapd_data *hapd = priv;
99
100         if (!hapd->driver->enable_controlled_port)
101                 return -1;
102         return hapd->driver->enable_controlled_port(hapd->drv_priv, enabled);
103 }
104
105
106 static int hapd_get_receive_lowest_pn(void *priv, struct receive_sa *sa)
107 {
108         struct hostapd_data *hapd = priv;
109
110         if (!hapd->driver->get_receive_lowest_pn)
111                 return -1;
112         return hapd->driver->get_receive_lowest_pn(hapd->drv_priv, sa);
113 }
114
115
116 static int hapd_get_transmit_next_pn(void *priv, struct transmit_sa *sa)
117 {
118         struct hostapd_data *hapd = priv;
119
120         if (!hapd->driver->get_transmit_next_pn)
121                 return -1;
122         return hapd->driver->get_transmit_next_pn(hapd->drv_priv, sa);
123 }
124
125
126 static int hapd_set_transmit_next_pn(void *priv, struct transmit_sa *sa)
127 {
128         struct hostapd_data *hapd = priv;
129
130         if (!hapd->driver->set_transmit_next_pn)
131                 return -1;
132         return hapd->driver->set_transmit_next_pn(hapd->drv_priv, sa);
133 }
134
135
136 static unsigned int conf_offset_val(enum confidentiality_offset co)
137 {
138         switch (co) {
139         case CONFIDENTIALITY_OFFSET_30:
140                 return 30;
141                 break;
142         case CONFIDENTIALITY_OFFSET_50:
143                 return 50;
144         default:
145                 return 0;
146         }
147 }
148
149
150 static int hapd_create_receive_sc(void *priv, struct receive_sc *sc,
151                                   enum validate_frames vf,
152                                   enum confidentiality_offset co)
153 {
154         struct hostapd_data *hapd = priv;
155
156         if (!hapd->driver->create_receive_sc)
157                 return -1;
158         return hapd->driver->create_receive_sc(hapd->drv_priv, sc,
159                                                conf_offset_val(co), vf);
160 }
161
162
163 static int hapd_delete_receive_sc(void *priv, struct receive_sc *sc)
164 {
165         struct hostapd_data *hapd = priv;
166
167         if (!hapd->driver->delete_receive_sc)
168                 return -1;
169         return hapd->driver->delete_receive_sc(hapd->drv_priv, sc);
170 }
171
172
173 static int hapd_create_receive_sa(void *priv, struct receive_sa *sa)
174 {
175         struct hostapd_data *hapd = priv;
176
177         if (!hapd->driver->create_receive_sa)
178                 return -1;
179         return hapd->driver->create_receive_sa(hapd->drv_priv, sa);
180 }
181
182
183 static int hapd_delete_receive_sa(void *priv, struct receive_sa *sa)
184 {
185         struct hostapd_data *hapd = priv;
186
187         if (!hapd->driver->delete_receive_sa)
188                 return -1;
189         return hapd->driver->delete_receive_sa(hapd->drv_priv, sa);
190 }
191
192
193 static int hapd_enable_receive_sa(void *priv, struct receive_sa *sa)
194 {
195         struct hostapd_data *hapd = priv;
196
197         if (!hapd->driver->enable_receive_sa)
198                 return -1;
199         return hapd->driver->enable_receive_sa(hapd->drv_priv, sa);
200 }
201
202
203 static int hapd_disable_receive_sa(void *priv, struct receive_sa *sa)
204 {
205         struct hostapd_data *hapd = priv;
206
207         if (!hapd->driver->disable_receive_sa)
208                 return -1;
209         return hapd->driver->disable_receive_sa(hapd->drv_priv, sa);
210 }
211
212
213 static int
214 hapd_create_transmit_sc(void *priv, struct transmit_sc *sc,
215                         enum confidentiality_offset co)
216 {
217         struct hostapd_data *hapd = priv;
218
219         if (!hapd->driver->create_transmit_sc)
220                 return -1;
221         return hapd->driver->create_transmit_sc(hapd->drv_priv, sc,
222                                                 conf_offset_val(co));
223 }
224
225
226 static int hapd_delete_transmit_sc(void *priv, struct transmit_sc *sc)
227 {
228         struct hostapd_data *hapd = priv;
229
230         if (!hapd->driver->delete_transmit_sc)
231                 return -1;
232         return hapd->driver->delete_transmit_sc(hapd->drv_priv, sc);
233 }
234
235
236 static int hapd_create_transmit_sa(void *priv, struct transmit_sa *sa)
237 {
238         struct hostapd_data *hapd = priv;
239
240         if (!hapd->driver->create_transmit_sa)
241                 return -1;
242         return hapd->driver->create_transmit_sa(hapd->drv_priv, sa);
243 }
244
245
246 static int hapd_delete_transmit_sa(void *priv, struct transmit_sa *sa)
247 {
248         struct hostapd_data *hapd = priv;
249
250         if (!hapd->driver->delete_transmit_sa)
251                 return -1;
252         return hapd->driver->delete_transmit_sa(hapd->drv_priv, sa);
253 }
254
255
256 static int hapd_enable_transmit_sa(void *priv, struct transmit_sa *sa)
257 {
258         struct hostapd_data *hapd = priv;
259
260         if (!hapd->driver->enable_transmit_sa)
261                 return -1;
262         return hapd->driver->enable_transmit_sa(hapd->drv_priv, sa);
263 }
264
265
266 static int hapd_disable_transmit_sa(void *priv, struct transmit_sa *sa)
267 {
268         struct hostapd_data *hapd = priv;
269
270         if (!hapd->driver->disable_transmit_sa)
271                 return -1;
272         return hapd->driver->disable_transmit_sa(hapd->drv_priv, sa);
273 }
274
275
276 int ieee802_1x_alloc_kay_sm_hapd(struct hostapd_data *hapd,
277                                  struct sta_info *sta)
278 {
279         struct ieee802_1x_kay_ctx *kay_ctx;
280         struct ieee802_1x_kay *res = NULL;
281         enum macsec_policy policy;
282
283         ieee802_1x_dealloc_kay_sm_hapd(hapd);
284
285         if (!hapd->conf || hapd->conf->macsec_policy == 0)
286                 return 0;
287
288         if (hapd->conf->macsec_policy == 1) {
289                 if (hapd->conf->macsec_integ_only == 1)
290                         policy = SHOULD_SECURE;
291                 else
292                         policy = SHOULD_ENCRYPT;
293         } else {
294                 policy = DO_NOT_SECURE;
295         }
296
297         wpa_printf(MSG_DEBUG, "%s: if_name=%s", __func__, hapd->conf->iface);
298         kay_ctx = os_zalloc(sizeof(*kay_ctx));
299         if (!kay_ctx)
300                 return -1;
301
302         kay_ctx->ctx = hapd;
303
304         kay_ctx->macsec_init = hapd_macsec_init;
305         kay_ctx->macsec_deinit = hapd_macsec_deinit;
306         kay_ctx->macsec_get_capability = hapd_macsec_get_capability;
307         kay_ctx->enable_protect_frames = hapd_enable_protect_frames;
308         kay_ctx->enable_encrypt = hapd_enable_encrypt;
309         kay_ctx->set_replay_protect = hapd_set_replay_protect;
310         kay_ctx->set_current_cipher_suite = hapd_set_current_cipher_suite;
311         kay_ctx->enable_controlled_port = hapd_enable_controlled_port;
312         kay_ctx->get_receive_lowest_pn = hapd_get_receive_lowest_pn;
313         kay_ctx->get_transmit_next_pn = hapd_get_transmit_next_pn;
314         kay_ctx->set_transmit_next_pn = hapd_set_transmit_next_pn;
315         kay_ctx->create_receive_sc = hapd_create_receive_sc;
316         kay_ctx->delete_receive_sc = hapd_delete_receive_sc;
317         kay_ctx->create_receive_sa = hapd_create_receive_sa;
318         kay_ctx->delete_receive_sa = hapd_delete_receive_sa;
319         kay_ctx->enable_receive_sa = hapd_enable_receive_sa;
320         kay_ctx->disable_receive_sa = hapd_disable_receive_sa;
321         kay_ctx->create_transmit_sc = hapd_create_transmit_sc;
322         kay_ctx->delete_transmit_sc = hapd_delete_transmit_sc;
323         kay_ctx->create_transmit_sa = hapd_create_transmit_sa;
324         kay_ctx->delete_transmit_sa = hapd_delete_transmit_sa;
325         kay_ctx->enable_transmit_sa = hapd_enable_transmit_sa;
326         kay_ctx->disable_transmit_sa = hapd_disable_transmit_sa;
327
328         res = ieee802_1x_kay_init(kay_ctx, policy,
329                                   hapd->conf->macsec_replay_protect,
330                                   hapd->conf->macsec_replay_window,
331                                   hapd->conf->macsec_port,
332                                   hapd->conf->mka_priority, hapd->conf->iface,
333                                   hapd->own_addr);
334         /* ieee802_1x_kay_init() frees kay_ctx on failure */
335         if (!res)
336                 return -1;
337
338         hapd->kay = res;
339
340         return 0;
341 }
342
343
344 void ieee802_1x_dealloc_kay_sm_hapd(struct hostapd_data *hapd)
345 {
346         if (!hapd->kay)
347                 return;
348
349         ieee802_1x_kay_deinit(hapd->kay);
350         hapd->kay = NULL;
351 }
352
353
354 static int ieee802_1x_auth_get_session_id(struct hostapd_data *hapd,
355                                           struct sta_info *sta, u8 *sid,
356                                           size_t *len)
357 {
358         const u8 *session_id;
359         size_t id_len, need_len;
360
361         session_id = ieee802_1x_get_session_id(sta->eapol_sm, &id_len);
362         if (!session_id) {
363                 wpa_printf(MSG_DEBUG,
364                            "MACsec: Failed to get SessionID from EAPOL state machines");
365                 return -1;
366         }
367
368         need_len = 1 + 2 * 32 /* random size */;
369         if (need_len > id_len) {
370                 wpa_printf(MSG_DEBUG, "EAP Session-Id not long enough");
371                 return -1;
372         }
373
374         os_memcpy(sid, session_id, need_len);
375         *len = need_len;
376
377         return 0;
378 }
379
380
381 static int ieee802_1x_auth_get_msk(struct hostapd_data *hapd,
382                                    struct sta_info *sta, u8 *msk, size_t *len)
383 {
384         const u8 *key;
385         size_t keylen;
386
387         if (!sta->eapol_sm)
388                 return -1;
389
390         key = ieee802_1x_get_key(sta->eapol_sm, &keylen);
391         if (key == NULL) {
392                 wpa_printf(MSG_DEBUG,
393                            "MACsec: Failed to get MSK from EAPOL state machines");
394                 return -1;
395         }
396         wpa_printf(MSG_DEBUG, "MACsec: Successfully fetched key (len=%lu)",
397                    (unsigned long) keylen);
398         wpa_hexdump_key(MSG_DEBUG, "MSK: ", key, keylen);
399
400         if (keylen > *len)
401                 keylen = *len;
402         os_memcpy(msk, key, keylen);
403         *len = keylen;
404
405         return 0;
406 }
407
408
409 void * ieee802_1x_notify_create_actor_hapd(struct hostapd_data *hapd,
410                                            struct sta_info *sta)
411 {
412         u8 *sid;
413         size_t sid_len = 128;
414         struct mka_key_name *ckn;
415         struct mka_key *cak;
416         struct mka_key *msk;
417         void *res = NULL;
418
419         if (!hapd->kay || hapd->kay->policy == DO_NOT_SECURE)
420                 return NULL;
421
422         wpa_printf(MSG_DEBUG,
423                    "IEEE 802.1X: External notification - Create MKA for "
424                    MACSTR, MAC2STR(sta->addr));
425
426         msk = os_zalloc(sizeof(*msk));
427         sid = os_zalloc(sid_len);
428         ckn = os_zalloc(sizeof(*ckn));
429         cak = os_zalloc(sizeof(*cak));
430         if (!msk || !sid || !ckn || !cak)
431                 goto fail;
432
433         msk->len = DEFAULT_KEY_LEN;
434         if (ieee802_1x_auth_get_msk(hapd, sta, msk->key, &msk->len)) {
435                 wpa_printf(MSG_ERROR, "IEEE 802.1X: Could not get MSK");
436                 goto fail;
437         }
438
439         if (ieee802_1x_auth_get_session_id(hapd, sta, sid, &sid_len))
440         {
441                 wpa_printf(MSG_ERROR,
442                            "IEEE 802.1X: Could not get EAP Session Id");
443                 goto fail;
444         }
445
446         wpa_hexdump(MSG_DEBUG, "own_addr", hapd->own_addr, ETH_ALEN);
447         wpa_hexdump(MSG_DEBUG, "sta_addr", sta->addr, ETH_ALEN);
448
449         /* Derive CAK from MSK */
450         cak->len = DEFAULT_KEY_LEN;
451         if (ieee802_1x_cak_aes_cmac(msk->key, msk->len, hapd->own_addr,
452                                     sta->addr, cak->key, cak->len)) {
453                 wpa_printf(MSG_ERROR, "IEEE 802.1X: Deriving CAK failed");
454                 goto fail;
455         }
456         wpa_hexdump_key(MSG_DEBUG, "Derived CAK", cak->key, cak->len);
457
458         /* Derive CKN from MSK */
459         ckn->len = DEFAULT_CKN_LEN;
460         if (ieee802_1x_ckn_aes_cmac(msk->key, msk->len, hapd->own_addr,
461                                     sta->addr, sid, sid_len, ckn->name)) {
462                 wpa_printf(MSG_ERROR, "IEEE 802.1X: Deriving CKN failed");
463                 goto fail;
464         }
465         wpa_hexdump(MSG_DEBUG, "Derived CKN", ckn->name, ckn->len);
466
467         res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, EAP_EXCHANGE,
468                                         TRUE);
469
470 fail:
471         bin_clear_free(msk, sizeof(*msk));
472         os_free(sid);
473         os_free(ckn);
474         bin_clear_free(cak, sizeof(*cak));
475
476         return res;
477 }
478
479
480 void * ieee802_1x_create_preshared_mka_hapd(struct hostapd_data *hapd,
481                                             struct sta_info *sta)
482 {
483         struct mka_key *cak;
484         struct mka_key_name *ckn;
485         void *res = NULL;
486
487         if ((hapd->conf->mka_psk_set & MKA_PSK_SET) != MKA_PSK_SET)
488                 goto end;
489
490         ckn = os_zalloc(sizeof(*ckn));
491         if (!ckn)
492                 goto end;
493
494         cak = os_zalloc(sizeof(*cak));
495         if (!cak)
496                 goto free_ckn;
497
498         if (ieee802_1x_alloc_kay_sm_hapd(hapd, sta) < 0 || !hapd->kay)
499                 goto free_cak;
500
501         if (hapd->kay->policy == DO_NOT_SECURE)
502                 goto dealloc;
503
504         cak->len = hapd->conf->mka_cak_len;
505         os_memcpy(cak->key, hapd->conf->mka_cak, cak->len);
506
507         ckn->len = hapd->conf->mka_ckn_len;;
508         os_memcpy(ckn->name, hapd->conf->mka_ckn, ckn->len);
509
510         res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, PSK, TRUE);
511         if (res)
512                 goto free_cak;
513
514 dealloc:
515         /* Failed to create MKA */
516         ieee802_1x_dealloc_kay_sm_hapd(hapd);
517 free_cak:
518         os_free(cak);
519 free_ckn:
520         os_free(ckn);
521 end:
522         return res;
523 }