new file mode 100644
@@ -0,0 +1,2 @@
+bin
+.config
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,159 @@
+ALL=dragonstar
+CONFIG_FILE = .config
+
+include ../src/build.rules
+
+CFLAGS += $(EXTRA_CFLAGS)
+CFLAGS += -I$(abspath ../src)
+CFLAGS += -I$(abspath ../src/utils)
+
+ifndef CONFIG_OS
+ifdef CONFIG_NATIVE_WINDOWS
+CONFIG_OS=win32
+else
+CONFIG_OS=unix
+endif
+endif
+
+ifeq ($(CONFIG_OS), internal)
+CFLAGS += -DOS_NO_C_LIB_DEFINES
+endif
+
+ifdef CONFIG_NATIVE_WINDOWS
+CFLAGS += -DCONFIG_NATIVE_WINDOWS
+LIBS += -lws2_32
+endif
+
+# By default for Dragonstar Tester
+CONFIG_SAE=y
+OBJS = dragonstar.o
+
+CFLAGS += -O3
+BIN_DIR="bin"
+OBJS += ../src/common/common_module_tests.o
+CFLAGS += -DCONFIG_MODULE_TESTS
+
+NEED_RC4=y
+NEED_AES=y
+NEED_MD5=y
+NEED_SHA1=y
+
+OBJS += ../src/utils/common.o
+OBJS += ../src/utils/wpa_debug.o
+OBJS += ../src/utils/wpabuf.o
+OBJS += ../src/utils/os_$(CONFIG_OS).o
+
+ifdef CONFIG_SAE
+CFLAGS += -DCONFIG_SAE
+OBJS += ../src/common/sae.o
+ifdef CONFIG_SAE_PK
+CFLAGS += -DCONFIG_SAE_PK
+OBJS += ../src/common/sae_pk.o
+endif
+NEED_ECC=y
+NEED_DH_GROUPS=y
+NEED_HMAC_SHA256_KDF=y
+NEED_AP_MLME=y
+NEED_DRAGONFLY=y
+endif
+
+ifdef CONFIG_EAP
+CFLAGS += -DEAP_SERVER
+endif
+
+ifdef CONFIG_PKCS12
+CFLAGS += -DPKCS12_FUNCS
+endif
+
+ifdef NEED_DRAGONFLY
+OBJS += ../src/common/dragonfly.o
+endif
+
+ifndef CONFIG_CRYPTO
+CONFIG_CRYPTO=hacl
+endif
+
+ifeq ($(CONFIG_CRYPTO), hacl)
+OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
+CFLAGS += -DCONFIG_HACL
+CFLAGS += -DCONFIG_CRYPTO_INTERNAL
+CFLAGS += $(INCLUDE_HACL)
+LIBS += -levercrypt
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_DES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD4=y
+CONFIG_INTERNAL_MD5=y
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_SHA384=y
+CONFIG_INTERNAL_SHA512=y
+CONFIG_INTERNAL_RC4=y
+CONFIG_INTERNAL_DH_GROUP5=y
+endif
+
+ifdef NEED_SHA1
+SHA1OBJS += ../src/crypto/sha1.o
+SHA1OBJS += ../src/crypto/sha1-prf.o
+ifdef CONFIG_INTERNAL_SHA1
+SHA1OBJS += ../src/crypto/sha1-internal.o
+endif
+OBJS += $(SHA1OBJS)
+endif
+
+CFLAGS += -DCONFIG_SHA256
+OBJS += ../src/crypto/sha256-prf.o
+ifdef CONFIG_INTERNAL_SHA256
+OBJS += ../src/crypto/sha256-internal.o
+endif
+ifdef NEED_TLS_PRF_SHA256
+OBJS += ../src/crypto/sha256-tlsprf.o
+endif
+ifdef NEED_TLS_PRF_SHA384
+OBJS += ../src/crypto/sha384-tlsprf.o
+endif
+ifdef NEED_HMAC_SHA256_KDF
+OBJS += ../src/crypto/sha256-kdf.o
+endif
+ifdef NEED_HMAC_SHA384_KDF
+OBJS += ../src/crypto/sha384-kdf.o
+endif
+ifdef NEED_HMAC_SHA512_KDF
+OBJS += ../src/crypto/sha512-kdf.o
+endif
+ifdef NEED_SHA384
+CFLAGS += -DCONFIG_SHA384
+OBJS += ../src/crypto/sha384-prf.o
+endif
+ifdef NEED_SHA512
+CFLAGS += -DCONFIG_SHA512
+OBJS += ../src/crypto/sha512-prf.o
+endif
+
+ifdef NEED_ECC
+CFLAGS += -DCONFIG_ECC
+endif
+
+ifdef CONFIG_NO_RANDOM_POOL
+CFLAGS += -DCONFIG_NO_RANDOM_POOL
+else
+ifdef CONFIG_GETRANDOM
+CFLAGS += -DCONFIG_GETRANDOM
+endif
+OBJS += ../src/crypto/random.o
+OBJS += ../src/utils/eloop.o
+endif
+
+ifdef CONFIG_DEBUG_SYSLOG
+CFLAGS += -DCONFIG_DEBUG_SYSLOG
+endif
+
+_OBJS_VAR := OBJS
+include ../src/objs.mk
+
+dragonstar: $(OBJS)
+ mkdir -p $(BIN_DIR)
+ $(Q)$(CC) $(LDFLAGS) -o $(BIN_DIR)/dragonstar $(OBJS) $(LIBS)
+ @$(E) " LD " $@
+
+clean: common-clean
+ rm -f $(BIN_DIR)/dragonstar
new file mode 100644
@@ -0,0 +1,93 @@
+# Dragonstar: A plugin verified cryptographic implementation for Dragonfly
+
+The PAKE Dragonfly is used during a WPA3 authentication, as part of SAE(-PT).
+However, multiple side-channel vulnerabilities have impacted its
+implementations, some focusing on the Wi-Fi daemon, other leveraging
+vulnerabilities in the third-party cryptographic libraries used as providers.
+
+Here, we introduce an alternative cryptographic provider. It is based on HaCl*,
+a formally verified cryptographic library, ensuring a secret-independent, memory
+safe and functionally-correct implementation. This alternative cryptographic
+provider can be used as a plugin in the hostap project (compatible with both
+wpa_supplicant and hostapd), and focuses on the support of WPA3, with the NIST
+P-256.
+
+## Disclamer
+
+This is an experimental work. It currently supports a subset of the
+functionalities provided by hostap, focused on establishing a WPA3 session
+(relying on either SAE or SAE-PT) using the NIST curve P256. In the current
+state, using HaCl* as a cryptographic provider enables establishing a secure
+Wi-Fi connexion using WPA3 (SAE and SAE-PT are supported, for the curve P-256
+only).
+
+Since HaCl* is a cryptographic library focusing on modern cryptographic
+algorithms, some legacy functionalities cannot be supported (DES, MD4, RC4). In
+addition, we did not implement a complete mapping between hostap's cryptographic
+API and HaCl*. In particular, the following mapping is not implemented yet: AES,
+SHA-1, SHA-2 and DH groups. Feel free to contribute and complete it in
+`src/crypto/crypto_hacl.c`. For missing cryptographic functionalities, we
+currently rely on internal implementations.
+
+In particular, the following changes are made to the default configuration when
+using HaCl*:
+* DDP is disabled: DPP functions initialize big numbers. However, since HaCl*
+ works with fixed-size numbers, the initialization function signature had to be
+ changed to include the byte length of the number. These changes were not
+ propagated to the DPP implementation because we do not know enough about them
+ to ensure le absence of side-effect.
+* The finite field-based (DH group-based) authentication for SAE is disabled. We
+ only provide an implementation of the protocol with the P256 curve (as
+ required by the standard).
+* TLS is not supported. Radius and EAP methods are not fully supported either.
+
+
+## Setup
+
+As this addon relies on the formally verified library HaCl*, we assume the
+library to be installed and available on the system, or the proper environment
+variable being set to include the path to the HaCl* library and the
+corresponding headers.
+
+Then, the projects hostapd and wpa_supplicant can be built using the Makefile
+while defining the `CONFIG_TLS=hacl` in the .config file.
+
+In the project wpa_supplicant, please use the dragonstarconfig file instead of
+defconfig.
+
+## Usage
+
+This repository contains a simple tester, with the appropriate configuration to
+build a tester running the unit tests on SAE using the HaCl* library as a
+cryptographic library.
+
+You can run the unit tests by simply executing the binary:
+```sh
+./bin/dragonstar
+```
+
+You can also verify the proper establishment of a session using a custom
+password (or a list of passwords to run multiple tests), by providing them in
+the command line. It will run at `wpa_debug_level = MSG_EXCESSIVE` to display
+intermediate value.
+
+```sh
+./bin/dragonstar testpassword testpassword2
+```
+
+You can also run tests for SAE-PT by providing an additional password identifier
+to the arguments. The following command line will run a session establishment
+using SAE-PT with the password identifier "pidentifier" and password
+"testpassword":
+```sh
+./bin/dragonstar -i pidentifier testpassword
+```
+
+------------------
+
+## Contributors
+
+* Daniel De Almeida Braga <ddealmei.0@gmail.com>
+* Mohamed Sabt <mohamed.sabt@irisa.fr>
+* Pierre-Alain Fouque <pa.fouque@gmail.com>
+* Alexandre Sanchez <alexandre.sanchez@inria.fr>
new file mode 100644
@@ -0,0 +1,412 @@
+# Example hostapd build time configuration
+#
+# This file lists the configuration options that are used when building the
+# hostapd binary. All lines starting with # are ignored. Configuration option
+# lines must be commented out complete, if they are not to be included, i.e.,
+# just setting VARIABLE=n is not disabling that variable.
+#
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
+# be modified from here. In most cass, these lines should use += in order not
+# to override previous values of the variables.
+
+# Driver interface for Host AP driver
+CONFIG_DRIVER_HOSTAP=y
+
+# Driver interface for wired authenticator
+#CONFIG_DRIVER_WIRED=y
+
+# Driver interface for drivers using the nl80211 kernel interface
+CONFIG_DRIVER_NL80211=y
+
+# QCA vendor extensions to nl80211
+#CONFIG_DRIVER_NL80211_QCA=y
+
+# driver_nl80211.c requires libnl. If you are compiling it yourself
+# you may need to point hostapd to your version of libnl.
+#
+#CFLAGS += -I$<path to libnl include files>
+#LIBS += -L$<path to libnl library files>
+
+# Use libnl v2.0 (or 3.0) libraries.
+#CONFIG_LIBNL20=y
+
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
+CONFIG_LIBNL32=y
+
+
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
+#CONFIG_DRIVER_BSD=y
+#CFLAGS += -I/usr/local/include
+#LIBS += -L/usr/local/lib
+#LIBS_p += -L/usr/local/lib
+#LIBS_c += -L/usr/local/lib
+
+# Driver interface for no driver (e.g., RADIUS server only)
+#CONFIG_DRIVER_NONE=y
+
+# WPA2/IEEE 802.11i RSN pre-authentication
+CONFIG_RSN_PREAUTH=y
+
+# Support Operating Channel Validation
+#CONFIG_OCV=y
+
+# Integrated EAP server
+CONFIG_EAP=y
+
+# EAP Re-authentication Protocol (ERP) in integrated EAP server
+CONFIG_ERP=y
+
+# EAP-MD5 for the integrated EAP server
+CONFIG_EAP_MD5=y
+
+# EAP-TLS for the integrated EAP server
+CONFIG_EAP_TLS=y
+
+# EAP-MSCHAPv2 for the integrated EAP server
+CONFIG_EAP_MSCHAPV2=y
+
+# EAP-PEAP for the integrated EAP server
+CONFIG_EAP_PEAP=y
+
+# EAP-GTC for the integrated EAP server
+CONFIG_EAP_GTC=y
+
+# EAP-TTLS for the integrated EAP server
+CONFIG_EAP_TTLS=y
+
+# EAP-SIM for the integrated EAP server
+#CONFIG_EAP_SIM=y
+
+# EAP-AKA for the integrated EAP server
+#CONFIG_EAP_AKA=y
+
+# EAP-AKA' for the integrated EAP server
+# This requires CONFIG_EAP_AKA to be enabled, too.
+#CONFIG_EAP_AKA_PRIME=y
+
+# EAP-PAX for the integrated EAP server
+#CONFIG_EAP_PAX=y
+
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
+#CONFIG_EAP_PSK=y
+
+# EAP-pwd for the integrated EAP server (secure authentication with a password)
+#CONFIG_EAP_PWD=y
+
+# EAP-SAKE for the integrated EAP server
+#CONFIG_EAP_SAKE=y
+
+# EAP-GPSK for the integrated EAP server
+#CONFIG_EAP_GPSK=y
+# Include support for optional SHA256 cipher suite in EAP-GPSK
+#CONFIG_EAP_GPSK_SHA256=y
+
+# EAP-FAST for the integrated EAP server
+#CONFIG_EAP_FAST=y
+
+# EAP-TEAP for the integrated EAP server
+# Note: The current EAP-TEAP implementation is experimental and should not be
+# enabled for production use. The IETF RFC 7170 that defines EAP-TEAP has number
+# of conflicting statements and missing details and the implementation has
+# vendor specific workarounds for those and as such, may not interoperate with
+# any other implementation. This should not be used for anything else than
+# experimentation and interoperability testing until those issues has been
+# resolved.
+#CONFIG_EAP_TEAP=y
+
+# Wi-Fi Protected Setup (WPS)
+#CONFIG_WPS=y
+# Enable UPnP support for external WPS Registrars
+#CONFIG_WPS_UPNP=y
+# Enable WPS support with NFC config method
+#CONFIG_WPS_NFC=y
+
+# EAP-IKEv2
+#CONFIG_EAP_IKEV2=y
+
+# Trusted Network Connect (EAP-TNC)
+#CONFIG_EAP_TNC=y
+
+# EAP-EKE for the integrated EAP server
+#CONFIG_EAP_EKE=y
+
+# PKCS#12 (PFX) support (used to read private key and certificate file from
+# a file that usually has extension .p12 or .pfx)
+CONFIG_PKCS12=y
+
+# RADIUS authentication server. This provides access to the integrated EAP
+# server from external hosts using RADIUS.
+#CONFIG_RADIUS_SERVER=y
+
+# Build IPv6 support for RADIUS operations
+CONFIG_IPV6=y
+
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
+#CONFIG_IEEE80211R=y
+
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
+# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
+#CONFIG_DRIVER_RADIUS_ACL=y
+
+# Wireless Network Management (IEEE Std 802.11v-2011)
+# Note: This is experimental and not complete implementation.
+#CONFIG_WNM=y
+
+# IEEE 802.11ac (Very High Throughput) support
+#CONFIG_IEEE80211AC=y
+
+# IEEE 802.11ax HE support
+# Note: This is experimental and work in progress. The definitions are still
+# subject to change and this should not be expected to interoperate with the
+# final IEEE 802.11ax version.
+#CONFIG_IEEE80211AX=y
+
+# Remove debugging code that is printing out debug messages to stdout.
+# This can be used to reduce the size of the hostapd considerably if debugging
+# code is not needed.
+#CONFIG_NO_STDOUT_DEBUG=y
+
+# Add support for writing debug log to a file: -f /tmp/hostapd.log
+# Disabled by default.
+#CONFIG_DEBUG_FILE=y
+
+# Send debug messages to syslog instead of stdout
+#CONFIG_DEBUG_SYSLOG=y
+
+# Add support for sending all debug messages (regardless of debug verbosity)
+# to the Linux kernel tracing facility. This helps debug the entire stack by
+# making it easy to record everything happening from the driver up into the
+# same file, e.g., using trace-cmd.
+#CONFIG_DEBUG_LINUX_TRACING=y
+
+# Remove support for RADIUS accounting
+#CONFIG_NO_ACCOUNTING=y
+
+# Remove support for RADIUS
+#CONFIG_NO_RADIUS=y
+
+# Remove support for VLANs
+#CONFIG_NO_VLAN=y
+
+# Enable support for fully dynamic VLANs. This enables hostapd to
+# automatically create bridge and VLAN interfaces if necessary.
+#CONFIG_FULL_DYNAMIC_VLAN=y
+
+# Use netlink-based kernel API for VLAN operations instead of ioctl()
+# Note: This requires libnl 3.1 or newer.
+#CONFIG_VLAN_NETLINK=y
+
+# Remove support for dumping internal state through control interface commands
+# This can be used to reduce binary size at the cost of disabling a debugging
+# option.
+#CONFIG_NO_DUMP_STATE=y
+
+# Enable tracing code for developer debugging
+# This tracks use of memory allocations and other registrations and reports
+# incorrect use with a backtrace of call (or allocation) location.
+#CONFIG_WPA_TRACE=y
+# For BSD, comment out these.
+#LIBS += -lexecinfo
+#LIBS_p += -lexecinfo
+#LIBS_c += -lexecinfo
+
+# Use libbfd to get more details for developer debugging
+# This enables use of libbfd to get more detailed symbols for the backtraces
+# generated by CONFIG_WPA_TRACE=y.
+#CONFIG_WPA_TRACE_BFD=y
+# For BSD, comment out these.
+#LIBS += -lbfd -liberty -lz
+#LIBS_p += -lbfd -liberty -lz
+#LIBS_c += -lbfd -liberty -lz
+
+# hostapd depends on strong random number generation being available from the
+# operating system. os_get_random() function is used to fetch random data when
+# needed, e.g., for key generation. On Linux and BSD systems, this works by
+# reading /dev/urandom. It should be noted that the OS entropy pool needs to be
+# properly initialized before hostapd is started. This is important especially
+# on embedded devices that do not have a hardware random number generator and
+# may by default start up with minimal entropy available for random number
+# generation.
+#
+# As a safety net, hostapd is by default trying to internally collect
+# additional entropy for generating random data to mix in with the data
+# fetched from the OS. This by itself is not considered to be very strong, but
+# it may help in cases where the system pool is not initialized properly.
+# However, it is very strongly recommended that the system pool is initialized
+# with enough entropy either by using hardware assisted random number
+# generator or by storing state over device reboots.
+#
+# hostapd can be configured to maintain its own entropy store over restarts to
+# enhance random number generation. This is not perfect, but it is much more
+# secure than using the same sequence of random numbers after every reboot.
+# This can be enabled with -e<entropy file> command line option. The specified
+# file needs to be readable and writable by hostapd.
+#
+# If the os_get_random() is known to provide strong random data (e.g., on
+# Linux/BSD, the board in question is known to have reliable source of random
+# data from /dev/urandom), the internal hostapd random pool can be disabled.
+# This will save some in binary size and CPU use. However, this should only be
+# considered for builds that are known to be used on devices that meet the
+# requirements described above.
+#CONFIG_NO_RANDOM_POOL=y
+
+# Should we attempt to use the getrandom(2) call that provides more reliable
+# yet secure randomness source than /dev/random on Linux 3.17 and newer.
+# Requires glibc 2.25 to build, falls back to /dev/random if unavailable.
+#CONFIG_GETRANDOM=y
+
+# Should we use poll instead of select? Select is used by default.
+#CONFIG_ELOOP_POLL=y
+
+# Should we use epoll instead of select? Select is used by default.
+#CONFIG_ELOOP_EPOLL=y
+
+# Should we use kqueue instead of select? Select is used by default.
+#CONFIG_ELOOP_KQUEUE=y
+
+# Select TLS implementation
+# openssl = OpenSSL (default)
+# gnutls = GnuTLS
+# internal = Internal TLSv1 implementation (experimental)
+# linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
+# none = Empty template
+#CONFIG_TLS=openssl
+
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
+# can be enabled to get a stronger construction of messages when block ciphers
+# are used.
+#CONFIG_TLSV11=y
+
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
+# can be enabled to enable use of stronger crypto algorithms.
+#CONFIG_TLSV12=y
+
+# Select which ciphers to use by default with OpenSSL if the user does not
+# specify them.
+#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
+
+# If CONFIG_TLS=internal is used, additional library and include paths are
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
+# and drawbacks of this option.
+#CONFIG_INTERNAL_LIBTOMMATH=y
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
+#LTM_PATH=/usr/src/libtommath-0.39
+#CFLAGS += -I$(LTM_PATH)
+#LIBS += -L$(LTM_PATH)
+#LIBS_p += -L$(LTM_PATH)
+#endif
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
+# can be configured to include faster routines for exptmod, sqr, and div to
+# speed up DH and RSA calculation considerably
+#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
+
+# Interworking (IEEE 802.11u)
+# This can be used to enable functionality to improve interworking with
+# external networks.
+#CONFIG_INTERWORKING=y
+
+# Hotspot 2.0
+#CONFIG_HS20=y
+
+# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
+#CONFIG_SQLITE=y
+
+# Enable Fast Session Transfer (FST)
+#CONFIG_FST=y
+
+# Enable CLI commands for FST testing
+#CONFIG_FST_TEST=y
+
+# Testing options
+# This can be used to enable some testing options (see also the example
+# configuration file) that are really useful only for testing clients that
+# connect to this hostapd. These options allow, for example, to drop a
+# certain percentage of probe requests or auth/(re)assoc frames.
+#
+#CONFIG_TESTING_OPTIONS=y
+
+# Automatic Channel Selection
+# This will allow hostapd to pick the channel automatically when channel is set
+# to "acs_survey" or "0". Eventually, other ACS algorithms can be added in
+# similar way.
+#
+# Automatic selection is currently only done through initialization, later on
+# we hope to do background checks to keep us moving to more ideal channels as
+# time goes by. ACS is currently only supported through the nl80211 driver and
+# your driver must have survey dump capability that is filled by the driver
+# during scanning.
+#
+# You can customize the ACS survey algorithm with the hostapd.conf variable
+# acs_num_scans.
+#
+# Supported ACS drivers:
+# * ath9k
+# * ath5k
+# * ath10k
+#
+# For more details refer to:
+# https://wireless.wiki.kernel.org/en/users/documentation/acs
+#
+#CONFIG_ACS=y
+
+# Multiband Operation support
+# These extensions facilitate efficient use of multiple frequency bands
+# available to the AP and the devices that may associate with it.
+#CONFIG_MBO=y
+
+# Client Taxonomy
+# Has the AP retain the Probe Request and (Re)Association Request frames from
+# a client, from which a signature can be produced which can identify the model
+# of client device like "Nexus 6P" or "iPhone 5s".
+#CONFIG_TAXONOMY=y
+
+# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
+#CONFIG_FILS=y
+# FILS shared key authentication with PFS
+#CONFIG_FILS_SK_PFS=y
+
+# Include internal line edit mode in hostapd_cli. This can be used to provide
+# limited command line editing and history support.
+#CONFIG_WPA_CLI_EDIT=y
+
+# Opportunistic Wireless Encryption (OWE)
+# Experimental implementation of draft-harkins-owe-07.txt
+#CONFIG_OWE=y
+
+# Airtime policy support
+#CONFIG_AIRTIME_POLICY=y
+
+# Override default value for the wpa_disable_eapol_key_retries configuration
+# parameter. See that parameter in hostapd.conf for more details.
+#CFLAGS += -DDEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES=1
+
+# Wired equivalent privacy (WEP)
+# WEP is an obsolete cryptographic data confidentiality algorithm that is not
+# considered secure. It should not be used for anything anymore. The
+# functionality needed to use WEP is available in the current hostapd
+# release under this optional build parameter. This functionality is subject to
+# be completely removed in a future release.
+#CONFIG_WEP=y
+
+# Remove all TKIP functionality
+# TKIP is an old cryptographic data confidentiality algorithm that is not
+# considered secure. It should not be used anymore. For now, the default hostapd
+# build includes this to allow mixed mode WPA+WPA2 networks to be enabled, but
+# that functionality is subject to be removed in the future.
+#CONFIG_NO_TKIP=y
+
+# Pre-Association Security Negotiation (PASN)
+# Experimental implementation based on IEEE P802.11z/D2.6 and the protocol
+# design is still subject to change. As such, this should not yet be enabled in
+# production use.
+# This requires CONFIG_IEEE80211W=y to be enabled, too.
+#CONFIG_PASN=y
+
+# Device Provisioning Protocol (DPP) (also known as Wi-Fi Easy Connect)
+CONFIG_DPP=y
+# DPP version 2 support
+CONFIG_DPP2=y
+# DPP version 3 support (experimental and still changing; do not enable for
+# production use)
+#CONFIG_DPP3=y
new file mode 100644
@@ -0,0 +1,168 @@
+/* This file only contains some structure instanciation and tests to see if
+ * everything is working as intended.
+ * None of the following code needs to be implemented in HaCl*
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include "utils/common.h"
+#include "utils/module_tests.h"
+#include "common/sae.h"
+#include "wpabuf.h"
+#include "crypto/crypto.h"
+
+#define SSID "My SSID"
+#define GRP_ID 19
+#define NB_TESTS 1000
+static const uint8_t macA[] = { 0x98, 0xe7, 0x43, 0xd8, 0x6f, 0xbd };
+static const uint8_t macB[] = { 0x04, 0xed, 0x33, 0xc0, 0x85, 0x9b };
+
+static struct wpabuf* auth_build_sae_commit(struct sae_data* sae, char* pwd, char* pwd_id, struct sae_pt* pt) {
+ struct wpabuf* buf;
+ int use_pt = 0;
+ size_t pwd_len = strlen(pwd);
+
+ use_pt = pt != NULL;
+
+ if (use_pt &&
+ sae_prepare_commit_pt(sae, pt, macA, macB,
+ NULL, NULL) < 0) {
+ sae_deinit_pt(pt);
+ return NULL;
+ }
+ if (!use_pt &&
+ sae_prepare_commit(macA, macB, (const u8*) pwd, pwd_len,
+ sae) < 0) {
+ fprintf(stderr, "SAE: Could not pick PWE\n");
+ return NULL;
+ }
+
+ buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN +
+ (pwd_id ? 3 + strlen(pwd_id) : 0));
+ if (buf &&
+ sae_write_commit(sae, buf, sae->tmp ?
+ sae->tmp->anti_clogging_token : NULL,
+ pwd_id) < 0) {
+ wpabuf_free(buf);
+ buf = NULL;
+ }
+
+ return buf;
+}
+
+
+static struct wpabuf* auth_build_sae_confirm(struct sae_data* sae) {
+ struct wpabuf* buf;
+
+ buf = wpabuf_alloc(SAE_CONFIRM_MAX_LEN);
+ if (buf == NULL)
+ return NULL;
+
+ if (sae_write_confirm(sae, buf) < 0) {
+ wpabuf_free(buf);
+ return NULL;
+ }
+
+ return buf;
+}
+
+static int sae_test_custom(int group_id, char* pwd, char* pwd_id, struct sae_pt* pt) {
+ int err = -1;
+ struct sae_data saeA, saeB;
+
+ struct wpabuf* commitA = NULL, * commitB = NULL;
+ struct wpabuf* confirmA = NULL, * confirmB = NULL;
+
+ int h2e = pwd_id != NULL;
+
+ memset(&saeA, 0, sizeof(saeA));
+ memset(&saeB, 0, sizeof(saeB));
+
+ // Set the group
+ err = sae_set_group(&saeA, group_id);
+ if (err) goto end;
+ err = sae_set_group(&saeB, group_id);
+ if (err) goto end;
+
+ // Both part compute the commit message
+ commitA = auth_build_sae_commit(&saeA, pwd, pwd_id, pt);
+ if (commitA == NULL) goto end;
+ commitB = auth_build_sae_commit(&saeB, pwd, pwd_id, pt);
+ if (commitB == NULL) goto end;
+
+ // Both part receive the commit, parse it, and process it
+ err = sae_parse_commit(&saeA, wpabuf_mhead_u8(commitB), wpabuf_len(commitB),
+ NULL, NULL, NULL, h2e);
+ if (err < 0) goto end;
+ err = sae_process_commit(&saeA);
+ if (err != 0) goto end;
+ err = sae_parse_commit(&saeB, wpabuf_mhead_u8(commitA), wpabuf_len(commitA),
+ NULL, NULL, NULL, h2e);
+ if (err < 0) goto end;
+ err = sae_process_commit(&saeB);
+ if (err != 0) goto end;
+
+ // Build the confirmation message
+ confirmA = auth_build_sae_confirm(&saeA);
+ if (confirmA == NULL) goto end;
+ confirmB = auth_build_sae_confirm(&saeB);
+ if (confirmB == NULL) goto end;
+
+ // Both part verify the confirmation message of the other
+ err = sae_check_confirm(&saeA, wpabuf_mhead_u8(confirmB), wpabuf_len(confirmB));
+ if (err != 0) goto end;
+ err = sae_check_confirm(&saeB, wpabuf_mhead_u8(confirmA), wpabuf_len(confirmA));
+ if (err != 0) goto end;
+
+end:
+ sae_clear_data(&saeA);
+ sae_clear_data(&saeB);
+ if (commitA) wpabuf_free(commitA);
+ if (commitB) wpabuf_free(commitB);
+ if (confirmA) wpabuf_free(confirmA);
+ if (confirmB) wpabuf_free(confirmB);
+
+ return err;
+}
+
+int main(int argc, char** argv) {
+ int err = 0;
+ int idx = 1;
+
+ wpa_debug_level = MSG_EXCESSIVE;
+ wpa_debug_show_keys = 1;
+ wpa_printf(MSG_DEBUG, "DRAGONSTAR DEBUG MODE ACTIVATED");
+
+ if (common_module_tests())
+ fprintf(stderr, "hostapd_test: NOK\n");
+ else
+ fprintf(stderr, "hostapd_test: OK\n");
+
+ int group_id = 19;
+ char* pwd_id = NULL;
+ struct sae_pt* pt = NULL;
+ if (strcmp(argv[idx], "-i") == 0) {
+ idx++;
+ pwd_id = argv[idx++];
+ }
+
+ // Go through all passwords
+ for (int i = idx; i < argc; i++) {
+ //Run two sessions (A and B) from commit to confirmation
+ fprintf(stderr, "custom_pwd_test_%s\n", argv[i]);
+
+ if (pwd_id) {
+ pt = sae_derive_pt(NULL, (const uint8_t*) SSID, strlen(SSID),
+ (const uint8_t*) argv[i], strlen(argv[i]), pwd_id);
+ if (pt == NULL)
+ fprintf(stderr, "error when computing pt\n");
+ }
+
+ err |= sae_test_custom(group_id, argv[i], pwd_id, pt);
+
+ if (pt) { sae_deinit_pt(pt); pt = NULL; }
+ }
+
+ return err;
+}
@@ -568,7 +568,13 @@ endif
endif
-ifdef CONFIG_DPP
+ifeq ($(CONFIG_TLS), hacl)
+CONFIG_DPP=n
+CONFIG_DPP2=n
+CONFIG_DPP3=n
+endif
+
+ifeq ($(CONFIG_DPP), y)
CFLAGS += -DCONFIG_DPP
OBJS += ../src/common/dpp.o
OBJS += ../src/common/dpp_auth.o
@@ -590,10 +596,10 @@ NEED_JSON=y
NEED_GAS=y
NEED_BASE64=y
NEED_ASN1=y
-ifdef CONFIG_DPP2
+ifeq ($(CONFIG_DPP2), y)
CFLAGS += -DCONFIG_DPP2
endif
-ifdef CONFIG_DPP3
+ifeq ($(CONFIG_DPP3), y)
CFLAGS += -DCONFIG_DPP3
endif
endif
@@ -884,6 +890,34 @@ OBJS += ../src/crypto/sha1-internal.o
endif
endif
+ifeq ($(CONFIG_TLS), hacl)
+ifdef TLS_FUNCS
+OBJS += ../src/crypto/tls_none.o
+CFLAGS += -DEAP_TLS_NONE
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD5=y
+endif
+
+CFLAGS += -DCONFIG_HACL
+
+CONFIG_CRYPTO=hacl
+OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
+HOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
+CFLAGS += -DCONFIG_CRYPTO_INTERNAL
+LIBS += -levercrypt
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_DES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD4=y
+CONFIG_INTERNAL_MD5=y
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_SHA384=y
+CONFIG_INTERNAL_SHA512=y
+CONFIG_INTERNAL_RC4=y
+CONFIG_INTERNAL_DH_GROUP5=y
+endif
+
ifeq ($(CONFIG_TLS), none)
ifdef TLS_FUNCS
OBJS += ../src/crypto/tls_none.o
@@ -1044,6 +1078,7 @@ endif
CFLAGS += -DCONFIG_SHA256
ifneq ($(CONFIG_TLS), openssl)
+ifneq ($(CONFIG_TLS), hacl)
ifneq ($(CONFIG_TLS), linux)
ifneq ($(CONFIG_TLS), gnutls)
ifneq ($(CONFIG_TLS), wolfssl)
@@ -1052,6 +1087,7 @@ endif
endif
endif
endif
+endif
OBJS += ../src/crypto/sha256-prf.o
ifdef CONFIG_INTERNAL_SHA256
OBJS += ../src/crypto/sha256-internal.o
@@ -1112,6 +1148,7 @@ ifdef NEED_ASN1
OBJS += ../src/tls/asn1.o
endif
+ifneq ($(CONFIG_TLS), hacl)
ifdef NEED_DH_GROUPS
OBJS += ../src/crypto/dh_groups.o
endif
@@ -1123,6 +1160,7 @@ ifdef NEED_DH_GROUPS
OBJS += ../src/crypto/dh_group5.o
endif
endif
+endif
ifdef NEED_ECC
CFLAGS += -DCONFIG_ECC
@@ -269,6 +269,7 @@ CONFIG_IPV6=y
# gnutls = GnuTLS
# internal = Internal TLSv1 implementation (experimental)
# linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
+# hacl = cryptographic implementation for Dragonfly based on Hacl*(experimental)
# none = Empty template
#CONFIG_TLS=openssl
@@ -26,6 +26,7 @@ struct ieee802_11_parse_test_data {
int count;
};
+#ifndef CONFIG_HACL
static const struct ieee802_11_parse_test_data parse_tests[] = {
{ (u8 *) "", 0, ParseOK, 0 },
{ (u8 *) " ", 1, ParseFailed, 0 },
@@ -83,9 +84,11 @@ static const struct ieee802_11_parse_test_data parse_tests[] = {
{ (u8 *) "\xff\x01\x0d", 3, ParseOK, 1 },
{ NULL, 0, ParseOK, 0 }
};
+#endif /* CONFIG_HACL */
static int ieee802_11_parse_tests(void)
{
+#ifndef CONFIG_HACL
int i, ret = 0;
struct wpabuf *buf;
@@ -143,9 +146,13 @@ static int ieee802_11_parse_tests(void)
wpabuf_free(buf);
return ret;
+#else
+ return 0;
+#endif /* CONFIG_HACL */
}
+#ifndef CONFIG_HACL
struct rsn_ie_parse_test_data {
u8 *data;
size_t len;
@@ -200,9 +207,11 @@ static const struct rsn_ie_parse_test_data rsn_parse_tests[] = {
30, 0 },
{ NULL, 0, 0 }
};
+#endif /* CONFIG_HACL */
static int rsn_ie_parse_tests(void)
{
+#ifndef CONFIG_HACL
int i, ret = 0;
wpa_printf(MSG_INFO, "rsn_ie_parse tests");
@@ -220,11 +229,15 @@ static int rsn_ie_parse_tests(void)
}
return ret;
+#else
+ return 0;
+#endif /* CONFIG_HACL */
}
static int gas_tests(void)
{
+#ifndef CONFIG_HACL
struct wpabuf *buf;
wpa_printf(MSG_INFO, "gas tests");
@@ -246,6 +259,7 @@ static int gas_tests(void)
wpabuf_put_u8(buf, 0);
gas_anqp_set_len(buf);
wpabuf_free(buf);
+#endif
return 0;
}
@@ -334,6 +348,9 @@ static int sae_tests(void)
0x1a, 0x5e, 0xe8, 0x26, 0x9d, 0x06, 0x03, 0x82,
0xcc, 0xbf, 0x33, 0xe6, 0x14, 0xff, 0x59, 0xa0
};
+// Dragonstar/Hacl only supports group 19
+// So the Dragonstar Tester needs to bypass other groups
+#ifndef CONFIG_HACL
const u8 pwe_15[384] = {
0x69, 0x68, 0x73, 0x65, 0x8f, 0x65, 0x31, 0x42,
0x9f, 0x97, 0x39, 0x6f, 0xb8, 0x5f, 0x89, 0xe1,
@@ -385,6 +402,9 @@ static int sae_tests(void)
0x1e, 0xac, 0xcf, 0x33, 0x01, 0x99, 0xc1, 0x62
};
int pt_groups[] = { 19, 20, 21, 25, 26, 28, 29, 30, 15, 0 };
+#else
+ int pt_groups[] = { 19, 0 };
+#endif
struct sae_pt *pt_info, *pt;
const u8 addr1b[ETH_ALEN] = { 0x00, 0x09, 0x5b, 0x66, 0xec, 0x1e };
const u8 addr2b[ETH_ALEN] = { 0x00, 0x0b, 0x6b, 0xd9, 0x02, 0x46 };
@@ -399,12 +419,20 @@ static int sae_tests(void)
/* Override local values based on SAE test vector */
crypto_bignum_deinit(sae.tmp->sae_rand, 1);
+
+#ifndef CONFIG_HACL
sae.tmp->sae_rand = crypto_bignum_init_set(local_rand,
sizeof(local_rand));
mask = crypto_bignum_init_set(local_mask, sizeof(local_mask));
+#else
+ sae.tmp->sae_rand = crypto_bignum_static_init_set(local_rand,
+ sizeof(local_rand), sizeof(local_rand));
+ mask = crypto_bignum_static_init_set(local_mask, sizeof(local_mask), sizeof(local_mask));
+#endif
if (!sae.tmp->sae_rand || !mask)
goto fail;
+#ifndef CONFIG_HACL
if (crypto_bignum_add(sae.tmp->sae_rand, mask,
sae.tmp->own_commit_scalar) < 0 ||
crypto_bignum_mod(sae.tmp->own_commit_scalar, sae.tmp->order,
@@ -413,6 +441,14 @@ static int sae_tests(void)
sae.tmp->own_commit_element_ecc) < 0 ||
crypto_ec_point_invert(sae.tmp->ec,
sae.tmp->own_commit_element_ecc) < 0)
+#else
+ if (crypto_bignum_addmod(sae.tmp->sae_rand, mask, sae.tmp->order,
+ sae.tmp->own_commit_scalar) < 0 ||
+ crypto_ec_point_mul(sae.tmp->ec, sae.tmp->pwe_ecc, mask,
+ sae.tmp->own_commit_element_ecc) < 0 ||
+ crypto_ec_point_invert(sae.tmp->ec,
+ sae.tmp->own_commit_element_ecc) < 0)
+#endif
goto fail;
/* Check that output matches the test vector */
@@ -478,6 +514,8 @@ static int sae_tests(void)
crypto_ec_point_deinit(pwe, 1);
}
+#ifndef CONFIG_HACL
+#ifndef CONFIG_HACL
if (pt->group == 15) {
struct crypto_bignum *pwe;
u8 bin[SAE_MAX_PRIME_LEN];
@@ -499,6 +537,8 @@ static int sae_tests(void)
}
crypto_bignum_deinit(pwe, 1);
}
+#endif
+#endif
}
sae_deinit_pt(pt_info);
@@ -518,6 +558,7 @@ fail:
static int sae_pk_tests(void)
{
#ifdef CONFIG_SAE_PK
+#ifndef CONFIG_HACL
const char *invalid[] = { "a2bc-de3f-ghim-", "a2bcde3fghim", "", NULL };
struct {
const char *pw;
@@ -598,6 +639,9 @@ static int sae_pk_tests(void)
}
return failed ? -1 : 0;
+#else
+ return 0;
+#endif /* CONFIG_HACL */
#else /* CONFIG_SAE_PK */
return 0;
#endif /* CONFIG_SAE_PK */
@@ -768,9 +812,11 @@ static int pasn_test_no_pasn_auth(void)
static int pasn_tests(void)
{
#ifdef CONFIG_PASN
+#ifndef CONFIG_HACL
if (pasn_test_pasn_auth() ||
pasn_test_no_pasn_auth())
return -1;
+#endif /* CONFIG_HACL */
#endif /* CONFIG_PASN */
return 0;
}
@@ -25,14 +25,19 @@ int dragonfly_suitable_group(int group, int ecc_only)
* groups that use Brainpool curves as well for now since they leak more
* timing information due to the prime not being close to a power of
* two. */
+#ifndef CONFIG_HACL
return group == 19 || group == 20 || group == 21 ||
(!ecc_only &&
(group == 15 || group == 16 || group == 17 || group == 18));
+#else
+ return group == 19;
+#endif
}
unsigned int dragonfly_min_pwe_loop_iter(int group)
{
+#ifndef CONFIG_HACL
if (group == 22 || group == 23 || group == 24) {
/* FFC groups for which pwd-value is likely to be >= p
* frequently */
@@ -44,7 +49,7 @@ unsigned int dragonfly_min_pwe_loop_iter(int group)
/* FFC groups that have prime that is close to a power of two */
return 1;
}
-
+#endif
/* Default to 40 (this covers most ECC groups) */
return 40;
}
@@ -60,7 +65,11 @@ int dragonfly_get_random_qr_qnr(const struct crypto_bignum *prime,
struct crypto_bignum *tmp;
int res;
+#ifndef CONFIG_HACL
tmp = crypto_bignum_init();
+#else
+ tmp = crypto_bignum_static_init(crypto_bignum_static_size(prime));
+#endif
if (!tmp || crypto_bignum_rand(tmp, prime) < 0) {
crypto_bignum_deinit(tmp, 0);
break;
@@ -88,10 +97,17 @@ static struct crypto_bignum *
dragonfly_get_rand_1_to_p_1(const struct crypto_bignum *prime)
{
struct crypto_bignum *tmp, *pm1, *one;
+#ifdef CONFIG_HACL
+ size_t prime_len = crypto_bignum_static_size(prime);
+ tmp = crypto_bignum_static_init(prime_len);
+ pm1 = crypto_bignum_static_init(prime_len);
+ one = crypto_bignum_static_init_set((const u8 *) "\x01", 1, prime_len);
+#else
tmp = crypto_bignum_init();
pm1 = crypto_bignum_init();
one = crypto_bignum_init_set((const u8 *) "\x01", 1);
+#endif
if (!tmp || !pm1 || !one ||
crypto_bignum_sub(prime, one, pm1) < 0 ||
crypto_bignum_rand(tmp, pm1) < 0 ||
@@ -133,7 +149,11 @@ int dragonfly_is_quadratic_residue_blind(struct crypto_ec *ec,
if (!r)
return -1;
+#ifndef CONFIG_HACL
num = crypto_bignum_init();
+#else
+ num = crypto_bignum_static_init(prime_len);
+#endif
if (!num ||
crypto_bignum_mulmod(val, r, prime, num) < 0 ||
crypto_bignum_mulmod(num, r, prime, num) < 0)
@@ -154,7 +174,11 @@ int dragonfly_is_quadratic_residue_blind(struct crypto_ec *ec,
*/
mask = const_time_is_zero(crypto_bignum_is_odd(r));
const_time_select_bin(mask, qnr, qr, prime_len, qr_or_qnr_bin);
+#ifndef CONFIG_HACL
qr_or_qnr = crypto_bignum_init_set(qr_or_qnr_bin, prime_len);
+#else
+ qr_or_qnr = crypto_bignum_static_init_set(qr_or_qnr_bin, prime_len, prime_len);
+#endif
if (!qr_or_qnr ||
crypto_bignum_mulmod(num, qr_or_qnr, prime, num) < 0)
goto fail;
@@ -200,8 +224,12 @@ int dragonfly_generate_scalar(const struct crypto_bignum *order,
for (count = 0; count < 100; count++) {
if (dragonfly_get_rand_2_to_r_1(_rand, order) &&
dragonfly_get_rand_2_to_r_1(_mask, order) &&
+#ifndef CONFIG_HACL
crypto_bignum_add(_rand, _mask, scalar) == 0 &&
crypto_bignum_mod(scalar, order, scalar) == 0 &&
+#else
+ crypto_bignum_addmod(_rand, _mask, order, scalar) == 0 &&
+#endif
!crypto_bignum_is_zero(scalar) &&
!crypto_bignum_is_one(scalar))
return 0;
@@ -229,8 +257,13 @@ int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val,
prime = crypto_ec_get_prime(ec);
prime_len = crypto_ec_prime_len(ec);
+#ifndef CONFIG_HACL
tmp = crypto_bignum_init();
one = crypto_bignum_init_uint(1);
+#else
+ tmp = crypto_bignum_static_init(prime_len);
+ one = crypto_bignum_static_init_uint(1, prime_len);
+#endif
if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin),
prime_len) < 0 ||
@@ -8,6 +8,8 @@
#include "includes.h"
+#include <stdio.h>
+
#include "common.h"
#include "utils/const_time.h"
#include "crypto/crypto.h"
@@ -52,6 +54,7 @@ int sae_set_group(struct sae_data *sae, int group)
return 0;
}
+#ifndef CONFIG_HACL
/* Not an ECC group, check FFC */
tmp->dh = dh_groups_get(group);
if (tmp->dh) {
@@ -87,6 +90,7 @@ int sae_set_group(struct sae_data *sae, int group)
/* Unsupported group */
wpa_printf(MSG_DEBUG,
"SAE: Group %d not supported by the crypto library", group);
+#endif
return -1;
}
@@ -172,7 +176,11 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
* cmp_prime >= 0 (return 0 here), but go through them regardless to
* minimize externally observable differences in behavior. */
+#ifndef CONFIG_HACL
x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
+#else
+ x_cand = crypto_bignum_static_init_set(pwd_value, sae->tmp->prime_len, sae->tmp->prime_len);
+#endif
if (!x_cand)
return -1;
y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand);
@@ -189,6 +197,7 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
}
+#ifndef CONFIG_HACL
/* Returns -1 on fatal failure, 0 if PWE cannot be derived from the provided
* pwd-seed, or 1 if a valid PWE was derived from pwd-seed. */
static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
@@ -276,7 +285,7 @@ fail:
crypto_bignum_deinit(b, 1);
return res;
}
-
+#endif
static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
const u8 *addr2, const u8 *password,
@@ -392,7 +401,11 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
goto fail;
}
+#ifndef CONFIG_HACL
x = crypto_bignum_init_set(x_bin, prime_len);
+#else
+ x = crypto_bignum_static_init_set(x_bin, prime_len, prime_len);
+#endif
if (!x) {
res = -1;
goto fail;
@@ -444,6 +457,7 @@ fail:
}
+#ifndef CONFIG_HACL
static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
const u8 *addr2, const u8 *password,
size_t password_len)
@@ -528,7 +542,7 @@ fail:
bin_clear_free(pwe_buf, prime_len * 2);
return sae->tmp->pwe_ffc ? 0 : -1;
}
-
+#endif
static int hkdf_extract(size_t hash_len, const u8 *salt, size_t salt_len,
size_t num_elem, const u8 *addr[], const size_t len[],
@@ -582,6 +596,7 @@ static int sswu_curve_param(int group, int *z)
case 19:
*z = -10;
return 0;
+#ifndef CONFIG_HACL
case 20:
*z = -12;
return 0;
@@ -601,6 +616,7 @@ static int sswu_curve_param(int group, int *z)
case 30:
*z = 7;
return 0;
+#endif
}
return -1;
@@ -645,6 +661,7 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group,
a = crypto_ec_get_a(ec);
b = crypto_ec_get_b(ec);
+#ifndef CONFIG_HACL
u2 = crypto_bignum_init();
t1 = crypto_bignum_init();
t2 = crypto_bignum_init();
@@ -659,6 +676,22 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group,
x2 = crypto_bignum_init();
gx1 = crypto_bignum_init();
gx2 = crypto_bignum_init();
+#else
+ u2 = crypto_bignum_static_init(prime_len);
+ t1 = crypto_bignum_static_init(prime_len);
+ t2 = crypto_bignum_static_init(prime_len);
+ z = crypto_bignum_static_init_uint(abs(z_int), prime_len);
+ t = crypto_bignum_static_init(prime_len);
+ zero = crypto_bignum_static_init_uint(0, prime_len);
+ one = crypto_bignum_static_init_uint(1, prime_len);
+ two = crypto_bignum_static_init_uint(2, prime_len);
+ three = crypto_bignum_static_init_uint(3, prime_len);
+ x1a = crypto_bignum_static_init(prime_len);
+ x1b = crypto_bignum_static_init(prime_len);
+ x2 = crypto_bignum_static_init(prime_len);
+ gx1 = crypto_bignum_static_init(prime_len);
+ gx2 = crypto_bignum_static_init(prime_len);
+#endif
if (!u2 || !t1 || !t2 || !z || !t || !zero || !one || !two || !three ||
!x1a || !x1b || !x2 || !gx1 || !gx2)
goto fail;
@@ -712,7 +745,11 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group,
crypto_bignum_to_bin(x1b, bin2, sizeof(bin2), prime_len) < 0)
goto fail;
const_time_select_bin(m_is_zero, bin1, bin2, prime_len, bin);
+#ifndef CONFIG_HACL
x1 = crypto_bignum_init_set(bin, prime_len);
+#else
+ x1 = crypto_bignum_static_init_set(bin, prime_len, prime_len);
+#endif
if (!x1)
goto fail;
debug_print_bignum("SSWU: x1 = CSEL(l, x1a, x1b)", x1, prime_len);
@@ -754,7 +791,11 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group,
crypto_bignum_to_bin(gx2, bin2, sizeof(bin2), prime_len) < 0)
goto fail;
const_time_select_bin(is_qr, bin1, bin2, prime_len, bin);
+#ifndef CONFIG_HACL
v = crypto_bignum_init_set(bin, prime_len);
+#else
+ v = crypto_bignum_static_init_set(bin, prime_len, prime_len);
+#endif
if (!v)
goto fail;
debug_print_bignum("SSWU: v = CSEL(l, gx1, gx2)", v, prime_len);
@@ -767,7 +808,11 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group,
wpa_hexdump_key(MSG_DEBUG, "SSWU: x = CSEL(l, x1, x2)", x_y, prime_len);
/* y = sqrt(v) */
+#ifndef CONFIG_HACL
y = crypto_bignum_init();
+#else
+ y = crypto_bignum_static_init(prime_len);
+#endif
if (!y || dragonfly_sqrt(ec, v, y) < 0)
goto fail;
debug_print_bignum("SSWU: y = sqrt(v)", y, prime_len);
@@ -870,6 +915,9 @@ sae_derive_pt_ecc(struct crypto_ec *ec, int group,
size_t pwd_value_len, hash_len, prime_len;
const struct crypto_bignum *prime;
struct crypto_bignum *bn = NULL;
+#ifdef CONFIG_HACL
+ struct crypto_bignum *tmp = NULL;
+#endif
struct crypto_ec_point *p1 = NULL, *p2 = NULL, *pt = NULL;
prime = crypto_ec_get_prime(ec);
@@ -891,15 +939,27 @@ sae_derive_pt_ecc(struct crypto_ec *ec, int group,
"SAE Hash to Element u1 P1", pwd_value, pwd_value_len) <
0)
goto fail;
+
wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value (u1 P1)",
pwd_value, pwd_value_len);
+#ifndef CONFIG_HACL
/* u1 = pwd-value modulo p */
bn = crypto_bignum_init_set(pwd_value, pwd_value_len);
if (!bn || crypto_bignum_mod(bn, prime, bn) < 0 ||
crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value),
prime_len) < 0)
goto fail;
+#else
+ /* u1 = pwd-value modulo p */
+ bn = crypto_bignum_static_init(prime_len);
+ tmp = crypto_bignum_static_init_set(pwd_value, pwd_value_len, 2 * prime_len);
+ if (!bn || !tmp || crypto_bignum_mod(tmp, prime, bn) < 0 ||
+ crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value),
+ prime_len) < 0)
+ goto fail;
+#endif
+
wpa_hexdump_key(MSG_DEBUG, "SAE: u1", pwd_value, prime_len);
/* P1 = SSWU(u1) */
@@ -913,9 +973,11 @@ sae_derive_pt_ecc(struct crypto_ec *ec, int group,
"SAE Hash to Element u2 P2", pwd_value,
pwd_value_len) < 0)
goto fail;
+
wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value (u2 P2)",
pwd_value, pwd_value_len);
+#ifndef CONFIG_HACL
/* u2 = pwd-value modulo p */
crypto_bignum_deinit(bn, 1);
bn = crypto_bignum_init_set(pwd_value, pwd_value_len);
@@ -923,6 +985,18 @@ sae_derive_pt_ecc(struct crypto_ec *ec, int group,
crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value),
prime_len) < 0)
goto fail;
+#else
+ /* u2 = pwd-value modulo p */
+ crypto_bignum_deinit(bn, 1);
+ crypto_bignum_deinit(tmp, 1);
+ bn = crypto_bignum_static_init(prime_len);
+ tmp = crypto_bignum_static_init_set(pwd_value, pwd_value_len, 2 * prime_len);
+ if (!bn || !tmp || crypto_bignum_mod(tmp, prime, bn) < 0 ||
+ crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value),
+ prime_len) < 0)
+ goto fail;
+#endif
+
wpa_hexdump_key(MSG_DEBUG, "SAE: u2", pwd_value, prime_len);
/* P2 = SSWU(u2) */
@@ -943,12 +1017,16 @@ fail:
forced_memzero(pwd_seed, sizeof(pwd_seed));
forced_memzero(pwd_value, sizeof(pwd_value));
crypto_bignum_deinit(bn, 1);
+#ifdef CONFIG_HACL
+ crypto_bignum_deinit(tmp, 1);
+#endif
crypto_ec_point_deinit(p1, 1);
crypto_ec_point_deinit(p2, 1);
return pt;
}
+#ifndef CONFIG_HACL
size_t sae_ffc_prime_len_2_hash_len(size_t prime_len)
{
if (prime_len <= 2048 / 8)
@@ -957,8 +1035,10 @@ size_t sae_ffc_prime_len_2_hash_len(size_t prime_len)
return 48;
return 64;
}
+#endif
+#ifndef CONFIG_HACL
static struct crypto_bignum *
sae_derive_pt_ffc(const struct dh_group *dh, int group,
const u8 *ssid, size_t ssid_len,
@@ -1035,6 +1115,7 @@ fail:
crypto_bignum_deinit(order, 0);
return pt;
}
+#endif
static struct sae_pt *
@@ -1071,6 +1152,7 @@ sae_derive_pt_group(int group, const u8 *ssid, size_t ssid_len,
return pt;
}
+#ifndef CONFIG_HACL
pt->dh = dh_groups_get(group);
if (!pt->dh) {
wpa_printf(MSG_DEBUG, "SAE: Unsupported group %d", group);
@@ -1085,6 +1167,7 @@ sae_derive_pt_group(int group, const u8 *ssid, size_t ssid_len,
}
return pt;
+#endif
fail:
sae_deinit_pt(pt);
return NULL;
@@ -1152,6 +1235,7 @@ sae_derive_pwe_from_pt_ecc(const struct sae_pt *pt,
if (crypto_ec_point_to_bin(pt->ec, pt->ecc_pt,
bin, bin + prime_len) < 0)
return NULL;
+
wpa_hexdump_key(MSG_DEBUG, "SAE: PT.x", bin, prime_len);
wpa_hexdump_key(MSG_DEBUG, "SAE: PT.y", bin + prime_len, prime_len);
@@ -1168,9 +1252,15 @@ sae_derive_pwe_from_pt_ecc(const struct sae_pt *pt,
/* val = val modulo (q - 1) + 1 */
order = crypto_ec_get_order(pt->ec);
+#ifndef CONFIG_HACL
tmp = crypto_bignum_init();
val = crypto_bignum_init_set(hash, hash_len);
one = crypto_bignum_init_uint(1);
+#else
+ tmp = crypto_bignum_static_init(prime_len);
+ val = crypto_bignum_static_init_set(hash, hash_len, prime_len);
+ one = crypto_bignum_static_init_uint(1, prime_len);
+#endif
if (!tmp || !val || !one ||
crypto_bignum_sub(order, one, tmp) < 0 ||
crypto_bignum_mod(val, tmp, val) < 0 ||
@@ -1187,6 +1277,7 @@ sae_derive_pwe_from_pt_ecc(const struct sae_pt *pt,
pwe = NULL;
goto fail;
}
+
wpa_hexdump_key(MSG_DEBUG, "SAE: PWE.x", bin, prime_len);
wpa_hexdump_key(MSG_DEBUG, "SAE: PWE.y", bin + prime_len, prime_len);
@@ -1198,6 +1289,7 @@ fail:
}
+#ifndef CONFIG_HACL
struct crypto_bignum *
sae_derive_pwe_from_pt_ffc(const struct sae_pt *pt,
const u8 *addr1, const u8 *addr2)
@@ -1256,6 +1348,7 @@ fail:
crypto_bignum_deinit(order, 0);
return pwe;
}
+#endif
void sae_deinit_pt(struct sae_pt *pt)
@@ -1296,6 +1389,7 @@ static int sae_derive_commit_element_ecc(struct sae_data *sae,
}
+#ifndef CONFIG_HACL
static int sae_derive_commit_element_ffc(struct sae_data *sae,
struct crypto_bignum *mask)
{
@@ -1317,6 +1411,7 @@ static int sae_derive_commit_element_ffc(struct sae_data *sae,
return 0;
}
+#endif
static int sae_derive_commit(struct sae_data *sae)
@@ -1324,19 +1419,33 @@ static int sae_derive_commit(struct sae_data *sae)
struct crypto_bignum *mask;
int ret;
+#ifndef CONFIG_HACL
mask = crypto_bignum_init();
if (!sae->tmp->sae_rand)
sae->tmp->sae_rand = crypto_bignum_init();
if (!sae->tmp->own_commit_scalar)
sae->tmp->own_commit_scalar = crypto_bignum_init();
+#else
+ mask = crypto_bignum_static_init(32);
+ if (!sae->tmp->sae_rand)
+ sae->tmp->sae_rand = crypto_bignum_static_init(32);
+ if (!sae->tmp->own_commit_scalar)
+ sae->tmp->own_commit_scalar = crypto_bignum_static_init(32);
+#endif
ret = !mask || !sae->tmp->sae_rand || !sae->tmp->own_commit_scalar ||
dragonfly_generate_scalar(sae->tmp->order, sae->tmp->sae_rand,
mask,
sae->tmp->own_commit_scalar) < 0 ||
+#ifndef CONFIG_HACL
(sae->tmp->ec &&
sae_derive_commit_element_ecc(sae, mask) < 0) ||
(sae->tmp->dh &&
sae_derive_commit_element_ffc(sae, mask) < 0);
+#else
+ (sae->tmp->ec &&
+ sae_derive_commit_element_ecc(sae, mask) < 0);
+#endif
+
crypto_bignum_deinit(mask, 1);
return ret ? -1 : 0;
}
@@ -1346,11 +1455,17 @@ int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
const u8 *password, size_t password_len,
struct sae_data *sae)
{
+#ifndef CONFIG_HACL
if (sae->tmp == NULL ||
(sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
password_len) < 0) ||
(sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
password_len) < 0))
+#else
+ if (sae->tmp == NULL ||
+ (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
+ password_len) < 0))
+#endif
return -1;
sae->h2e = 0;
@@ -1406,6 +1521,7 @@ int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
return -1;
}
+#ifndef CONFIG_HACL
if (pt->dh) {
crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
sae->tmp->pwe_ffc = sae_derive_pwe_from_pt_ffc(pt, addr1,
@@ -1413,6 +1529,7 @@ int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
if (!sae->tmp->pwe_ffc)
return -1;
}
+#endif
sae->h2e = 1;
return sae_derive_commit(sae);
@@ -1455,6 +1572,7 @@ fail:
}
+#ifndef CONFIG_HACL
static int sae_derive_k_ffc(struct sae_data *sae, u8 *k)
{
struct crypto_bignum *K;
@@ -1491,6 +1609,7 @@ fail:
crypto_bignum_deinit(K, 1);
return ret;
}
+#endif
static int sae_kdf_hash(size_t hash_len, const u8 *k, const char *label,
@@ -1527,7 +1646,11 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k)
const u8 *addr[1];
size_t len[1];
+#ifndef CONFIG_HACL
tmp = crypto_bignum_init();
+#else
+ tmp = crypto_bignum_static_init(prime_len);
+#endif
if (tmp == NULL)
goto fail;
@@ -1541,8 +1664,10 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k)
*/
if (!sae->h2e)
hash_len = SHA256_MAC_LEN;
+#ifndef CONFIG_HACL
else if (sae->tmp->dh)
hash_len = sae_ffc_prime_len_2_hash_len(prime_len);
+#endif
else
hash_len = sae_ecc_prime_len_2_hash_len(prime_len);
if (sae->h2e && (sae->tmp->own_rejected_groups ||
@@ -1579,15 +1704,22 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k)
}
wpa_hexdump(MSG_DEBUG, "SAE: salt for keyseed derivation",
salt, salt_len);
+
addr[0] = k;
len[0] = prime_len;
if (hkdf_extract(hash_len, salt, salt_len, 1, addr, len, keyseed) < 0)
goto fail;
+
wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, hash_len);
+#ifndef CONFIG_HACL
if (crypto_bignum_add(sae->tmp->own_commit_scalar,
sae->peer_commit_scalar, tmp) < 0 ||
crypto_bignum_mod(tmp, sae->tmp->order, tmp) < 0)
+#else
+ if (crypto_bignum_addmod(sae->tmp->own_commit_scalar,
+ sae->peer_commit_scalar, sae->tmp->order, tmp) < 0)
+#endif
goto fail;
/* IEEE Std 802.11-2016 is not exactly clear on the encoding of the bit
* string that is needed for KCK, PMK, and PMKID derivation, but it
@@ -1632,6 +1764,7 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k)
}
#endif /* CONFIG_SAE_PK */
forced_memzero(keys, sizeof(keys));
+
wpa_hexdump_key(MSG_DEBUG, "SAE: KCK",
sae->tmp->kck, sae->tmp->kck_len);
wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN);
@@ -1649,7 +1782,9 @@ int sae_process_commit(struct sae_data *sae)
u8 k[SAE_MAX_PRIME_LEN];
if (sae->tmp == NULL ||
(sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) ||
+#ifndef CONFIG_HACL
(sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) ||
+#endif
sae_derive_keys(sae, k) < 0)
return -1;
return 0;
@@ -1670,22 +1805,28 @@ int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token",
wpabuf_head(token), wpabuf_len(token));
}
+
pos = wpabuf_put(buf, sae->tmp->prime_len);
+
if (crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
sae->tmp->prime_len, sae->tmp->prime_len) < 0)
return -1;
+
wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar",
pos, sae->tmp->prime_len);
+
if (sae->tmp->ec) {
pos = wpabuf_put(buf, 2 * sae->tmp->prime_len);
if (crypto_ec_point_to_bin(sae->tmp->ec,
sae->tmp->own_commit_element_ecc,
pos, pos + sae->tmp->prime_len) < 0)
return -1;
+
wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)",
pos, sae->tmp->prime_len);
wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)",
pos + sae->tmp->prime_len, sae->tmp->prime_len);
+#ifndef CONFIG_HACL
} else {
pos = wpabuf_put(buf, sae->tmp->prime_len);
if (crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos,
@@ -1694,6 +1835,7 @@ int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
return -1;
wpa_hexdump(MSG_DEBUG, "SAE: own commit-element",
pos, sae->tmp->prime_len);
+#endif
}
if (identifier) {
@@ -1762,11 +1904,13 @@ u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
+#ifndef CONFIG_HACL
if (sae->tmp->dh && !allowed_groups) {
wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without "
"explicit configuration enabling it", group);
return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
}
+#endif
return WLAN_STATUS_SUCCESS;
}
@@ -1830,6 +1974,7 @@ static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
}
wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
+
if (token)
*token = *pos;
if (token_len)
@@ -1844,10 +1989,12 @@ static void sae_parse_token_container(struct sae_data *sae,
{
wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
pos, end - pos);
+
if (!sae_is_token_container_elem(pos, end))
return;
*token = pos + 3;
*token_len = pos[1] - 1;
+
wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token (in container)",
*token, *token_len);
}
@@ -1863,7 +2010,11 @@ static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos,
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
+#ifndef CONFIG_HACL
peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len);
+#else
+ peer_scalar = crypto_bignum_static_init_set(*pos, sae->tmp->prime_len, sae->tmp->prime_len);
+#endif
if (peer_scalar == NULL)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -1894,8 +2045,10 @@ static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos,
crypto_bignum_deinit(sae->peer_commit_scalar, 0);
sae->peer_commit_scalar = peer_scalar;
+
wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar",
*pos, sae->tmp->prime_len);
+
*pos += sae->tmp->prime_len;
return WLAN_STATUS_SUCCESS;
@@ -1949,6 +2102,7 @@ static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 **pos,
}
+#ifndef CONFIG_HACL
static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 **pos,
const u8 *end)
{
@@ -1997,13 +2151,16 @@ static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 **pos,
return WLAN_STATUS_SUCCESS;
}
+#endif
static u16 sae_parse_commit_element(struct sae_data *sae, const u8 **pos,
const u8 *end)
{
+#ifndef CONFIG_HACL
if (sae->tmp->dh)
return sae_parse_commit_element_ffc(sae, pos, end);
+#endif
return sae_parse_commit_element_ecc(sae, pos, end);
}
@@ -2016,6 +2173,7 @@ static int sae_parse_password_identifier(struct sae_data *sae,
wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
*pos, end - *pos);
+
if (!sae_is_password_id_elem(*pos, end)) {
if (sae->tmp->pw_id) {
wpa_printf(MSG_DEBUG,
@@ -2066,6 +2224,7 @@ static int sae_parse_rejected_groups(struct sae_data *sae,
wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
*pos, end - *pos);
+
if (!sae_is_rejected_groups_elem(*pos, end))
return WLAN_STATUS_SUCCESS;
@@ -2140,10 +2299,12 @@ u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
if (!sae->tmp->own_commit_scalar ||
crypto_bignum_cmp(sae->tmp->own_commit_scalar,
sae->peer_commit_scalar) != 0 ||
+#ifndef CONFIG_HACL
(sae->tmp->dh &&
(!sae->tmp->own_commit_element_ffc ||
crypto_bignum_cmp(sae->tmp->own_commit_element_ffc,
sae->tmp->peer_commit_element_ffc) != 0)) ||
+#endif
(sae->tmp->ec &&
(!sae->tmp->own_commit_element_ecc ||
crypto_ec_point_cmp(sae->tmp->ec,
@@ -2222,6 +2383,7 @@ static int sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
}
+#ifndef CONFIG_HACL
static int sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
const struct crypto_bignum *scalar1,
const struct crypto_bignum *element1,
@@ -2242,13 +2404,14 @@ static int sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
return -1;
return 0;
}
+#endif
int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
{
const u8 *sc;
size_t hash_len;
- int res;
+ int res = -1;
if (sae->tmp == NULL)
return -1;
@@ -2267,12 +2430,14 @@ int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
sae->peer_commit_scalar,
sae->tmp->peer_commit_element_ecc,
wpabuf_put(buf, hash_len));
+#ifndef CONFIG_HACL
else
res = sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar,
sae->tmp->own_commit_element_ffc,
sae->peer_commit_scalar,
sae->tmp->peer_commit_element_ffc,
wpabuf_put(buf, hash_len));
+#endif
if (res)
return res;
@@ -2315,6 +2480,7 @@ int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
sae->tmp->own_commit_element_ecc,
verifier) < 0)
return -1;
+#ifndef CONFIG_HACL
} else {
if (!sae->tmp->peer_commit_element_ffc ||
!sae->tmp->own_commit_element_ffc ||
@@ -2324,14 +2490,17 @@ int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
sae->tmp->own_commit_element_ffc,
verifier) < 0)
return -1;
+#endif
}
if (os_memcmp_const(verifier, data + 2, hash_len) != 0) {
wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
+
wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
data + 2, hash_len);
wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
verifier, hash_len);
+
return -1;
}
@@ -532,6 +532,29 @@ struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len);
*/
struct crypto_bignum * crypto_bignum_init_uint(unsigned int val);
+/**
+ * crypto_bignum_static_init - Allocate memory for bignum
+ * Returns: Pointer to allocated bignum or %NULL on failure
+ */
+struct crypto_bignum* crypto_bignum_static_init(size_t len);
+
+/**
+ * crypto_bignum_static_init_set - Allocate memory for bignum and set the value
+ * @buf: Buffer with unsigned binary value - usually SECRET, but may be public in some cases
+ * @buflen: Length of buf in octets - usually PUBLIC
+ * @len: Length of the big number in bytes
+ * Returns: Pointer to allocated bignum or %NULL on failure - same as @buf
+ */
+struct crypto_bignum* crypto_bignum_static_init_set(const u8* buf, size_t buflen, size_t len);
+
+/**
+ * crypto_bignum_static_init_uint - Allocate memory for bignum and set the value
+ * @val: unsigned value - usually SECRET, but may be public in some cases
+ * @len: Length of the big number in bytes
+ * Returns: Pointer to allocated bignum or %NULL on failure - same as @val
+ */
+struct crypto_bignum* crypto_bignum_static_init_uint(unsigned int val, size_t len);
+
/**
* crypto_bignum_deinit - Free bignum
* @n: Bignum from crypto_bignum_init() or crypto_bignum_init_set()
@@ -539,6 +562,13 @@ struct crypto_bignum * crypto_bignum_init_uint(unsigned int val);
*/
void crypto_bignum_deinit(struct crypto_bignum *n, int clear);
+/**
+ * crypto_bignum_static_size - Return the size in bytes of a bignum
+ * @n: Bignum
+ * Returns: The size in bytes of the bignum in input
+ */
+size_t crypto_bignum_static_size(const struct crypto_bignum *n);
+
/**
* crypto_bignum_to_bin - Set binary buffer to unsigned bignum
* @a: Bignum
new file mode 100644
@@ -0,0 +1,1062 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <Hacl_HKDF.h>
+#include <Hacl_HMAC.h>
+#include <Hacl_Bignum256.h>
+#include <Hacl_Bignum.h>
+#include <Hacl_P256.h>
+#include <Lib_RandomBuffer_System.h>
+
+#include "common.h"
+#include "const_time.h"
+#include "crypto.h"
+
+#ifdef CONFIG_SHA256
+
+/* No HMAC_update mecanism exposed in HaCl, we need to expose one, or to allocate a new buffer and copy all the elements of addr into it before calling HMAC, which will induce an overhead... */
+int hmac_sha256_vector(const u8* key, size_t key_len, size_t num_elem,
+ const u8* addr[], const size_t* len, u8* mac)
+{
+ u8 *buf;
+ size_t buf_len = 0;
+ for (size_t i = 0; i < num_elem; i++)
+ buf_len += len[i];
+ buf = os_malloc(buf_len);
+ int offset = 0;
+ for (size_t i = 0; i < num_elem; i++) {
+ memcpy(buf + offset, addr[i], len[i]);
+ offset += len[i];
+ }
+
+ Hacl_HMAC_compute_sha2_256(mac, (u8*) key, key_len, buf, buf_len);
+
+ Lib_Memzero0_memzero(buf, buf_len);
+ os_free(buf);
+ return 1;
+}
+
+
+int hmac_sha256(const u8* key, size_t key_len, const u8* data,
+ size_t data_len, u8* mac)
+{
+ Hacl_HMAC_compute_sha2_256(mac, (u8*) key, key_len, (u8 *)data, data_len);
+ return 1;
+}
+
+#endif /* CONFIG_SHA256 */
+
+int crypto_get_random(void* buf, size_t len)
+{
+ // Loop until we read enough data, we might want to expose the inner function to avoid infinite loop, and return an error instead.
+ Lib_RandomBuffer_System_crypto_random(buf, len);
+ return 0;
+}
+
+
+struct bignum_static_methods {
+ Hacl_Bignum_MontArithmetic_bn_mont_ctx_u64* (*init_ctx)(u64* n);
+ void (*free_ctx)(Hacl_Bignum_MontArithmetic_bn_mont_ctx_u64*);
+ u64* (*new_bn_from_bytes)(u32, u8*);
+ void (*bn_to_bytes)(u64*, u8*);
+ u64(*add)(u64*, u64*, u64*);
+ u64(*sub)(u64*, u64*, u64*);
+ void (*mul)(u64*, u64*, u64*);
+ void (*sqr)(u64*, u64*);
+ bool (*mod)(u64*, u64*, u64*);
+ void (*mod_precomp)(Hacl_Bignum_MontArithmetic_bn_mont_ctx_u64*, u64*, u64*);
+ bool (*modexp_consttime)(u64*, u64*, u32, u64*, u64*);
+ void (*modexp_consttime_precomp)(Hacl_Bignum_MontArithmetic_bn_mont_ctx_u64*, u64*, u32, u64*, u64*);
+ bool (*modinv)(u64*, u64*, u64*);
+ void (*modinv_precomp)(Hacl_Bignum_MontArithmetic_bn_mont_ctx_u64*, u64*, u64*);
+ void (*add_mod)(u64*, u64*, u64*, u64*);
+ u64 (*is_lt)(u64*, u64*);
+ u64 (*is_eq)(u64*, u64*);
+};
+
+const static struct bignum_static_methods bignum_static_methods_256 =
+{
+ .init_ctx = Hacl_Bignum256_mont_ctx_init,
+ .free_ctx = Hacl_Bignum256_mont_ctx_free,
+ .new_bn_from_bytes = Hacl_Bignum256_new_bn_from_bytes_be,
+ .bn_to_bytes = Hacl_Bignum256_bn_to_bytes_be,
+ .add = Hacl_Bignum256_add,
+ .sub = Hacl_Bignum256_sub,
+ .mul = Hacl_Bignum256_mul,
+ .sqr = Hacl_Bignum256_sqr,
+ .mod = Hacl_Bignum256_mod,
+ .mod_precomp = Hacl_Bignum256_mod_precomp,
+ .modexp_consttime = Hacl_Bignum256_mod_exp_consttime,
+ .modexp_consttime_precomp = Hacl_Bignum256_mod_exp_consttime_precomp,
+ .modinv = Hacl_Bignum256_mod_inv_prime_vartime,
+ .modinv_precomp = Hacl_Bignum256_mod_inv_prime_vartime_precomp,
+ .add_mod = Hacl_Bignum256_add_mod,
+ .is_lt = Hacl_Bignum256_lt_mask,
+ .is_eq = Hacl_Bignum256_eq_mask,
+};
+
+
+struct crypto_bignum {
+ u64* data;
+ size_t data_size;
+ const struct bignum_static_methods* meth;
+ Hacl_Bignum_MontArithmetic_bn_mont_ctx_u64* ctx;
+};
+
+
+void crypto_bignum_print(char* label, const struct crypto_bignum* x) {
+ fprintf(stdout, "%s: ", label);
+ for (int i = (x->data_size >> 3) - 1; i >= 0; i--)
+ fprintf(stdout, "%016lX", x->data[i]);
+ fprintf(stdout, "\n");
+}
+
+
+struct crypto_bignum* crypto_bignum_static_init(size_t len)
+{
+ struct crypto_bignum* bn;
+
+ if (TEST_FAIL())
+ return NULL;
+
+ bn = os_zalloc(sizeof(*bn));
+ if(bn == NULL)
+ return NULL;
+
+ bn->data_size = len;
+ bn->data = os_zalloc(len);
+ if (bn->data == NULL) {
+ os_free(bn);
+ return NULL;
+ }
+
+ switch (len) {
+ case 32:
+ bn->meth = &bignum_static_methods_256;
+ break;
+ default:
+ // For now we do not have methods for other length
+ bn->meth = NULL;
+ break;
+ }
+ bn->ctx = NULL;
+
+ return bn;
+}
+
+
+struct crypto_bignum* crypto_bignum_static_init_set(const u8* buf, size_t buflen, size_t len)
+{
+ struct crypto_bignum* bn;
+ u8* tmp;
+
+ if (TEST_FAIL())
+ return NULL;
+
+ if (buflen > len)
+ return NULL;
+
+ bn = os_zalloc(sizeof(*bn));
+ if (bn == NULL)
+ return NULL;
+ bn->data_size = len;
+ switch (len) {
+ case 32:
+ bn->meth = &bignum_static_methods_256;
+ break;
+ default:
+ // For now we do not have methods for other length
+ bn->meth = NULL;
+ }
+
+ /* use a temporary buffer to ensure we deal with the right length */
+ if (buflen != len) {
+ tmp = os_zalloc(len);
+ memcpy(tmp + (len - buflen), buf, buflen);
+ }
+ else
+ tmp = (u8*) buf;
+
+ if (bn->meth)
+ bn->data = bn->meth->new_bn_from_bytes(len, tmp);
+ else
+ bn->data = Hacl_Bignum256_new_bn_from_bytes_be(len, tmp);
+ bn->ctx = NULL;
+
+ if (bn->data == NULL) {
+ free(bn);
+ bn = NULL;
+ goto end;
+ }
+
+
+end:
+ if (tmp != buf && tmp)
+ free(tmp);
+ return (struct crypto_bignum*) bn;
+}
+
+
+struct crypto_bignum* crypto_bignum_static_init_uint(unsigned int val, size_t len)
+{
+ struct crypto_bignum* bn;
+ u8 *buf = NULL;
+ buf = os_malloc(sizeof(val));
+ for (int i = sizeof(val)-1; i > -1; i--) {
+ buf[i] = (u8) val & 0xFF;
+ val >>= 8;
+ }
+
+ bn = crypto_bignum_static_init_set(buf, sizeof(val), len);
+
+ os_free(buf);
+ return bn;
+}
+
+
+void crypto_bignum_deinit(struct crypto_bignum* n, int clear)
+{
+ if (n == NULL)
+ return;
+ if (clear)
+ Lib_Memzero0_memzero((u8 *)n->data, n->data_size);
+ if (n->data)
+ os_free(n->data);
+ if (n->ctx)
+ n->meth->free_ctx(n->ctx);
+ os_free(n);
+}
+
+
+size_t crypto_bignum_static_size(const struct crypto_bignum* n)
+{
+ return n ? n->data_size : 0;
+}
+
+
+int crypto_bignum_to_bin(const struct crypto_bignum* a,
+ u8* buf, size_t buflen, size_t padlen)
+{
+ int offset;
+
+ if (TEST_FAIL())
+ return -1;
+
+ if (padlen > buflen || buflen < a->data_size)
+ return -1;
+ if (a->data_size > buflen)
+ return -1;
+
+ if (padlen > (size_t) a->data_size)
+ offset = padlen - a->data_size;
+ else
+ offset = 0;
+
+ memset(buf, 0, offset);
+ a->meth->bn_to_bytes((u64*) a->data, buf + offset);
+
+ return a->data_size + offset;
+}
+
+
+int crypto_bignum_rand(struct crypto_bignum* r, const struct crypto_bignum* m)
+{
+ if (TEST_FAIL())
+ return -1;
+
+ do {
+ crypto_get_random((u8 *)r->data, r->data_size);
+ } while (crypto_bignum_cmp(r, m) > 0);
+ return 0;
+}
+
+/* Carefull, this retruns the carry */
+int crypto_bignum_add(const struct crypto_bignum* a,
+ const struct crypto_bignum* b, struct crypto_bignum* c)
+{
+ if (a->data_size != b->data_size || b->data_size != c->data_size)
+ return -1;
+ /* carefull with the carry... */
+ return a->meth->add(a->data, b->data, c->data);
+}
+
+
+static inline void static_mod_even(const struct crypto_bignum* a,
+ const struct crypto_bignum* b, struct crypto_bignum* c)
+{
+ struct crypto_bignum* zero = crypto_bignum_static_init_uint(0, a->data_size);
+ crypto_bignum_addmod(a, zero, b, c);
+ crypto_bignum_deinit(zero, 0);
+}
+
+
+static inline void static_mod_odd(const struct crypto_bignum* a,
+ const struct crypto_bignum* b, struct crypto_bignum* c)
+{
+ u64* tmp;
+
+ // The operand should be twice the size of the modulus
+ if (a->data_size != 2 * b->data_size) {
+ tmp = os_zalloc(2 * b->data_size);
+ os_memcpy(tmp, a->data, a->data_size);
+ }
+ else
+ tmp = a->data;
+
+ if (b->ctx)
+ b->meth->mod_precomp(b->ctx, tmp, c->data);
+ else
+ b->meth->mod(b->data, tmp, c->data);
+
+ if (a->data_size != 2 * b->data_size)
+ os_free(tmp);
+}
+
+
+/* Not ct wrt the modulus (leaks its parity), we could do only ststic_mod_even though */
+int crypto_bignum_mod(const struct crypto_bignum* a,
+ const struct crypto_bignum* b, struct crypto_bignum* c)
+{
+ if (crypto_bignum_is_odd(b))
+ static_mod_odd(a, b, c);
+ else
+ static_mod_even(a, b, c);
+ return 0;
+}
+
+
+int crypto_bignum_exptmod(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ const struct crypto_bignum *c,
+ struct crypto_bignum *d)
+{
+ int res = 1;
+ if (c->ctx)
+ c->meth->modexp_consttime_precomp(c->ctx, a->data, 256, b->data, d->data);
+ else
+ res = a->meth->modexp_consttime(c->data, a->data, 256, b->data, d->data);
+ return res ? 0 : -1;
+}
+
+
+int crypto_bignum_inverse(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c)
+{
+ int res = 1;
+ if (b->ctx)
+ b->meth->modinv_precomp(b->ctx, a->data, c->data);
+ else
+ res = a->meth->modinv(b->data, a->data, c->data);
+ return res ? 0 : -1;
+}
+
+/* Carefull, this retruns the carry */
+int crypto_bignum_sub(const struct crypto_bignum* a, const struct crypto_bignum* b, struct crypto_bignum* c)
+{
+ if (TEST_FAIL())
+ return -1;
+
+ if (a->data_size != b->data_size || b->data_size != c->data_size)
+ return -1;
+ /* carefull with the carry... */
+ return a->meth->sub(a->data, b->data, c->data);
+}
+
+
+int crypto_bignum_addmod(const struct crypto_bignum* a,
+ const struct crypto_bignum* b,
+ const struct crypto_bignum* c,
+ struct crypto_bignum* d)
+{
+ if (TEST_FAIL())
+ return -1;
+
+ if (a->data_size != b->data_size || b->data_size != c->data_size || c->data_size != d->data_size)
+ return -1;
+ c->meth->add_mod(c->data, a->data, b->data, d->data);
+ return 0;
+}
+
+
+int crypto_bignum_mulmod(const struct crypto_bignum* a,
+ const struct crypto_bignum* b,
+ const struct crypto_bignum* c,
+ struct crypto_bignum* d)
+{
+ int success = 1;
+ struct crypto_bignum* tmp;
+
+ if (TEST_FAIL())
+ return -1;
+
+ if (a->data_size != b->data_size || b->data_size != c->data_size || c->data_size != d->data_size)
+ return -1;
+
+ tmp = crypto_bignum_static_init(a->data_size*2);
+ if (tmp == NULL)
+ return -1;
+
+ a->meth->mul(a->data, b->data, tmp->data);
+ if (c->ctx)
+ a->meth->mod_precomp(c->ctx, tmp->data, d->data);
+ else
+ success = a->meth->mod(c->data, tmp->data, d->data);
+
+ crypto_bignum_deinit(tmp, 1);
+ return success ? 0 : -1;
+}
+
+
+int crypto_bignum_sqrmod(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c)
+{
+ int success = 1;
+ struct crypto_bignum* tmp;
+
+ if (TEST_FAIL())
+ return -1;
+
+ if (a->data_size != b->data_size || b->data_size != c->data_size)
+ return -1;
+
+ tmp = crypto_bignum_static_init(a->data_size * 2);
+ if (tmp == NULL)
+ return -1;
+
+ b->meth->sqr(a->data, tmp->data);
+ if (b->ctx)
+ b->meth->mod_precomp(b->ctx, tmp->data, c->data);
+ else
+ success = b->meth->mod(b->data, tmp->data, c->data);
+
+ crypto_bignum_deinit(tmp, 1);
+ return success ? 0 : -1;
+}
+
+
+static int crypto_bignum_rshift1(const struct crypto_bignum* a, struct crypto_bignum* r) {
+ u64* ap, * rp, t, c;
+ int i;
+ u64 limb_size_2, limb_mask_2;
+
+ if (r == NULL)
+ r = crypto_bignum_static_init(a->data_size);
+
+ // if (crypto_bignum_is_zero(a)) {
+ // memset(r->data, 0, r->data_size);
+ // return 0;
+ // }
+ limb_size_2 = sizeof(a->data[0]) << 3;
+ limb_mask_2 = -1;
+
+ ap = a->data;
+ rp = r->data;
+ i = a->data_size >> 3;
+ t = ap[--i];
+ rp[i] = t >> 1;
+ c = t << (limb_size_2 - 1);
+
+ while (i > 0) {
+ t = ap[--i];
+ rp[i] = ((t >> 1) & limb_mask_2) | c;
+ c = t << (limb_size_2 - 1);
+ }
+
+ return 0;
+}
+
+int crypto_bignum_rshift(const struct crypto_bignum* a, int n, struct crypto_bignum* r) {
+ int err = 0;
+ for (size_t i = 0; i < n; i++)
+ err |= crypto_bignum_rshift1(a, r);
+ return err;
+}
+
+
+int crypto_bignum_cmp(const struct crypto_bignum* a,
+ const struct crypto_bignum* b)
+{
+ u64 is_lt, is_eq;
+ u64 res = 1;
+ u64 eq = 0, lt = -1;
+
+ is_lt = a->meth->is_lt(a->data, b->data);
+ is_eq = a->meth->is_eq(a->data, b->data);
+ res = (is_lt & lt) | (~is_lt & res);
+ res = (is_eq & eq) | (~is_eq & res);
+
+ return (int) res;
+}
+
+
+int crypto_bignum_is_zero(const struct crypto_bignum* a)
+{
+ int zero_limbs = 0;
+
+ if (a == NULL || a->data == NULL)
+ return -1;
+ zero_limbs = a->data[0] == 0;
+ for (int i = 1; i < a->data_size >> 3 ; i++)
+ zero_limbs += a->data[i] == 0;
+ return zero_limbs == a->data_size >> 3;
+}
+
+
+int crypto_bignum_is_one(const struct crypto_bignum* a)
+{
+ int valid_limbs = 0;
+
+ if (a == NULL || a->data == NULL)
+ return -1;
+ valid_limbs = a->data[0] == 1;
+ for (int i = 1; i < a->data_size >> 3; i++)
+ valid_limbs += a->data[i] == 0;
+ return valid_limbs == a->data_size >> 3;
+}
+
+
+// CHECK THIS FOR CORRECTNESS...
+int crypto_bignum_is_odd(const struct crypto_bignum* a)
+{
+ return (a->data)[0] & 1;
+}
+
+
+static const u64 one_bn256[4U] =
+{
+ 0x1U,
+ 0x0U,
+ 0x0U,
+ 0x0U
+};
+
+
+int crypto_bignum_legendre(const struct crypto_bignum* a,
+ const struct crypto_bignum* p)
+{
+ struct crypto_bignum* tmp = NULL, *exp = NULL;
+ int res = -2;
+ unsigned int mask;
+
+ if (TEST_FAIL())
+ return -2;
+
+ if (a->data_size != p->data_size)
+ goto fail;
+
+ exp = crypto_bignum_static_init(a->data_size);
+ if (exp == NULL)
+ goto fail;
+ tmp = crypto_bignum_static_init(a->data_size);
+ if (tmp == NULL)
+ goto fail;
+
+ if (a->meth->sub(p->data, (u64*)one_bn256, exp->data))
+ goto fail;
+ if (crypto_bignum_rshift1(exp, exp))
+ goto fail;
+
+ if (p->ctx)
+ a->meth->modexp_consttime_precomp(p->ctx, a->data, 256, exp->data, tmp->data);
+ else
+ if (!a->meth->modexp_consttime(p->data, a->data, 256, exp->data, tmp->data))
+ goto fail;
+
+ /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need to use
+ * constant time selection to avoid branches here. */
+ res = -1;
+ mask = const_time_eq(crypto_bignum_is_one(tmp), 1);
+ res = const_time_select_int(mask, 1, res);
+ mask = const_time_eq(crypto_bignum_is_zero(tmp), 1);
+ res = const_time_select_int(mask, 0, res);
+
+fail:
+ crypto_bignum_deinit(tmp, 1);
+ crypto_bignum_deinit(exp, 1);
+
+ return res;
+}
+
+#ifdef CONFIG_ECC
+
+/* P256 related constants */
+
+const u8 p256prime_bin[32U] =
+{
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+
+const u8 p256order_bin[32U] =
+{
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51
+};
+
+
+const u8 p256a_bin[32U] =
+{
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc
+};
+
+
+const u8 p256b_bin[32U] =
+{
+ 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b
+};
+
+
+struct ec_methods {
+ void(*point_to_bin)(u8*, u8*);
+ void(*add)(u64*, u64*, u64*);
+ u64(*scalar_mult)(u8*, u8*, u8*);
+ void(*point_inv)(u64*, u64*);
+ bool(*set_compressed_coordinates)(u8*, u8*); // FIXME : 2nd arg should be u64*
+ bool(*is_on_curve)(u8*); // FIXME: should take u64*
+ void (*jacobianToAffine)(u64* , u64*);
+ void (*affineToJacobian)(u64* , u64*);
+ void (*toBin)(u64* , u8*);
+ void (*fromBin)(u8* , u64*);
+};
+
+
+const static struct ec_methods p256_methods =
+{
+ .point_to_bin = Hacl_P256_compression_not_compressed_form_p256,
+ .add = Hacl_P256_point_add_out, // FIXME: input format is currently not indomain
+ .scalar_mult = Hacl_P256_ecp256dh_r_private_radix,
+ .point_inv = Hacl_P256_point_inv,
+ .set_compressed_coordinates = Hacl_P256_decompression_compressed_form_p256,
+ .is_on_curve = Hacl_P256_verify_q_private, //FIXME: currently take a u8...
+ .affineToJacobian = Hacl_P256_point_toDomain,
+ .jacobianToAffine = Hacl_P256_point_norm,
+ .toBin = Hacl_P256_point_fromForm,
+ .fromBin = Hacl_P256_point_toForm,
+};
+
+
+struct crypto_ec {
+ struct crypto_bignum* prime;
+ struct crypto_bignum* order;
+ struct crypto_bignum* a;
+ struct crypto_bignum* b;
+ const struct ec_methods* meth;
+};
+
+
+struct crypto_ec* crypto_ec_init(int group)
+{
+ struct crypto_ec* e;
+ e = os_malloc(sizeof(*e));
+ if (e == NULL)
+ return e;
+
+ switch (group) {
+ case 19:
+ e->prime = crypto_bignum_static_init_set(p256prime_bin, 32, 32);
+ e->prime->ctx = e->prime->meth->init_ctx(e->prime->data);
+ e->order = crypto_bignum_static_init_set(p256order_bin, 32, 32);
+ e->order->ctx = e->order->meth->init_ctx(e->order->data);
+ e->a = crypto_bignum_static_init_set(p256a_bin, 32, 32);
+ e->b = crypto_bignum_static_init_set(p256b_bin, 32, 32);
+ e->meth = &p256_methods;
+ break;
+ /* Only support P256 for now
+ case 20:
+ break;
+ case 21:
+ break;
+ case 25:
+ break;
+ case 26:
+ break;
+ case 27:
+ break;
+ #ifdef NID_brainpoolP256r1
+ case 28:
+ break;
+ case 29:
+ break;
+ case 30:
+ break;
+ */
+ default:
+ return NULL;
+ }
+ return e;
+}
+
+
+void crypto_ec_deinit(struct crypto_ec* e)
+{
+ if (e == NULL)
+ return;
+ crypto_bignum_deinit(e->order, 0);
+ crypto_bignum_deinit(e->prime, 0);
+ crypto_bignum_deinit(e->a, 0);
+ crypto_bignum_deinit(e->b, 0);
+ os_free(e);
+}
+
+
+struct crypto_ec_point {
+ u64 *data;
+ size_t size_bytes;
+ int in_domain;
+};
+
+
+struct crypto_ec_point* crypto_ec_point_init(struct crypto_ec *e)
+{
+ if (TEST_FAIL())
+ return NULL;
+ if (e == NULL)
+ return NULL;
+
+ struct crypto_ec_point *point;
+ point = os_malloc(sizeof(*point));
+ if (point == NULL)
+ return NULL;
+ point->in_domain = 0;
+ // store x, y, z in a row
+ point->size_bytes = 3 * e->prime->data_size;
+ point->data = os_zalloc(point->size_bytes);
+ if (point->data == NULL) {
+ os_free(point);
+ return NULL;
+ }
+ // set the third coordinate to 1
+ size_t pos_z = 2 * (point->size_bytes / (3 * sizeof(*point->data)));
+ point->data[pos_z] = 1U;
+
+ return point;
+}
+
+
+size_t crypto_ec_prime_len(struct crypto_ec *e)
+{
+ return e == NULL ? 0 : crypto_bignum_static_size(e->prime);
+}
+
+
+size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
+{
+ return e == NULL ? 0 : crypto_bignum_static_size(e->prime) << 3;
+}
+
+
+size_t crypto_ec_order_len(struct crypto_ec *e)
+{
+ return e == NULL ? 0 : crypto_bignum_static_size(e->order);
+}
+
+
+const struct crypto_bignum* crypto_ec_get_prime(struct crypto_ec *e)
+{
+ return e->prime;
+}
+
+
+const struct crypto_bignum* crypto_ec_get_order(struct crypto_ec *e)
+{
+ return e->order;
+}
+
+
+const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e)
+{
+ return (const struct crypto_bignum *) e->a;
+}
+
+
+const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e)
+{
+ return (const struct crypto_bignum *) e->b;
+}
+
+
+void crypto_ec_point_deinit(struct crypto_ec_point* p, int clear)
+{
+ if (p == NULL)
+ return;
+ if (p->data) {
+ if (clear)
+ Lib_Memzero0_memzero((u8 *) p->data, p->size_bytes);
+ os_free(p->data);
+ }
+ os_free(p);
+}
+
+
+/* x and y should already be allocated if we want their coordinate */
+int crypto_ec_point_to_bin(struct crypto_ec *e,
+ const struct crypto_ec_point* point, u8* x, u8* y)
+{
+ int ret = -1;
+ size_t len = crypto_ec_prime_len(e);
+ struct crypto_ec_point* q = (struct crypto_ec_point*) point;
+
+ if (TEST_FAIL())
+ return -1;
+
+ if (q->in_domain)
+ {
+ q = crypto_ec_point_init(e);
+ e->meth->jacobianToAffine(point->data, q->data);
+ }
+ u8* buf = os_malloc(2 * len);
+ if (buf == NULL) {
+ if (q != point && q) {
+ crypto_ec_point_deinit(q, 1);
+ }
+ return -1;
+ }
+ e->meth->toBin(q->data, buf);
+ //FIXME: shouldn't be needed...
+ u8 waste[112];
+ e->meth->toBin(q->data, waste);
+
+ if (x)
+ memcpy(x, buf, len);
+ if (y)
+ memcpy(y, buf+len, len);
+ ret = 0;
+
+ if (q != point && q) {
+ crypto_ec_point_deinit(q, 1);
+ }
+
+ Lib_Memzero0_memzero(buf, 2*len);
+ os_free(buf);
+
+ return ret;
+}
+
+
+struct crypto_ec_point* crypto_ec_point_from_bin(struct crypto_ec *e, const u8* val)
+{
+ struct crypto_ec_point* point = NULL;
+
+ if (TEST_FAIL())
+ return NULL;
+
+ point = crypto_ec_point_init(e);
+ if (point == NULL)
+ return NULL;
+ e->meth->fromBin((u8 *) val, point->data);
+
+ return point;
+}
+
+
+int crypto_ec_point_add(struct crypto_ec *e,
+ const struct crypto_ec_point* a, const struct crypto_ec_point* b,
+ struct crypto_ec_point* c)
+{
+ int ret = -1;
+ struct crypto_ec_point *p = (struct crypto_ec_point*) a;
+ struct crypto_ec_point* q = (struct crypto_ec_point*) b;
+
+ if (TEST_FAIL())
+ return -1;
+
+ if (!a->in_domain) {
+ p = crypto_ec_point_init(e);
+ e->meth->affineToJacobian(a->data, p->data);
+ p->in_domain = 1;
+ }
+ if (!b->in_domain) {
+ q = crypto_ec_point_init(e);
+ e->meth->affineToJacobian(b->data, q->data);
+ q->in_domain = 1;
+ }
+
+ e->meth->add(p->data, q->data, c->data);
+ c->in_domain = 1;
+
+ ret = 0;
+ if (p != a && p)
+ crypto_ec_point_deinit(p, 1);
+ if (q != b && q)
+ crypto_ec_point_deinit(q, 1);
+ return ret;
+}
+
+
+int crypto_ec_point_mul(struct crypto_ec *e,
+ const struct crypto_ec_point* p, const struct crypto_bignum* b,
+ struct crypto_ec_point* res)
+{
+ int ret = -1;
+ u8 *scalar;
+ u8* res_buf;
+ u8* point_buf;
+
+ if (TEST_FAIL())
+ return -1;
+
+ scalar = os_malloc(b->data_size);
+ res_buf = os_malloc(p->size_bytes);
+ point_buf = os_malloc(p->size_bytes);
+ if (scalar != NULL && p->data != NULL && res_buf != NULL && point_buf != NULL) {
+ // Convert our u64* point into unit8_t*
+ crypto_ec_point_to_bin(e, p, point_buf, point_buf + 32);
+ point_buf[p->size_bytes - 1] = 1U;
+ // Convert our bignum into u8
+ crypto_bignum_to_bin(b, scalar, b->data_size, b->data_size);
+
+ ret = e->meth->scalar_mult(res_buf, point_buf, scalar);
+ res->in_domain = 0;
+ e->meth->fromBin(res_buf, res->data);
+ int limb_size = (p->size_bytes / (3 * sizeof(*p->data)));
+ res->data[2*limb_size] = 1U;
+ }
+
+ if (scalar) os_free(scalar);
+ if (res_buf) os_free(res_buf);
+ if (point_buf) os_free(point_buf);
+
+ return ret == 1 ? 0 : -1;
+}
+
+
+int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point* p) {
+ int ret = -1;
+ // FIXME: Inplace inversion instead ? For now w zero out the result at the begining...
+ u64 *buf;
+
+ if (TEST_FAIL())
+ return -1;
+
+ buf = os_malloc(p->size_bytes);
+ if (buf == NULL)
+ return -1;
+ memcpy((u8*) buf, (u8*) p->data, p->size_bytes);
+ if (e != NULL && p != NULL && p->data != NULL) {
+ e->meth->point_inv(buf, p->data);
+ ret = 0;
+ }
+
+ Lib_Memzero0_memzero((u8*)buf, p->size_bytes);
+ os_free(buf);
+ return ret;
+}
+
+
+struct crypto_bignum* crypto_ec_point_compute_y_sqr(
+ struct crypto_ec *e, const struct crypto_bignum* x)
+{
+ struct crypto_bignum *ysqr;
+
+ if (TEST_FAIL())
+ return NULL;
+
+ ysqr = crypto_bignum_static_init(x->data_size);
+ if (ysqr == NULL)
+ return NULL;
+
+ // (x^2 + a)*x + b % p
+ crypto_bignum_sqrmod(x, e->prime, ysqr);
+ crypto_bignum_addmod(ysqr, e->a, e->prime, ysqr);
+ crypto_bignum_mulmod(ysqr, x, e->prime, ysqr);
+ crypto_bignum_addmod(ysqr, e->b, e->prime, ysqr);
+
+ return ysqr;
+}
+
+
+int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
+ const struct crypto_ec_point* p)
+{
+ u64 res = 0;
+ struct crypto_ec_point* q = (struct crypto_ec_point*) p;
+
+ if (p->in_domain) {
+ q = crypto_ec_point_init(e);
+ e->meth->jacobianToAffine(p->data, q->data);
+ q->in_domain = 0;
+ }
+ // Discard the check on Z coordinate
+ size_t pos_z = 2 * (q->size_bytes / (3 * sizeof(*q->data)));
+ for (size_t i = 0; i < pos_z; i++) {
+ res |= q->data[i] != 0;
+ }
+
+ if (q != p && q)
+ crypto_ec_point_deinit(q, 1);
+
+ return res == 0 ? 1 : 0;
+}
+
+
+// FIXME: u64 instead of u8
+int crypto_ec_point_is_on_curve(struct crypto_ec *e,
+ const struct crypto_ec_point* p)
+{
+ int ret = -1;
+ u64 *q = p->data;
+ u8* buf = os_malloc(p->size_bytes);
+ if (buf == NULL) {
+ os_free(q);
+ return -1;
+ }
+ if (p->in_domain) {
+ q = os_malloc(p->size_bytes);
+ if (q == NULL) {
+ os_free(buf);
+ return -1;
+ }
+ e->meth->jacobianToAffine(p->data, q);
+ }
+ e->meth->toBin(q, buf);
+ if (q == p->data) {
+ //FIXME: shouldn't be needed...
+ u8 waste[112];
+ e->meth->toBin(q, waste);
+ }
+ ret = e->meth->is_on_curve(buf) == 0 ? 0 : -1;
+ if (q != p->data && q) {
+ Lib_Memzero0_memzero((u8*) q, p->size_bytes);
+ os_free(q);
+ }
+ Lib_Memzero0_memzero((u8*) buf, p->size_bytes);
+ os_free(buf);
+ return ret;
+}
+
+
+int crypto_ec_point_cmp(const struct crypto_ec *e,
+ const struct crypto_ec_point* a, const struct crypto_ec_point* b)
+{
+ int ret = 0;
+ struct crypto_ec_point *p, *q;
+
+ if (a == NULL || b == NULL)
+ return -1;
+ p = (struct crypto_ec_point*) a;
+ q = (struct crypto_ec_point*) b;
+ if (p->in_domain != q->in_domain){
+ if (!a->in_domain) {
+ p = crypto_ec_point_init((struct crypto_ec *)e);
+ e->meth->affineToJacobian(a->data, p->data);
+ }
+ else {
+ q = crypto_ec_point_init((struct crypto_ec *)e);
+ e->meth->affineToJacobian(b->data, q->data);
+ }
+ }
+
+ for (int i = 0; i < a->size_bytes/sizeof(*(a->data)); i++)
+ ret |= p->data[i] != q->data[i];
+
+ if (p != a && p)
+ crypto_ec_point_deinit(p, 1);
+ if (q != b && q)
+ crypto_ec_point_deinit(q, 1);
+ return ret;
+}
+
+
+#endif /* CONFIG_ECC */
@@ -270,7 +270,13 @@ NEED_DH_GROUPS_ALL=y
endif
endif
-ifdef CONFIG_DPP
+ifeq ($(CONFIG_TLS), hacl)
+CONFIG_DPP=n
+CONFIG_DPP2=n
+CONFIG_DPP3=n
+endif
+
+ifeq ($(CONFIG_DPP), y)
CFLAGS += -DCONFIG_DPP
OBJS += ../src/common/dpp.o
OBJS += ../src/common/dpp_auth.o
@@ -291,10 +297,10 @@ NEED_JSON=y
NEED_GAS_SERVER=y
NEED_BASE64=y
NEED_ASN1=y
-ifdef CONFIG_DPP2
+ifeq ($(CONFIG_DPP2), y)
CFLAGS += -DCONFIG_DPP2
endif
-ifdef CONFIG_DPP3
+ifeq ($(CONFIG_DPP3), y)
CFLAGS += -DCONFIG_DPP3
endif
endif
@@ -974,7 +980,7 @@ CFLAGS += -DEAP_SERVER_WSC
OBJS += ../src/ap/wps_hostapd.o
OBJS += ../src/eap_server/eap_server_wsc.o
endif
-ifdef CONFIG_DPP
+ifeq ($(CONFIG_DPP), y)
OBJS += ../src/ap/dpp_hostapd.o
OBJS += ../src/ap/gas_query_ap.o
NEED_AP_GAS_SERV=y
@@ -1279,6 +1285,35 @@ OBJS += ../src/crypto/sha1-internal.o
endif
endif
+ifeq ($(CONFIG_TLS), hacl)
+ifdef TLS_FUNCS
+OBJS += ../src/crypto/tls_none.o
+CFLAGS += -DEAP_TLS_NONE
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD5=y
+endif
+
+CFLAGS += -DCONFIG_HACL
+
+CONFIG_CRYPTO=hacl
+OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
+OBJS_p += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
+HOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
+CFLAGS += -DCONFIG_CRYPTO_INTERNAL
+LIBS += -levercrypt
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_DES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD4=y
+CONFIG_INTERNAL_MD5=y
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_SHA384=y
+CONFIG_INTERNAL_SHA512=y
+CONFIG_INTERNAL_RC4=y
+CONFIG_INTERNAL_DH_GROUP5=y
+endif
+
ifeq ($(CONFIG_TLS), none)
ifdef TLS_FUNCS
OBJS += ../src/crypto/tls_none.o
@@ -1473,6 +1508,7 @@ endif
SHA256OBJS = # none by default
CFLAGS += -DCONFIG_SHA256
ifneq ($(CONFIG_TLS), openssl)
+ifneq ($(CONFIG_TLS), hacl)
ifneq ($(CONFIG_TLS), linux)
ifneq ($(CONFIG_TLS), gnutls)
ifneq ($(CONFIG_TLS), wolfssl)
@@ -1481,6 +1517,7 @@ endif
endif
endif
endif
+endif
SHA256OBJS += ../src/crypto/sha256-prf.o
ifdef CONFIG_INTERNAL_SHA256
SHA256OBJS += ../src/crypto/sha256-internal.o
@@ -1543,6 +1580,7 @@ ifdef NEED_ASN1
OBJS += ../src/tls/asn1.o
endif
+ifneq ($(CONFIG_TLS), hacl)
ifdef NEED_DH_GROUPS
OBJS += ../src/crypto/dh_groups.o
endif
@@ -1554,6 +1592,7 @@ ifdef NEED_DH_GROUPS
OBJS += ../src/crypto/dh_group5.o
endif
endif
+endif
ifdef NEED_ECC
CFLAGS += -DCONFIG_ECC
@@ -318,6 +318,7 @@ CONFIG_BACKEND=file
# gnutls = GnuTLS
# internal = Internal TLSv1 implementation (experimental)
# linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
+# hacl = cryptographic implementation for Dragonfly based on Hacl*(experimental)
# none = Empty template
#CONFIG_TLS=openssl
new file mode 100644
@@ -0,0 +1,636 @@
+# Example wpa_supplicant build time configuration
+#
+# This file lists the configuration options that are used when building the
+# wpa_supplicant binary. All lines starting with # are ignored. Configuration
+# option lines must be commented out complete, if they are not to be included,
+# i.e., just setting VARIABLE=n is not disabling that variable.
+#
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
+# be modified from here. In most cases, these lines should use += in order not
+# to override previous values of the variables.
+
+
+# Uncomment following two lines and fix the paths if you have installed OpenSSL
+# or GnuTLS in non-default location
+#CFLAGS += -I/usr/local/openssl/include
+#LIBS += -L/usr/local/openssl/lib
+
+# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
+# the kerberos files are not in the default include path. Following line can be
+# used to fix build issues on such systems (krb5.h not found).
+#CFLAGS += -I/usr/include/kerberos
+
+# Driver interface for generic Linux wireless extensions
+# Note: WEXT is deprecated in the current Linux kernel version and no new
+# functionality is added to it. nl80211-based interface is the new
+# replacement for WEXT and its use allows wpa_supplicant to properly control
+# the driver to improve existing functionality like roaming and to support new
+# functionality.
+CONFIG_DRIVER_WEXT=y
+
+# Driver interface for Linux drivers using the nl80211 kernel interface
+CONFIG_DRIVER_NL80211=y
+
+# QCA vendor extensions to nl80211
+#CONFIG_DRIVER_NL80211_QCA=y
+
+# driver_nl80211.c requires libnl. If you are compiling it yourself
+# you may need to point hostapd to your version of libnl.
+#
+#CFLAGS += -I$<path to libnl include files>
+#LIBS += -L$<path to libnl library files>
+
+# Use libnl v2.0 (or 3.0) libraries.
+#CONFIG_LIBNL20=y
+
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
+CONFIG_LIBNL32=y
+
+
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
+#CONFIG_DRIVER_BSD=y
+#CFLAGS += -I/usr/local/include
+#LIBS += -L/usr/local/lib
+#LIBS_p += -L/usr/local/lib
+#LIBS_c += -L/usr/local/lib
+
+# Driver interface for Windows NDIS
+#CONFIG_DRIVER_NDIS=y
+#CFLAGS += -I/usr/include/w32api/ddk
+#LIBS += -L/usr/local/lib
+# For native build using mingw
+#CONFIG_NATIVE_WINDOWS=y
+# Additional directories for cross-compilation on Linux host for mingw target
+#CFLAGS += -I/opt/mingw/mingw32/include/ddk
+#LIBS += -L/opt/mingw/mingw32/lib
+#CC=mingw32-gcc
+# By default, driver_ndis uses WinPcap for low-level operations. This can be
+# replaced with the following option which replaces WinPcap calls with NDISUIO.
+# However, this requires that WZC is disabled (net stop wzcsvc) before starting
+# wpa_supplicant.
+# CONFIG_USE_NDISUIO=y
+
+# Driver interface for wired Ethernet drivers
+CONFIG_DRIVER_WIRED=y
+
+# Driver interface for MACsec capable Qualcomm Atheros drivers
+#CONFIG_DRIVER_MACSEC_QCA=y
+
+# Driver interface for Linux MACsec drivers
+CONFIG_DRIVER_MACSEC_LINUX=y
+
+# Driver interface for the Broadcom RoboSwitch family
+#CONFIG_DRIVER_ROBOSWITCH=y
+
+# Driver interface for no driver (e.g., WPS ER only)
+#CONFIG_DRIVER_NONE=y
+
+# Solaris libraries
+#LIBS += -lsocket -ldlpi -lnsl
+#LIBS_c += -lsocket
+
+# Enable IEEE 802.1X Supplicant (automatically included if any EAP method or
+# MACsec is included)
+CONFIG_IEEE8021X_EAPOL=y
+
+# EAP-MD5
+CONFIG_EAP_MD5=y
+
+# EAP-MSCHAPv2
+CONFIG_EAP_MSCHAPV2=y
+
+# EAP-TLS
+CONFIG_EAP_TLS=y
+
+# EAL-PEAP
+CONFIG_EAP_PEAP=y
+
+# EAP-TTLS
+CONFIG_EAP_TTLS=y
+
+# EAP-FAST
+#CONFIG_EAP_FAST=y
+
+# EAP-TEAP
+# Note: The current EAP-TEAP implementation is experimental and should not be
+# enabled for production use. The IETF RFC 7170 that defines EAP-TEAP has number
+# of conflicting statements and missing details and the implementation has
+# vendor specific workarounds for those and as such, may not interoperate with
+# any other implementation. This should not be used for anything else than
+# experimentation and interoperability testing until those issues has been
+# resolved.
+#CONFIG_EAP_TEAP=y
+
+# EAP-GTC
+CONFIG_EAP_GTC=y
+
+# EAP-OTP
+CONFIG_EAP_OTP=y
+
+# EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used)
+#CONFIG_EAP_SIM=y
+
+# Enable SIM simulator (Milenage) for EAP-SIM
+#CONFIG_SIM_SIMULATOR=y
+
+# EAP-PSK (experimental; this is _not_ needed for WPA-PSK)
+#CONFIG_EAP_PSK=y
+
+# EAP-pwd (secure authentication using only a password)
+#CONFIG_EAP_PWD=y
+
+# EAP-PAX
+CONFIG_EAP_PAX=y
+
+# LEAP
+CONFIG_EAP_LEAP=y
+
+# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
+#CONFIG_EAP_AKA=y
+
+# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
+# This requires CONFIG_EAP_AKA to be enabled, too.
+#CONFIG_EAP_AKA_PRIME=y
+
+# Enable USIM simulator (Milenage) for EAP-AKA
+#CONFIG_USIM_SIMULATOR=y
+
+# EAP-SAKE
+CONFIG_EAP_SAKE=y
+
+# EAP-GPSK
+CONFIG_EAP_GPSK=y
+# Include support for optional SHA256 cipher suite in EAP-GPSK
+CONFIG_EAP_GPSK_SHA256=y
+
+# EAP-TNC and related Trusted Network Connect support (experimental)
+CONFIG_EAP_TNC=y
+
+# Wi-Fi Protected Setup (WPS)
+#CONFIG_WPS=y
+# Enable WPS external registrar functionality
+#CONFIG_WPS_ER=y
+# Disable credentials for an open network by default when acting as a WPS
+# registrar.
+#CONFIG_WPS_REG_DISABLE_OPEN=y
+# Enable WPS support with NFC config method
+#CONFIG_WPS_NFC=y
+
+# EAP-IKEv2
+#CONFIG_EAP_IKEV2=y
+
+# EAP-EKE
+#CONFIG_EAP_EKE=y
+
+# MACsec
+CONFIG_MACSEC=y
+
+# PKCS#12 (PFX) support (used to read private key and certificate file from
+# a file that usually has extension .p12 or .pfx)
+CONFIG_PKCS12=y
+
+# Smartcard support (i.e., private key on a smartcard), e.g., with openssl
+# engine.
+CONFIG_SMARTCARD=y
+
+# PC/SC interface for smartcards (USIM, GSM SIM)
+# Enable this if EAP-SIM or EAP-AKA is included
+#CONFIG_PCSC=y
+
+# Support HT overrides (disable HT/HT40, mask MCS rates, etc.)
+#CONFIG_HT_OVERRIDES=y
+
+# Support VHT overrides (disable VHT, mask MCS rates, etc.)
+#CONFIG_VHT_OVERRIDES=y
+
+# Development testing
+#CONFIG_EAPOL_TEST=y
+
+# Select control interface backend for external programs, e.g, wpa_cli:
+# unix = UNIX domain sockets (default for Linux/*BSD)
+# udp = UDP sockets using localhost (127.0.0.1)
+# udp6 = UDP IPv6 sockets using localhost (::1)
+# named_pipe = Windows Named Pipe (default for Windows)
+# udp-remote = UDP sockets with remote access (only for tests systems/purpose)
+# udp6-remote = UDP IPv6 sockets with remote access (only for tests purpose)
+# y = use default (backwards compatibility)
+# If this option is commented out, control interface is not included in the
+# build.
+CONFIG_CTRL_IFACE=y
+
+# Include support for GNU Readline and History Libraries in wpa_cli.
+# When building a wpa_cli binary for distribution, please note that these
+# libraries are licensed under GPL and as such, BSD license may not apply for
+# the resulting binary.
+#CONFIG_READLINE=y
+
+# Include internal line edit mode in wpa_cli. This can be used as a replacement
+# for GNU Readline to provide limited command line editing and history support.
+#CONFIG_WPA_CLI_EDIT=y
+
+# Remove debugging code that is printing out debug message to stdout.
+# This can be used to reduce the size of the wpa_supplicant considerably
+# if debugging code is not needed. The size reduction can be around 35%
+# (e.g., 90 kB).
+#CONFIG_NO_STDOUT_DEBUG=y
+
+# Remove WPA support, e.g., for wired-only IEEE 802.1X supplicant, to save
+# 35-50 kB in code size.
+#CONFIG_NO_WPA=y
+
+# Remove IEEE 802.11i/WPA-Personal ASCII passphrase support
+# This option can be used to reduce code size by removing support for
+# converting ASCII passphrases into PSK. If this functionality is removed, the
+# PSK can only be configured as the 64-octet hexstring (e.g., from
+# wpa_passphrase). This saves about 0.5 kB in code size.
+#CONFIG_NO_WPA_PASSPHRASE=y
+
+# Simultaneous Authentication of Equals (SAE), WPA3-Personal
+CONFIG_SAE=y
+
+# Disable scan result processing (ap_scan=1) to save code size by about 1 kB.
+# This can be used if ap_scan=1 mode is never enabled.
+#CONFIG_NO_SCAN_PROCESSING=y
+
+# Select configuration backend:
+# file = text file (e.g., wpa_supplicant.conf; note: the configuration file
+# path is given on command line, not here; this option is just used to
+# select the backend that allows configuration files to be used)
+# winreg = Windows registry (see win_example.reg for an example)
+CONFIG_BACKEND=file
+
+# Remove configuration write functionality (i.e., to allow the configuration
+# file to be updated based on runtime configuration changes). The runtime
+# configuration can still be changed, the changes are just not going to be
+# persistent over restarts. This option can be used to reduce code size by
+# about 3.5 kB.
+#CONFIG_NO_CONFIG_WRITE=y
+
+# Remove support for configuration blobs to reduce code size by about 1.5 kB.
+#CONFIG_NO_CONFIG_BLOBS=y
+
+# Select program entry point implementation:
+# main = UNIX/POSIX like main() function (default)
+# main_winsvc = Windows service (read parameters from registry)
+# main_none = Very basic example (development use only)
+#CONFIG_MAIN=main
+
+# Select wrapper for operating system and C library specific functions
+# unix = UNIX/POSIX like systems (default)
+# win32 = Windows systems
+# none = Empty template
+#CONFIG_OS=unix
+
+# Select event loop implementation
+# eloop = select() loop (default)
+# eloop_win = Windows events and WaitForMultipleObject() loop
+#CONFIG_ELOOP=eloop
+
+# Should we use poll instead of select? Select is used by default.
+#CONFIG_ELOOP_POLL=y
+
+# Should we use epoll instead of select? Select is used by default.
+#CONFIG_ELOOP_EPOLL=y
+
+# Should we use kqueue instead of select? Select is used by default.
+#CONFIG_ELOOP_KQUEUE=y
+
+# Select layer 2 packet implementation
+# linux = Linux packet socket (default)
+# pcap = libpcap/libdnet/WinPcap
+# freebsd = FreeBSD libpcap
+# winpcap = WinPcap with receive thread
+# ndis = Windows NDISUIO (note: requires CONFIG_USE_NDISUIO=y)
+# none = Empty template
+#CONFIG_L2_PACKET=linux
+
+# Disable Linux packet socket workaround applicable for station interface
+# in a bridge for EAPOL frames. This should be uncommented only if the kernel
+# is known to not have the regression issue in packet socket behavior with
+# bridge interfaces (commit 'bridge: respect RFC2863 operational state')').
+#CONFIG_NO_LINUX_PACKET_SOCKET_WAR=y
+
+# Support Operating Channel Validation
+#CONFIG_OCV=y
+
+# Select TLS implementation
+# openssl = OpenSSL (default)
+# gnutls = GnuTLS
+# internal = Internal TLSv1 implementation (experimental)
+# linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
+# hacl = cryptographic implementation for Dragonfly based on Hacl*(experimental)
+# none = Empty template
+CONFIG_TLS=hacl
+
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
+# can be enabled to get a stronger construction of messages when block ciphers
+# are used. It should be noted that some existing TLS v1.0 -based
+# implementation may not be compatible with TLS v1.1 message (ClientHello is
+# sent prior to negotiating which version will be used)
+#CONFIG_TLSV11=y
+
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
+# can be enabled to enable use of stronger crypto algorithms. It should be
+# noted that some existing TLS v1.0 -based implementation may not be compatible
+# with TLS v1.2 message (ClientHello is sent prior to negotiating which version
+# will be used)
+#CONFIG_TLSV12=y
+
+# Select which ciphers to use by default with OpenSSL if the user does not
+# specify them.
+#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
+
+# If CONFIG_TLS=internal is used, additional library and include paths are
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
+# and drawbacks of this option.
+#CONFIG_INTERNAL_LIBTOMMATH=y
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
+#LTM_PATH=/usr/src/libtommath-0.39
+#CFLAGS += -I$(LTM_PATH)
+#LIBS += -L$(LTM_PATH)
+#LIBS_p += -L$(LTM_PATH)
+#endif
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
+# can be configured to include faster routines for exptmod, sqr, and div to
+# speed up DH and RSA calculation considerably
+#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
+
+# Include NDIS event processing through WMI into wpa_supplicant/wpasvc.
+# This is only for Windows builds and requires WMI-related header files and
+# WbemUuid.Lib from Platform SDK even when building with MinGW.
+#CONFIG_NDIS_EVENTS_INTEGRATED=y
+#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
+
+# Add support for new DBus control interface
+# (fi.w1.wpa_supplicant1)
+CONFIG_CTRL_IFACE_DBUS_NEW=y
+
+# Add introspection support for new DBus control interface
+CONFIG_CTRL_IFACE_DBUS_INTRO=y
+
+# Add support for loading EAP methods dynamically as shared libraries.
+# When this option is enabled, each EAP method can be either included
+# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).
+# Dynamic EAP methods are build as shared objects (eap_*.so) and they need to
+# be loaded in the beginning of the wpa_supplicant configuration file
+# (see load_dynamic_eap parameter in the example file) before being used in
+# the network blocks.
+#
+# Note that some shared parts of EAP methods are included in the main program
+# and in order to be able to use dynamic EAP methods using these parts, the
+# main program must have been build with the EAP method enabled (=y or =dyn).
+# This means that EAP-TLS/PEAP/TTLS/FAST cannot be added as dynamic libraries
+# unless at least one of them was included in the main build to force inclusion
+# of the shared code. Similarly, at least one of EAP-SIM/AKA must be included
+# in the main build to be able to load these methods dynamically.
+#
+# Please also note that using dynamic libraries will increase the total binary
+# size. Thus, it may not be the best option for targets that have limited
+# amount of memory/flash.
+#CONFIG_DYNAMIC_EAP_METHODS=y
+
+# IEEE Std 802.11r-2008 (Fast BSS Transition) for station mode
+CONFIG_IEEE80211R=y
+
+# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt)
+CONFIG_DEBUG_FILE=y
+
+# Send debug messages to syslog instead of stdout
+CONFIG_DEBUG_SYSLOG=y
+# Set syslog facility for debug messages
+#CONFIG_DEBUG_SYSLOG_FACILITY=LOG_DAEMON
+
+# Add support for sending all debug messages (regardless of debug verbosity)
+# to the Linux kernel tracing facility. This helps debug the entire stack by
+# making it easy to record everything happening from the driver up into the
+# same file, e.g., using trace-cmd.
+#CONFIG_DEBUG_LINUX_TRACING=y
+
+# Add support for writing debug log to Android logcat instead of standard
+# output
+#CONFIG_ANDROID_LOG=y
+
+# Enable privilege separation (see README 'Privilege separation' for details)
+#CONFIG_PRIVSEP=y
+
+# Enable mitigation against certain attacks against TKIP by delaying Michael
+# MIC error reports by a random amount of time between 0 and 60 seconds
+#CONFIG_DELAYED_MIC_ERROR_REPORT=y
+
+# Enable tracing code for developer debugging
+# This tracks use of memory allocations and other registrations and reports
+# incorrect use with a backtrace of call (or allocation) location.
+#CONFIG_WPA_TRACE=y
+# For BSD, uncomment these.
+#LIBS += -lexecinfo
+#LIBS_p += -lexecinfo
+#LIBS_c += -lexecinfo
+
+# Use libbfd to get more details for developer debugging
+# This enables use of libbfd to get more detailed symbols for the backtraces
+# generated by CONFIG_WPA_TRACE=y.
+#CONFIG_WPA_TRACE_BFD=y
+# For BSD, uncomment these.
+#LIBS += -lbfd -liberty -lz
+#LIBS_p += -lbfd -liberty -lz
+#LIBS_c += -lbfd -liberty -lz
+
+# wpa_supplicant depends on strong random number generation being available
+# from the operating system. os_get_random() function is used to fetch random
+# data when needed, e.g., for key generation. On Linux and BSD systems, this
+# works by reading /dev/urandom. It should be noted that the OS entropy pool
+# needs to be properly initialized before wpa_supplicant is started. This is
+# important especially on embedded devices that do not have a hardware random
+# number generator and may by default start up with minimal entropy available
+# for random number generation.
+#
+# As a safety net, wpa_supplicant is by default trying to internally collect
+# additional entropy for generating random data to mix in with the data fetched
+# from the OS. This by itself is not considered to be very strong, but it may
+# help in cases where the system pool is not initialized properly. However, it
+# is very strongly recommended that the system pool is initialized with enough
+# entropy either by using hardware assisted random number generator or by
+# storing state over device reboots.
+#
+# wpa_supplicant can be configured to maintain its own entropy store over
+# restarts to enhance random number generation. This is not perfect, but it is
+# much more secure than using the same sequence of random numbers after every
+# reboot. This can be enabled with -e<entropy file> command line option. The
+# specified file needs to be readable and writable by wpa_supplicant.
+#
+# If the os_get_random() is known to provide strong random data (e.g., on
+# Linux/BSD, the board in question is known to have reliable source of random
+# data from /dev/urandom), the internal wpa_supplicant random pool can be
+# disabled. This will save some in binary size and CPU use. However, this
+# should only be considered for builds that are known to be used on devices
+# that meet the requirements described above.
+#CONFIG_NO_RANDOM_POOL=y
+
+# Should we attempt to use the getrandom(2) call that provides more reliable
+# yet secure randomness source than /dev/random on Linux 3.17 and newer.
+# Requires glibc 2.25 to build, falls back to /dev/random if unavailable.
+#CONFIG_GETRANDOM=y
+
+# IEEE 802.11ac (Very High Throughput) support (mainly for AP mode)
+CONFIG_IEEE80211AC=y
+
+# Wireless Network Management (IEEE Std 802.11v-2011)
+# Note: This is experimental and not complete implementation.
+#CONFIG_WNM=y
+
+# Interworking (IEEE 802.11u)
+# This can be used to enable functionality to improve interworking with
+# external networks (GAS/ANQP to learn more about the networks and network
+# selection based on available credentials).
+CONFIG_INTERWORKING=y
+
+# Hotspot 2.0
+CONFIG_HS20=y
+
+# Enable interface matching in wpa_supplicant
+#CONFIG_MATCH_IFACE=y
+
+# Disable roaming in wpa_supplicant
+#CONFIG_NO_ROAMING=y
+
+# AP mode operations with wpa_supplicant
+# This can be used for controlling AP mode operations with wpa_supplicant. It
+# should be noted that this is mainly aimed at simple cases like
+# WPA2-Personal while more complex configurations like WPA2-Enterprise with an
+# external RADIUS server can be supported with hostapd.
+CONFIG_AP=y
+
+# P2P (Wi-Fi Direct)
+# This can be used to enable P2P support in wpa_supplicant. See README-P2P for
+# more information on P2P operations.
+#CONFIG_P2P=y
+
+# Enable TDLS support
+CONFIG_TDLS=y
+
+# Wi-Fi Display
+# This can be used to enable Wi-Fi Display extensions for P2P using an external
+# program to control the additional information exchanges in the messages.
+CONFIG_WIFI_DISPLAY=y
+
+# Autoscan
+# This can be used to enable automatic scan support in wpa_supplicant.
+# See wpa_supplicant.conf for more information on autoscan usage.
+#
+# Enabling directly a module will enable autoscan support.
+# For exponential module:
+#CONFIG_AUTOSCAN_EXPONENTIAL=y
+# For periodic module:
+#CONFIG_AUTOSCAN_PERIODIC=y
+
+# Password (and passphrase, etc.) backend for external storage
+# These optional mechanisms can be used to add support for storing passwords
+# and other secrets in external (to wpa_supplicant) location. This allows, for
+# example, operating system specific key storage to be used
+#
+# External password backend for testing purposes (developer use)
+#CONFIG_EXT_PASSWORD_TEST=y
+# File-based backend to read passwords from an external file.
+#CONFIG_EXT_PASSWORD_FILE=y
+
+# Enable Fast Session Transfer (FST)
+#CONFIG_FST=y
+
+# Enable CLI commands for FST testing
+#CONFIG_FST_TEST=y
+
+# OS X builds. This is only for building eapol_test.
+#CONFIG_OSX=y
+
+# Automatic Channel Selection
+# This will allow wpa_supplicant to pick the channel automatically when channel
+# is set to "0".
+#
+# TODO: Extend parser to be able to parse "channel=acs_survey" as an alternative
+# to "channel=0". This would enable us to eventually add other ACS algorithms in
+# similar way.
+#
+# Automatic selection is currently only done through initialization, later on
+# we hope to do background checks to keep us moving to more ideal channels as
+# time goes by. ACS is currently only supported through the nl80211 driver and
+# your driver must have survey dump capability that is filled by the driver
+# during scanning.
+#
+# TODO: In analogy to hostapd be able to customize the ACS survey algorithm with
+# a newly to create wpa_supplicant.conf variable acs_num_scans.
+#
+# Supported ACS drivers:
+# * ath9k
+# * ath5k
+# * ath10k
+#
+# For more details refer to:
+# http://wireless.kernel.org/en/users/Documentation/acs
+#CONFIG_ACS=y
+
+# Support Multi Band Operation
+#CONFIG_MBO=y
+
+# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
+#CONFIG_FILS=y
+# FILS shared key authentication with PFS
+#CONFIG_FILS_SK_PFS=y
+
+# Support RSN on IBSS networks
+# This is needed to be able to use mode=1 network profile with proto=RSN and
+# key_mgmt=WPA-PSK (i.e., full key management instead of WPA-None).
+CONFIG_IBSS_RSN=y
+
+# External PMKSA cache control
+# This can be used to enable control interface commands that allow the current
+# PMKSA cache entries to be fetched and new entries to be added.
+#CONFIG_PMKSA_CACHE_EXTERNAL=y
+
+# Mesh Networking (IEEE 802.11s)
+#CONFIG_MESH=y
+
+# Background scanning modules
+# These can be used to request wpa_supplicant to perform background scanning
+# operations for roaming within an ESS (same SSID). See the bgscan parameter in
+# the wpa_supplicant.conf file for more details.
+# Periodic background scans based on signal strength
+CONFIG_BGSCAN_SIMPLE=y
+# Learn channels used by the network and try to avoid bgscans on other
+# channels (experimental)
+#CONFIG_BGSCAN_LEARN=y
+
+# Opportunistic Wireless Encryption (OWE)
+# Experimental implementation of draft-harkins-owe-07.txt
+#CONFIG_OWE=y
+
+# Device Provisioning Protocol (DPP) (also known as Wi-Fi Easy Connect)
+CONFIG_DPP=y
+# DPP version 2 support
+CONFIG_DPP2=y
+# DPP version 3 support (experimental and still changing; do not enable for
+# production use)
+#CONFIG_DPP3=y
+
+# Wired equivalent privacy (WEP)
+# WEP is an obsolete cryptographic data confidentiality algorithm that is not
+# considered secure. It should not be used for anything anymore. The
+# functionality needed to use WEP is available in the current wpa_supplicant
+# release under this optional build parameter. This functionality is subject to
+# be completely removed in a future release.
+#CONFIG_WEP=y
+
+# Remove all TKIP functionality
+# TKIP is an old cryptographic data confidentiality algorithm that is not
+# considered secure. It should not be used anymore for anything else than a
+# backwards compatibility option as a group cipher when connecting to APs that
+# use WPA+WPA2 mixed mode. For now, the default wpa_supplicant build includes
+# support for this by default, but that functionality is subject to be removed
+# in the future.
+#CONFIG_NO_TKIP=y
+
+# Pre-Association Security Negotiation (PASN)
+# Experimental implementation based on IEEE P802.11z/D2.6 and the protocol
+# design is still subject to change. As such, this should not yet be enabled in
+# production use.
+#CONFIG_PASN=y