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
