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