Merge changes from topic "wifi-keystore-conversion"
* changes:
Replace call into Wifi Keystore with a call into the new get_certificate method.
Add callback path from wpa_supplicant core to AidlManager::getCertificate.
Add logic to retrieve KS2 certificates in supplicant.
Add non-standard certicate methods to supplicant.
diff --git a/hostapd/Android.bp b/hostapd/Android.bp
index 020396d..0c5d96b 100644
--- a/hostapd/Android.bp
+++ b/hostapd/Android.bp
@@ -55,7 +55,6 @@
"libcrypto",
"libssl",
"libnl",
- "libkeystore-wifi-hidl",
],
relative_install_path: "hw",
soc_specific: true,
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index 7a2ee32..e215762 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -682,4 +682,13 @@
*/
bool tls_connection_get_own_cert_used(struct tls_connection *conn);
+/**
+ * tls_register_cert_callback - Register a callback to retrieve certificates
+ * @cb: Callback object to register
+ */
+typedef ssize_t (*tls_get_certificate_cb)
+(void* ctx, const char* alias, uint8_t** value);
+
+void tls_register_cert_callback(tls_get_certificate_cb cb);
+
#endif /* TLS_H */
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index dc8a1b4..ab82e3d 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -126,9 +126,28 @@
}
#endif
+static int tls_openssl_ref_count = 0;
+static int tls_ex_idx_session = -1;
+
+struct tls_session_data {
+ struct dl_list list;
+ struct wpabuf *buf;
+};
+
+struct tls_context {
+ void (*event_cb)(void *ctx, enum tls_event ev,
+ union tls_event_data *data);
+ void *cb_ctx;
+ int cert_in_cb;
+ char *ocsp_stapling_response;
+ struct dl_list sessions; /* struct tls_session_data */
+};
+
+static struct tls_context *tls_global = NULL;
+static tls_get_certificate_cb certificate_callback_global = NULL;
+
#ifdef ANDROID
#include <openssl/pem.h>
-#include <keystore/keystore_get.h>
#include <log/log.h>
#include <log/log_event_list.h>
@@ -152,9 +171,11 @@
{
BIO *bio = NULL;
uint8_t *value = NULL;
- int length = keystore_get(alias, strlen(alias), &value);
- if (length != -1 && (bio = BIO_new(BIO_s_mem())) != NULL)
- BIO_write(bio, value, length);
+ if (tls_global != NULL && certificate_callback_global != NULL) {
+ int length = (*certificate_callback_global)(tls_global->cb_ctx, alias, &value);
+ if (length != -1 && (bio = BIO_new(BIO_s_mem())) != NULL)
+ BIO_write(bio, value, length);
+ }
free(value);
return bio;
}
@@ -229,26 +250,6 @@
#endif /* ANDROID */
-static int tls_openssl_ref_count = 0;
-static int tls_ex_idx_session = -1;
-
-struct tls_session_data {
- struct dl_list list;
- struct wpabuf *buf;
-};
-
-struct tls_context {
- void (*event_cb)(void *ctx, enum tls_event ev,
- union tls_event_data *data);
- void *cb_ctx;
- int cert_in_cb;
- char *ocsp_stapling_response;
- struct dl_list sessions; /* struct tls_session_data */
-};
-
-static struct tls_context *tls_global = NULL;
-
-
struct tls_data {
SSL_CTX *ssl;
unsigned int tls_session_lifetime;
@@ -6025,3 +6026,8 @@
return SSL_get_certificate(conn->ssl) != NULL;
return false;
}
+
+void tls_register_cert_callback(tls_get_certificate_cb cb)
+{
+ certificate_callback_global = cb;
+}
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index a7dee37..15664df 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -2196,6 +2196,14 @@
os_free(hash_hex);
}
+ssize_t tls_certificate_callback(void* ctx, const char* alias, uint8_t** value) {
+ if (alias == NULL || ctx == NULL || value == NULL) return -1;
+ struct eap_sm *sm = (struct eap_sm*) ctx;
+ if (sm->eapol_cb && sm->eapol_cb->get_certificate) {
+ return sm->eapol_cb->get_certificate(sm->eapol_ctx, alias, value);
+ }
+ return -1;
+}
/**
* eap_peer_sm_init - Allocate and initialize EAP peer state machine
@@ -2239,6 +2247,7 @@
tlsconf.event_cb = eap_peer_sm_tls_event;
tlsconf.cb_ctx = sm;
tlsconf.cert_in_cb = conf->cert_in_cb;
+ tls_register_cert_callback(&tls_certificate_callback);
sm->ssl_ctx = tls_init(&tlsconf);
if (sm->ssl_ctx == NULL) {
wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
diff --git a/src/eap_peer/eap.h b/src/eap_peer/eap.h
index 8f83d0b..b98e878 100644
--- a/src/eap_peer/eap.h
+++ b/src/eap_peer/eap.h
@@ -304,6 +304,16 @@
* @reason_string: Information to log about the event
*/
void (*notify_open_ssl_failure)(void *ctx, const char* reason_string);
+
+ /**
+ * get_certificate - Retrieve a certificate from the certificate store
+ * @ctx: eapol_ctx from eap_peer_sm_init() call
+ * @alias: key into the certificate key-value store
+ * @value: pointer reference - pointer to the retrieved certificate will
+ * be stored here on success
+ * Returns: size of the retrieved certificate or -1 on error
+ */
+ ssize_t (*get_certificate)(void* ctx, const char* alias, uint8_t** value);
};
/**
diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c
index a0bc6ab..a8ac6fd 100644
--- a/src/eapol_supp/eapol_supp_sm.c
+++ b/src/eapol_supp/eapol_supp_sm.c
@@ -2112,6 +2112,17 @@
sm->ctx->open_ssl_failure_cb(sm->ctx->ctx, reason_string);
}
+static ssize_t
+eapol_sm_get_certificate(void *ctx, const char* alias, uint8_t** value)
+{
+ struct eapol_sm *sm = ctx;
+
+ if (sm->ctx->get_certificate_cb) {
+ return sm->ctx->get_certificate_cb(alias, value);
+ }
+ return -1;
+}
+
static const struct eapol_callbacks eapol_cb =
{
eapol_sm_get_config,
@@ -2135,7 +2146,8 @@
#endif /* CONFIG_EAP_PROXY */
eapol_sm_set_anon_id,
eapol_sm_notify_eap_method_selected,
- eapol_sm_notify_open_ssl_failure
+ eapol_sm_notify_open_ssl_failure,
+ eapol_sm_get_certificate
};
diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h
index ad94cf5..fe34ec9 100644
--- a/src/eapol_supp/eapol_supp_sm.h
+++ b/src/eapol_supp/eapol_supp_sm.h
@@ -336,6 +336,15 @@
* Returns: Whether the current session requires encryption
*/
bool (*encryption_required)(void *ctx);
+
+ /**
+ * get_certificate_cb - Retrieve a certificate from the certificate store
+ * @alias: key into the certificate key-value store
+ * @value: pointer reference - pointer to the retrieved certificate will
+ * be stored here on success
+ * Returns: size of the retrieved certificate or -1 on error
+ */
+ ssize_t (*get_certificate_cb)(const char* alias, uint8_t** value);
};
diff --git a/wpa_supplicant/Android.bp b/wpa_supplicant/Android.bp
index 05c79c0..be79765 100644
--- a/wpa_supplicant/Android.bp
+++ b/wpa_supplicant/Android.bp
@@ -68,13 +68,13 @@
srcs: [":wpa_supplicant_srcs"],
shared_libs: [
"android.hardware.wifi.supplicant-V2-ndk",
+ "android.system.keystore2-V1-ndk",
"libbase",
"libbinder_ndk",
"libc",
"libcrypto",
"libcutils",
"libkeystore-engine-wifi-hidl",
- "libkeystore-wifi-hidl",
"liblog",
"libnl",
"libssl",
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 1da9e61..33dabf3 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -1791,7 +1791,7 @@
LOCAL_SHARED_LIBRARIES += $(LIB_SHARED_EAP_PROXY)
endif
ifeq ($(CONFIG_TLS), openssl)
-LOCAL_SHARED_LIBRARIES += libcrypto libssl libkeystore-wifi-hidl
+LOCAL_SHARED_LIBRARIES += libcrypto libssl
endif
# With BoringSSL we need libkeystore-engine in order to provide access to
@@ -1813,6 +1813,7 @@
endif
ifeq ($(WPA_SUPPLICANT_USE_AIDL), y)
LOCAL_SHARED_LIBRARIES += android.hardware.wifi.supplicant-V2-ndk
+LOCAL_SHARED_LIBRARIES += android.system.keystore2-V1-ndk
LOCAL_SHARED_LIBRARIES += libutils libbase
LOCAL_SHARED_LIBRARIES += libbinder_ndk
LOCAL_STATIC_LIBRARIES += libwpa_aidl
@@ -1877,6 +1878,7 @@
LOCAL_SRC_FILES := \
aidl/aidl.cpp \
aidl/aidl_manager.cpp \
+ aidl/certificate_utils.cpp \
aidl/iface_config_utils.cpp \
aidl/p2p_iface.cpp \
aidl/p2p_network.cpp \
@@ -1885,6 +1887,7 @@
aidl/supplicant.cpp
LOCAL_SHARED_LIBRARIES := \
android.hardware.wifi.supplicant-V2-ndk \
+ android.system.keystore2-V1-ndk \
libbinder_ndk \
libbase \
libutils \
diff --git a/wpa_supplicant/aidl/Android.bp b/wpa_supplicant/aidl/Android.bp
index 24c2079..d7dcf97 100644
--- a/wpa_supplicant/aidl/Android.bp
+++ b/wpa_supplicant/aidl/Android.bp
@@ -34,8 +34,10 @@
soc_specific: true,
shared_libs: [
"android.hardware.wifi.supplicant-V2-ndk",
+ "android.system.keystore2-V1-ndk",
"libbinder_ndk",
"libbase",
+ "libcrypto",
"libutils",
"liblog",
"libssl",
diff --git a/wpa_supplicant/aidl/aidl.cpp b/wpa_supplicant/aidl/aidl.cpp
index 6bc13ad..75050c1 100644
--- a/wpa_supplicant/aidl/aidl.cpp
+++ b/wpa_supplicant/aidl/aidl.cpp
@@ -1063,3 +1063,11 @@
aidl_manager->notifyQosPolicyRequest(wpa_s, policies, num_policies);
}
+ssize_t wpas_aidl_get_certificate(const char* alias, uint8_t** value)
+{
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return -1;
+
+ return aidl_manager->getCertificate(alias, value);
+}
diff --git a/wpa_supplicant/aidl/aidl.h b/wpa_supplicant/aidl/aidl.h
index 40eb860..f0470e2 100644
--- a/wpa_supplicant/aidl/aidl.h
+++ b/wpa_supplicant/aidl/aidl.h
@@ -145,6 +145,7 @@
void wpas_aidl_notify_qos_policy_reset(struct wpa_supplicant *wpa_s);
void wpas_aidl_notify_qos_policy_request(struct wpa_supplicant *wpa_s,
struct dscp_policy_data *policies, int num_policies);
+ ssize_t wpas_aidl_get_certificate(const char* alias, uint8_t** value);
#else // CONFIG_CTRL_IFACE_AIDL
static inline int wpas_aidl_register_interface(struct wpa_supplicant *wpa_s)
{
@@ -322,6 +323,8 @@
struct dscp_policy_data *policies,
int num_policies)
{}
+ssize_t wpas_aidl_get_certificate(const char* alias, uint8_t** value)
+{}
#endif // CONFIG_CTRL_IFACE_AIDL
#ifdef _cplusplus
diff --git a/wpa_supplicant/aidl/aidl_manager.cpp b/wpa_supplicant/aidl/aidl_manager.cpp
index 063d400..4833938 100644
--- a/wpa_supplicant/aidl/aidl_manager.cpp
+++ b/wpa_supplicant/aidl/aidl_manager.cpp
@@ -2209,6 +2209,21 @@
}
/**
+ * Store the |INonStandardCertCallback| aidl object reference.
+ *
+ * @param callback Aidl reference of the |INonStandardCertCallback| object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::registerNonStandardCertCallbackAidlObject(
+ const std::shared_ptr<INonStandardCertCallback> &callback)
+{
+ if (callback == nullptr) return 1;
+ non_standard_cert_callback_ = callback;
+ return 0;
+}
+
+/**
* Add a new iface callback aidl object reference to our
* interface callback list.
*
@@ -2560,6 +2575,20 @@
std::placeholders::_1, wpa_s->dscp_req_dialog_token, qosPolicyData));
}
+ssize_t AidlManager::getCertificate(const char* alias, uint8_t** value) {
+ if (alias == nullptr || value == nullptr) {
+ wpa_printf(MSG_ERROR, "Null pointer argument was passed to getCertificate");
+ return -1;
+ }
+ if (auto cert = certificate_utils::getCertificate(alias, non_standard_cert_callback_)) {
+ *value = (uint8_t *) os_malloc(cert->size());
+ if (*value == nullptr) return -1;
+ os_memcpy(*value, cert->data(), cert->size());
+ return cert->size();
+ }
+ return -1;
+}
+
} // namespace supplicant
} // namespace wifi
} // namespace hardware
diff --git a/wpa_supplicant/aidl/aidl_manager.h b/wpa_supplicant/aidl/aidl_manager.h
index 5224ef2..e4af31a 100644
--- a/wpa_supplicant/aidl/aidl_manager.h
+++ b/wpa_supplicant/aidl/aidl_manager.h
@@ -16,6 +16,7 @@
#include <aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.h>
#include <aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.h>
+#include "certificate_utils.h"
#include "p2p_iface.h"
#include "p2p_network.h"
#include "rsn_supp/pmksa_cache.h"
@@ -162,6 +163,7 @@
void notifyQosPolicyRequest(struct wpa_supplicant *wpa_s,
struct dscp_policy_data *policies,
int num_policies);
+ ssize_t getCertificate(const char* alias, uint8_t** value);
// Methods called from aidl objects.
void notifyExtRadioWorkStart(struct wpa_supplicant *wpa_s, uint32_t id);
@@ -191,6 +193,8 @@
int addStaNetworkCallbackAidlObject(
const std::string &ifname, int network_id,
const std::shared_ptr<ISupplicantStaNetworkCallback> &callback);
+ int registerNonStandardCertCallbackAidlObject(
+ const std::shared_ptr<INonStandardCertCallback> &callback);
private:
AidlManager() = default;
@@ -278,6 +282,8 @@
const std::string,
std::vector<std::shared_ptr<ISupplicantStaNetworkCallback>>>
sta_network_callbacks_map_;
+ // NonStandardCertCallback registered by the client.
+ std::shared_ptr<INonStandardCertCallback> non_standard_cert_callback_;
};
// The aidl interface uses some values which are the same as internal ones to
diff --git a/wpa_supplicant/aidl/certificate_utils.cpp b/wpa_supplicant/aidl/certificate_utils.cpp
new file mode 100644
index 0000000..79fe38b
--- /dev/null
+++ b/wpa_supplicant/aidl/certificate_utils.cpp
@@ -0,0 +1,196 @@
+/*
+ * WPA Supplicant - Certificate utils
+ * Copyright (c) 2022, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "certificate_utils.h"
+
+#define AT __func__ << ":" << __LINE__ << " "
+
+namespace ks2 = aidl::android::system::keystore2;
+namespace KMV1 = aidl::android::hardware::security::keymint;
+
+using aidl::android::hardware::wifi::supplicant::INonStandardCertCallback;
+
+namespace {
+
+constexpr const int64_t KS2_NAMESPACE_WIFI = 102;
+
+constexpr const char kKeystore2ServiceName[] = "android.system.keystore2.IKeystoreService/default";
+
+const std::string keystore2_grant_id_prefix("ks2_keystore-engine_grant_id:");
+
+ks2::KeyDescriptor mkKeyDescriptor(const std::string& alias) {
+ // If the key_id starts with the grant id prefix, we parse the following string as numeric
+ // grant id. We can then use the grant domain without alias to load the designated key.
+ if (::android::base::StartsWith(alias, keystore2_grant_id_prefix)) {
+ std::stringstream s(alias.substr(keystore2_grant_id_prefix.size()));
+ uint64_t tmp;
+ s >> std::hex >> tmp;
+ if (s.fail() || !s.eof()) {
+ wpa_printf(MSG_ERROR, "Couldn't parse grant name: %s", alias.c_str());
+ }
+ return {
+ .domain = ks2::Domain::GRANT,
+ .nspace = static_cast<int64_t>(tmp),
+ .alias = std::nullopt,
+ .blob = std::nullopt,
+ };
+ } else {
+ return {
+ .domain = ks2::Domain::SELINUX,
+ .nspace = KS2_NAMESPACE_WIFI,
+ .alias = alias,
+ .blob = std::nullopt,
+ };
+ }
+}
+
+// Helper method to convert certs in DER format to PEM format required by
+// openssl library used by supplicant. If boringssl cannot parse the input as one or more
+// X509 certificates in DER encoding, this function returns the input as-is. The assumption in
+// that case is that either the `cert_bytes` is already PEM encoded, or `cert_bytes` is something
+// completely different that was intentionally installed by the Wi-Fi subsystem and it must not
+// be changed here.
+// If any error occurs during PEM encoding, this function returns std::nullopt and logs an error.
+std::optional<std::vector<uint8_t>> convertDerCertToPemOrPassthrough(
+ const std::vector<uint8_t>& cert_bytes) {
+ // If cert_bytes is a DER encoded X509 certificate, it must be reencoded as PEM, because
+ // wpa_supplicant only understand PEM. Otherwise the cert_bytes are returned as is.
+ const uint8_t* cert_current = cert_bytes.data();
+ const uint8_t* cert_end = cert_current + cert_bytes.size();
+ bssl::UniquePtr<BIO> pem_bio(BIO_new(BIO_s_mem()));
+ while (cert_current < cert_end) {
+ auto cert =
+ bssl::UniquePtr<X509>(d2i_X509(nullptr, &cert_current, cert_end - cert_current));
+ // If part of the bytes cannot be parsed as X509 DER certificate, the original blob
+ // shall be returned as-is.
+ if (!cert) {
+ wpa_printf(MSG_WARNING, "Could not parse DER X509 cert from buffer. Returning blob as is.");
+ return cert_bytes;
+ }
+
+ if (!PEM_write_bio_X509(pem_bio.get(), cert.get())) {
+ wpa_printf(MSG_ERROR, "Could not convert cert to PEM format.");
+ return std::nullopt;
+ }
+ }
+
+ const uint8_t* pem_bytes;
+ size_t pem_len;
+ if (!BIO_mem_contents(pem_bio.get(), &pem_bytes, &pem_len)) {
+ wpa_printf(MSG_ERROR, "Could not extract pem_bytes from BIO.");
+ return std::nullopt;
+ }
+ return {{pem_bytes, pem_bytes + pem_len}};
+}
+
+std::optional<std::vector<uint8_t>> getKeystore2Cert(const std::string& key) {
+ ::ndk::SpAIBinder keystoreBinder(AServiceManager_checkService(kKeystore2ServiceName));
+ auto keystore2 = ks2::IKeystoreService::fromBinder(keystoreBinder);
+
+ if (!keystore2) {
+ wpa_printf(MSG_WARNING, "Unable to connect to Keystore 2.");
+ return {};
+ }
+
+ bool ca_cert = false;
+ std::string alias = key.c_str();
+ if (::android::base::StartsWith(alias, "CACERT_")) {
+ alias = alias.substr(7);
+ ca_cert = true;
+ } else if (::android::base::StartsWith(alias, "USRCERT_")) {
+ alias = alias.substr(8);
+ }
+
+ ks2::KeyDescriptor descriptor = mkKeyDescriptor(alias);
+
+ // If the key_id starts with the grant id prefix, we parse the following string as numeric
+ // grant id. We can then use the grant domain without alias to load the designated key.
+ if (::android::base::StartsWith(alias, keystore2_grant_id_prefix)) {
+ std::stringstream s(alias.substr(keystore2_grant_id_prefix.size()));
+ uint64_t tmp;
+ s >> std::hex >> tmp;
+ if (s.fail() || !s.eof()) {
+ wpa_printf(MSG_ERROR, "Couldn't parse grant name: %s", alias.c_str());
+ }
+ descriptor.nspace = static_cast<int64_t>(tmp);
+ descriptor.domain = ks2::Domain::GRANT;
+ descriptor.alias = std::nullopt;
+ }
+
+ ks2::KeyEntryResponse response;
+ auto rc = keystore2->getKeyEntry(descriptor, &response);
+ if (!rc.isOk()) {
+ if (rc.getServiceSpecificError() != int32_t(ks2::ResponseCode::KEY_NOT_FOUND)) {
+ wpa_printf(MSG_WARNING, "Entry not found in Keystore 2.");
+ } else {
+ wpa_printf(MSG_WARNING, "Keystore 2 getKeyEntry failed error: %s", rc.getDescription().c_str());
+ }
+ return {};
+ }
+
+ if (ca_cert && response.metadata.certificateChain) {
+ return std::move(*response.metadata.certificateChain);
+ } else if (!ca_cert && response.metadata.certificate) {
+ return std::move(*response.metadata.certificate);
+ } else {
+ wpa_printf(MSG_WARNING, "No %s certificate found.", (ca_cert ? "CA" : "client"));
+ return {};
+ }
+}
+
+std::optional<std::vector<uint8_t>> getNonStandardCert(const std::string& alias,
+ const std::shared_ptr<INonStandardCertCallback> &non_standard_callback) {
+ if (non_standard_callback == nullptr) {
+ wpa_printf(MSG_ERROR, "Non-standard cert callback is not available");
+ return std::nullopt;
+ }
+ std::vector<uint8_t> blob;
+ const auto& status = non_standard_callback->getBlob(alias, &blob);
+ if (!status.isOk()) {
+ wpa_printf(MSG_ERROR, "Cert callback error, code=%d",
+ status.getServiceSpecificError());
+ return std::nullopt;
+ }
+ return blob;
+}
+
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace certificate_utils {
+
+std::optional<std::vector<uint8_t>> getCertificate(const std::string& alias,
+ const std::shared_ptr<INonStandardCertCallback> &non_standard_callback) {
+ std::vector<uint8_t> cert;
+ if (auto ks2_cert = getKeystore2Cert(alias)) {
+ cert = std::move(*ks2_cert);
+ } else if (auto blob = getNonStandardCert(alias, non_standard_callback)) {
+ cert = std::move(*blob);
+ } else {
+ wpa_printf(MSG_ERROR, "Failed to get certificate.");
+ return std::nullopt;
+ }
+
+ if (auto result_cert = convertDerCertToPemOrPassthrough(cert)) {
+ return result_cert;
+ } else {
+ wpa_printf(MSG_ERROR, "Conversion to PEM failed.");
+ return std::nullopt;
+ }
+}
+
+} // namespace certificate_utils
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wpa_supplicant/aidl/certificate_utils.h b/wpa_supplicant/aidl/certificate_utils.h
new file mode 100644
index 0000000..09da74b
--- /dev/null
+++ b/wpa_supplicant/aidl/certificate_utils.h
@@ -0,0 +1,40 @@
+/*
+ * WPA Supplicant - Certificate utils
+ * Copyright (c) 2022, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/wifi/supplicant/INonStandardCertCallback.h>
+#include <aidl/android/system/keystore2/IKeystoreService.h>
+#include <aidl/android/system/keystore2/ResponseCode.h>
+#include <android-base/strings.h>
+#include <android/binder_manager.h>
+#include <openssl/base.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+#include <vector>
+
+extern "C"
+{
+#include "utils/common.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace certificate_utils {
+ std::optional<std::vector<uint8_t>> getCertificate(const std::string& alias,
+ const std::shared_ptr<INonStandardCertCallback> &non_standard_callback);
+} // namespace certificate_utils
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wpa_supplicant/aidl/supplicant.cpp b/wpa_supplicant/aidl/supplicant.cpp
index 799790b..74602e4 100644
--- a/wpa_supplicant/aidl/supplicant.cpp
+++ b/wpa_supplicant/aidl/supplicant.cpp
@@ -239,6 +239,14 @@
&Supplicant::registerCallbackInternal, in_callback);
}
+::ndk::ScopedAStatus Supplicant::registerNonStandardCertCallback(
+ const std::shared_ptr<INonStandardCertCallback>& in_callback)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &Supplicant::registerNonStandardCertCallbackInternal, in_callback);
+}
+
::ndk::ScopedAStatus Supplicant::setDebugParams(
DebugLevel in_level, bool in_showTimestamp,
bool in_showKeys)
@@ -547,6 +555,17 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Supplicant::registerNonStandardCertCallbackInternal(
+ const std::shared_ptr<INonStandardCertCallback>& callback)
+{
+ AidlManager* aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager ||
+ aidl_manager->registerNonStandardCertCallbackAidlObject(callback)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
ndk::ScopedAStatus Supplicant::setDebugParamsInternal(
DebugLevel level, bool show_timestamp, bool show_keys)
{
diff --git a/wpa_supplicant/aidl/supplicant.h b/wpa_supplicant/aidl/supplicant.h
index cbe9a67..12b9299 100644
--- a/wpa_supplicant/aidl/supplicant.h
+++ b/wpa_supplicant/aidl/supplicant.h
@@ -64,6 +64,8 @@
std::vector<IfaceInfo>* _aidl_return) override;
::ndk::ScopedAStatus registerCallback(
const std::shared_ptr<ISupplicantCallback>& in_callback) override;
+ ::ndk::ScopedAStatus registerNonStandardCertCallback(
+ const std::shared_ptr<INonStandardCertCallback>& in_callback) override;
::ndk::ScopedAStatus setDebugParams(
DebugLevel in_level, bool in_showTimestamp, bool in_showKeys) override;
::ndk::ScopedAStatus getDebugLevel(DebugLevel* _aidl_return) override;
@@ -82,11 +84,13 @@
getP2pInterfaceInternal(const std::string& name);
std::pair<std::shared_ptr<ISupplicantStaIface>, ndk::ScopedAStatus>
getStaInterfaceInternal(const std::string& name);
-
+
ndk::ScopedAStatus removeInterfaceInternal(const IfaceInfo& iface_info);
std::pair<std::vector<IfaceInfo>, ndk::ScopedAStatus> listInterfacesInternal();
ndk::ScopedAStatus registerCallbackInternal(
const std::shared_ptr<ISupplicantCallback>& callback);
+ ndk::ScopedAStatus registerNonStandardCertCallbackInternal(
+ const std::shared_ptr<INonStandardCertCallback>& callback);
ndk::ScopedAStatus setDebugParamsInternal(
DebugLevel level, bool show_timestamp, bool show_keys);
ndk::ScopedAStatus setConcurrencyPriorityInternal(IfaceType type);
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 7e6d042..7ec0f0d 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -1352,3 +1352,8 @@
wpas_aidl_notify_frequency_changed(wpa_s, frequency);
}
+
+ssize_t wpas_get_certificate(const char *alias, uint8_t** value)
+{
+ return wpas_aidl_get_certificate(alias, value);
+}
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index e1b9f17..9a818ef 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -221,5 +221,6 @@
void wpas_notify_qos_policy_request(struct wpa_supplicant *wpa_s,
struct dscp_policy_data *policies, int num_policies);
void wpas_notify_frequency_changed(struct wpa_supplicant *wpa_s, int frequency);
+ssize_t wpas_get_certificate(const char *alias, uint8_t** value);
#endif /* NOTIFY_H */
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index a733ae3..28faa94 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -1203,6 +1203,12 @@
wpa_sm_pmf_enabled(wpa_s->wpa);
}
+static ssize_t wpa_supplicant_get_certificate_cb(
+ const char* alias, uint8_t** value)
+{
+ return wpas_get_certificate(alias, value);
+}
+
#endif /* IEEE8021X_EAPOL */
@@ -1252,6 +1258,7 @@
ctx->set_anon_id = wpa_supplicant_set_anon_id;
ctx->eap_method_selected_cb = wpa_supplicant_eap_method_selected_cb;
ctx->open_ssl_failure_cb = wpa_supplicant_open_ssl_failure_cb;
+ ctx->get_certificate_cb = wpa_supplicant_get_certificate_cb;
ctx->encryption_required = wpas_encryption_required;
ctx->cb_ctx = wpa_s;
wpa_s->eapol = eapol_sm_init(ctx);