diff mbox series

Adding support for formally verified crypto provider

Message ID 20230123103230.20885-1-daniel.de-almeida-braga@irisa.fr
State New
Headers show
Series Adding support for formally verified crypto provider | expand

Commit Message

daniel.de-almeida-braga@irisa.fr Jan. 23, 2023, 10:32 a.m. UTC
From: Alexandre Sanchez <alexandre.sanchez@inria.fr>

Hostap relies on existing crypto libraries to perform various tasks. Unfortunately,
and despite all the efforts to keep them secure, different bugs continue to plague
these crypto libraries. This patch implements the support for a formally verified
cryptographic library (HaCl*), to benefit from its security properties on the
cryptographic layer. This includes memory safety and functional correctness. In
addition, Hostap, and more precisely WPA3, has been recently the target of some
side channels attacks (e.g., dragonblood). HaCl* formally guarantees secret
independence, namely no branching or memory access on secrets to avoid side-channel
leakage.

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.

We added the appropriate options in config files and Makefiles. We also provide
a simple tester (nonregression testing) in hostap/dragonstar/.

Please note that HACL* does not only offer formally verified security, but also
provides decent efficiency. It outperforms OpenSSL noasm. However, it is slower
when assembly code leveraging specialized CPU instructions is used.
An archive for the proper version of HaCl* is available at the following link,
with the according installation instructions:
https://ddealmei.github.io/assets/files/hacl_installer.zip

Tha patch is based on the last release from hostap (hostap_2_10).

Signed-off-by: Daniel De Almeida Braga <ddealmei.0@gmail.com>
Signed-off-by: Mohamed Sabt <mohamed.sabt@irisa.fr>
Signed-off-by: Alexandre Sanchez <alexandre.sanchez@inria.fr>
---
 dragonstar/.gitignore            |    2 +
 dragonstar/Makefile              |  159 +++++
 dragonstar/README.md             |   93 +++
 dragonstar/defconfig             |  412 ++++++++++++
 dragonstar/dragonstar.c          |  168 +++++
 hostapd/Makefile                 |   44 +-
 hostapd/defconfig                |    1 +
 src/common/common_module_tests.c |   46 ++
 src/common/dragonfly.c           |   35 +-
 src/common/sae.c                 |  175 ++++-
 src/crypto/crypto.h              |   30 +
 src/crypto/crypto_hacl.c         | 1062 ++++++++++++++++++++++++++++++
 wpa_supplicant/Makefile          |   47 +-
 wpa_supplicant/defconfig         |    1 +
 wpa_supplicant/dragonstarconfig  |  636 ++++++++++++++++++
 15 files changed, 2900 insertions(+), 11 deletions(-)
 create mode 100644 dragonstar/.gitignore
 create mode 100644 dragonstar/Makefile
 create mode 100644 dragonstar/README.md
 create mode 100644 dragonstar/defconfig
 create mode 100644 dragonstar/dragonstar.c
 create mode 100644 src/crypto/crypto_hacl.c
 create mode 100644 wpa_supplicant/dragonstarconfig
diff mbox series

Patch

diff --git a/dragonstar/.gitignore b/dragonstar/.gitignore
new file mode 100644
index 000000000..305ba5e6f
--- /dev/null
+++ b/dragonstar/.gitignore
@@ -0,0 +1,2 @@ 
+bin
+.config
\ No newline at end of file
diff --git a/dragonstar/Makefile b/dragonstar/Makefile
new file mode 100644
index 000000000..4f3462adc
--- /dev/null
+++ b/dragonstar/Makefile
@@ -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
diff --git a/dragonstar/README.md b/dragonstar/README.md
new file mode 100644
index 000000000..d699a8c0b
--- /dev/null
+++ b/dragonstar/README.md
@@ -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>
diff --git a/dragonstar/defconfig b/dragonstar/defconfig
new file mode 100644
index 000000000..6b50b6c59
--- /dev/null
+++ b/dragonstar/defconfig
@@ -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
diff --git a/dragonstar/dragonstar.c b/dragonstar/dragonstar.c
new file mode 100644
index 000000000..4cb6de105
--- /dev/null
+++ b/dragonstar/dragonstar.c
@@ -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;
+}
diff --git a/hostapd/Makefile b/hostapd/Makefile
index e37c13b27..ec124ebf0 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -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
diff --git a/hostapd/defconfig b/hostapd/defconfig
index 6b50b6c59..1ca0700c2 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -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
 
diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c
index 8aba713f9..95a67f62d 100644
--- a/src/common/common_module_tests.c
+++ b/src/common/common_module_tests.c
@@ -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;
 }
diff --git a/src/common/dragonfly.c b/src/common/dragonfly.c
index 1e8427166..daa240237 100644
--- a/src/common/dragonfly.c
+++ b/src/common/dragonfly.c
@@ -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 ||
diff --git a/src/common/sae.c b/src/common/sae.c
index c0f154e91..b919d966a 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -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;
 	}
 
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index e6150b0cf..6a1d48cc1 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -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
diff --git a/src/crypto/crypto_hacl.c b/src/crypto/crypto_hacl.c
new file mode 100644
index 000000000..516718f2b
--- /dev/null
+++ b/src/crypto/crypto_hacl.c
@@ -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 */
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index cb66defac..ed38ee1b9 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -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
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index a4719dbb5..e65aa3a93 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -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
 
diff --git a/wpa_supplicant/dragonstarconfig b/wpa_supplicant/dragonstarconfig
new file mode 100644
index 000000000..b37251019
--- /dev/null
+++ b/wpa_supplicant/dragonstarconfig
@@ -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