15a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/* 25a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * IEEE 802.1X-2010 KaY Interface 35a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * Copyright (c) 2013-2014, Qualcomm Atheros, Inc. 45a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * 55a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * This software may be distributed under the terms of the BSD license. 65a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * See README for more details. 75a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */ 85a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include <openssl/ssl.h> 95a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "utils/includes.h" 105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "utils/common.h" 125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "eap_peer/eap.h" 135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "eap_peer/eap_i.h" 145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "eapol_supp/eapol_supp_sm.h" 155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "pae/ieee802_1x_key.h" 165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "pae/ieee802_1x_kay.h" 175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "wpa_supplicant_i.h" 185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "config.h" 195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "config_ssid.h" 205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "driver_i.h" 215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "wpas_kay.h" 225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#define DEFAULT_KEY_LEN 16 255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/* secure Connectivity Association Key Name (CKN) */ 265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#define DEFAULT_CKN_LEN 16 275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_macsec_init(void *priv, struct macsec_init_params *params) 305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_macsec_init(priv, params); 325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_macsec_deinit(void *priv) 365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_macsec_deinit(priv); 385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_enable_protect_frames(void *wpa_s, Boolean enabled) 425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_enable_protect_frames(wpa_s, enabled); 445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_set_replay_protect(void *wpa_s, Boolean enabled, u32 window) 485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_set_replay_protect(wpa_s, enabled, window); 505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_set_current_cipher_suite(void *wpa_s, const u8 *cs, 545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt size_t cs_len) 555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_set_current_cipher_suite(wpa_s, cs, cs_len); 575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_enable_controlled_port(void *wpa_s, Boolean enabled) 615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_enable_controlled_port(wpa_s, enabled); 635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_get_receive_lowest_pn(void *wpa_s, u32 channel, 675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt u8 an, u32 *lowest_pn) 685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_get_receive_lowest_pn(wpa_s, channel, an, lowest_pn); 705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_get_transmit_next_pn(void *wpa_s, u32 channel, 745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt u8 an, u32 *next_pn) 755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_get_transmit_next_pn(wpa_s, channel, an, next_pn); 775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_set_transmit_next_pn(void *wpa_s, u32 channel, 815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt u8 an, u32 next_pn) 825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_set_transmit_next_pn(wpa_s, channel, an, next_pn); 845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_get_available_receive_sc(void *wpa_s, u32 *channel) 885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_get_available_receive_sc(wpa_s, channel); 905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic unsigned int conf_offset_val(enum confidentiality_offset co) 945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt switch (co) { 965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt case CONFIDENTIALITY_OFFSET_30: 975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return 30; 985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt break; 995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt case CONFIDENTIALITY_OFFSET_50: 1005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return 50; 1015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt default: 1025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return 0; 1035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 1045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_create_receive_sc(void *wpa_s, u32 channel, 1085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt struct ieee802_1x_mka_sci *sci, 1095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt enum validate_frames vf, 1105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt enum confidentiality_offset co) 1115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_create_receive_sc(wpa_s, channel, sci->addr, sci->port, 1135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt conf_offset_val(co), vf); 1145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_delete_receive_sc(void *wpa_s, u32 channel) 1185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_delete_receive_sc(wpa_s, channel); 1205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_create_receive_sa(void *wpa_s, u32 channel, u8 an, 1245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt u32 lowest_pn, const u8 *sak) 1255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_create_receive_sa(wpa_s, channel, an, lowest_pn, sak); 1275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_enable_receive_sa(void *wpa_s, u32 channel, u8 an) 1315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_enable_receive_sa(wpa_s, channel, an); 1335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_disable_receive_sa(void *wpa_s, u32 channel, u8 an) 1375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_disable_receive_sa(wpa_s, channel, an); 1395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_get_available_transmit_sc(void *wpa_s, u32 *channel) 1435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_get_available_transmit_sc(wpa_s, channel); 1455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int 1495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtwpas_create_transmit_sc(void *wpa_s, u32 channel, 1505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt const struct ieee802_1x_mka_sci *sci, 1515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt enum confidentiality_offset co) 1525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_create_transmit_sc(wpa_s, channel, sci->addr, sci->port, 1545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt conf_offset_val(co)); 1555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_delete_transmit_sc(void *wpa_s, u32 channel) 1595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_delete_transmit_sc(wpa_s, channel); 1615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_create_transmit_sa(void *wpa_s, u32 channel, u8 an, 1655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt u32 next_pn, Boolean confidentiality, 1665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt const u8 *sak) 1675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_create_transmit_sa(wpa_s, channel, an, next_pn, 1695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt confidentiality, sak); 1705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_enable_transmit_sa(void *wpa_s, u32 channel, u8 an) 1745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_enable_transmit_sa(wpa_s, channel, an); 1765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int wpas_disable_transmit_sa(void *wpa_s, u32 channel, u8 an) 1805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return wpa_drv_disable_transmit_sa(wpa_s, channel, an); 1825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 1835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) 1865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 1875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt struct ieee802_1x_kay_ctx *kay_ctx; 1885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt struct ieee802_1x_kay *res = NULL; 1895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt enum macsec_policy policy; 1905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt ieee802_1x_dealloc_kay_sm(wpa_s); 1925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (!ssid || ssid->macsec_policy == 0) 1945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return 0; 1955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt policy = ssid->macsec_policy == 1 ? SHOULD_SECURE : DO_NOT_SECURE; 1975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 1985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx = os_zalloc(sizeof(*kay_ctx)); 1995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (!kay_ctx) 2005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return -1; 2015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->ctx = wpa_s; 2035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->macsec_init = wpas_macsec_init; 2055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->macsec_deinit = wpas_macsec_deinit; 2065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->enable_protect_frames = wpas_enable_protect_frames; 2075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->set_replay_protect = wpas_set_replay_protect; 2085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->set_current_cipher_suite = wpas_set_current_cipher_suite; 2095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->enable_controlled_port = wpas_enable_controlled_port; 2105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->get_receive_lowest_pn = wpas_get_receive_lowest_pn; 2115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->get_transmit_next_pn = wpas_get_transmit_next_pn; 2125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->set_transmit_next_pn = wpas_set_transmit_next_pn; 2135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->get_available_receive_sc = wpas_get_available_receive_sc; 2145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->create_receive_sc = wpas_create_receive_sc; 2155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->delete_receive_sc = wpas_delete_receive_sc; 2165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->create_receive_sa = wpas_create_receive_sa; 2175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->enable_receive_sa = wpas_enable_receive_sa; 2185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->disable_receive_sa = wpas_disable_receive_sa; 2195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->get_available_transmit_sc = wpas_get_available_transmit_sc; 2205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->create_transmit_sc = wpas_create_transmit_sc; 2215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->delete_transmit_sc = wpas_delete_transmit_sc; 2225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->create_transmit_sa = wpas_create_transmit_sa; 2235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->enable_transmit_sa = wpas_enable_transmit_sa; 2245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt kay_ctx->disable_transmit_sa = wpas_disable_transmit_sa; 2255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt res = ieee802_1x_kay_init(kay_ctx, policy, wpa_s->ifname, 2275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_s->own_addr); 2285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (res == NULL) { 2295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_free(kay_ctx); 2305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return -1; 2315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 2325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_s->kay = res; 2345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return 0; 2365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 2375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtvoid ieee802_1x_dealloc_kay_sm(struct wpa_supplicant *wpa_s) 2405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 2415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (!wpa_s->kay) 2425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return; 2435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt ieee802_1x_kay_deinit(wpa_s->kay); 2455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_s->kay = NULL; 2465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 2475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int ieee802_1x_auth_get_session_id(struct wpa_supplicant *wpa_s, 2505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt const u8 *addr, u8 *sid, size_t *len) 2515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 2525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt const u8 *session_id; 2535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt size_t id_len, need_len; 2545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt session_id = eapol_sm_get_session_id(wpa_s->eapol, &id_len); 2565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (session_id == NULL) { 2575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_printf(MSG_DEBUG, 2585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt "Failed to get SessionID from EAPOL state machines"); 2595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return -1; 2605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 2615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt need_len = 1 + 2 * SSL3_RANDOM_SIZE; 2635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (need_len > id_len) { 2645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP Session-Id not long enough"); 2655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return -1; 2665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 2675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memcpy(sid, session_id, need_len); 2695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt *len = need_len; 2705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return 0; 2725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 2735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int ieee802_1x_auth_get_msk(struct wpa_supplicant *wpa_s, const u8 *addr, 2765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt u8 *msk, size_t *len) 2775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 2785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt u8 key[EAP_MSK_LEN]; 2795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt size_t keylen; 2805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt struct eapol_sm *sm; 2815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt int res; 2825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt sm = wpa_s->eapol; 2845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (sm == NULL) 2855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return -1; 2865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt keylen = EAP_MSK_LEN; 2885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt res = eapol_sm_get_key(sm, key, keylen); 2895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (res) { 2905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_printf(MSG_DEBUG, 2915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt "Failed to get MSK from EAPOL state machines"); 2925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return -1; 2935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 2945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 2955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (keylen > *len) 2965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt keylen = *len; 2975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memcpy(msk, key, keylen); 2985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt *len = keylen; 2995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 3005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return 0; 3015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 3025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 3035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 3045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtvoid * ieee802_1x_notify_create_actor(struct wpa_supplicant *wpa_s, 3055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt const u8 *peer_addr) 3065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{ 3075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt u8 *sid; 3085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt size_t sid_len = 128; 3095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt struct mka_key_name *ckn; 3105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt struct mka_key *cak; 3115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt struct mka_key *msk; 3125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt void *res = NULL; 3135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 3145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (!wpa_s->kay || wpa_s->kay->policy == DO_NOT_SECURE) 3155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return NULL; 3165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 3175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_printf(MSG_DEBUG, 3185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt "IEEE 802.1X: External notification - Create MKA for " 3195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt MACSTR, MAC2STR(peer_addr)); 3205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 3215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt msk = os_zalloc(sizeof(*msk)); 3225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt sid = os_zalloc(sid_len); 3235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt ckn = os_zalloc(sizeof(*ckn)); 3245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt cak = os_zalloc(sizeof(*cak)); 3255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (!msk || !sid || !ckn || !cak) 3265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt goto fail; 3275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 3285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt msk->len = DEFAULT_KEY_LEN; 3295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (ieee802_1x_auth_get_msk(wpa_s, wpa_s->bssid, msk->key, &msk->len)) { 3305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_printf(MSG_ERROR, "IEEE 802.1X: Could not get MSK"); 3315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt goto fail; 3325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 3335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 3345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (ieee802_1x_auth_get_session_id(wpa_s, wpa_s->bssid, sid, &sid_len)) 3355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt { 3365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_printf(MSG_ERROR, 3375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt "IEEE 802.1X: Could not get EAP Session Id"); 3385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt goto fail; 3395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 3405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 3415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt /* Derive CAK from MSK */ 3425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt cak->len = DEFAULT_KEY_LEN; 3435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (ieee802_1x_cak_128bits_aes_cmac(msk->key, wpa_s->own_addr, 3445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt peer_addr, cak->key)) { 3455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_printf(MSG_ERROR, 3465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt "IEEE 802.1X: Deriving CAK failed"); 3475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt goto fail; 3485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 3495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Derived CAK", cak->key, cak->len); 3505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 3515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt /* Derive CKN from MSK */ 3525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt ckn->len = DEFAULT_CKN_LEN; 3535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (ieee802_1x_ckn_128bits_aes_cmac(msk->key, wpa_s->own_addr, 3545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt peer_addr, sid, sid_len, 3555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt ckn->name)) { 3565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_printf(MSG_ERROR, 3575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt "IEEE 802.1X: Deriving CKN failed"); 3585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt goto fail; 3595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 3605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt wpa_hexdump(MSG_DEBUG, "Derived CKN", ckn->name, ckn->len); 3615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 3625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt res = ieee802_1x_kay_create_mka(wpa_s->kay, ckn, cak, 0, 3635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt EAP_EXCHANGE, FALSE); 3645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 3655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtfail: 3665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (msk) { 3675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memset(msk, 0, sizeof(*msk)); 3685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_free(msk); 3695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 3705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_free(sid); 3715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_free(ckn); 3725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (cak) { 3735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_memset(cak, 0, sizeof(*cak)); 3745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt os_free(cak); 3755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 3765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 3775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt return res; 3785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt} 379