aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Mok <keithmok@google.com>2023-11-18 23:39:50 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2023-11-18 23:39:50 +0000
commit2aa3a14416db2aa9a779d8f0f9d3b176f678695b (patch)
tree9b0435fdb83430626f4813d8352f88ab639da103
parent80b069714ebf9bae331a1deccc7b197f877c3bfa (diff)
parent86179725ccff702a161361c7e0a4e6702fcda5ed (diff)
downloadwpa_supplicant_8-2aa3a14416db2aa9a779d8f0f9d3b176f678695b.tar.gz
Merge "Add a variant of wpa_supplicant to support macsec" into main
-rw-r--r--src/pae/aidl/aidl_psk.cpp149
-rw-r--r--src/pae/aidl/aidl_psk.h33
-rw-r--r--src/pae/ieee802_1x_kay.c51
-rw-r--r--wpa_supplicant/Android.mk44
4 files changed, 275 insertions, 2 deletions
diff --git a/src/pae/aidl/aidl_psk.cpp b/src/pae/aidl/aidl_psk.cpp
new file mode 100644
index 00000000..67afef0e
--- /dev/null
+++ b/src/pae/aidl/aidl_psk.cpp
@@ -0,0 +1,149 @@
+/*
+ * WPA Supplicant - Aidl interface to access macsec PSK
+ * Copyright (c) 2023, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include <aidl/android/hardware/macsec/IMacsecPskPlugin.h>
+#include <android/binder_manager.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/includes.h"
+
+#include "aidl_psk.h"
+}
+
+using aidl::android::hardware::macsec::IMacsecPskPlugin;
+
+static std::shared_ptr<IMacsecPskPlugin> pskPlugin;
+
+int aidl_psk_init()
+{
+ if (pskPlugin != NULL) {
+ wpa_printf(MSG_ERROR, "Already connected to Macsec plugin");
+ return 0;
+ }
+ std::string instanceName = std::string(IMacsecPskPlugin::descriptor) + "/default";
+ pskPlugin = IMacsecPskPlugin::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(instanceName.c_str())));
+
+ if (pskPlugin == NULL) {
+ wpa_printf(MSG_ERROR, "Cannot get Macsec PSK plugin service");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+int aidl_psk_aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain,
+ u8 *cipher)
+{
+ if (pskPlugin == NULL)
+ return -ENODEV;
+
+ n = n * 8;
+
+ const std::vector<u8> key_id(kek, kek + kek_len);
+ const std::vector<u8> sak(plain, plain + n);
+ std::vector<u8> out(n + 8);
+
+ auto aidlStatus = pskPlugin->wrapSak(key_id, sak, &out);
+ if (!aidlStatus.isOk()) {
+ wpa_printf(MSG_ERROR, "wrapSak return error: %s", aidlStatus.getMessage());
+ return -ENODEV;
+ }
+
+ if (out.size() != (n + 8)) {
+ wpa_printf(MSG_ERROR, "wrapSak return size not n + 8");
+ return -ENODEV;
+ }
+
+ memcpy(cipher, out.data(), n + 8);
+
+ return 0;
+}
+
+int aidl_psk_aes_unwrap(const u8 *kek, size_t kek_len, int n,
+ const u8 *cipher, u8 *plain)
+{
+ if (pskPlugin == NULL)
+ return -ENODEV;
+
+ n = n * 8;
+ if (n < 8)
+ return -ENODEV;
+
+ const std::vector<u8> key_id(kek, kek + kek_len);
+ const std::vector<u8> sak(cipher, cipher + n);
+ std::vector<u8> out(n - 8);
+
+ auto aidlStatus = pskPlugin->unwrapSak(key_id, sak, &out);
+ if (!aidlStatus.isOk()) {
+ return -ENODEV;
+ }
+
+ if (out.size() != (n - 8)) {
+ return -ENODEV;
+ }
+
+ memcpy(plain, out.data(), n - 8);
+
+ return 0;
+}
+
+int aidl_psk_icv_hash(const u8 *ick, size_t ick_bytes, const u8 *msg,
+ size_t msg_bytes, u8 *icv)
+{
+ if (pskPlugin == NULL) {
+ wpa_printf(MSG_ERROR, "pskPlugin not init");
+ return -ENODEV;
+ }
+
+ const std::vector<u8> key_id(ick, ick + ick_bytes);
+ const std::vector<u8> data(msg, msg + msg_bytes);
+ std::vector<u8> out(16);
+
+ auto aidlStatus = pskPlugin->calcIcv(key_id, data, &out);
+ if (!aidlStatus.isOk()) {
+ wpa_printf(MSG_ERROR, "calcIcv return error: %s", aidlStatus.getMessage());
+ return -ENODEV;
+ }
+
+ if (out.size() != 16) {
+ wpa_printf(MSG_ERROR, "calcIcv out size not 16 bytes");
+ return -ENODEV;
+ }
+
+ memcpy(icv, out.data(), 16);
+
+ return 0;
+}
+
+int aidl_psk_sak_aes_cmac(const u8 *cak, size_t cak_bytes, const u8 *ctx,
+ size_t ctx_bytes, u8 *sak, size_t sak_bytes)
+{
+ if (pskPlugin == NULL)
+ return -ENODEV;
+
+ const std::vector<u8> key_id(cak, cak + cak_bytes);
+ const std::vector<u8> data(ctx, ctx + ctx_bytes);
+ std::vector<u8> out(sak_bytes);
+
+ auto aidlStatus = pskPlugin->generateSak(key_id, data, sak_bytes, &out);
+ if (!aidlStatus.isOk()) {
+ return -ENODEV;
+ }
+
+ if (out.size() != sak_bytes) {
+ return -ENODEV;
+ }
+
+ memcpy(sak, out.data(), sak_bytes);
+
+ return 0;
+}
diff --git a/src/pae/aidl/aidl_psk.h b/src/pae/aidl/aidl_psk.h
new file mode 100644
index 00000000..ad131bab
--- /dev/null
+++ b/src/pae/aidl/aidl_psk.h
@@ -0,0 +1,33 @@
+/*
+ * WPA Supplicant - Aidl interface to access macsec PSK
+ * Copyright (c) 2023, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_PAE_AIDL_PSK_H
+#define WPA_SUPPLICANT_PAE_AIDL_PSK_H
+
+#ifdef _cplusplus
+extern "C"
+{
+#endif // _cplusplus
+
+ /* cak, kek, ick are all reference index only for HAL, not real key, the
+ * HAL will use the actual key */
+ int aidl_psk_init();
+ int __must_check aidl_psk_aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain,
+ u8 *cipher);
+ int __must_check aidl_psk_aes_unwrap(const u8 *kek, size_t kek_len, int n,
+ const u8 *cipher, u8 *plain);
+ int aidl_psk_icv_hash(const u8 *ick, size_t ick_bytes, const u8 *msg,
+ size_t msg_bytes, u8 *icv);
+ int aidl_psk_sak_aes_cmac(const u8 *cak, size_t cak_bytes, const u8 *ctx,
+ size_t ctx_bytes, u8 *sak, size_t sak_bytes);
+
+#ifdef _cplusplus
+}
+#endif // _cplusplus
+
+#endif // WPA_SUPPLICANT_PAE_AIDL_PSK_H
diff --git a/src/pae/ieee802_1x_kay.c b/src/pae/ieee802_1x_kay.c
index 66c65aaf..741b0939 100644
--- a/src/pae/ieee802_1x_kay.c
+++ b/src/pae/ieee802_1x_kay.c
@@ -22,6 +22,10 @@
#include "ieee802_1x_kay_i.h"
#include "ieee802_1x_secy_ops.h"
+#ifdef CONFIG_AIDL_MACSEC_PSK_METHODS
+#include "aidl/aidl_psk.h"
+#endif
+
#define DEFAULT_SA_KEY_LEN 16
#define DEFAULT_ICV_LEN 16
@@ -1659,9 +1663,15 @@ ieee802_1x_mka_encode_dist_sak_body(
os_memcpy(body->sak, &cs, CS_ID_LEN);
sak_pos = CS_ID_LEN;
}
+#ifdef CONFIG_AIDL_MACSEC_PSK_METHODS
+ if (aidl_psk_aes_wrap(participant->kek.key, participant->kek.len,
+ cipher_suite_tbl[cs_index].sak_len / 8,
+ sak->key, body->sak + sak_pos)) {
+#else
if (aes_wrap(participant->kek.key, participant->kek.len,
cipher_suite_tbl[cs_index].sak_len / 8,
sak->key, body->sak + sak_pos)) {
+#endif
wpa_printf(MSG_ERROR, "KaY: AES wrap failed");
return -1;
}
@@ -1800,8 +1810,13 @@ ieee802_1x_mka_decode_dist_sak_body(
wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
return -1;
}
+#ifdef CONFIG_AIDL_MACSEC_PSK_METHODS
+ if (aidl_psk_aes_unwrap(participant->kek.key, participant->kek.len,
+ sak_len >> 3, wrap_sak, unwrap_sak)) {
+#else
if (aes_unwrap(participant->kek.key, participant->kek.len,
sak_len >> 3, wrap_sak, unwrap_sak)) {
+#endif
wpa_printf(MSG_ERROR, "KaY: AES unwrap failed");
os_free(unwrap_sak);
return -1;
@@ -1896,7 +1911,11 @@ ieee802_1x_mka_encode_icv_body(struct ieee802_1x_mka_participant *participant,
set_mka_param_body_len(body, length);
}
+#ifdef CONFIG_AIDL_MACSEC_PSK_METHODS
+ if (aidl_psk_icv_hash(
+#else
if (mka_alg_tbl[participant->kay->mka_algindex].icv_hash(
+#endif
participant->ick.key, participant->ick.len,
wpabuf_head(buf), wpabuf_len(buf), cmac)) {
wpa_printf(MSG_ERROR, "KaY: failed to calculate ICV");
@@ -2198,10 +2217,17 @@ ieee802_1x_kay_generate_new_sak(struct ieee802_1x_mka_participant *participant)
os_memcpy(context + ctx_offset, &kay->dist_kn, sizeof(kay->dist_kn));
if (key_len == 16 || key_len == 32) {
+#ifdef CONFIG_AIDL_MACSEC_PSK_METHODS
+ if (aidl_psk_sak_aes_cmac(participant->cak.key,
+ participant->cak.len,
+ context, ctx_len,
+ key, key_len)) {
+#else
if (ieee802_1x_sak_aes_cmac(participant->cak.key,
participant->cak.len,
context, ctx_len,
key, key_len)) {
+#endif
wpa_printf(MSG_ERROR, "KaY: Failed to generate SAK");
goto fail;
}
@@ -3183,7 +3209,11 @@ static int ieee802_1x_kay_mkpdu_validity_check(struct ieee802_1x_kay *kay,
* packet body length.
*/
if (len < mka_alg_tbl[kay->mka_algindex].icv_len ||
+#ifdef CONFIG_AIDL_MACSEC_PSK_METHODS
+ aidl_psk_icv_hash(
+#else
mka_alg_tbl[kay->mka_algindex].icv_hash(
+#endif
participant->ick.key, participant->ick.len,
buf, len - mka_alg_tbl[kay->mka_algindex].icv_len, icv)) {
wpa_printf(MSG_ERROR, "KaY: Failed to calculate ICV");
@@ -3745,6 +3775,18 @@ ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay,
wpa_printf(MSG_DEBUG, "KaY: Selected random MI: %s",
mi_txt(participant->mi));
+#ifdef CONFIG_AIDL_MACSEC_PSK_METHODS
+ if (mode != PSK) {
+ wpa_printf(MSG_ERROR, "CONFIG_AIDL_MACSEC_PSK_METHODS only support PSK");
+ goto fail;
+ }
+ wpa_printf(MSG_INFO, "Init macsec PSK HAL");
+ if (aidl_psk_init()) {
+ wpa_printf(MSG_ERROR, "Cannot init aidl macsec psk HAL");
+ goto fail;
+ }
+#endif
+
participant->lrx = false;
participant->ltx = false;
participant->orx = false;
@@ -3763,6 +3805,14 @@ ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay,
if (secy_create_transmit_sc(kay, participant->txsc))
goto fail;
+#ifdef CONFIG_AIDL_MACSEC_PSK_METHODS
+ /* If using external PSK methods, we don't need to generate kek and ick
+ * key here and cak.key is actually a reference index */
+ participant->kek.len = participant->cak.len;
+ participant->ick.len = participant->cak.len;
+ memcpy(participant->kek.key, participant->cak.key, participant->cak.len);
+ memcpy(participant->ick.key, participant->cak.key, participant->cak.len);
+#else
/* to derive KEK from CAK and CKN */
participant->kek.len = participant->cak.len;
if (mka_alg_tbl[kay->mka_algindex].kek_trfm(participant->cak.key,
@@ -3790,6 +3840,7 @@ ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay,
}
wpa_hexdump_key(MSG_DEBUG, "KaY: Derived ICK",
participant->ick.key, participant->ick.len);
+#endif
dl_list_add(&kay->participant_list, &participant->list);
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 9f685220..509dbbc0 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -1912,8 +1912,13 @@ LOCAL_C_INCLUDES := $(INCLUDES)
include $(BUILD_EXECUTABLE)
########################
+# Build wpa_supplicant
+#
+# $(1): if defined build wpa_supplicant with macsec support (with different executable name wpa_supplicant_macsec
+#
+define wpa_supplicant_gen
+
include $(CLEAR_VARS)
-LOCAL_MODULE := wpa_supplicant
LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD SPDX-license-identifier-BSD-3-Clause SPDX-license-identifier-ISC legacy_unencumbered
LOCAL_LICENSE_CONDITIONS := notice unencumbered
LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../LICENSE
@@ -1945,12 +1950,17 @@ else
LOCAL_STATIC_LIBRARIES += libnl_2
endif
endif
-LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := $(OBJS)
LOCAL_C_INCLUDES := $(INCLUDES)
ifeq ($(DBUS), y)
LOCAL_SHARED_LIBRARIES += libdbus
endif
+
+ifneq ($(1),)
+# wpa_supplicant for wifi
+LOCAL_CFLAGS := $(L_CFLAGS)
+LOCAL_MODULE := wpa_supplicant
+
ifeq ($(WPA_SUPPLICANT_USE_AIDL), y)
LOCAL_SHARED_LIBRARIES += android.hardware.wifi.supplicant-V3-ndk
LOCAL_SHARED_LIBRARIES += android.system.keystore2-V1-ndk
@@ -1962,7 +1972,37 @@ ifeq ($(WIFI_HIDL_UNIFIED_SUPPLICANT_SERVICE_RC_ENTRY), true)
LOCAL_INIT_RC=aidl/android.hardware.wifi.supplicant-service.rc
endif
endif
+
+else
+# wpa_supplicant for macsec
+# remove aidl control interface, standalone
+LOCAL_CFLAGS := $(patsubst -DCONFIG_CTRL_IFACE_AIDL,,$(patsubst -DCONFIG_AIDL,,$(L_CFLAGS)))
+LOCAL_CFLAGS += -DCONFIG_MACSEC -DCONFIG_DRIVER_MACSEC_LINUX
+# config macsec to use AIDL interface for CAK key.
+LOCAL_CFLAGS += -DCONFIG_AIDL_MACSEC_PSK_METHODS
+LOCAL_SRC_FILES += ../src/drivers/driver_macsec_linux.c \
+ ../src/drivers/driver_wired_common.c
+LOCAL_SRC_FILES += wpas_kay.c \
+ src/pae/ieee802_1x_cp.c \
+ src/pae/ieee802_1x_kay.c \
+ src/pae/ieee802_1x_key.c \
+ src/pae/ieee802_1x_secy_ops.c
+LOCAL_SRC_FILES += src/pae/aidl/aidl_psk.cpp
+LOCAL_SHARED_LIBRARIES += android.hardware.macsec-V1-ndk \
+ libbinder_ndk
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/aidl
+
+ifdef CONFIG_AP
+LOCAL_SRC_FILES += src/ap/wpa_auth_kay.c
+endif
+LOCAL_MODULE := wpa_supplicant_macsec
+endif
+
include $(BUILD_EXECUTABLE)
+endef
+
+$(eval $(call wpa_supplicant_gen,))
+$(eval $(call wpa_supplicant_gen, macsec))
########################
#