mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
wpa_supplicant: Port dpp feature from supplicant
Add files required for DPP feature from upstream. These file expose the functionality to create DPP packets. Ported crypto layer from openssl to mbedtls. Interfacing to use these API will be added in seperate commit
This commit is contained in:
parent
d85d3d969f
commit
ab784bb53a
@ -5,6 +5,10 @@ set(srcs "port/os_xtensa.c"
|
||||
"src/ap/wpa_auth_ie.c"
|
||||
"src/common/sae.c"
|
||||
"src/common/wpa_common.c"
|
||||
"src/common/dpp.c"
|
||||
"src/crypto/aes-ctr.c"
|
||||
"src/crypto/aes-siv.c"
|
||||
"src/crypto/sha256-kdf.c"
|
||||
"src/crypto/aes-cbc.c"
|
||||
"src/crypto/aes-ccm.c"
|
||||
"src/crypto/aes-internal-dec.c"
|
||||
@ -17,7 +21,8 @@ set(srcs "port/os_xtensa.c"
|
||||
"src/crypto/sha256-tlsprf.c"
|
||||
"src/crypto/bignum.c"
|
||||
"src/crypto/ccmp.c"
|
||||
"src/crypto/crypto_mbedtls.c"
|
||||
"src/crypto/crypto_mbedtls-bignum.c"
|
||||
"src/crypto/crypto_mbedtls-ec.c"
|
||||
"src/crypto/crypto_ops.c"
|
||||
"src/crypto/crypto_internal-cipher.c"
|
||||
"src/crypto/crypto_internal-modexp.c"
|
||||
@ -78,6 +83,7 @@ set(srcs "port/os_xtensa.c"
|
||||
"src/utils/uuid.c"
|
||||
"src/utils/wpabuf.c"
|
||||
"src/utils/wpa_debug.c"
|
||||
"src/utils/json.c"
|
||||
"src/wps/wps.c"
|
||||
"src/wps/wps_attr_build.c"
|
||||
"src/wps/wps_attr_parse.c"
|
||||
@ -114,4 +120,5 @@ target_compile_definitions(${COMPONENT_LIB} PRIVATE
|
||||
CONFIG_WPA3_SAE
|
||||
CONFIG_TLSV12
|
||||
CONFIG_SHA256
|
||||
CONFIG_DPP
|
||||
)
|
||||
|
@ -17,4 +17,11 @@ menu "Supplicant"
|
||||
Enabling this could increase the build size ~60kb
|
||||
depending on the project logging level.
|
||||
|
||||
config WPA_TESTING_OPTIONS
|
||||
bool "Add DPP testing code"
|
||||
default n
|
||||
help
|
||||
Select this to enable unity test for DPP.
|
||||
|
||||
|
||||
endmenu
|
||||
|
@ -2,4 +2,4 @@ COMPONENT_ADD_INCLUDEDIRS := include port/include include/esp_supplicant
|
||||
COMPONENT_PRIV_INCLUDEDIRS := src
|
||||
COMPONENT_SRCDIRS := port src/ap src/common src/crypto src/eap_peer src/rsn_supp src/tls src/utils src/esp_supplicant src/wps
|
||||
|
||||
CFLAGS += -DCONFIG_WPA3_SAE -DCONFIG_IEEE80211W -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing
|
||||
CFLAGS += -DCONFIG_DPP -DCONFIG_WPA3_SAE -DCONFIG_IEEE80211W -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing
|
||||
|
@ -38,7 +38,7 @@ void wpabuf_free(struct wpabuf *buf);
|
||||
void * wpabuf_put(struct wpabuf *buf, size_t len);
|
||||
struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b);
|
||||
struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len);
|
||||
void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) PRINTF_FORMAT(2, 3);
|
||||
void wpabuf_printf(struct wpabuf *buf, const char *fmt, ...) PRINTF_FORMAT(2, 3);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -35,6 +35,15 @@ struct os_time {
|
||||
suseconds_t usec;
|
||||
};
|
||||
|
||||
struct os_tm {
|
||||
int sec; /* 0..59 or 60 for leap seconds */
|
||||
int min; /* 0..59 */
|
||||
int hour; /* 0..23 */
|
||||
int day; /* 1..31 */
|
||||
int month; /* 1..12 */
|
||||
int year; /* Four digit year */
|
||||
};
|
||||
|
||||
/**
|
||||
* os_get_time - Get current time (sec, usec)
|
||||
* @t: Pointer to buffer for the time
|
||||
@ -76,6 +85,7 @@ int os_get_time(struct os_time *t);
|
||||
int os_mktime(int year, int month, int day, int hour, int min, int sec,
|
||||
os_time_t *t);
|
||||
|
||||
int os_gmtime(os_time_t t, struct os_tm *tm);
|
||||
|
||||
/**
|
||||
* os_daemonize - Run in the background (detach from the controlling terminal)
|
||||
@ -293,7 +303,4 @@ static inline int os_snprintf_error(size_t size, int res)
|
||||
* This function matches in behavior with the strlcpy(3) function in OpenBSD.
|
||||
*/
|
||||
size_t os_strlcpy(char *dest, const char *src, size_t siz);
|
||||
|
||||
|
||||
|
||||
#endif /* OS_H */
|
||||
|
6398
components/wpa_supplicant/src/common/dpp.c
Normal file
6398
components/wpa_supplicant/src/common/dpp.c
Normal file
File diff suppressed because it is too large
Load Diff
594
components/wpa_supplicant/src/common/dpp.h
Normal file
594
components/wpa_supplicant/src/common/dpp.h
Normal file
@ -0,0 +1,594 @@
|
||||
/*
|
||||
* DPP functionality shared between hostapd and wpa_supplicant
|
||||
* Copyright (c) 2017, Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef DPP_H
|
||||
#define DPP_H
|
||||
|
||||
#ifdef CONFIG_DPP
|
||||
|
||||
#include "utils/list.h"
|
||||
#include "common/wpa_common.h"
|
||||
#include "crypto/sha256.h"
|
||||
|
||||
struct crypto_ecdh;
|
||||
struct hostapd_ip_addr;
|
||||
struct dpp_global;
|
||||
|
||||
#define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */
|
||||
#define DPP_TCP_PORT 7871
|
||||
#define SSID_MAX_LEN 32
|
||||
#define PMKID_LEN 16
|
||||
#define PMK_LEN 32
|
||||
#define PMK_LEN_SUITE_B_192 48
|
||||
#define PMK_LEN_MAX 64
|
||||
|
||||
/* DPP events */
|
||||
#define DPP_EVENT_AUTH_SUCCESS "DPP-AUTH-SUCCESS "
|
||||
#define DPP_EVENT_AUTH_INIT_FAILED "DPP-AUTH-INIT-FAILED "
|
||||
#define DPP_EVENT_NOT_COMPATIBLE "DPP-NOT-COMPATIBLE "
|
||||
#define DPP_EVENT_RESPONSE_PENDING "DPP-RESPONSE-PENDING "
|
||||
#define DPP_EVENT_SCAN_PEER_QR_CODE "DPP-SCAN-PEER-QR-CODE "
|
||||
#define DPP_EVENT_AUTH_DIRECTION "DPP-AUTH-DIRECTION "
|
||||
#define DPP_EVENT_CONF_RECEIVED "DPP-CONF-RECEIVED "
|
||||
#define DPP_EVENT_CONF_SENT "DPP-CONF-SENT "
|
||||
#define DPP_EVENT_CONF_FAILED "DPP-CONF-FAILED "
|
||||
#define DPP_EVENT_CONN_STATUS_RESULT "DPP-CONN-STATUS-RESULT "
|
||||
#define DPP_EVENT_CONFOBJ_AKM "DPP-CONFOBJ-AKM "
|
||||
#define DPP_EVENT_CONFOBJ_SSID "DPP-CONFOBJ-SSID "
|
||||
#define DPP_EVENT_CONFOBJ_SSID_CHARSET "DPP-CONFOBJ-SSID-CHARSET "
|
||||
#define DPP_EVENT_CONFOBJ_PASS "DPP-CONFOBJ-PASS "
|
||||
#define DPP_EVENT_CONFOBJ_PSK "DPP-CONFOBJ-PSK "
|
||||
#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR "
|
||||
#define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY "
|
||||
#define DPP_EVENT_NET_ACCESS_KEY "DPP-NET-ACCESS-KEY "
|
||||
#define DPP_EVENT_MISSING_CONNECTOR "DPP-MISSING-CONNECTOR "
|
||||
#define DPP_EVENT_NETWORK_ID "DPP-NETWORK-ID "
|
||||
#define DPP_EVENT_RX "DPP-RX "
|
||||
#define DPP_EVENT_TX "DPP-TX "
|
||||
#define DPP_EVENT_TX_STATUS "DPP-TX-STATUS "
|
||||
#define DPP_EVENT_FAIL "DPP-FAIL "
|
||||
#define DPP_EVENT_PKEX_T_LIMIT "DPP-PKEX-T-LIMIT "
|
||||
#define DPP_EVENT_INTRO "DPP-INTRO "
|
||||
#define DPP_EVENT_CONF_REQ_RX "DPP-CONF-REQ-RX "
|
||||
|
||||
|
||||
#define WLAN_ACTION_PUBLIC 4
|
||||
#define WLAN_PA_VENDOR_SPECIFIC 9
|
||||
#define OUI_WFA 0x506f9a
|
||||
#define DPP_OUI_TYPE 0x1A
|
||||
|
||||
#define WLAN_EID_ADV_PROTO 108
|
||||
#define WLAN_EID_VENDOR_SPECIFIC 221
|
||||
|
||||
#define WLAN_PA_GAS_INITIAL_REQ 10
|
||||
|
||||
enum dpp_public_action_frame_type {
|
||||
DPP_PA_AUTHENTICATION_REQ = 0,
|
||||
DPP_PA_AUTHENTICATION_RESP = 1,
|
||||
DPP_PA_AUTHENTICATION_CONF = 2,
|
||||
DPP_PA_PEER_DISCOVERY_REQ = 5,
|
||||
DPP_PA_PEER_DISCOVERY_RESP = 6,
|
||||
DPP_PA_PKEX_EXCHANGE_REQ = 7,
|
||||
DPP_PA_PKEX_EXCHANGE_RESP = 8,
|
||||
DPP_PA_PKEX_COMMIT_REVEAL_REQ = 9,
|
||||
DPP_PA_PKEX_COMMIT_REVEAL_RESP = 10,
|
||||
DPP_PA_CONFIGURATION_RESULT = 11,
|
||||
DPP_PA_CONNECTION_STATUS_RESULT = 12,
|
||||
};
|
||||
|
||||
enum dpp_attribute_id {
|
||||
DPP_ATTR_STATUS = 0x1000,
|
||||
DPP_ATTR_I_BOOTSTRAP_KEY_HASH = 0x1001,
|
||||
DPP_ATTR_R_BOOTSTRAP_KEY_HASH = 0x1002,
|
||||
DPP_ATTR_I_PROTOCOL_KEY = 0x1003,
|
||||
DPP_ATTR_WRAPPED_DATA = 0x1004,
|
||||
DPP_ATTR_I_NONCE = 0x1005,
|
||||
DPP_ATTR_I_CAPABILITIES = 0x1006,
|
||||
DPP_ATTR_R_NONCE = 0x1007,
|
||||
DPP_ATTR_R_CAPABILITIES = 0x1008,
|
||||
DPP_ATTR_R_PROTOCOL_KEY = 0x1009,
|
||||
DPP_ATTR_I_AUTH_TAG = 0x100A,
|
||||
DPP_ATTR_R_AUTH_TAG = 0x100B,
|
||||
DPP_ATTR_CONFIG_OBJ = 0x100C,
|
||||
DPP_ATTR_CONNECTOR = 0x100D,
|
||||
DPP_ATTR_CONFIG_ATTR_OBJ = 0x100E,
|
||||
DPP_ATTR_BOOTSTRAP_KEY = 0x100F,
|
||||
DPP_ATTR_OWN_NET_NK_HASH = 0x1011,
|
||||
DPP_ATTR_FINITE_CYCLIC_GROUP = 0x1012,
|
||||
DPP_ATTR_ENCRYPTED_KEY = 0x1013,
|
||||
DPP_ATTR_ENROLLEE_NONCE = 0x1014,
|
||||
DPP_ATTR_CODE_IDENTIFIER = 0x1015,
|
||||
DPP_ATTR_TRANSACTION_ID = 0x1016,
|
||||
DPP_ATTR_BOOTSTRAP_INFO = 0x1017,
|
||||
DPP_ATTR_CHANNEL = 0x1018,
|
||||
DPP_ATTR_PROTOCOL_VERSION = 0x1019,
|
||||
DPP_ATTR_ENVELOPED_DATA = 0x101A,
|
||||
DPP_ATTR_SEND_CONN_STATUS = 0x101B,
|
||||
DPP_ATTR_CONN_STATUS = 0x101C,
|
||||
};
|
||||
|
||||
enum dpp_status_error {
|
||||
DPP_STATUS_OK = 0,
|
||||
DPP_STATUS_NOT_COMPATIBLE = 1,
|
||||
DPP_STATUS_AUTH_FAILURE = 2,
|
||||
DPP_STATUS_UNWRAP_FAILURE = 3,
|
||||
DPP_STATUS_BAD_GROUP = 4,
|
||||
DPP_STATUS_CONFIGURE_FAILURE = 5,
|
||||
DPP_STATUS_RESPONSE_PENDING = 6,
|
||||
DPP_STATUS_INVALID_CONNECTOR = 7,
|
||||
DPP_STATUS_NO_MATCH = 8,
|
||||
DPP_STATUS_CONFIG_REJECTED = 9,
|
||||
DPP_STATUS_NO_AP = 10,
|
||||
};
|
||||
|
||||
#define DPP_CAPAB_ENROLLEE BIT(0)
|
||||
#define DPP_CAPAB_CONFIGURATOR BIT(1)
|
||||
#define DPP_CAPAB_ROLE_MASK (BIT(0) | BIT(1))
|
||||
|
||||
#define DPP_BOOTSTRAP_MAX_FREQ 30
|
||||
#define DPP_MAX_NONCE_LEN 32
|
||||
#define DPP_MAX_HASH_LEN 64
|
||||
#define DPP_MAX_SHARED_SECRET_LEN 66
|
||||
|
||||
struct dpp_curve_params {
|
||||
const char *name;
|
||||
size_t hash_len;
|
||||
size_t aes_siv_key_len;
|
||||
size_t nonce_len;
|
||||
size_t prime_len;
|
||||
const char *jwk_crv;
|
||||
u16 ike_group;
|
||||
const char *jws_alg;
|
||||
};
|
||||
|
||||
enum dpp_bootstrap_type {
|
||||
DPP_BOOTSTRAP_QR_CODE,
|
||||
DPP_BOOTSTRAP_PKEX,
|
||||
DPP_BOOTSTRAP_NFC_URI,
|
||||
};
|
||||
|
||||
struct dpp_bootstrap_info {
|
||||
struct dl_list list;
|
||||
unsigned int id;
|
||||
enum dpp_bootstrap_type type;
|
||||
char *uri;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
char *info;
|
||||
unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ];
|
||||
unsigned int num_freq;
|
||||
int own;
|
||||
struct crypto_key *pubkey;
|
||||
u8 pubkey_hash[SHA256_MAC_LEN];
|
||||
const struct dpp_curve_params *curve;
|
||||
unsigned int pkex_t; /* number of failures before dpp_pkex
|
||||
* instantiation */
|
||||
};
|
||||
|
||||
#define PKEX_COUNTER_T_LIMIT 5
|
||||
|
||||
struct dpp_pkex {
|
||||
void *msg_ctx;
|
||||
unsigned int initiator:1;
|
||||
unsigned int exchange_done:1;
|
||||
unsigned int failed:1;
|
||||
struct dpp_bootstrap_info *own_bi;
|
||||
u8 own_mac[ETH_ALEN];
|
||||
u8 peer_mac[ETH_ALEN];
|
||||
char *identifier;
|
||||
char *code;
|
||||
struct crypto_key *x;
|
||||
struct crypto_key *y;
|
||||
u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
|
||||
u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
|
||||
u8 z[DPP_MAX_HASH_LEN];
|
||||
struct crypto_key *peer_bootstrap_key;
|
||||
struct wpabuf *exchange_req;
|
||||
struct wpabuf *exchange_resp;
|
||||
unsigned int t; /* number of failures on code use */
|
||||
unsigned int exch_req_wait_time;
|
||||
unsigned int exch_req_tries;
|
||||
unsigned int freq;
|
||||
};
|
||||
|
||||
enum dpp_akm {
|
||||
DPP_AKM_UNKNOWN,
|
||||
DPP_AKM_DPP,
|
||||
DPP_AKM_PSK,
|
||||
DPP_AKM_SAE,
|
||||
DPP_AKM_PSK_SAE,
|
||||
DPP_AKM_SAE_DPP,
|
||||
DPP_AKM_PSK_SAE_DPP,
|
||||
};
|
||||
|
||||
enum dpp_netrole {
|
||||
DPP_NETROLE_STA,
|
||||
DPP_NETROLE_AP,
|
||||
DPP_NETROLE_CONFIGURATOR,
|
||||
};
|
||||
|
||||
struct dpp_configuration {
|
||||
u8 ssid[32];
|
||||
size_t ssid_len;
|
||||
int ssid_charset;
|
||||
enum dpp_akm akm;
|
||||
enum dpp_netrole netrole;
|
||||
|
||||
/* For DPP configuration (connector) */
|
||||
os_time_t netaccesskey_expiry;
|
||||
|
||||
/* TODO: groups */
|
||||
char *group_id;
|
||||
|
||||
/* For legacy configuration */
|
||||
char *passphrase;
|
||||
u8 psk[32];
|
||||
int psk_set;
|
||||
};
|
||||
|
||||
#define DPP_MAX_CONF_OBJ 10
|
||||
|
||||
struct dpp_authentication {
|
||||
void *msg_ctx;
|
||||
u8 peer_version;
|
||||
const struct dpp_curve_params *curve;
|
||||
struct dpp_bootstrap_info *peer_bi;
|
||||
struct dpp_bootstrap_info *own_bi;
|
||||
struct dpp_bootstrap_info *tmp_own_bi;
|
||||
u8 waiting_pubkey_hash[SHA256_MAC_LEN];
|
||||
int response_pending;
|
||||
enum dpp_status_error auth_resp_status;
|
||||
enum dpp_status_error conf_resp_status;
|
||||
u8 peer_mac_addr[ETH_ALEN];
|
||||
u8 i_nonce[DPP_MAX_NONCE_LEN];
|
||||
u8 r_nonce[DPP_MAX_NONCE_LEN];
|
||||
u8 e_nonce[DPP_MAX_NONCE_LEN];
|
||||
u8 i_capab;
|
||||
u8 r_capab;
|
||||
struct crypto_key *own_protocol_key;
|
||||
struct crypto_key *peer_protocol_key;
|
||||
struct wpabuf *req_msg;
|
||||
struct wpabuf *resp_msg;
|
||||
/* Intersection of possible frequencies for initiating DPP
|
||||
* Authentication exchange */
|
||||
unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ];
|
||||
unsigned int num_freq, freq_idx;
|
||||
unsigned int curr_freq;
|
||||
unsigned int neg_freq;
|
||||
unsigned int num_freq_iters;
|
||||
size_t secret_len;
|
||||
u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
|
||||
size_t Mx_len;
|
||||
u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
|
||||
size_t Nx_len;
|
||||
u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
|
||||
size_t Lx_len;
|
||||
u8 k1[DPP_MAX_HASH_LEN];
|
||||
u8 k2[DPP_MAX_HASH_LEN];
|
||||
u8 ke[DPP_MAX_HASH_LEN];
|
||||
int initiator;
|
||||
int waiting_auth_resp;
|
||||
int waiting_auth_conf;
|
||||
int auth_req_ack;
|
||||
unsigned int auth_resp_tries;
|
||||
u8 allowed_roles;
|
||||
int configurator;
|
||||
int remove_on_tx_status;
|
||||
int connect_on_tx_status;
|
||||
int waiting_conf_result;
|
||||
int waiting_conn_status_result;
|
||||
int auth_success;
|
||||
struct wpabuf *conf_req;
|
||||
const struct wpabuf *conf_resp; /* owned by GAS server */
|
||||
struct dpp_configuration *conf_ap;
|
||||
struct dpp_configuration *conf2_ap;
|
||||
struct dpp_configuration *conf_sta;
|
||||
struct dpp_configuration *conf2_sta;
|
||||
struct dpp_configurator *conf;
|
||||
struct dpp_config_obj {
|
||||
char *connector; /* received signedConnector */
|
||||
u8 ssid[SSID_MAX_LEN];
|
||||
u8 ssid_len;
|
||||
int ssid_charset;
|
||||
char passphrase[64];
|
||||
u8 psk[PMK_LEN];
|
||||
int psk_set;
|
||||
enum dpp_akm akm;
|
||||
struct wpabuf *c_sign_key;
|
||||
} conf_obj[DPP_MAX_CONF_OBJ];
|
||||
unsigned int num_conf_obj;
|
||||
struct wpabuf *net_access_key;
|
||||
os_time_t net_access_key_expiry;
|
||||
int send_conn_status;
|
||||
int conn_status_requested;
|
||||
int akm_use_selector;
|
||||
#ifdef CONFIG_WPA_TESTING_OPTIONS
|
||||
char *config_obj_override;
|
||||
char *discovery_override;
|
||||
char *groups_override;
|
||||
unsigned int ignore_netaccesskey_mismatch:1;
|
||||
#endif /* CONFIG_WPA_TESTING_OPTIONS */
|
||||
};
|
||||
|
||||
struct dpp_configurator {
|
||||
struct dl_list list;
|
||||
unsigned int id;
|
||||
int own;
|
||||
struct crypto_key *csign;
|
||||
char *kid;
|
||||
const struct dpp_curve_params *curve;
|
||||
};
|
||||
|
||||
struct dpp_introduction {
|
||||
u8 pmkid[PMKID_LEN];
|
||||
u8 pmk[PMK_LEN_MAX];
|
||||
size_t pmk_len;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_WPA_TESTING_OPTIONS
|
||||
enum dpp_test_behavior {
|
||||
DPP_TEST_DISABLED = 0,
|
||||
DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ = 1,
|
||||
DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP = 2,
|
||||
DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF = 3,
|
||||
DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ = 4,
|
||||
DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP = 5,
|
||||
DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ = 6,
|
||||
DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP = 7,
|
||||
DPP_TEST_ZERO_I_CAPAB = 8,
|
||||
DPP_TEST_ZERO_R_CAPAB = 9,
|
||||
DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_REQ = 10,
|
||||
DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_REQ = 11,
|
||||
DPP_TEST_NO_I_PROTO_KEY_AUTH_REQ = 12,
|
||||
DPP_TEST_NO_I_NONCE_AUTH_REQ = 13,
|
||||
DPP_TEST_NO_I_CAPAB_AUTH_REQ = 14,
|
||||
DPP_TEST_NO_WRAPPED_DATA_AUTH_REQ = 15,
|
||||
DPP_TEST_NO_STATUS_AUTH_RESP = 16,
|
||||
DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP = 17,
|
||||
DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP = 18,
|
||||
DPP_TEST_NO_R_PROTO_KEY_AUTH_RESP = 19,
|
||||
DPP_TEST_NO_R_NONCE_AUTH_RESP = 20,
|
||||
DPP_TEST_NO_I_NONCE_AUTH_RESP = 21,
|
||||
DPP_TEST_NO_R_CAPAB_AUTH_RESP = 22,
|
||||
DPP_TEST_NO_R_AUTH_AUTH_RESP = 23,
|
||||
DPP_TEST_NO_WRAPPED_DATA_AUTH_RESP = 24,
|
||||
DPP_TEST_NO_STATUS_AUTH_CONF = 25,
|
||||
DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_CONF = 26,
|
||||
DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_CONF = 27,
|
||||
DPP_TEST_NO_I_AUTH_AUTH_CONF = 28,
|
||||
DPP_TEST_NO_WRAPPED_DATA_AUTH_CONF = 29,
|
||||
DPP_TEST_I_NONCE_MISMATCH_AUTH_RESP = 30,
|
||||
DPP_TEST_INCOMPATIBLE_R_CAPAB_AUTH_RESP = 31,
|
||||
DPP_TEST_R_AUTH_MISMATCH_AUTH_RESP = 32,
|
||||
DPP_TEST_I_AUTH_MISMATCH_AUTH_CONF = 33,
|
||||
DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ = 34,
|
||||
DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ = 35,
|
||||
DPP_TEST_NO_STATUS_PKEX_EXCHANGE_RESP = 36,
|
||||
DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP = 37,
|
||||
DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_REQ = 38,
|
||||
DPP_TEST_NO_I_AUTH_TAG_PKEX_CR_REQ = 39,
|
||||
DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_REQ = 40,
|
||||
DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_RESP = 41,
|
||||
DPP_TEST_NO_R_AUTH_TAG_PKEX_CR_RESP = 42,
|
||||
DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_RESP = 43,
|
||||
DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ = 44,
|
||||
DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP = 45,
|
||||
DPP_TEST_INVALID_STATUS_PKEX_EXCHANGE_RESP = 46,
|
||||
DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_REQ = 47,
|
||||
DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_RESP = 48,
|
||||
DPP_TEST_I_AUTH_TAG_MISMATCH_PKEX_CR_REQ = 49,
|
||||
DPP_TEST_R_AUTH_TAG_MISMATCH_PKEX_CR_RESP = 50,
|
||||
DPP_TEST_NO_E_NONCE_CONF_REQ = 51,
|
||||
DPP_TEST_NO_CONFIG_ATTR_OBJ_CONF_REQ = 52,
|
||||
DPP_TEST_NO_WRAPPED_DATA_CONF_REQ = 53,
|
||||
DPP_TEST_NO_E_NONCE_CONF_RESP = 54,
|
||||
DPP_TEST_NO_CONFIG_OBJ_CONF_RESP = 55,
|
||||
DPP_TEST_NO_STATUS_CONF_RESP = 56,
|
||||
DPP_TEST_NO_WRAPPED_DATA_CONF_RESP = 57,
|
||||
DPP_TEST_INVALID_STATUS_CONF_RESP = 58,
|
||||
DPP_TEST_E_NONCE_MISMATCH_CONF_RESP = 59,
|
||||
DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ = 60,
|
||||
DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ = 61,
|
||||
DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP = 62,
|
||||
DPP_TEST_NO_STATUS_PEER_DISC_RESP = 63,
|
||||
DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP = 64,
|
||||
DPP_TEST_AUTH_RESP_IN_PLACE_OF_CONF = 65,
|
||||
DPP_TEST_INVALID_I_PROTO_KEY_AUTH_REQ = 66,
|
||||
DPP_TEST_INVALID_R_PROTO_KEY_AUTH_RESP = 67,
|
||||
DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_REQ = 68,
|
||||
DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_REQ = 69,
|
||||
DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP = 70,
|
||||
DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP = 71,
|
||||
DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_CONF = 72,
|
||||
DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_CONF = 73,
|
||||
DPP_TEST_INVALID_STATUS_AUTH_RESP = 74,
|
||||
DPP_TEST_INVALID_STATUS_AUTH_CONF = 75,
|
||||
DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ = 76,
|
||||
DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP = 77,
|
||||
DPP_TEST_INVALID_STATUS_PEER_DISC_RESP = 78,
|
||||
DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP = 79,
|
||||
DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ = 80,
|
||||
DPP_TEST_INVALID_I_NONCE_AUTH_REQ = 81,
|
||||
DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ = 82,
|
||||
DPP_TEST_INVALID_E_NONCE_CONF_REQ = 83,
|
||||
DPP_TEST_STOP_AT_PKEX_EXCHANGE_RESP = 84,
|
||||
DPP_TEST_STOP_AT_PKEX_CR_REQ = 85,
|
||||
DPP_TEST_STOP_AT_PKEX_CR_RESP = 86,
|
||||
DPP_TEST_STOP_AT_AUTH_REQ = 87,
|
||||
DPP_TEST_STOP_AT_AUTH_RESP = 88,
|
||||
DPP_TEST_STOP_AT_AUTH_CONF = 89,
|
||||
DPP_TEST_STOP_AT_CONF_REQ = 90,
|
||||
DPP_TEST_REJECT_CONFIG = 91,
|
||||
};
|
||||
|
||||
extern enum dpp_test_behavior dpp_test;
|
||||
extern u8 dpp_pkex_own_mac_override[ETH_ALEN];
|
||||
extern u8 dpp_pkex_peer_mac_override[ETH_ALEN];
|
||||
extern u8 dpp_pkex_ephemeral_key_override[600];
|
||||
extern size_t dpp_pkex_ephemeral_key_override_len;
|
||||
extern u8 dpp_protocol_key_override[600];
|
||||
extern size_t dpp_protocol_key_override_len;
|
||||
extern u8 dpp_nonce_override[DPP_MAX_NONCE_LEN];
|
||||
extern size_t dpp_nonce_override_len;
|
||||
#endif /* CONFIG_WPA_TESTING_OPTIONS */
|
||||
|
||||
void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info);
|
||||
const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type);
|
||||
int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi);
|
||||
int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
|
||||
const char *chan_list);
|
||||
int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac);
|
||||
int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info);
|
||||
char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
|
||||
u8 *privkey, size_t privkey_len);
|
||||
struct hostapd_hw_modes;
|
||||
struct dpp_authentication * dpp_auth_init(void *msg_ctx,
|
||||
struct dpp_bootstrap_info *peer_bi,
|
||||
struct dpp_bootstrap_info *own_bi,
|
||||
u8 dpp_allowed_roles,
|
||||
unsigned int neg_freq,
|
||||
struct hostapd_hw_modes *own_modes,
|
||||
u16 num_modes);
|
||||
struct dpp_authentication *
|
||||
dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
|
||||
struct dpp_bootstrap_info *peer_bi,
|
||||
struct dpp_bootstrap_info *own_bi,
|
||||
unsigned int freq, const u8 *hdr, const u8 *attr_start,
|
||||
size_t attr_len);
|
||||
struct wpabuf *
|
||||
dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
|
||||
const u8 *attr_start, size_t attr_len);
|
||||
struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth,
|
||||
const char *json);
|
||||
struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
|
||||
const char *name,
|
||||
enum dpp_netrole netrole,
|
||||
const char *mud_url, int *opclasses);
|
||||
int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
|
||||
const u8 *attr_start, size_t attr_len);
|
||||
int dpp_notify_new_qr_code(struct dpp_authentication *auth,
|
||||
struct dpp_bootstrap_info *peer_bi);
|
||||
struct dpp_configuration * dpp_configuration_alloc(const char *type);
|
||||
int dpp_akm_psk(enum dpp_akm akm);
|
||||
int dpp_akm_sae(enum dpp_akm akm);
|
||||
int dpp_akm_legacy(enum dpp_akm akm);
|
||||
int dpp_akm_dpp(enum dpp_akm akm);
|
||||
int dpp_akm_ver2(enum dpp_akm akm);
|
||||
int dpp_configuration_valid(const struct dpp_configuration *conf);
|
||||
void dpp_configuration_free(struct dpp_configuration *conf);
|
||||
int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx,
|
||||
struct dpp_authentication *auth,
|
||||
const char *cmd);
|
||||
void dpp_auth_deinit(struct dpp_authentication *auth);
|
||||
struct wpabuf *
|
||||
dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
|
||||
size_t attr_len);
|
||||
int dpp_conf_resp_rx(struct dpp_authentication *auth,
|
||||
const struct wpabuf *resp);
|
||||
enum dpp_status_error dpp_conf_result_rx(struct dpp_authentication *auth,
|
||||
const u8 *hdr,
|
||||
const u8 *attr_start, size_t attr_len);
|
||||
struct wpabuf * dpp_build_conf_result(struct dpp_authentication *auth,
|
||||
enum dpp_status_error status);
|
||||
enum dpp_status_error dpp_conn_status_result_rx(struct dpp_authentication *auth,
|
||||
const u8 *hdr,
|
||||
const u8 *attr_start,
|
||||
size_t attr_len,
|
||||
u8 *ssid, size_t *ssid_len,
|
||||
char **channel_list);
|
||||
struct wpabuf * dpp_build_conn_status_result(struct dpp_authentication *auth,
|
||||
enum dpp_status_error result,
|
||||
const u8 *ssid, size_t ssid_len,
|
||||
const char *channel_list);
|
||||
struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type,
|
||||
size_t len);
|
||||
const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len);
|
||||
int dpp_check_attrs(const u8 *buf, size_t len);
|
||||
int dpp_key_expired(const char *timestamp, os_time_t *expiry);
|
||||
const char * dpp_akm_str(enum dpp_akm akm);
|
||||
const char * dpp_akm_selector_str(enum dpp_akm akm);
|
||||
int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
|
||||
size_t buflen);
|
||||
void dpp_configurator_free(struct dpp_configurator *conf);
|
||||
struct dpp_configurator *
|
||||
dpp_keygen_configurator(const char *curve, u8 *privkey,
|
||||
size_t privkey_len);
|
||||
int dpp_configurator_own_config(struct dpp_authentication *auth,
|
||||
const char *curve, int ap);
|
||||
enum dpp_status_error
|
||||
dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
|
||||
const u8 *net_access_key, size_t net_access_key_len,
|
||||
const u8 *csign_key, size_t csign_key_len,
|
||||
const u8 *peer_connector, size_t peer_connector_len,
|
||||
os_time_t *expiry);
|
||||
struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
|
||||
const u8 *own_mac,
|
||||
const char *identifier,
|
||||
const char *code);
|
||||
struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
||||
struct dpp_bootstrap_info *bi,
|
||||
const u8 *own_mac,
|
||||
const u8 *peer_mac,
|
||||
const char *identifier,
|
||||
const char *code,
|
||||
const u8 *buf, size_t len);
|
||||
struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
|
||||
const u8 *peer_mac,
|
||||
const u8 *buf, size_t len);
|
||||
struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
|
||||
const u8 *hdr,
|
||||
const u8 *buf, size_t len);
|
||||
int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr,
|
||||
const u8 *buf, size_t len);
|
||||
void dpp_pkex_free(struct dpp_pkex *pkex);
|
||||
|
||||
char * dpp_corrupt_connector_signature(const char *connector);
|
||||
|
||||
|
||||
struct dpp_pfs {
|
||||
struct crypto_ecdh *ecdh;
|
||||
const struct dpp_curve_params *curve;
|
||||
struct wpabuf *ie;
|
||||
struct wpabuf *secret;
|
||||
};
|
||||
|
||||
struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
|
||||
size_t net_access_key_len);
|
||||
int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len);
|
||||
void dpp_pfs_free(struct dpp_pfs *pfs);
|
||||
|
||||
struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
|
||||
const char *uri);
|
||||
struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
|
||||
const char *uri);
|
||||
int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd);
|
||||
struct dpp_bootstrap_info *
|
||||
dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id);
|
||||
int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id);
|
||||
struct dpp_bootstrap_info *
|
||||
dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer,
|
||||
unsigned int freq);
|
||||
const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id);
|
||||
int dpp_bootstrap_info(struct dpp_global *dpp, int id,
|
||||
char *reply, int reply_size);
|
||||
void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap,
|
||||
const u8 *r_bootstrap,
|
||||
struct dpp_bootstrap_info **own_bi,
|
||||
struct dpp_bootstrap_info **peer_bi);
|
||||
struct dpp_global_config {
|
||||
void *msg_ctx;
|
||||
void *cb_ctx;
|
||||
int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
|
||||
};
|
||||
|
||||
struct dpp_global * dpp_global_init(struct dpp_global_config *config);
|
||||
void dpp_global_clear(struct dpp_global *dpp);
|
||||
void dpp_global_deinit(struct dpp_global *dpp);
|
||||
|
||||
#endif /* CONFIG_DPP */
|
||||
#endif /* DPP_H */
|
@ -27,14 +27,6 @@ void wpabuf_clear_free(struct wpabuf *buf)
|
||||
}
|
||||
}
|
||||
|
||||
void bin_clear_free(void *bin, size_t len)
|
||||
{
|
||||
if (bin) {
|
||||
os_memset(bin, 0, len);
|
||||
os_free(bin);
|
||||
}
|
||||
}
|
||||
|
||||
int sae_set_group(struct sae_data *sae, int group)
|
||||
{
|
||||
struct sae_temporary_data *tmp;
|
||||
|
89
components/wpa_supplicant/src/crypto/aes-ctr.c
Normal file
89
components/wpa_supplicant/src/crypto/aes-ctr.c
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* AES-128/192/256 CTR
|
||||
*
|
||||
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
#include "utils/includes.h"
|
||||
#include "utils/common.h"
|
||||
|
||||
#include "crypto/aes.h"
|
||||
#include "crypto/aes_wrap.h"
|
||||
#ifdef USE_MBEDTLS_CRYPTO
|
||||
#include "mbedtls/aes.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* aes_ctr_encrypt - AES-128/192/256 CTR mode encryption
|
||||
* @key: Key for encryption (key_len bytes)
|
||||
* @key_len: Length of the key (16, 24, or 32 bytes)
|
||||
* @nonce: Nonce for counter mode (16 bytes)
|
||||
* @data: Data to encrypt in-place
|
||||
* @data_len: Length of data in bytes
|
||||
* Returns: 0 on success, Negative value on failure
|
||||
*/
|
||||
int aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce,
|
||||
u8 *data, size_t data_len)
|
||||
{
|
||||
#ifdef USE_MBEDTLS_CRYPTO
|
||||
int ret;
|
||||
mbedtls_aes_context ctx;
|
||||
uint8_t stream_block[AES_BLOCK_SIZE];
|
||||
size_t offset = 0;
|
||||
|
||||
mbedtls_aes_init(&ctx);
|
||||
ret = mbedtls_aes_setkey_enc(&ctx, key, key_len * 8);
|
||||
if (ret < 0)
|
||||
goto cleanup;
|
||||
ret = mbedtls_aes_crypt_ctr(&ctx, data_len, &offset, (u8 *)nonce, stream_block, data, data);
|
||||
cleanup:
|
||||
mbedtls_aes_free(&ctx);
|
||||
return ret;
|
||||
#else
|
||||
void *ctx;
|
||||
size_t j, len, left = data_len;
|
||||
int i;
|
||||
u8 *pos = data;
|
||||
u8 counter[AES_BLOCK_SIZE], buf[AES_BLOCK_SIZE];
|
||||
|
||||
ctx = aes_encrypt_init(key, key_len);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
os_memcpy(counter, nonce, AES_BLOCK_SIZE);
|
||||
|
||||
while (left > 0) {
|
||||
aes_encrypt(ctx, counter, buf);
|
||||
|
||||
len = (left < AES_BLOCK_SIZE) ? left : AES_BLOCK_SIZE;
|
||||
for (j = 0; j < len; j++)
|
||||
pos[j] ^= buf[j];
|
||||
pos += len;
|
||||
left -= len;
|
||||
|
||||
for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
|
||||
counter[i]++;
|
||||
if (counter[i])
|
||||
break;
|
||||
}
|
||||
}
|
||||
aes_encrypt_deinit(ctx);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* aes_128_ctr_encrypt - AES-128 CTR mode encryption
|
||||
* @key: Key for encryption (key_len bytes)
|
||||
* @nonce: Nonce for counter mode (16 bytes)
|
||||
* @data: Data to encrypt in-place
|
||||
* @data_len: Length of data in bytes
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
|
||||
u8 *data, size_t data_len)
|
||||
{
|
||||
return aes_ctr_encrypt(key, 16, nonce, data, data_len);
|
||||
}
|
208
components/wpa_supplicant/src/crypto/aes-siv.c
Normal file
208
components/wpa_supplicant/src/crypto/aes-siv.c
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* AES SIV (RFC 5297)
|
||||
* Copyright (c) 2013 Cozybit, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include "utils/common.h"
|
||||
|
||||
#include "crypto/aes.h"
|
||||
#include "crypto/aes_wrap.h"
|
||||
#include "crypto/aes_siv.h"
|
||||
|
||||
|
||||
static const u8 zero[AES_BLOCK_SIZE];
|
||||
|
||||
|
||||
static void dbl(u8 *pad)
|
||||
{
|
||||
int i, carry;
|
||||
|
||||
carry = pad[0] & 0x80;
|
||||
for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
|
||||
pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
|
||||
pad[AES_BLOCK_SIZE - 1] <<= 1;
|
||||
if (carry)
|
||||
pad[AES_BLOCK_SIZE - 1] ^= 0x87;
|
||||
}
|
||||
|
||||
|
||||
static void xor(u8 *a, const u8 *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AES_BLOCK_SIZE; i++)
|
||||
*a++ ^= *b++;
|
||||
}
|
||||
|
||||
|
||||
static void xorend(u8 *a, int alen, const u8 *b, int blen)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (alen < blen)
|
||||
return;
|
||||
|
||||
for (i = 0; i < blen; i++)
|
||||
a[alen - blen + i] ^= b[i];
|
||||
}
|
||||
|
||||
|
||||
static void pad_block(u8 *pad, const u8 *addr, size_t len)
|
||||
{
|
||||
os_memset(pad, 0, AES_BLOCK_SIZE);
|
||||
os_memcpy(pad, addr, len);
|
||||
|
||||
if (len < AES_BLOCK_SIZE)
|
||||
pad[len] = 0x80;
|
||||
}
|
||||
|
||||
|
||||
static int aes_s2v(const u8 *key, size_t key_len,
|
||||
size_t num_elem, const u8 *addr[], size_t *len, u8 *mac)
|
||||
{
|
||||
u8 tmp[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
|
||||
u8 *buf = NULL;
|
||||
int ret;
|
||||
size_t i;
|
||||
const u8 *data[1];
|
||||
size_t data_len[1];
|
||||
|
||||
if (!num_elem) {
|
||||
os_memcpy(tmp, zero, sizeof(zero));
|
||||
tmp[AES_BLOCK_SIZE - 1] = 1;
|
||||
data[0] = tmp;
|
||||
data_len[0] = sizeof(tmp);
|
||||
return omac1_aes_vector(key, key_len, 1, data, data_len, mac);
|
||||
}
|
||||
|
||||
data[0] = zero;
|
||||
data_len[0] = sizeof(zero);
|
||||
ret = omac1_aes_vector(key, key_len, 1, data, data_len, tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < num_elem - 1; i++) {
|
||||
ret = omac1_aes_vector(key, key_len, 1, &addr[i], &len[i],
|
||||
tmp2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dbl(tmp);
|
||||
xor(tmp, tmp2);
|
||||
}
|
||||
if (len[i] >= AES_BLOCK_SIZE) {
|
||||
buf = os_memdup(addr[i], len[i]);
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
xorend(buf, len[i], tmp, AES_BLOCK_SIZE);
|
||||
data[0] = buf;
|
||||
ret = omac1_aes_vector(key, key_len, 1, data, &len[i], mac);
|
||||
bin_clear_free(buf, len[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dbl(tmp);
|
||||
pad_block(tmp2, addr[i], len[i]);
|
||||
xor(tmp, tmp2);
|
||||
|
||||
data[0] = tmp;
|
||||
data_len[0] = sizeof(tmp);
|
||||
return omac1_aes_vector(key, key_len, 1, data, data_len, mac);
|
||||
}
|
||||
|
||||
|
||||
int aes_siv_encrypt(const u8 *key, size_t key_len,
|
||||
const u8 *pw, size_t pwlen,
|
||||
size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *out)
|
||||
{
|
||||
const u8 *_addr[6];
|
||||
size_t _len[6];
|
||||
const u8 *k1, *k2;
|
||||
u8 v[AES_BLOCK_SIZE];
|
||||
size_t i;
|
||||
u8 *iv, *crypt_pw;
|
||||
|
||||
if (num_elem > ARRAY_SIZE(_addr) - 1 ||
|
||||
(key_len != 32 && key_len != 48 && key_len != 64))
|
||||
return -1;
|
||||
|
||||
key_len /= 2;
|
||||
k1 = key;
|
||||
k2 = key + key_len;
|
||||
|
||||
for (i = 0; i < num_elem; i++) {
|
||||
_addr[i] = addr[i];
|
||||
_len[i] = len[i];
|
||||
}
|
||||
_addr[num_elem] = pw;
|
||||
_len[num_elem] = pwlen;
|
||||
|
||||
if (aes_s2v(k1, key_len, num_elem + 1, _addr, _len, v))
|
||||
return -1;
|
||||
|
||||
iv = out;
|
||||
crypt_pw = out + AES_BLOCK_SIZE;
|
||||
|
||||
os_memcpy(iv, v, AES_BLOCK_SIZE);
|
||||
os_memcpy(crypt_pw, pw, pwlen);
|
||||
|
||||
/* zero out 63rd and 31st bits of ctr (from right) */
|
||||
v[8] &= 0x7f;
|
||||
v[12] &= 0x7f;
|
||||
return aes_ctr_encrypt(k2, key_len, v, crypt_pw, pwlen);
|
||||
}
|
||||
|
||||
|
||||
int aes_siv_decrypt(const u8 *key, size_t key_len,
|
||||
const u8 *iv_crypt, size_t iv_c_len,
|
||||
size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *out)
|
||||
{
|
||||
const u8 *_addr[6];
|
||||
size_t _len[6];
|
||||
const u8 *k1, *k2;
|
||||
size_t crypt_len;
|
||||
size_t i;
|
||||
int ret;
|
||||
u8 iv[AES_BLOCK_SIZE];
|
||||
u8 check[AES_BLOCK_SIZE];
|
||||
|
||||
if (iv_c_len < AES_BLOCK_SIZE || num_elem > ARRAY_SIZE(_addr) - 1 ||
|
||||
(key_len != 32 && key_len != 48 && key_len != 64))
|
||||
return -1;
|
||||
crypt_len = iv_c_len - AES_BLOCK_SIZE;
|
||||
key_len /= 2;
|
||||
k1 = key;
|
||||
k2 = key + key_len;
|
||||
|
||||
for (i = 0; i < num_elem; i++) {
|
||||
_addr[i] = addr[i];
|
||||
_len[i] = len[i];
|
||||
}
|
||||
_addr[num_elem] = out;
|
||||
_len[num_elem] = crypt_len;
|
||||
|
||||
os_memcpy(iv, iv_crypt, AES_BLOCK_SIZE);
|
||||
os_memcpy(out, iv_crypt + AES_BLOCK_SIZE, crypt_len);
|
||||
|
||||
iv[8] &= 0x7f;
|
||||
iv[12] &= 0x7f;
|
||||
|
||||
ret = aes_ctr_encrypt(k2, key_len, iv, out, crypt_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = aes_s2v(k1, key_len, num_elem + 1, _addr, _len, check);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (os_memcmp(check, iv_crypt, AES_BLOCK_SIZE) == 0)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
21
components/wpa_supplicant/src/crypto/aes_siv.h
Normal file
21
components/wpa_supplicant/src/crypto/aes_siv.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* AES SIV (RFC 5297)
|
||||
* Copyright (c) 2013 Cozybit, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef AES_SIV_H
|
||||
#define AES_SIV_H
|
||||
|
||||
int aes_siv_encrypt(const u8 *key, size_t key_len,
|
||||
const u8 *pw, size_t pwlen,
|
||||
size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *out);
|
||||
int aes_siv_decrypt(const u8 *key, size_t key_len,
|
||||
const u8 *iv_crypt, size_t iv_c_len,
|
||||
size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *out);
|
||||
|
||||
#endif /* AES_SIV_H */
|
@ -35,6 +35,8 @@ int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len,
|
||||
int __must_check omac1_aes_256(const u8 *key, const u8 *data, size_t data_len,
|
||||
u8 *mac);
|
||||
int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out);
|
||||
int __must_check aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce,
|
||||
u8 *data, size_t data_len);
|
||||
int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
|
||||
u8 *data, size_t data_len);
|
||||
int __must_check aes_128_eax_encrypt(const u8 *key,
|
||||
|
@ -468,18 +468,6 @@ int rc4_skip(const u8 *key, size_t keylen, size_t skip,
|
||||
u8 *data, size_t data_len);
|
||||
|
||||
|
||||
/**
|
||||
* crypto_get_random - Generate cryptographically strong pseudy-random bytes
|
||||
* @buf: Buffer for data
|
||||
* @len: Number of bytes to generate
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* If the PRNG does not have enough entropy to ensure unpredictable byte
|
||||
* sequence, this functions must return -1.
|
||||
*/
|
||||
int crypto_get_random(void *buf, size_t len);
|
||||
|
||||
|
||||
/**
|
||||
* struct crypto_bignum - bignum
|
||||
*
|
||||
@ -488,6 +476,14 @@ int crypto_get_random(void *buf, size_t len);
|
||||
*/
|
||||
struct crypto_bignum;
|
||||
|
||||
/**
|
||||
* struct crypto_key - key
|
||||
*
|
||||
* Internal data structure for ssl key. The contents is specific
|
||||
* to the used crypto library.
|
||||
*/
|
||||
struct crypto_key;
|
||||
|
||||
/**
|
||||
* crypto_bignum_init - Allocate memory for bignum
|
||||
* Returns: Pointer to allocated bignum or %NULL on failure
|
||||
@ -825,5 +821,217 @@ int crypto_ec_point_cmp(const struct crypto_ec *e,
|
||||
const struct crypto_ec_point *a,
|
||||
const struct crypto_ec_point *b);
|
||||
|
||||
/**
|
||||
* crypto_ec_get_publickey_buf - Write EC public key to buffer
|
||||
* @key: crypto key
|
||||
* @key_buf: key buffer
|
||||
* @len: length of buffer
|
||||
* Returns: 0 on success, non-zero otherwise
|
||||
*/
|
||||
int crypto_ec_get_publickey_buf(struct crypto_key *key, u8 *key_buf, int len);
|
||||
|
||||
/**
|
||||
* crypto_ec_get_group_from_key - Write EC group from key
|
||||
* @key: crypto key
|
||||
* Returns: EC group
|
||||
*/
|
||||
struct crypto_ec_group *crypto_ec_get_group_from_key(struct crypto_key *key);
|
||||
|
||||
/**
|
||||
* crypto_ec_get_private_key - Get EC private key (in bignum format)
|
||||
* @key: crypto key
|
||||
* Returns: Private key
|
||||
*/
|
||||
struct crypto_bignum *crypto_ec_get_private_key(struct crypto_key *key);
|
||||
|
||||
/**
|
||||
* crypto_ec_get_key - Read key from character stream
|
||||
* @privkey: Private key
|
||||
* @privkey_len: private key len
|
||||
* Returns: Crypto key
|
||||
*/
|
||||
struct crypto_key *crypto_ec_get_key(const u8 *privkey, size_t privkey_len);
|
||||
|
||||
/**
|
||||
* crypto_ec_get_mbedtls_to_nist_group_id - get nist group from mbedtls internal group
|
||||
* @id: mbedtls group
|
||||
* Returns: NIST group
|
||||
*/
|
||||
unsigned int crypto_ec_get_mbedtls_to_nist_group_id(int id);
|
||||
|
||||
/**
|
||||
* crypto_ec_get_curve_id - get curve id from ec group
|
||||
* @group: EC group
|
||||
* Returns: curve ID
|
||||
*/
|
||||
int crypto_ec_get_curve_id(const struct crypto_ec_group *group);
|
||||
|
||||
/**
|
||||
* crypto_ecdh: crypto ecdh
|
||||
* @key_own: own key
|
||||
* @key_peer: peer key
|
||||
* @secret: secret
|
||||
* @secret_len: secret len
|
||||
* Returns: 0 if success else negative value
|
||||
*/
|
||||
int crypto_ecdh(struct crypto_key *key_own, struct crypto_key *key_peer,
|
||||
u8 *secret, size_t *secret_len);
|
||||
|
||||
/**
|
||||
* crypto_ecdsa_get_sign: get crypto ecdsa signed hash
|
||||
* @hash: signed hash
|
||||
* @r: ecdsa r
|
||||
* @s: ecdsa s
|
||||
* @csign: csign
|
||||
* @hash_len: length of hash
|
||||
* Return: 0 if success else negative value
|
||||
*/
|
||||
int crypto_ecdsa_get_sign(unsigned char *hash,
|
||||
const struct crypto_bignum *r, const struct crypto_bignum *s,
|
||||
struct crypto_key *csign, int hash_len);
|
||||
|
||||
/**
|
||||
* crypto_edcsa_sign_verify: verify crypto ecdsa signed hash
|
||||
* @hash: signed hash
|
||||
* @r: ecdsa r
|
||||
* @s: ecdsa s
|
||||
* @csign: csign
|
||||
* @hlen: length of hash
|
||||
* Return: 0 if success else negative value
|
||||
*/
|
||||
int crypto_edcsa_sign_verify(const unsigned char *hash, const struct crypto_bignum *r,
|
||||
const struct crypto_bignum *s, struct crypto_key *csign, int hlen);
|
||||
|
||||
/**
|
||||
* crypto_ec_parse_subpub_key: get EC key context from sub public key
|
||||
* @p: data
|
||||
* @len: data len
|
||||
* Return: crypto_key
|
||||
*/
|
||||
struct crypto_key *crypto_ec_parse_subpub_key(const unsigned char *p, size_t len);
|
||||
|
||||
/**
|
||||
* crypto_is_ec_key: check whether a key is EC key or not
|
||||
* @key: crypto key
|
||||
* Return: true if key else false
|
||||
*/
|
||||
int crypto_is_ec_key(struct crypto_key *key);
|
||||
|
||||
/**
|
||||
* crypto_ec_gen_keypair: generate crypto ec keypair
|
||||
* @ike_group: grpup
|
||||
* Return: crypto key
|
||||
*/
|
||||
struct crypto_key * crypto_ec_gen_keypair(u16 ike_group);
|
||||
|
||||
/**
|
||||
* crypto_ec_write_pub_key: return public key in charater buffer
|
||||
* @key: crypto key
|
||||
* @der_len: buffer len
|
||||
* Return: public key buffer
|
||||
*/
|
||||
int crypto_ec_write_pub_key(struct crypto_key *key, unsigned char **key_buf);
|
||||
|
||||
/**
|
||||
* crypto_ec_set_pubkey_point: set bignum point on ec curve
|
||||
* @group: ec group
|
||||
* @buf: x,y coordinate
|
||||
* @len: length of x and y coordiate
|
||||
* Return : crypto key
|
||||
*/
|
||||
struct crypto_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *group,
|
||||
const u8 *buf, size_t len);
|
||||
/**
|
||||
* crypto_ec_free_key: free crypto key
|
||||
* Return : None
|
||||
*/
|
||||
void crypto_ec_free_key(struct crypto_key *key);
|
||||
/**
|
||||
* crypto_debug_print_ec_key: print ec key
|
||||
* @title: title
|
||||
* @key: crypto key
|
||||
* Return: None
|
||||
*/
|
||||
void crypto_debug_print_ec_key(const char *title, struct crypto_key *key);
|
||||
|
||||
/**
|
||||
* crypto_ec_get_public_key: Public key from crypto key
|
||||
* @key: crypto key
|
||||
* Return : Public key
|
||||
*/
|
||||
struct crypto_ec_point *crypto_ec_get_public_key(struct crypto_key *key);
|
||||
|
||||
/**
|
||||
* crypto_get_order: free crypto key
|
||||
* Return : None
|
||||
*/
|
||||
int crypto_get_order(struct crypto_ec_group *group, struct crypto_bignum *x);
|
||||
|
||||
/**
|
||||
* crypto_bignum_addmod: a = (b + c) mod d
|
||||
* Return : 0 in success
|
||||
*/
|
||||
int crypto_bignum_addmod(struct crypto_bignum *a,
|
||||
struct crypto_bignum *b,
|
||||
struct crypto_bignum *c,
|
||||
struct crypto_bignum *d);
|
||||
|
||||
/**
|
||||
* crypto_ec_get_affine_coordinates : get affine corrdinate of ec curve
|
||||
* @e: ec curve
|
||||
* @pt: point
|
||||
* @x: x coordinate
|
||||
* @y: y coordinate
|
||||
* Return : 0 if success
|
||||
*/
|
||||
int crypto_ec_get_affine_coordinates(struct crypto_ec *e, struct crypto_ec_point *pt,
|
||||
struct crypto_bignum *x, struct crypto_bignum *y);
|
||||
|
||||
/**
|
||||
* crypto_ec_get_group_byname: get ec curve group by name
|
||||
* @name: ec curve name
|
||||
* Return : EC group
|
||||
*/
|
||||
struct crypto_ec_group *crypto_ec_get_group_byname(const char *name);
|
||||
|
||||
/**
|
||||
* crypto_key_compare: check whether two keys belong to same
|
||||
* Return : 1 if yes else 0
|
||||
*/
|
||||
int crypto_key_compare(struct crypto_key *key1, struct crypto_key *key2);
|
||||
|
||||
/*
|
||||
* crypto_write_pubkey_der: get public key in der format
|
||||
* @csign: key
|
||||
* @key_buf: key buffer in charater format
|
||||
* Return : len of char buffer if success
|
||||
*/
|
||||
int crypto_write_pubkey_der(struct crypto_key *csign, unsigned char **key_buf);
|
||||
|
||||
/**
|
||||
* crypto_free_buffer: free buffer allocated by crypto API
|
||||
* @buf: buffer pointer
|
||||
* Return : None
|
||||
*/
|
||||
void crypto_free_buffer(unsigned char *buf);
|
||||
|
||||
/**
|
||||
* @crypto_ec_get_priv_key_der: get private key in der format
|
||||
* @key: key structure
|
||||
* @key_data: key data in charater buffer
|
||||
* @key_len = key lenght of charater buffer
|
||||
* Return : 0 if success
|
||||
*/
|
||||
int crypto_ec_get_priv_key_der(struct crypto_key *key, unsigned char **key_data, int *key_len);
|
||||
|
||||
/**
|
||||
* crypto_bignum_to_string: get big number in ascii format
|
||||
* @a: big number
|
||||
* @buf: buffer in which number will written to
|
||||
* @buflen: buffer length
|
||||
* @padlen: padding length
|
||||
* Return : 0 if success
|
||||
*/
|
||||
int crypto_bignum_to_string(const struct crypto_bignum *a,
|
||||
u8 *buf, size_t buflen, size_t padlen);
|
||||
#endif /* CRYPTO_H */
|
||||
|
277
components/wpa_supplicant/src/crypto/crypto_mbedtls-bignum.c
Normal file
277
components/wpa_supplicant/src/crypto/crypto_mbedtls-bignum.c
Normal file
@ -0,0 +1,277 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "esp_system.h"
|
||||
#include "mbedtls/bignum.h"
|
||||
#endif
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include "utils/common.h"
|
||||
#include "crypto.h"
|
||||
#include "random.h"
|
||||
#include "sha256.h"
|
||||
#include "mbedtls/pk.h"
|
||||
|
||||
struct crypto_bignum *crypto_bignum_init(void)
|
||||
{
|
||||
mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi));
|
||||
if (bn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_mpi_init(bn);
|
||||
|
||||
return (struct crypto_bignum *)bn;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_bignum *crypto_bignum_init_set(const u8 *buf, size_t len)
|
||||
{
|
||||
int ret = 0;
|
||||
mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi));
|
||||
if (bn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(bn, buf, len));
|
||||
return (struct crypto_bignum *) bn;
|
||||
|
||||
cleanup:
|
||||
os_free(bn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
|
||||
{
|
||||
mbedtls_mpi_free((mbedtls_mpi *)n);
|
||||
os_free((mbedtls_mpi *)n);
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_to_bin(const struct crypto_bignum *a,
|
||||
u8 *buf, size_t buflen, size_t padlen)
|
||||
{
|
||||
int num_bytes, offset;
|
||||
|
||||
if (padlen > buflen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
num_bytes = mbedtls_mpi_size((mbedtls_mpi *) a);
|
||||
|
||||
if ((size_t) num_bytes > buflen) {
|
||||
return -1;
|
||||
}
|
||||
if (padlen > (size_t) num_bytes) {
|
||||
offset = padlen - num_bytes;
|
||||
} else {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
os_memset(buf, 0, offset);
|
||||
mbedtls_mpi_write_binary((mbedtls_mpi *) a, buf + offset, mbedtls_mpi_size((mbedtls_mpi *)a) );
|
||||
|
||||
return num_bytes + offset;
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_add(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_bignum *c)
|
||||
{
|
||||
return mbedtls_mpi_add_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
|
||||
-1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_mod(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_bignum *c)
|
||||
{
|
||||
return mbedtls_mpi_mod_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_exptmod(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
const struct crypto_bignum *c,
|
||||
struct crypto_bignum *d)
|
||||
{
|
||||
return mbedtls_mpi_exp_mod((mbedtls_mpi *) d, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b, (const mbedtls_mpi *) c, NULL) ? -1 : 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_inverse(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_bignum *c)
|
||||
{
|
||||
return mbedtls_mpi_inv_mod((mbedtls_mpi *) c, (const mbedtls_mpi *) a,
|
||||
(const mbedtls_mpi *) b) ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_sub(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_bignum *c)
|
||||
{
|
||||
return mbedtls_mpi_sub_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
|
||||
-1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_div(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_bignum *c)
|
||||
{
|
||||
return mbedtls_mpi_div_mpi((mbedtls_mpi *) c, NULL, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
|
||||
-1 : 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 res;
|
||||
#if ALLOW_EVEN_MOD // Must enable this macro if c is even.
|
||||
mbedtls_mpi temp;
|
||||
mbedtls_mpi_init(&temp);
|
||||
|
||||
res = mbedtls_mpi_mul_mpi(&temp, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b);
|
||||
if (res) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = mbedtls_mpi_mod_mpi((mbedtls_mpi *) d, &temp, (mbedtls_mpi *) c);
|
||||
|
||||
mbedtls_mpi_free(&temp);
|
||||
#else
|
||||
// Works with odd modulus only, but it is faster with HW acceleration
|
||||
res = esp_mpi_mul_mpi_mod((mbedtls_mpi *) d, (mbedtls_mpi *) a, (mbedtls_mpi *) b, (mbedtls_mpi *) c);
|
||||
#endif
|
||||
return res ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_cmp(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b)
|
||||
{
|
||||
return mbedtls_mpi_cmp_mpi((const mbedtls_mpi *) a, (const mbedtls_mpi *) b);
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_bits(const struct crypto_bignum *a)
|
||||
{
|
||||
return mbedtls_mpi_bitlen((const mbedtls_mpi *) a);
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_is_zero(const struct crypto_bignum *a)
|
||||
{
|
||||
return (mbedtls_mpi_cmp_int((const mbedtls_mpi *) a, 0) == 0);
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_is_one(const struct crypto_bignum *a)
|
||||
{
|
||||
return (mbedtls_mpi_cmp_int((const mbedtls_mpi *) a, 1) == 0);
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_legendre(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *p)
|
||||
{
|
||||
mbedtls_mpi exp, tmp;
|
||||
int res = -2, ret;
|
||||
|
||||
mbedtls_mpi_init(&exp);
|
||||
mbedtls_mpi_init(&tmp);
|
||||
|
||||
/* exp = (p-1) / 2 */
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&exp, (const mbedtls_mpi *) p, 1));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&exp, 1));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&tmp, (const mbedtls_mpi *) a, &exp, (const mbedtls_mpi *) p, NULL));
|
||||
|
||||
if (mbedtls_mpi_cmp_int(&tmp, 1) == 0) {
|
||||
res = 1;
|
||||
} else if (mbedtls_mpi_cmp_int(&tmp, 0) == 0
|
||||
/* The below check is workaround for the case where HW
|
||||
* does not behave properly for X ^ A mod M when X is
|
||||
* power of M. Instead of returning value 0, value M is
|
||||
* returned.*/
|
||||
|| mbedtls_mpi_cmp_mpi(&tmp, (const mbedtls_mpi *)p) == 0) {
|
||||
res = 0;
|
||||
} else {
|
||||
res = -1;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&tmp);
|
||||
mbedtls_mpi_free(&exp);
|
||||
return res;
|
||||
}
|
||||
|
||||
int crypto_bignum_to_string(const struct crypto_bignum *a,
|
||||
u8 *buf, size_t buflen, size_t padlen)
|
||||
{
|
||||
int num_bytes, offset;
|
||||
size_t outlen;
|
||||
|
||||
if (padlen > buflen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
num_bytes = mbedtls_mpi_size((mbedtls_mpi *) a);
|
||||
|
||||
if (padlen > (size_t) num_bytes) {
|
||||
offset = padlen - num_bytes;
|
||||
} else {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
os_memset(buf, 0, offset);
|
||||
mbedtls_mpi_write_string((mbedtls_mpi *) a, 16, (char *)(buf + offset),
|
||||
mbedtls_mpi_size((mbedtls_mpi *)a), &outlen);
|
||||
|
||||
return outlen;
|
||||
}
|
||||
|
||||
int crypto_bignum_addmod(struct crypto_bignum *a,
|
||||
struct crypto_bignum *b,
|
||||
struct crypto_bignum *c,
|
||||
struct crypto_bignum *d)
|
||||
{
|
||||
struct crypto_bignum *tmp = crypto_bignum_init();
|
||||
int ret = -1;
|
||||
|
||||
if (mbedtls_mpi_add_mpi((mbedtls_mpi *) tmp, (const mbedtls_mpi *) b, (const mbedtls_mpi *) c) < 0)
|
||||
goto fail;
|
||||
|
||||
if (mbedtls_mpi_mod_mpi( (mbedtls_mpi *) a, (const mbedtls_mpi *) tmp, (const mbedtls_mpi *) d) < 0)
|
||||
goto fail;
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
crypto_bignum_deinit(tmp, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void crypto_free_buffer(unsigned char *buf)
|
||||
{
|
||||
os_free(buf);
|
||||
}
|
987
components/wpa_supplicant/src/crypto/crypto_mbedtls-ec.c
Normal file
987
components/wpa_supplicant/src/crypto/crypto_mbedtls-ec.c
Normal file
@ -0,0 +1,987 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "esp_system.h"
|
||||
#include "mbedtls/bignum.h"
|
||||
#endif
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include "utils/common.h"
|
||||
#include "crypto.h"
|
||||
#include "sha256.h"
|
||||
#include "random.h"
|
||||
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
|
||||
#include "mbedtls/pk.h"
|
||||
#include "mbedtls/ecdh.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
#include "mbedtls/asn1write.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/oid.h"
|
||||
|
||||
#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES
|
||||
|
||||
#ifdef CONFIG_ECC
|
||||
struct crypto_ec {
|
||||
mbedtls_ecp_group group;
|
||||
};
|
||||
|
||||
int crypto_rng_wrapper(void *ctx, unsigned char *buf, size_t len)
|
||||
{
|
||||
return random_get_bytes(buf, len);
|
||||
}
|
||||
|
||||
struct crypto_ec *crypto_ec_init(int group)
|
||||
{
|
||||
struct crypto_ec *e;
|
||||
|
||||
mbedtls_ecp_group_id grp_id;
|
||||
|
||||
/* IANA registry to mbedtls internal mapping*/
|
||||
switch (group) {
|
||||
case IANA_SECP256R1:
|
||||
/* For now just support NIST-P256.
|
||||
* This is of type "short Weierstrass".
|
||||
*/
|
||||
grp_id = MBEDTLS_ECP_DP_SECP256R1;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
|
||||
}
|
||||
e = os_zalloc(sizeof(*e));
|
||||
if (e == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_ecp_group_init(&e->group);
|
||||
|
||||
if (mbedtls_ecp_group_load(&e->group, grp_id)) {
|
||||
crypto_ec_deinit(e);
|
||||
e = NULL;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
void crypto_ec_deinit(struct crypto_ec *e)
|
||||
{
|
||||
if (e == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
mbedtls_ecp_group_free(&e->group);
|
||||
os_free(e);
|
||||
}
|
||||
|
||||
|
||||
struct crypto_ec_point *crypto_ec_point_init(struct crypto_ec *e)
|
||||
{
|
||||
mbedtls_ecp_point *pt;
|
||||
if (e == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pt = os_zalloc(sizeof(mbedtls_ecp_point));
|
||||
|
||||
if( pt == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_ecp_point_init(pt);
|
||||
|
||||
return (struct crypto_ec_point *) pt;
|
||||
}
|
||||
|
||||
|
||||
size_t crypto_ec_prime_len(struct crypto_ec *e)
|
||||
{
|
||||
return mbedtls_mpi_size(&e->group.P);
|
||||
}
|
||||
|
||||
|
||||
size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
|
||||
{
|
||||
return mbedtls_mpi_bitlen(&e->group.P);
|
||||
}
|
||||
struct crypto_ec_group *crypto_ec_get_group_byname(const char *name)
|
||||
{
|
||||
struct crypto_ec *e;
|
||||
const mbedtls_ecp_curve_info *curve = mbedtls_ecp_curve_info_from_name(name);
|
||||
|
||||
e = os_zalloc(sizeof(*e));
|
||||
if (e == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_ecp_group_init( &e->group );
|
||||
|
||||
if (mbedtls_ecp_group_load(&e->group, curve->grp_id)) {
|
||||
crypto_ec_deinit(e);
|
||||
e = NULL;
|
||||
}
|
||||
|
||||
return (struct crypto_ec_group *) &e->group;
|
||||
}
|
||||
|
||||
const struct crypto_bignum *crypto_ec_get_prime(struct crypto_ec *e)
|
||||
{
|
||||
return (const struct crypto_bignum *) &e->group.P;
|
||||
}
|
||||
|
||||
|
||||
const struct crypto_bignum *crypto_ec_get_order(struct crypto_ec *e)
|
||||
{
|
||||
return (const struct crypto_bignum *) &e->group.N;
|
||||
}
|
||||
|
||||
|
||||
void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
|
||||
{
|
||||
mbedtls_ecp_point_free((mbedtls_ecp_point *) p);
|
||||
os_free(p);
|
||||
}
|
||||
|
||||
int crypto_ec_point_to_bin(struct crypto_ec *e,
|
||||
const struct crypto_ec_point *point, u8 *x, u8 *y)
|
||||
{
|
||||
int len = mbedtls_mpi_size(&e->group.P);
|
||||
|
||||
if (x) {
|
||||
if(crypto_bignum_to_bin((struct crypto_bignum *) & ((mbedtls_ecp_point *) point)->X,
|
||||
x, len, len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (y) {
|
||||
if(crypto_bignum_to_bin((struct crypto_bignum *) & ((mbedtls_ecp_point *) point)->Y,
|
||||
y, len, len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypto_ec_get_affine_coordinates(struct crypto_ec *e, struct crypto_ec_point *pt,
|
||||
struct crypto_bignum *x, struct crypto_bignum *y)
|
||||
{
|
||||
int ret = -1;
|
||||
mbedtls_ecp_point *point = (mbedtls_ecp_point *)pt;
|
||||
|
||||
if (!mbedtls_ecp_is_zero(point) && (mbedtls_mpi_cmp_int( &point->Z, 1 ) == 0 )) {
|
||||
// Affine coordinates mean that z should be 1,
|
||||
wpa_printf(MSG_ERROR, "Z coordinate is neither 0 or 1");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (x) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_copy((mbedtls_mpi*) x, &((mbedtls_ecp_point* )point)->X));
|
||||
}
|
||||
if (y) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_copy((mbedtls_mpi*) y, &((mbedtls_ecp_point* )point)->Y));
|
||||
}
|
||||
return 0;
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct crypto_ec_point *crypto_ec_point_from_bin(struct crypto_ec *e,
|
||||
const u8 *val)
|
||||
{
|
||||
mbedtls_ecp_point *pt;
|
||||
int len, ret;
|
||||
|
||||
if (e == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = mbedtls_mpi_size(&e->group.P);
|
||||
|
||||
pt = os_zalloc(sizeof(mbedtls_ecp_point));
|
||||
mbedtls_ecp_point_init(pt);
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->X, val, len));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->Y, val + len, len));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset((&pt->Z), 1));
|
||||
|
||||
return (struct crypto_ec_point *) pt;
|
||||
|
||||
cleanup:
|
||||
mbedtls_ecp_point_free(pt);
|
||||
os_free(pt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
mbedtls_mpi one;
|
||||
|
||||
mbedtls_mpi_init(&one);
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset( &one, 1 ));
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&e->group, (mbedtls_ecp_point *) c, &one, (const mbedtls_ecp_point *)a , &one, (const mbedtls_ecp_point *)b));
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&one);
|
||||
return ret ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
|
||||
mbedtls_entropy_init(&entropy);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
|
||||
NULL, 0));
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&e->group,
|
||||
(mbedtls_ecp_point *) res,
|
||||
(const mbedtls_mpi *)b,
|
||||
(const mbedtls_ecp_point *)p,
|
||||
mbedtls_ctr_drbg_random,
|
||||
&ctr_drbg));
|
||||
cleanup:
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
return ret ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/* Currently mbedtls does not have any function for inverse
|
||||
* This function calculates inverse of a point.
|
||||
* Set R = -P
|
||||
*/
|
||||
static int ecp_opp(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point *P)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Copy */
|
||||
if (R != P) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P));
|
||||
}
|
||||
|
||||
/* In-place opposite */
|
||||
if (mbedtls_mpi_cmp_int(&R->Y, 0) != 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&R->Y, &grp->P, &R->Y));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
return (ret );
|
||||
}
|
||||
|
||||
int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
|
||||
{
|
||||
return ecp_opp(&e->group, (mbedtls_ecp_point *) p, (mbedtls_ecp_point *) p) ? -1 : 0;
|
||||
}
|
||||
|
||||
int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
|
||||
struct crypto_ec_point *p,
|
||||
const struct crypto_bignum *x, int y_bit)
|
||||
{
|
||||
mbedtls_mpi temp;
|
||||
mbedtls_mpi *y_sqr, *y;
|
||||
mbedtls_mpi_init(&temp);
|
||||
int ret = 0;
|
||||
|
||||
y = &((mbedtls_ecp_point *)p)->Y;
|
||||
|
||||
/* Faster way to find sqrt
|
||||
* Works only with curves having prime p
|
||||
* such that p ≡ 3 (mod 4)
|
||||
* y_ = (y2 ^ ((p+1)/4)) mod p
|
||||
*
|
||||
* if LSB of both x and y are same: y = y_
|
||||
* else y = p - y_
|
||||
* y_bit is LSB of x
|
||||
*/
|
||||
y_bit = (y_bit != 0);
|
||||
|
||||
y_sqr = (mbedtls_mpi *) crypto_ec_point_compute_y_sqr(e, x);
|
||||
|
||||
if (y_sqr) {
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&temp, &e->group.P, 1));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(&temp, NULL, &temp, 4));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(y, y_sqr, &temp, &e->group.P, NULL));
|
||||
|
||||
if (y_bit != mbedtls_mpi_get_bit(y, 0))
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(y, &e->group.P, y));
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&((mbedtls_ecp_point* )p)->X, (const mbedtls_mpi*) x));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&((mbedtls_ecp_point *)p)->Z, 1));
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&temp);
|
||||
mbedtls_mpi_free(y_sqr);
|
||||
os_free(y_sqr);
|
||||
return ret ? -1 : 0;
|
||||
}
|
||||
|
||||
int crypto_get_order(struct crypto_ec_group *group, struct crypto_bignum *x)
|
||||
{
|
||||
return mbedtls_mpi_copy((mbedtls_mpi *) x, &((mbedtls_ecp_group *)group)->N);
|
||||
}
|
||||
|
||||
struct crypto_bignum *crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
|
||||
const struct crypto_bignum *x)
|
||||
{
|
||||
mbedtls_mpi temp, temp2, num;
|
||||
int ret = 0;
|
||||
|
||||
mbedtls_mpi *y_sqr = os_zalloc(sizeof(mbedtls_mpi));
|
||||
if (y_sqr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_mpi_init(&temp);
|
||||
mbedtls_mpi_init(&temp2);
|
||||
mbedtls_mpi_init(&num);
|
||||
mbedtls_mpi_init(y_sqr);
|
||||
|
||||
/* y^2 = x^3 + ax + b mod P*/
|
||||
/* mbedtls does not have mod-add or mod-mul apis.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Calculate x^3 mod P*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&num, 3));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&temp, (const mbedtls_mpi *) x, &num, &e->group.P, NULL));
|
||||
|
||||
/* Calculate ax mod P*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&num, -3));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&temp2, (const mbedtls_mpi *) x, &num));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&temp2, &temp2, &e->group.P));
|
||||
|
||||
/* Calculate ax + b mod P. Note that b is already < P*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&temp2, &temp2, &e->group.B));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&temp2, &temp2, &e->group.P));
|
||||
|
||||
/* Calculate x^3 + ax + b mod P*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&temp2, &temp2, &temp));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(y_sqr, &temp2, &e->group.P));
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&temp);
|
||||
mbedtls_mpi_free(&temp2);
|
||||
mbedtls_mpi_free(&num);
|
||||
if (ret) {
|
||||
mbedtls_mpi_free(y_sqr);
|
||||
os_free(y_sqr);
|
||||
return NULL;
|
||||
} else {
|
||||
return (struct crypto_bignum *) y_sqr;
|
||||
}
|
||||
}
|
||||
|
||||
int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
|
||||
const struct crypto_ec_point *p)
|
||||
{
|
||||
return mbedtls_ecp_is_zero((mbedtls_ecp_point *) p);
|
||||
}
|
||||
|
||||
int crypto_ec_point_is_on_curve(struct crypto_ec *e,
|
||||
const struct crypto_ec_point *p)
|
||||
{
|
||||
mbedtls_mpi y_sqr_lhs, *y_sqr_rhs = NULL, two;
|
||||
int ret = 0, on_curve = 0;
|
||||
|
||||
mbedtls_mpi_init(&y_sqr_lhs);
|
||||
mbedtls_mpi_init(&two);
|
||||
|
||||
/* Calculate y^2 mod P*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&two, 2));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&y_sqr_lhs, &((const mbedtls_ecp_point *)p)->Y , &two, &e->group.P, NULL));
|
||||
|
||||
y_sqr_rhs = (mbedtls_mpi *) crypto_ec_point_compute_y_sqr(e, (const struct crypto_bignum *) & ((const mbedtls_ecp_point *)p)->X);
|
||||
|
||||
if (y_sqr_rhs && (mbedtls_mpi_cmp_mpi(y_sqr_rhs, &y_sqr_lhs) == 0)) {
|
||||
on_curve = 1;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&y_sqr_lhs);
|
||||
mbedtls_mpi_free(y_sqr_rhs);
|
||||
os_free(y_sqr_rhs);
|
||||
return (ret == 0) && (on_curve == 1);
|
||||
}
|
||||
|
||||
int crypto_ec_point_cmp(const struct crypto_ec *e,
|
||||
const struct crypto_ec_point *a,
|
||||
const struct crypto_ec_point *b)
|
||||
{
|
||||
return mbedtls_ecp_point_cmp((const mbedtls_ecp_point *) a,
|
||||
(const mbedtls_ecp_point *) b);
|
||||
}
|
||||
int crypto_key_compare(struct crypto_key *key1, struct crypto_key *key2)
|
||||
{
|
||||
if (mbedtls_pk_check_pair((mbedtls_pk_context *)key1, (mbedtls_pk_context *)key2) < 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void crypto_debug_print_point(const char *title, struct crypto_ec *e,
|
||||
const struct crypto_ec_point *point)
|
||||
{
|
||||
u8 x[32], y[32];
|
||||
|
||||
if (crypto_ec_point_to_bin(e, point, x, y) < 0) {
|
||||
wpa_printf(MSG_ERROR, "error: failed to get corrdinates\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wpa_hexdump(MSG_ERROR, "x:", x, 32);
|
||||
wpa_hexdump(MSG_ERROR, "y:", y, 32);
|
||||
}
|
||||
|
||||
static struct crypto_key *crypto_alloc_key(void)
|
||||
{
|
||||
mbedtls_pk_context *key = os_malloc(sizeof(*key));
|
||||
|
||||
if (!key) {
|
||||
wpa_printf(MSG_ERROR, "%s: memory allocation failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
mbedtls_pk_init(key);
|
||||
|
||||
return (struct crypto_key *)key;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *group,
|
||||
const u8 *buf, size_t len)
|
||||
{
|
||||
mbedtls_ecp_point *point = NULL;
|
||||
struct crypto_key *pkey = NULL;
|
||||
int ret;
|
||||
mbedtls_pk_context *key = (mbedtls_pk_context *)crypto_alloc_key();
|
||||
|
||||
if (!key) {
|
||||
wpa_printf(MSG_ERROR, "%s: memory allocation failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
point = (mbedtls_ecp_point *)crypto_ec_point_from_bin((struct crypto_ec *)group, buf);
|
||||
if (crypto_ec_point_is_at_infinity((struct crypto_ec *)group, (struct crypto_ec_point *)point)) {
|
||||
wpa_printf(MSG_ERROR, "Point is at infinity");
|
||||
goto fail;
|
||||
}
|
||||
if (!crypto_ec_point_is_on_curve((struct crypto_ec *)group, (struct crypto_ec_point *)point)) {
|
||||
wpa_printf(MSG_ERROR, "Point not on curve");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (mbedtls_ecp_check_pubkey((mbedtls_ecp_group *)group, point) < 0) { //typecast
|
||||
// ideally should have failed in upper condition, duplicate code??
|
||||
wpa_printf(MSG_ERROR, "Invalid key");
|
||||
goto fail;
|
||||
}
|
||||
mbedtls_ecp_keypair *ecp_key = malloc(sizeof (*ecp_key));
|
||||
if (!ecp_key) {
|
||||
wpa_printf(MSG_ERROR, "key allocation failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Init keypair */
|
||||
mbedtls_ecp_keypair_init(ecp_key);
|
||||
// TODO Is it needed? check?
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_copy(&ecp_key->Q, point));
|
||||
|
||||
/* Assign values */
|
||||
if( ( ret = mbedtls_pk_setup( key,
|
||||
mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY) ) ) != 0 )
|
||||
goto fail;
|
||||
|
||||
if (key->pk_ctx)
|
||||
os_free(key->pk_ctx);
|
||||
key->pk_ctx = ecp_key;
|
||||
mbedtls_ecp_copy(&mbedtls_pk_ec(*key)->Q, point);
|
||||
mbedtls_ecp_group_load(&mbedtls_pk_ec(*key)->grp, MBEDTLS_ECP_DP_SECP256R1);
|
||||
|
||||
pkey = (struct crypto_key *)key;
|
||||
cleanup:
|
||||
crypto_ec_point_deinit((struct crypto_ec_point *)point, 0);
|
||||
return pkey;
|
||||
fail:
|
||||
if (point)
|
||||
crypto_ec_point_deinit((struct crypto_ec_point *)point, 0);
|
||||
if (key)
|
||||
mbedtls_pk_free(key);
|
||||
pkey = NULL;
|
||||
return pkey;
|
||||
}
|
||||
|
||||
|
||||
void crypto_ec_free_key(struct crypto_key *key)
|
||||
{
|
||||
mbedtls_pk_context *pkey = (mbedtls_pk_context *)key;
|
||||
mbedtls_pk_free(pkey);
|
||||
os_free(key);
|
||||
}
|
||||
|
||||
struct crypto_ec_point *crypto_ec_get_public_key(struct crypto_key *key)
|
||||
{
|
||||
mbedtls_pk_context *pkey = (mbedtls_pk_context *)key;
|
||||
|
||||
return (struct crypto_ec_point *)&mbedtls_pk_ec(*pkey)->Q;
|
||||
}
|
||||
|
||||
|
||||
int crypto_ec_get_priv_key_der(struct crypto_key *key, unsigned char **key_data, int *key_len)
|
||||
{
|
||||
mbedtls_pk_context *pkey = (mbedtls_pk_context *)key;
|
||||
char der_data[ECP_PRV_DER_MAX_BYTES];
|
||||
|
||||
*key_len = mbedtls_pk_write_key_der(pkey, (unsigned char *)der_data, ECP_PRV_DER_MAX_BYTES);
|
||||
if (!*key_len)
|
||||
return -1;
|
||||
|
||||
*key_data = os_malloc(*key_len);
|
||||
|
||||
if (!*key_data) {
|
||||
wpa_printf(MSG_ERROR, "memory allocation failed\n");
|
||||
return -1;
|
||||
}
|
||||
os_memcpy(*key_data, der_data, *key_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct crypto_ec_group *crypto_ec_get_group_from_key(struct crypto_key *key)
|
||||
{
|
||||
mbedtls_pk_context *pkey = (mbedtls_pk_context *)key;
|
||||
|
||||
return (struct crypto_ec_group *)&(mbedtls_pk_ec(*pkey)->grp);
|
||||
}
|
||||
|
||||
struct crypto_bignum *crypto_ec_get_private_key(struct crypto_key *key)
|
||||
{
|
||||
mbedtls_pk_context *pkey = (mbedtls_pk_context *)key;
|
||||
|
||||
return ((struct crypto_bignum *)&(mbedtls_pk_ec(*pkey)->d));
|
||||
}
|
||||
|
||||
int crypto_ec_get_publickey_buf(struct crypto_key *key, u8 *key_buf, int len)
|
||||
{
|
||||
mbedtls_pk_context *pkey = (mbedtls_pk_context *)key;
|
||||
unsigned char buf[MBEDTLS_MPI_MAX_SIZE + 10]; /* tag, length + MPI */
|
||||
unsigned char *c = buf + sizeof(buf );
|
||||
size_t pk_len = 0;
|
||||
|
||||
memset(buf, 0, sizeof(buf) );
|
||||
pk_len = mbedtls_pk_write_pubkey( &c, buf, pkey);
|
||||
|
||||
if (!pk_len)
|
||||
return -1;
|
||||
|
||||
if (len == 0)
|
||||
return pk_len;
|
||||
|
||||
os_memcpy(key_buf, buf + MBEDTLS_MPI_MAX_SIZE + 10 - pk_len, pk_len);
|
||||
|
||||
return pk_len;
|
||||
}
|
||||
|
||||
int crypto_write_pubkey_der(struct crypto_key *key, unsigned char **key_buf)
|
||||
{
|
||||
unsigned char output_buf[1600] = {0};
|
||||
int len = mbedtls_pk_write_pubkey_der((mbedtls_pk_context *)key, output_buf, 1600);
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
|
||||
*key_buf = os_malloc(len);
|
||||
if (!*key_buf) {
|
||||
return 0;
|
||||
}
|
||||
os_memcpy(*key_buf, output_buf + 1600 - len, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
struct crypto_key *crypto_ec_get_key(const u8 *privkey, size_t privkey_len)
|
||||
{
|
||||
int ret;
|
||||
mbedtls_pk_context *kctx = (mbedtls_pk_context *)crypto_alloc_key();
|
||||
|
||||
if (!kctx) {
|
||||
wpa_printf(MSG_ERROR, "memory allocation failed\n");
|
||||
return NULL;
|
||||
}
|
||||
ret = mbedtls_pk_parse_key(kctx, privkey, privkey_len, NULL, 0);
|
||||
|
||||
if (ret < 0) {
|
||||
//crypto_print_error_string(ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return (struct crypto_key *)kctx;
|
||||
|
||||
fail:
|
||||
mbedtls_pk_free(kctx);
|
||||
os_free(kctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int crypto_ec_get_mbedtls_to_nist_group_id(int id)
|
||||
{
|
||||
unsigned int nist_grpid = 0;
|
||||
switch (id) {
|
||||
case MBEDTLS_ECP_DP_SECP256R1:
|
||||
nist_grpid = 19;
|
||||
break;
|
||||
case MBEDTLS_ECP_DP_SECP384R1:
|
||||
nist_grpid = 20;
|
||||
break;
|
||||
case MBEDTLS_ECP_DP_SECP521R1:
|
||||
nist_grpid = 21;
|
||||
break;
|
||||
case MBEDTLS_ECP_DP_BP256R1:
|
||||
nist_grpid = 28;
|
||||
break;
|
||||
case MBEDTLS_ECP_DP_BP384R1:
|
||||
nist_grpid = 29;
|
||||
break;
|
||||
case MBEDTLS_ECP_DP_BP512R1:
|
||||
nist_grpid = 30;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return nist_grpid;
|
||||
}
|
||||
|
||||
int crypto_ec_get_curve_id(const struct crypto_ec_group *group)
|
||||
{
|
||||
mbedtls_ecp_group *grp = (mbedtls_ecp_group *)group;
|
||||
return (crypto_ec_get_mbedtls_to_nist_group_id(grp->id));
|
||||
}
|
||||
|
||||
int crypto_ecdh(struct crypto_key *key_own, struct crypto_key *key_peer,
|
||||
u8 *secret, size_t *secret_len)
|
||||
{
|
||||
mbedtls_ecdh_context *ctx;
|
||||
mbedtls_pk_context *own = (mbedtls_pk_context *)key_own;
|
||||
mbedtls_pk_context *peer = (mbedtls_pk_context *)key_peer;
|
||||
|
||||
int ret = -1;
|
||||
|
||||
*secret_len = 0;
|
||||
ctx = os_malloc(sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_CTX_new failed: %s",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mbedtls_ecdh_init(ctx);
|
||||
/* No need to setup, done through mbedtls_ecdh_get_params */
|
||||
|
||||
/* set params from our key */
|
||||
if (mbedtls_ecdh_get_params(ctx, mbedtls_pk_ec(*own), MBEDTLS_ECDH_OURS) < 0) {
|
||||
wpa_printf(MSG_ERROR, "failed to set our ecdh params\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifndef DPP_MAX_SHARED_SECRET_LEN
|
||||
#define DPP_MAX_SHARED_SECRET_LEN 66
|
||||
#endif
|
||||
/* set params from peers key */
|
||||
if (mbedtls_ecdh_get_params(ctx, mbedtls_pk_ec(*peer), MBEDTLS_ECDH_THEIRS) < 0) {
|
||||
wpa_printf(MSG_ERROR, "failed to set peer's ecdh params\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (mbedtls_ecdh_calc_secret(ctx, secret_len, secret, DPP_MAX_SHARED_SECRET_LEN, NULL, NULL) < 0) {
|
||||
wpa_printf(MSG_ERROR, "failed to calculate secret\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) {
|
||||
wpa_printf(MSG_ERROR, "secret len=%d is too big\n", *secret_len);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
fail:
|
||||
mbedtls_ecdh_free(ctx);
|
||||
os_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int crypto_ecdsa_get_sign(unsigned char *hash,
|
||||
const struct crypto_bignum *r, const struct crypto_bignum *s, struct crypto_key *csign, int hash_len)
|
||||
{
|
||||
int ret = -1;
|
||||
mbedtls_pk_context *pkey = (mbedtls_pk_context *)csign;
|
||||
|
||||
mbedtls_ecdsa_context *ctx = os_malloc(sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
wpa_printf(MSG_ERROR,"failed to allcate memory\n");
|
||||
return -1;
|
||||
}
|
||||
mbedtls_ecdsa_init(ctx);
|
||||
|
||||
if (mbedtls_ecdsa_from_keypair(ctx, mbedtls_pk_ec(*pkey)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
ret = mbedtls_ecdsa_sign(&ctx->grp, (mbedtls_mpi *)r, (mbedtls_mpi *)s,
|
||||
&ctx->d, hash, SHA256_MAC_LEN, crypto_rng_wrapper, NULL);
|
||||
|
||||
fail:
|
||||
mbedtls_ecdsa_free(ctx);
|
||||
os_free(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int crypto_edcsa_sign_verify(const unsigned char *hash,
|
||||
const struct crypto_bignum *r, const struct crypto_bignum *s, struct crypto_key *csign, int hlen)
|
||||
{
|
||||
mbedtls_pk_context *pkey = (mbedtls_pk_context *)csign;
|
||||
int ret = 0;
|
||||
|
||||
mbedtls_ecdsa_context *ctx = os_malloc(sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
wpa_printf(MSG_ERROR, "failed to allcate memory\n");
|
||||
return ret;
|
||||
}
|
||||
mbedtls_ecdsa_init(ctx);
|
||||
|
||||
if (mbedtls_ecdsa_from_keypair(ctx, mbedtls_pk_ec(*pkey)) < 0)
|
||||
return ret;
|
||||
|
||||
if((ret = mbedtls_ecdsa_verify(&ctx->grp, hash, hlen,
|
||||
&ctx->Q, (mbedtls_mpi *)r, (mbedtls_mpi *)s)) != 0){
|
||||
wpa_printf(MSG_ERROR, "ecdsa verification failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
mbedtls_ecdsa_free(ctx);
|
||||
os_free(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void crypto_debug_print_ec_key(const char *title, struct crypto_key *key)
|
||||
{
|
||||
#ifdef DEBUG_PRINT
|
||||
mbedtls_pk_context *pkey = (mbedtls_pk_context *)key;
|
||||
mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( *pkey );
|
||||
u8 x[32], y[32], d[32];
|
||||
wpa_printf(MSG_ERROR, "curve: %s\n",
|
||||
mbedtls_ecp_curve_info_from_grp_id( ecp->grp.id )->name );
|
||||
int len = mbedtls_mpi_size((mbedtls_mpi *)crypto_ec_get_prime((struct crypto_ec *)crypto_ec_get_group_from_key(key)));
|
||||
|
||||
wpa_printf(MSG_ERROR, "prime len is %d\n", len);
|
||||
crypto_ec_point_to_bin((struct crypto_ec *)crypto_ec_get_group_from_key(key), crypto_ec_get_public_key(key), x, y);
|
||||
crypto_bignum_to_bin(crypto_ec_get_private_key(key),
|
||||
d, len, len);
|
||||
wpa_hexdump(MSG_ERROR, "Q_x:", x, 32);
|
||||
wpa_hexdump(MSG_ERROR, "Q_y:", y, 32);
|
||||
wpa_hexdump(MSG_ERROR, "d: ", d , 32);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct crypto_key *crypto_ec_parse_subpub_key(const unsigned char *p, size_t len)
|
||||
{
|
||||
int ret;
|
||||
mbedtls_pk_context *pkey = (mbedtls_pk_context *)crypto_alloc_key();
|
||||
ret = mbedtls_pk_parse_subpubkey((unsigned char **)&p, p + len, pkey);
|
||||
|
||||
if (ret < 0) {
|
||||
os_free(pkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (struct crypto_key *)pkey;
|
||||
}
|
||||
|
||||
int crypto_is_ec_key(struct crypto_key *key)
|
||||
{
|
||||
int ret = mbedtls_pk_can_do((mbedtls_pk_context *)key, MBEDTLS_PK_ECKEY);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct crypto_key * crypto_ec_gen_keypair(u16 ike_group)
|
||||
{
|
||||
mbedtls_pk_context *kctx = (mbedtls_pk_context *)crypto_alloc_key();
|
||||
|
||||
if (!kctx) {
|
||||
wpa_printf(MSG_ERROR, "%s: memory allocation failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(mbedtls_pk_setup(kctx,
|
||||
mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) != 0 )
|
||||
goto fail;
|
||||
|
||||
mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(*kctx), //get this from argument
|
||||
crypto_rng_wrapper, NULL);
|
||||
|
||||
return (struct crypto_key *)kctx;
|
||||
fail:
|
||||
mbedtls_pk_free(kctx);
|
||||
os_free(kctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ECParameters ::= CHOICE {
|
||||
* namedCurve OBJECT IDENTIFIER
|
||||
* }
|
||||
*/
|
||||
static int pk_write_ec_param( unsigned char **p, unsigned char *start,
|
||||
mbedtls_ecp_keypair *ec )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
const char *oid;
|
||||
size_t oid_len;
|
||||
|
||||
if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
|
||||
|
||||
return( (int) len );
|
||||
}
|
||||
|
||||
static int pk_write_ec_pubkey_formatted( unsigned char **p, unsigned char *start,
|
||||
mbedtls_ecp_keypair *ec, int format )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
|
||||
|
||||
if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q,
|
||||
format,
|
||||
&len, buf, sizeof( buf ) ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( *p < start || (size_t)( *p - start ) < len )
|
||||
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
|
||||
|
||||
*p -= len;
|
||||
memcpy( *p, buf, len );
|
||||
|
||||
return( (int) len );
|
||||
}
|
||||
|
||||
int mbedtls_pk_write_pubkey_formatted( unsigned char **p, unsigned char *start,
|
||||
const mbedtls_pk_context *key, int format )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
|
||||
MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey_formatted( p, start, mbedtls_pk_ec( *key ), format ) );
|
||||
else
|
||||
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
|
||||
|
||||
return( (int) len );
|
||||
}
|
||||
|
||||
int crypto_pk_write_formatted_pubkey_der(mbedtls_pk_context *key, unsigned char *buf, size_t size, int format)
|
||||
{
|
||||
int ret;
|
||||
unsigned char *c;
|
||||
size_t len = 0, par_len = 0, oid_len;
|
||||
const char *oid;
|
||||
|
||||
if( size == 0 )
|
||||
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
|
||||
|
||||
c = buf + size;
|
||||
|
||||
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey_formatted( &c, buf, key, format) );
|
||||
|
||||
if( c - buf < 1 )
|
||||
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
|
||||
|
||||
/*
|
||||
* SubjectPublicKeyInfo ::= SEQUENCE {
|
||||
* algorithm AlgorithmIdentifier,
|
||||
* subjectPublicKey BIT STRING }
|
||||
*/
|
||||
*--c = 0;
|
||||
len += 1;
|
||||
|
||||
|
||||
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
|
||||
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );
|
||||
|
||||
if( ( ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ),
|
||||
&oid, &oid_len ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
|
||||
{
|
||||
MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) );
|
||||
}
|
||||
|
||||
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
|
||||
par_len ) );
|
||||
|
||||
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
|
||||
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
|
||||
MBEDTLS_ASN1_SEQUENCE ) );
|
||||
|
||||
return( (int) len );
|
||||
}
|
||||
|
||||
int crypto_ec_write_pub_key(struct crypto_key *key, unsigned char **key_buf)
|
||||
{
|
||||
unsigned char output_buf[1600] = {0};
|
||||
int len = crypto_pk_write_formatted_pubkey_der((mbedtls_pk_context *)key, output_buf, 1600, 1);
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
|
||||
*key_buf = os_malloc(len);
|
||||
if (!*key_buf) {
|
||||
wpa_printf(MSG_ERROR, "%s: memory allocation failed\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
os_memcpy(*key_buf, output_buf + 1600 - len, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
#endif /* CONFIG_ECC */
|
@ -1,605 +0,0 @@
|
||||
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "esp_system.h"
|
||||
#include "mbedtls/bignum.h"
|
||||
#endif
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include "utils/common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
int crypto_get_random(void *buf, size_t len)
|
||||
{
|
||||
if (!buf) {
|
||||
return -1;
|
||||
}
|
||||
esp_fill_random(buf, len);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct crypto_bignum *crypto_bignum_init(void)
|
||||
{
|
||||
mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi));
|
||||
if (bn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_mpi_init(bn);
|
||||
|
||||
return (struct crypto_bignum *)bn;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_bignum *crypto_bignum_init_set(const u8 *buf, size_t len)
|
||||
{
|
||||
int ret = 0;
|
||||
mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi));
|
||||
if (bn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(bn, buf, len));
|
||||
return (struct crypto_bignum *) bn;
|
||||
|
||||
cleanup:
|
||||
os_free(bn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
|
||||
{
|
||||
mbedtls_mpi_free((mbedtls_mpi *)n);
|
||||
os_free((mbedtls_mpi *)n);
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_to_bin(const struct crypto_bignum *a,
|
||||
u8 *buf, size_t buflen, size_t padlen)
|
||||
{
|
||||
int num_bytes, offset;
|
||||
|
||||
if (padlen > buflen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
num_bytes = mbedtls_mpi_size((mbedtls_mpi *) a);
|
||||
|
||||
if ((size_t) num_bytes > buflen) {
|
||||
return -1;
|
||||
}
|
||||
if (padlen > (size_t) num_bytes) {
|
||||
offset = padlen - num_bytes;
|
||||
} else {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
os_memset(buf, 0, offset);
|
||||
mbedtls_mpi_write_binary((mbedtls_mpi *) a, buf + offset, mbedtls_mpi_size((mbedtls_mpi *)a) );
|
||||
|
||||
return num_bytes + offset;
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_add(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_bignum *c)
|
||||
{
|
||||
return mbedtls_mpi_add_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
|
||||
-1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_mod(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_bignum *c)
|
||||
{
|
||||
return mbedtls_mpi_mod_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_exptmod(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
const struct crypto_bignum *c,
|
||||
struct crypto_bignum *d)
|
||||
{
|
||||
return mbedtls_mpi_exp_mod((mbedtls_mpi *) d, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b, (const mbedtls_mpi *) c, NULL) ? -1 : 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_inverse(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_bignum *c)
|
||||
{
|
||||
return mbedtls_mpi_inv_mod((mbedtls_mpi *) c, (const mbedtls_mpi *) a,
|
||||
(const mbedtls_mpi *) b) ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_sub(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_bignum *c)
|
||||
{
|
||||
return mbedtls_mpi_sub_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
|
||||
-1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_div(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_bignum *c)
|
||||
{
|
||||
return mbedtls_mpi_div_mpi((mbedtls_mpi *) c, NULL, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
|
||||
-1 : 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 res;
|
||||
#if ALLOW_EVEN_MOD // Must enable this macro if c is even.
|
||||
mbedtls_mpi temp;
|
||||
mbedtls_mpi_init(&temp);
|
||||
|
||||
res = mbedtls_mpi_mul_mpi(&temp, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b);
|
||||
if (res) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = mbedtls_mpi_mod_mpi((mbedtls_mpi *) d, &temp, (mbedtls_mpi *) c);
|
||||
|
||||
mbedtls_mpi_free(&temp);
|
||||
#else
|
||||
// Works with odd modulus only, but it is faster with HW acceleration
|
||||
res = esp_mpi_mul_mpi_mod((mbedtls_mpi *) d, (mbedtls_mpi *) a, (mbedtls_mpi *) b, (mbedtls_mpi *) c);
|
||||
#endif
|
||||
return res ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_cmp(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b)
|
||||
{
|
||||
return mbedtls_mpi_cmp_mpi((const mbedtls_mpi *) a, (const mbedtls_mpi *) b);
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_bits(const struct crypto_bignum *a)
|
||||
{
|
||||
return mbedtls_mpi_bitlen((const mbedtls_mpi *) a);
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_is_zero(const struct crypto_bignum *a)
|
||||
{
|
||||
return (mbedtls_mpi_cmp_int((const mbedtls_mpi *) a, 0) == 0);
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_is_one(const struct crypto_bignum *a)
|
||||
{
|
||||
return (mbedtls_mpi_cmp_int((const mbedtls_mpi *) a, 1) == 0);
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_legendre(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *p)
|
||||
{
|
||||
mbedtls_mpi exp, tmp;
|
||||
int res = -2, ret;
|
||||
|
||||
mbedtls_mpi_init(&exp);
|
||||
mbedtls_mpi_init(&tmp);
|
||||
|
||||
/* exp = (p-1) / 2 */
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&exp, (const mbedtls_mpi *) p, 1));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&exp, 1));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&tmp, (const mbedtls_mpi *) a, &exp, (const mbedtls_mpi *) p, NULL));
|
||||
|
||||
if (mbedtls_mpi_cmp_int(&tmp, 1) == 0) {
|
||||
res = 1;
|
||||
} else if (mbedtls_mpi_cmp_int(&tmp, 0) == 0
|
||||
/* The below check is workaround for the case where HW
|
||||
* does not behave properly for X ^ A mod M when X is
|
||||
* power of M. Instead of returning value 0, value M is
|
||||
* returned.*/
|
||||
|| mbedtls_mpi_cmp_mpi(&tmp, (const mbedtls_mpi *)p) == 0) {
|
||||
res = 0;
|
||||
} else {
|
||||
res = -1;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&tmp);
|
||||
mbedtls_mpi_free(&exp);
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ECC
|
||||
struct crypto_ec {
|
||||
mbedtls_ecp_group group;
|
||||
};
|
||||
|
||||
struct crypto_ec *crypto_ec_init(int group)
|
||||
{
|
||||
struct crypto_ec *e;
|
||||
|
||||
mbedtls_ecp_group_id grp_id;
|
||||
|
||||
/* IANA registry to mbedtls internal mapping*/
|
||||
switch (group) {
|
||||
case IANA_SECP256R1:
|
||||
/* For now just support NIST-P256.
|
||||
* This is of type "short Weierstrass".
|
||||
*/
|
||||
grp_id = MBEDTLS_ECP_DP_SECP256R1;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
|
||||
}
|
||||
e = os_zalloc(sizeof(*e));
|
||||
if (e == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_ecp_group_init(&e->group);
|
||||
|
||||
if (mbedtls_ecp_group_load(&e->group, grp_id)) {
|
||||
crypto_ec_deinit(e);
|
||||
e = NULL;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
void crypto_ec_deinit(struct crypto_ec *e)
|
||||
{
|
||||
if (e == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
mbedtls_ecp_group_free(&e->group);
|
||||
os_free(e);
|
||||
}
|
||||
|
||||
|
||||
struct crypto_ec_point *crypto_ec_point_init(struct crypto_ec *e)
|
||||
{
|
||||
mbedtls_ecp_point *pt;
|
||||
if (e == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pt = os_zalloc(sizeof(mbedtls_ecp_point));
|
||||
|
||||
if( pt == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_ecp_point_init(pt);
|
||||
|
||||
return (struct crypto_ec_point *) pt;
|
||||
}
|
||||
|
||||
|
||||
size_t crypto_ec_prime_len(struct crypto_ec *e)
|
||||
{
|
||||
return mbedtls_mpi_size(&e->group.P);
|
||||
}
|
||||
|
||||
|
||||
size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
|
||||
{
|
||||
return mbedtls_mpi_bitlen(&e->group.P);
|
||||
}
|
||||
|
||||
|
||||
const struct crypto_bignum *crypto_ec_get_prime(struct crypto_ec *e)
|
||||
{
|
||||
return (const struct crypto_bignum *) &e->group.P;
|
||||
}
|
||||
|
||||
|
||||
const struct crypto_bignum *crypto_ec_get_order(struct crypto_ec *e)
|
||||
{
|
||||
return (const struct crypto_bignum *) &e->group.N;
|
||||
}
|
||||
|
||||
|
||||
void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
|
||||
{
|
||||
mbedtls_ecp_point_free((mbedtls_ecp_point *) p);
|
||||
os_free(p);
|
||||
}
|
||||
|
||||
|
||||
int crypto_ec_point_to_bin(struct crypto_ec *e,
|
||||
const struct crypto_ec_point *point, u8 *x, u8 *y)
|
||||
{
|
||||
int len = mbedtls_mpi_size(&e->group.P);
|
||||
|
||||
if (x) {
|
||||
if(crypto_bignum_to_bin((struct crypto_bignum *) & ((mbedtls_ecp_point *) point)->X,
|
||||
x, len, len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (y) {
|
||||
if(crypto_bignum_to_bin((struct crypto_bignum *) & ((mbedtls_ecp_point *) point)->Y,
|
||||
y, len, len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_ec_point *crypto_ec_point_from_bin(struct crypto_ec *e,
|
||||
const u8 *val)
|
||||
{
|
||||
mbedtls_ecp_point *pt;
|
||||
int len, ret;
|
||||
|
||||
if (e == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = mbedtls_mpi_size(&e->group.P);
|
||||
|
||||
pt = os_zalloc(sizeof(mbedtls_ecp_point));
|
||||
mbedtls_ecp_point_init(pt);
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->X, val, len));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->Y, val + len, len));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset((&pt->Z), 1));
|
||||
|
||||
return (struct crypto_ec_point *) pt;
|
||||
|
||||
cleanup:
|
||||
mbedtls_ecp_point_free(pt);
|
||||
os_free(pt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
mbedtls_mpi one;
|
||||
|
||||
mbedtls_mpi_init(&one);
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset( &one, 1 ));
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&e->group, (mbedtls_ecp_point *) c, &one, (const mbedtls_ecp_point *)a , &one, (const mbedtls_ecp_point *)b));
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&one);
|
||||
return ret ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
|
||||
mbedtls_entropy_init(&entropy);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
|
||||
NULL, 0));
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&e->group,
|
||||
(mbedtls_ecp_point *) res,
|
||||
(const mbedtls_mpi *)b,
|
||||
(const mbedtls_ecp_point *)p,
|
||||
mbedtls_ctr_drbg_random,
|
||||
&ctr_drbg));
|
||||
cleanup:
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
return ret ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/* Currently mbedtls does not have any function for inverse
|
||||
* This function calculates inverse of a point.
|
||||
* Set R = -P
|
||||
*/
|
||||
static int ecp_opp( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point *P)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Copy */
|
||||
if (R != P) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P));
|
||||
}
|
||||
|
||||
/* In-place opposite */
|
||||
if (mbedtls_mpi_cmp_int( &R->Y, 0) != 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&R->Y, &grp->P, &R->Y));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
return ( ret );
|
||||
}
|
||||
|
||||
int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
|
||||
{
|
||||
return ecp_opp(&e->group, (mbedtls_ecp_point *) p, (mbedtls_ecp_point *) p) ? -1 : 0;
|
||||
}
|
||||
|
||||
int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
|
||||
struct crypto_ec_point *p,
|
||||
const struct crypto_bignum *x, int y_bit)
|
||||
{
|
||||
mbedtls_mpi temp;
|
||||
mbedtls_mpi *y_sqr, *y;
|
||||
mbedtls_mpi_init(&temp);
|
||||
int ret = 0;
|
||||
|
||||
y = &((mbedtls_ecp_point *)p)->Y;
|
||||
|
||||
/* Faster way to find sqrt
|
||||
* Works only with curves having prime p
|
||||
* such that p ≡ 3 (mod 4)
|
||||
* y_ = (y2 ^ ((p+1)/4)) mod p
|
||||
*
|
||||
* if LSB of both x and y are same: y = y_
|
||||
* else y = p - y_
|
||||
* y_bit is LSB of x
|
||||
*/
|
||||
y_bit = (y_bit != 0);
|
||||
|
||||
y_sqr = (mbedtls_mpi *) crypto_ec_point_compute_y_sqr(e, x);
|
||||
|
||||
if (y_sqr) {
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&temp, &e->group.P, 1));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(&temp, NULL, &temp, 4));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(y, y_sqr, &temp, &e->group.P, NULL));
|
||||
|
||||
if (y_bit != mbedtls_mpi_get_bit(y, 0))
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(y, &e->group.P, y));
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&((mbedtls_ecp_point* )p)->X, (const mbedtls_mpi*) x));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&((mbedtls_ecp_point *)p)->Z, 1));
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&temp);
|
||||
mbedtls_mpi_free(y_sqr);
|
||||
os_free(y_sqr);
|
||||
return ret ? -1 : 0;
|
||||
}
|
||||
|
||||
struct crypto_bignum *
|
||||
crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
|
||||
const struct crypto_bignum *x)
|
||||
{
|
||||
mbedtls_mpi temp, temp2, num;
|
||||
int ret = 0;
|
||||
|
||||
mbedtls_mpi *y_sqr = os_zalloc(sizeof(mbedtls_mpi));
|
||||
if (y_sqr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_mpi_init(&temp);
|
||||
mbedtls_mpi_init(&temp2);
|
||||
mbedtls_mpi_init(&num);
|
||||
mbedtls_mpi_init(y_sqr);
|
||||
|
||||
/* y^2 = x^3 + ax + b mod P*/
|
||||
/* mbedtls does not have mod-add or mod-mul apis.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Calculate x^3 mod P*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset( &num, 3));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&temp, (const mbedtls_mpi *) x, &num, &e->group.P, NULL));
|
||||
|
||||
/* Calculate ax mod P*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset( &num, -3));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&temp2, (const mbedtls_mpi *) x, &num));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&temp2, &temp2, &e->group.P));
|
||||
|
||||
/* Calculate ax + b mod P. Note that b is already < P*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&temp2, &temp2, &e->group.B));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&temp2, &temp2, &e->group.P));
|
||||
|
||||
/* Calculate x^3 + ax + b mod P*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&temp2, &temp2, &temp));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(y_sqr, &temp2, &e->group.P));
|
||||
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&temp);
|
||||
mbedtls_mpi_free(&temp2);
|
||||
mbedtls_mpi_free(&num);
|
||||
if (ret) {
|
||||
mbedtls_mpi_free(y_sqr);
|
||||
os_free(y_sqr);
|
||||
return NULL;
|
||||
} else {
|
||||
return (struct crypto_bignum *) y_sqr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
|
||||
const struct crypto_ec_point *p)
|
||||
{
|
||||
return mbedtls_ecp_is_zero((mbedtls_ecp_point *) p);
|
||||
}
|
||||
|
||||
int crypto_ec_point_is_on_curve(struct crypto_ec *e,
|
||||
const struct crypto_ec_point *p)
|
||||
{
|
||||
mbedtls_mpi y_sqr_lhs, *y_sqr_rhs = NULL, two;
|
||||
int ret = 0, on_curve = 0;
|
||||
|
||||
mbedtls_mpi_init(&y_sqr_lhs);
|
||||
mbedtls_mpi_init(&two);
|
||||
|
||||
/* Calculate y^2 mod P*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset( &two, 2));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&y_sqr_lhs, &((const mbedtls_ecp_point *)p)->Y , &two, &e->group.P, NULL));
|
||||
|
||||
y_sqr_rhs = (mbedtls_mpi *) crypto_ec_point_compute_y_sqr(e, (const struct crypto_bignum *) & ((const mbedtls_ecp_point *)p)->X);
|
||||
|
||||
if (y_sqr_rhs && (mbedtls_mpi_cmp_mpi(y_sqr_rhs, &y_sqr_lhs) == 0)) {
|
||||
on_curve = 1;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&y_sqr_lhs);
|
||||
mbedtls_mpi_free(y_sqr_rhs);
|
||||
os_free(y_sqr_rhs);
|
||||
return (ret == 0) && (on_curve == 1);
|
||||
}
|
||||
|
||||
int crypto_ec_point_cmp(const struct crypto_ec *e,
|
||||
const struct crypto_ec_point *a,
|
||||
const struct crypto_ec_point *b)
|
||||
{
|
||||
return mbedtls_ecp_point_cmp((const mbedtls_ecp_point *) a,
|
||||
(const mbedtls_ecp_point *) b);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ECC */
|
87
components/wpa_supplicant/src/crypto/sha256-kdf.c
Normal file
87
components/wpa_supplicant/src/crypto/sha256-kdf.c
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* HMAC-SHA256 KDF (RFC 5295) and HKDF-Expand(SHA256) (RFC 5869)
|
||||
* Copyright (c) 2014-2017, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include "utils/common.h"
|
||||
|
||||
#include "crypto/sha256.h"
|
||||
|
||||
|
||||
/**
|
||||
* hmac_sha256_kdf - HMAC-SHA256 based KDF (RFC 5295)
|
||||
* @secret: Key for KDF
|
||||
* @secret_len: Length of the key in bytes
|
||||
* @label: A unique label for each purpose of the KDF or %NULL to select
|
||||
* RFC 5869 HKDF-Expand() with arbitrary seed (= info)
|
||||
* @seed: Seed value to bind into the key
|
||||
* @seed_len: Length of the seed
|
||||
* @out: Buffer for the generated pseudo-random key
|
||||
* @outlen: Number of bytes of key to generate
|
||||
* Returns: 0 on success, -1 on failure.
|
||||
*
|
||||
* This function is used to derive new, cryptographically separate keys from a
|
||||
* given key in ERP. This KDF is defined in RFC 5295, Chapter 3.1.2. When used
|
||||
* with label = NULL and seed = info, this matches HKDF-Expand() defined in
|
||||
* RFC 5869, Chapter 2.3.
|
||||
*/
|
||||
int hmac_sha256_kdf(const u8 *secret, size_t secret_len,
|
||||
const char *label, const u8 *seed, size_t seed_len,
|
||||
u8 *out, size_t outlen)
|
||||
{
|
||||
u8 T[SHA256_MAC_LEN];
|
||||
u8 iter = 1;
|
||||
const unsigned char *addr[4];
|
||||
size_t len[4];
|
||||
size_t pos, clen;
|
||||
|
||||
addr[0] = T;
|
||||
len[0] = SHA256_MAC_LEN;
|
||||
if (label) {
|
||||
addr[1] = (const unsigned char *) label;
|
||||
len[1] = os_strlen(label) + 1;
|
||||
} else {
|
||||
addr[1] = (const u8 *) "";
|
||||
len[1] = 0;
|
||||
}
|
||||
addr[2] = seed;
|
||||
len[2] = seed_len;
|
||||
addr[3] = &iter;
|
||||
len[3] = 1;
|
||||
|
||||
if (hmac_sha256_vector(secret, secret_len, 3, &addr[1], &len[1], T) < 0)
|
||||
return -1;
|
||||
|
||||
pos = 0;
|
||||
for (;;) {
|
||||
clen = outlen - pos;
|
||||
if (clen > SHA256_MAC_LEN)
|
||||
clen = SHA256_MAC_LEN;
|
||||
os_memcpy(out + pos, T, clen);
|
||||
pos += clen;
|
||||
|
||||
if (pos == outlen)
|
||||
break;
|
||||
|
||||
if (iter == 255) {
|
||||
os_memset(out, 0, outlen);
|
||||
os_memset(T, 0, SHA256_MAC_LEN);
|
||||
return -1;
|
||||
}
|
||||
iter++;
|
||||
|
||||
if (hmac_sha256_vector(secret, secret_len, 4, addr, len, T) < 0)
|
||||
{
|
||||
os_memset(out, 0, outlen);
|
||||
os_memset(T, 0, SHA256_MAC_LEN);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
os_memset(T, 0, SHA256_MAC_LEN);
|
||||
return 0;
|
||||
}
|
@ -116,11 +116,11 @@ int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
* @data_len: Length of the data area
|
||||
* @mac: Buffer for the hash (20 bytes)
|
||||
*/
|
||||
void
|
||||
int
|
||||
hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
|
||||
size_t data_len, u8 *mac)
|
||||
{
|
||||
hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
|
||||
return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac);
|
||||
void hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
|
||||
int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
|
||||
size_t data_len, u8 *mac);
|
||||
int sha256_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
|
||||
@ -30,4 +30,8 @@ void tls_prf_sha256(const u8 *secret, size_t secret_len,
|
||||
const char *label, const u8 *seed, size_t seed_len,
|
||||
u8 *out, size_t outlen);
|
||||
|
||||
int hmac_sha256_kdf(const u8 *secret, size_t secret_len,
|
||||
const char *label, const u8 *seed, size_t seed_len,
|
||||
u8 *out, size_t outlen);
|
||||
|
||||
#endif /* SHA256_H */
|
||||
|
@ -124,7 +124,7 @@ static int tlsv1_add_cert(struct x509_certificate **chain,
|
||||
return -1;
|
||||
}
|
||||
|
||||
der = base64_decode(pos, end - pos, &der_len);
|
||||
der = (unsigned char *)base64_decode((const char *)pos, end - pos, &der_len);
|
||||
if (der == NULL) {
|
||||
wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM "
|
||||
"certificate");
|
||||
@ -249,7 +249,7 @@ static struct crypto_private_key * tlsv1_set_key_pem(const u8 *key, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
der = base64_decode(pos, end - pos, &der_len);
|
||||
der = (unsigned char *)base64_decode((const char *)pos, end - pos, &der_len);
|
||||
if (!der)
|
||||
return NULL;
|
||||
pkey = crypto_private_key_import(der, der_len, NULL);
|
||||
@ -277,7 +277,7 @@ static struct crypto_private_key * tlsv1_set_key_enc_pem(const u8 *key,
|
||||
if (!end)
|
||||
return NULL;
|
||||
|
||||
der = base64_decode(pos, end - pos, &der_len);
|
||||
der = (unsigned char *)base64_decode((const char *)pos, end - pos, &der_len);
|
||||
if (!der)
|
||||
return NULL;
|
||||
pkey = crypto_private_key_import(der, der_len, passwd);
|
||||
@ -449,7 +449,7 @@ static int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred,
|
||||
return -1;
|
||||
}
|
||||
|
||||
der = base64_decode(pos, end - pos, &der_len);
|
||||
der = (unsigned char *)base64_decode((const char *)pos, end - pos, &der_len);
|
||||
if (der == NULL) {
|
||||
wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams");
|
||||
return -1;
|
||||
|
@ -1365,7 +1365,6 @@ static int x509_digest_oid(struct asn1_oid *oid)
|
||||
oid->oid[4] == 2 /* digestAlgorithm */;
|
||||
}
|
||||
|
||||
|
||||
static int x509_sha1_oid(struct asn1_oid *oid)
|
||||
{
|
||||
return oid->len == 6 &&
|
||||
@ -1377,7 +1376,6 @@ static int x509_sha1_oid(struct asn1_oid *oid)
|
||||
oid->oid[5] == 26 /* id-sha1 */;
|
||||
}
|
||||
|
||||
|
||||
static int x509_sha256_oid(struct asn1_oid *oid)
|
||||
{
|
||||
return oid->len == 9 &&
|
||||
|
@ -1,41 +1,36 @@
|
||||
/*
|
||||
* Base64 encoding/decoding (RFC1341)
|
||||
* Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2005-2019, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include "includes.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "os.h"
|
||||
#include "base64.h"
|
||||
|
||||
static const unsigned char base64_table[65] =
|
||||
static const char base64_table[65] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char base64_url_table[65] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
|
||||
/**
|
||||
* base64_encode - Base64 encode
|
||||
* @src: Data to be encoded
|
||||
* @len: Length of the data to be encoded
|
||||
* @out_len: Pointer to output length variable, or %NULL if not used
|
||||
* Returns: Allocated buffer of out_len bytes of encoded data,
|
||||
* or %NULL on failure
|
||||
*
|
||||
* Caller is responsible for freeing the returned buffer. Returned buffer is
|
||||
* nul terminated to make it easier to use as a C string. The nul terminator is
|
||||
* not included in out_len.
|
||||
*/
|
||||
unsigned char * base64_encode(const unsigned char *src, size_t len,
|
||||
size_t *out_len)
|
||||
|
||||
static char * base64_gen_encode(const unsigned char *src, size_t len,
|
||||
size_t *out_len, const char *table, int add_pad)
|
||||
{
|
||||
unsigned char *out, *pos;
|
||||
char *out, *pos;
|
||||
const unsigned char *end, *in;
|
||||
size_t olen;
|
||||
int line_len;
|
||||
|
||||
if (len >= SIZE_MAX / 4)
|
||||
return NULL;
|
||||
olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
|
||||
olen += olen / 72; /* line feeds */
|
||||
if (add_pad)
|
||||
olen += olen / 72; /* line feeds */
|
||||
olen++; /* nul termination */
|
||||
if (olen < len)
|
||||
return NULL; /* integer overflow */
|
||||
@ -48,33 +43,35 @@ unsigned char * base64_encode(const unsigned char *src, size_t len,
|
||||
pos = out;
|
||||
line_len = 0;
|
||||
while (end - in >= 3) {
|
||||
*pos++ = base64_table[in[0] >> 2];
|
||||
*pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
|
||||
*pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
|
||||
*pos++ = base64_table[in[2] & 0x3f];
|
||||
*pos++ = table[(in[0] >> 2) & 0x3f];
|
||||
*pos++ = table[(((in[0] & 0x03) << 4) | (in[1] >> 4)) & 0x3f];
|
||||
*pos++ = table[(((in[1] & 0x0f) << 2) | (in[2] >> 6)) & 0x3f];
|
||||
*pos++ = table[in[2] & 0x3f];
|
||||
in += 3;
|
||||
line_len += 4;
|
||||
if (line_len >= 72) {
|
||||
if (add_pad && line_len >= 72) {
|
||||
*pos++ = '\n';
|
||||
line_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (end - in) {
|
||||
*pos++ = base64_table[in[0] >> 2];
|
||||
*pos++ = table[(in[0] >> 2) & 0x3f];
|
||||
if (end - in == 1) {
|
||||
*pos++ = base64_table[(in[0] & 0x03) << 4];
|
||||
*pos++ = '=';
|
||||
*pos++ = table[((in[0] & 0x03) << 4) & 0x3f];
|
||||
if (add_pad)
|
||||
*pos++ = '=';
|
||||
} else {
|
||||
*pos++ = base64_table[((in[0] & 0x03) << 4) |
|
||||
(in[1] >> 4)];
|
||||
*pos++ = base64_table[(in[1] & 0x0f) << 2];
|
||||
*pos++ = table[(((in[0] & 0x03) << 4) |
|
||||
(in[1] >> 4)) & 0x3f];
|
||||
*pos++ = table[((in[1] & 0x0f) << 2) & 0x3f];
|
||||
}
|
||||
*pos++ = '=';
|
||||
if (add_pad)
|
||||
*pos++ = '=';
|
||||
line_len += 4;
|
||||
}
|
||||
|
||||
if (line_len)
|
||||
if (add_pad && line_len)
|
||||
*pos++ = '\n';
|
||||
|
||||
*pos = '\0';
|
||||
@ -84,49 +81,47 @@ unsigned char * base64_encode(const unsigned char *src, size_t len,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* base64_decode - Base64 decode
|
||||
* @src: Data to be decoded
|
||||
* @len: Length of the data to be decoded
|
||||
* @out_len: Pointer to output length variable
|
||||
* Returns: Allocated buffer of out_len bytes of decoded data,
|
||||
* or %NULL on failure
|
||||
*
|
||||
* Caller is responsible for freeing the returned buffer.
|
||||
*/
|
||||
unsigned char * base64_decode(const unsigned char *src, size_t len,
|
||||
size_t *out_len)
|
||||
static unsigned char * base64_gen_decode(const char *src, size_t len,
|
||||
size_t *out_len, const char *table)
|
||||
{
|
||||
unsigned char dtable[256], *out, *pos, block[4], tmp;
|
||||
size_t i, count, olen;
|
||||
int pad = 0;
|
||||
size_t extra_pad;
|
||||
|
||||
os_memset(dtable, 0x80, 256);
|
||||
for (i = 0; i < sizeof(base64_table) - 1; i++)
|
||||
dtable[base64_table[i]] = (unsigned char) i;
|
||||
dtable[(unsigned char) table[i]] = (unsigned char) i;
|
||||
dtable['='] = 0;
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (dtable[src[i]] != 0x80)
|
||||
if (dtable[(unsigned char) src[i]] != 0x80)
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0 || count % 4)
|
||||
if (count == 0)
|
||||
return NULL;
|
||||
extra_pad = (4 - count % 4) % 4;
|
||||
|
||||
olen = count / 4 * 3;
|
||||
olen = (count + extra_pad) / 4 * 3;
|
||||
pos = out = os_malloc(olen);
|
||||
if (out == NULL)
|
||||
return NULL;
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
tmp = dtable[src[i]];
|
||||
for (i = 0; i < len + extra_pad; i++) {
|
||||
unsigned char val;
|
||||
|
||||
if (i >= len)
|
||||
val = '=';
|
||||
else
|
||||
val = src[i];
|
||||
tmp = dtable[val];
|
||||
if (tmp == 0x80)
|
||||
continue;
|
||||
|
||||
if (src[i] == '=')
|
||||
if (val == '=')
|
||||
pad++;
|
||||
block[count] = tmp;
|
||||
count++;
|
||||
@ -153,3 +148,49 @@ unsigned char * base64_decode(const unsigned char *src, size_t len,
|
||||
*out_len = pos - out;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* base64_encode - Base64 encode
|
||||
* @src: Data to be encoded
|
||||
* @len: Length of the data to be encoded
|
||||
* @out_len: Pointer to output length variable, or %NULL if not used
|
||||
* Returns: Allocated buffer of out_len bytes of encoded data,
|
||||
* or %NULL on failure
|
||||
*
|
||||
* Caller is responsible for freeing the returned buffer. Returned buffer is
|
||||
* nul terminated to make it easier to use as a C string. The nul terminator is
|
||||
* not included in out_len.
|
||||
*/
|
||||
char * base64_encode(const void *src, size_t len, size_t *out_len)
|
||||
{
|
||||
return base64_gen_encode(src, len, out_len, base64_table, 1);
|
||||
}
|
||||
|
||||
|
||||
char * base64_url_encode(const void *src, size_t len, size_t *out_len)
|
||||
{
|
||||
return base64_gen_encode(src, len, out_len, base64_url_table, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* base64_decode - Base64 decode
|
||||
* @src: Data to be decoded
|
||||
* @len: Length of the data to be decoded
|
||||
* @out_len: Pointer to output length variable
|
||||
* Returns: Allocated buffer of out_len bytes of decoded data,
|
||||
* or %NULL on failure
|
||||
*
|
||||
* Caller is responsible for freeing the returned buffer.
|
||||
*/
|
||||
unsigned char * base64_decode(const char *src, size_t len, size_t *out_len)
|
||||
{
|
||||
return base64_gen_decode(src, len, out_len, base64_table);
|
||||
}
|
||||
|
||||
|
||||
unsigned char * base64_url_decode(const char *src, size_t len, size_t *out_len)
|
||||
{
|
||||
return base64_gen_decode(src, len, out_len, base64_url_table);
|
||||
}
|
||||
|
@ -2,22 +2,16 @@
|
||||
* Base64 encoding/decoding (RFC1341)
|
||||
* Copyright (c) 2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef BASE64_H
|
||||
#define BASE64_H
|
||||
|
||||
unsigned char * base64_encode(const unsigned char *src, size_t len,
|
||||
size_t *out_len);
|
||||
unsigned char * base64_decode(const unsigned char *src, size_t len,
|
||||
size_t *out_len);
|
||||
char * base64_encode(const void *src, size_t len, size_t *out_len);
|
||||
unsigned char * base64_decode(const char *src, size_t len, size_t *out_len);
|
||||
char * base64_url_encode(const void *src, size_t len, size_t *out_len);
|
||||
unsigned char * base64_url_decode(const char *src, size_t len, size_t *out_len);
|
||||
|
||||
#endif /* BASE64_H */
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include <time.h>
|
||||
|
||||
/**
|
||||
* inc_byte_array - Increment arbitrary length byte array by one
|
||||
@ -365,4 +366,128 @@ void wpa_bin_clear_free(void *bin, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
int int_array_len(const int *a)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; a && a[i]; i++)
|
||||
;
|
||||
return i;
|
||||
}
|
||||
|
||||
void bin_clear_free(void *bin, size_t len)
|
||||
{
|
||||
if (bin) {
|
||||
os_memset(bin, 0, len);
|
||||
os_free(bin);
|
||||
}
|
||||
}
|
||||
|
||||
void str_clear_free(char *str)
|
||||
{
|
||||
if (str) {
|
||||
size_t len = os_strlen(str);
|
||||
os_memset(str, 0, len);
|
||||
os_free(str);
|
||||
}
|
||||
}
|
||||
|
||||
int os_gmtime(os_time_t t, struct os_tm *tm)
|
||||
{
|
||||
struct tm *tm2;
|
||||
time_t t2 = t;
|
||||
|
||||
tm2 = gmtime(&t2);
|
||||
if (tm2 == NULL)
|
||||
return -1;
|
||||
tm->sec = tm2->tm_sec;
|
||||
tm->min = tm2->tm_min;
|
||||
tm->hour = tm2->tm_hour;
|
||||
tm->day = tm2->tm_mday;
|
||||
tm->month = tm2->tm_mon + 1;
|
||||
tm->year = tm2->tm_year + 1900;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int os_mktime(int year, int month, int day, int hour, int min, int sec,
|
||||
os_time_t *t)
|
||||
{
|
||||
struct tm tm;
|
||||
|
||||
if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
|
||||
hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
|
||||
sec > 60)
|
||||
return -1;
|
||||
|
||||
os_memset(&tm, 0, sizeof(tm));
|
||||
tm.tm_year = year - 1900;
|
||||
tm.tm_mon = month - 1;
|
||||
tm.tm_mday = day;
|
||||
tm.tm_hour = hour;
|
||||
tm.tm_min = min;
|
||||
tm.tm_sec = sec;
|
||||
|
||||
*t = (os_time_t) mktime(&tm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char * get_param(const char *cmd, const char *param)
|
||||
{
|
||||
const char *pos, *end;
|
||||
char *val;
|
||||
size_t len;
|
||||
|
||||
pos = os_strstr(cmd, param);
|
||||
if (!pos)
|
||||
return NULL;
|
||||
|
||||
pos += os_strlen(param);
|
||||
end = os_strchr(pos, ' ');
|
||||
if (end)
|
||||
len = end - pos;
|
||||
else
|
||||
len = os_strlen(pos);
|
||||
val = os_malloc(len + 1);
|
||||
if (!val)
|
||||
return NULL;
|
||||
os_memcpy(val, pos, len);
|
||||
val[len] = '\0';
|
||||
return val;
|
||||
}
|
||||
|
||||
void * os_memdup(const void *src, size_t len)
|
||||
{
|
||||
void *r = os_malloc(len);
|
||||
|
||||
if (r && src)
|
||||
os_memcpy(r, src, len);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
|
||||
* @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
|
||||
* @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
|
||||
* Returns: Characters used (> 0) on success, -1 on failure
|
||||
*/
|
||||
int hwaddr_aton2(const char *txt, u8 *addr)
|
||||
{
|
||||
int i;
|
||||
const char *pos = txt;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
int a, b;
|
||||
|
||||
while (*pos == ':' || *pos == '.' || *pos == '-')
|
||||
pos++;
|
||||
|
||||
a = hex2num(*pos++);
|
||||
if (a < 0)
|
||||
return -1;
|
||||
b = hex2num(*pos++);
|
||||
if (b < 0)
|
||||
return -1;
|
||||
*addr++ = (a << 4) | b;
|
||||
}
|
||||
|
||||
return pos - txt;
|
||||
}
|
||||
|
@ -434,6 +434,11 @@ struct wpa_freq_range_list {
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
void wpa_bin_clear_free(void *bin, size_t len);
|
||||
int int_array_len(const int *a);
|
||||
void bin_clear_free(void *bin, size_t len);
|
||||
void str_clear_free(char *str);
|
||||
char * get_param(const char *cmd, const char *param);
|
||||
void * os_memdup(const void *src, size_t len);
|
||||
|
||||
/*
|
||||
* gcc 4.4 ends up generating strict-aliasing warnings about some very common
|
||||
|
654
components/wpa_supplicant/src/utils/json.c
Normal file
654
components/wpa_supplicant/src/utils/json.c
Normal file
@ -0,0 +1,654 @@
|
||||
/*
|
||||
* JavaScript Object Notation (JSON) parser (RFC7159)
|
||||
* Copyright (c) 2017, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "base64.h"
|
||||
#include "json.h"
|
||||
|
||||
#define JSON_MAX_DEPTH 10
|
||||
#define JSON_MAX_TOKENS 500
|
||||
|
||||
|
||||
void json_escape_string(char *txt, size_t maxlen, const char *data, size_t len)
|
||||
{
|
||||
char *end = txt + maxlen;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (txt + 4 >= end)
|
||||
break;
|
||||
|
||||
switch (data[i]) {
|
||||
case '\"':
|
||||
*txt++ = '\\';
|
||||
*txt++ = '\"';
|
||||
break;
|
||||
case '\\':
|
||||
*txt++ = '\\';
|
||||
*txt++ = '\\';
|
||||
break;
|
||||
case '\n':
|
||||
*txt++ = '\\';
|
||||
*txt++ = 'n';
|
||||
break;
|
||||
case '\r':
|
||||
*txt++ = '\\';
|
||||
*txt++ = 'r';
|
||||
break;
|
||||
case '\t':
|
||||
*txt++ = '\\';
|
||||
*txt++ = 't';
|
||||
break;
|
||||
default:
|
||||
if (data[i] >= 32 && data[i] <= 126) {
|
||||
*txt++ = data[i];
|
||||
} else {
|
||||
txt += os_snprintf(txt, end - txt, "\\u%04x",
|
||||
(unsigned char) data[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*txt = '\0';
|
||||
}
|
||||
|
||||
|
||||
static char * json_parse_string(const char **json_pos, const char *end)
|
||||
{
|
||||
const char *pos = *json_pos;
|
||||
char *str, *spos, *s_end;
|
||||
size_t max_len, buf_len;
|
||||
u8 bin[2];
|
||||
|
||||
pos++; /* skip starting quote */
|
||||
|
||||
max_len = end - pos + 1;
|
||||
buf_len = max_len > 10 ? 10 : max_len;
|
||||
str = os_malloc(buf_len);
|
||||
if (!str)
|
||||
return NULL;
|
||||
spos = str;
|
||||
s_end = str + buf_len;
|
||||
|
||||
for (; pos < end; pos++) {
|
||||
if (buf_len < max_len && s_end - spos < 3) {
|
||||
char *tmp;
|
||||
int idx;
|
||||
|
||||
idx = spos - str;
|
||||
buf_len *= 2;
|
||||
if (buf_len > max_len)
|
||||
buf_len = max_len;
|
||||
tmp = os_realloc(str, buf_len);
|
||||
if (!tmp)
|
||||
goto fail;
|
||||
str = tmp;
|
||||
spos = str + idx;
|
||||
s_end = str + buf_len;
|
||||
}
|
||||
|
||||
switch (*pos) {
|
||||
case '\"': /* end string */
|
||||
*spos = '\0';
|
||||
/* caller will move to the next position */
|
||||
*json_pos = pos;
|
||||
return str;
|
||||
case '\\':
|
||||
pos++;
|
||||
if (pos >= end) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"JSON: Truncated \\ escape");
|
||||
goto fail;
|
||||
}
|
||||
switch (*pos) {
|
||||
case '"':
|
||||
case '\\':
|
||||
case '/':
|
||||
*spos++ = *pos;
|
||||
break;
|
||||
case 'n':
|
||||
*spos++ = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
*spos++ = '\r';
|
||||
break;
|
||||
case 't':
|
||||
*spos++ = '\t';
|
||||
break;
|
||||
case 'u':
|
||||
if (end - pos < 5 ||
|
||||
hexstr2bin(pos + 1, bin, 2) < 0 ||
|
||||
bin[1] == 0x00) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"JSON: Invalid \\u escape");
|
||||
goto fail;
|
||||
}
|
||||
if (bin[0] == 0x00) {
|
||||
*spos++ = bin[1];
|
||||
} else {
|
||||
*spos++ = bin[0];
|
||||
*spos++ = bin[1];
|
||||
}
|
||||
pos += 4;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"JSON: Unknown escape '%c'", *pos);
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*spos++ = *pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
os_free(str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int json_parse_number(const char **json_pos, const char *end,
|
||||
int *ret_val)
|
||||
{
|
||||
const char *pos = *json_pos;
|
||||
size_t len;
|
||||
char *str;
|
||||
|
||||
for (; pos < end; pos++) {
|
||||
if (*pos != '-' && (*pos < '0' || *pos > '9')) {
|
||||
pos--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pos == end)
|
||||
pos--;
|
||||
if (pos < *json_pos)
|
||||
return -1;
|
||||
len = pos - *json_pos + 1;
|
||||
str = os_malloc(len + 1);
|
||||
if (!str)
|
||||
return -1;
|
||||
os_memcpy(str, *json_pos, len);
|
||||
str[len] = '\0';
|
||||
|
||||
*ret_val = atoi(str);
|
||||
os_free(str);
|
||||
*json_pos = pos;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int json_check_tree_state(struct json_token *token)
|
||||
{
|
||||
if (!token)
|
||||
return 0;
|
||||
if (json_check_tree_state(token->child) < 0 ||
|
||||
json_check_tree_state(token->sibling) < 0)
|
||||
return -1;
|
||||
if (token->state != JSON_COMPLETED) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"JSON: Unexpected token state %d (name=%s type=%d)",
|
||||
token->state, token->name ? token->name : "N/A",
|
||||
token->type);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct json_token * json_alloc_token(unsigned int *tokens)
|
||||
{
|
||||
(*tokens)++;
|
||||
if (*tokens > JSON_MAX_TOKENS) {
|
||||
wpa_printf(MSG_DEBUG, "JSON: Maximum token limit exceeded");
|
||||
return NULL;
|
||||
}
|
||||
return os_zalloc(sizeof(struct json_token));
|
||||
}
|
||||
|
||||
|
||||
struct json_token * json_parse(const char *data, size_t data_len)
|
||||
{
|
||||
struct json_token *root = NULL, *curr_token = NULL, *token = NULL;
|
||||
const char *pos, *end;
|
||||
char *str;
|
||||
int num;
|
||||
unsigned int depth = 0;
|
||||
unsigned int tokens = 0;
|
||||
|
||||
pos = data;
|
||||
end = data + data_len;
|
||||
|
||||
for (; pos < end; pos++) {
|
||||
switch (*pos) {
|
||||
case '[': /* start array */
|
||||
case '{': /* start object */
|
||||
if (!curr_token) {
|
||||
token = json_alloc_token(&tokens);
|
||||
if (!token)
|
||||
goto fail;
|
||||
if (!root)
|
||||
root = token;
|
||||
} else if (curr_token->state == JSON_WAITING_VALUE) {
|
||||
token = curr_token;
|
||||
} else if (curr_token->parent &&
|
||||
curr_token->parent->type == JSON_ARRAY &&
|
||||
curr_token->parent->state == JSON_STARTED &&
|
||||
curr_token->state == JSON_EMPTY) {
|
||||
token = curr_token;
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"JSON: Invalid state for start array/object");
|
||||
goto fail;
|
||||
}
|
||||
depth++;
|
||||
if (depth > JSON_MAX_DEPTH) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"JSON: Max depth exceeded");
|
||||
goto fail;
|
||||
}
|
||||
token->type = *pos == '[' ? JSON_ARRAY : JSON_OBJECT;
|
||||
token->state = JSON_STARTED;
|
||||
token->child = json_alloc_token(&tokens);
|
||||
if (!token->child)
|
||||
goto fail;
|
||||
curr_token = token->child;
|
||||
curr_token->parent = token;
|
||||
curr_token->state = JSON_EMPTY;
|
||||
break;
|
||||
case ']': /* end array */
|
||||
case '}': /* end object */
|
||||
if (!curr_token || !curr_token->parent ||
|
||||
curr_token->parent->state != JSON_STARTED) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"JSON: Invalid state for end array/object");
|
||||
goto fail;
|
||||
}
|
||||
depth--;
|
||||
curr_token = curr_token->parent;
|
||||
if ((*pos == ']' &&
|
||||
curr_token->type != JSON_ARRAY) ||
|
||||
(*pos == '}' &&
|
||||
curr_token->type != JSON_OBJECT)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"JSON: Array/Object mismatch");
|
||||
goto fail;
|
||||
}
|
||||
if (curr_token->child->state == JSON_EMPTY &&
|
||||
!curr_token->child->child &&
|
||||
!curr_token->child->sibling) {
|
||||
/* Remove pending child token since the
|
||||
* array/object was empty. */
|
||||
json_free(curr_token->child);
|
||||
curr_token->child = NULL;
|
||||
}
|
||||
curr_token->state = JSON_COMPLETED;
|
||||
break;
|
||||
case '\"': /* string */
|
||||
str = json_parse_string(&pos, end);
|
||||
if (!str)
|
||||
goto fail;
|
||||
if (!curr_token) {
|
||||
token = json_alloc_token(&tokens);
|
||||
if (!token) {
|
||||
os_free(str);
|
||||
goto fail;
|
||||
}
|
||||
token->type = JSON_STRING;
|
||||
token->string = str;
|
||||
token->state = JSON_COMPLETED;
|
||||
} else if (curr_token->parent &&
|
||||
curr_token->parent->type == JSON_ARRAY &&
|
||||
curr_token->parent->state == JSON_STARTED &&
|
||||
curr_token->state == JSON_EMPTY) {
|
||||
curr_token->string = str;
|
||||
curr_token->state = JSON_COMPLETED;
|
||||
curr_token->type = JSON_STRING;
|
||||
wpa_printf(MSG_MSGDUMP,
|
||||
"JSON: String value: '%s'",
|
||||
curr_token->string);
|
||||
} else if (curr_token->state == JSON_EMPTY) {
|
||||
curr_token->type = JSON_VALUE;
|
||||
curr_token->name = str;
|
||||
curr_token->state = JSON_STARTED;
|
||||
} else if (curr_token->state == JSON_WAITING_VALUE) {
|
||||
curr_token->string = str;
|
||||
curr_token->state = JSON_COMPLETED;
|
||||
curr_token->type = JSON_STRING;
|
||||
wpa_printf(MSG_MSGDUMP,
|
||||
"JSON: String value: '%s' = '%s'",
|
||||
curr_token->name,
|
||||
curr_token->string);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"JSON: Invalid state for a string");
|
||||
os_free(str);
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
/* ignore whitespace */
|
||||
break;
|
||||
case ':': /* name/value separator */
|
||||
if (!curr_token || curr_token->state != JSON_STARTED)
|
||||
goto fail;
|
||||
curr_token->state = JSON_WAITING_VALUE;
|
||||
break;
|
||||
case ',': /* member separator */
|
||||
if (!curr_token)
|
||||
goto fail;
|
||||
curr_token->sibling = json_alloc_token(&tokens);
|
||||
if (!curr_token->sibling)
|
||||
goto fail;
|
||||
curr_token->sibling->parent = curr_token->parent;
|
||||
curr_token = curr_token->sibling;
|
||||
curr_token->state = JSON_EMPTY;
|
||||
break;
|
||||
case 't': /* true */
|
||||
case 'f': /* false */
|
||||
case 'n': /* null */
|
||||
if (!((end - pos >= 4 &&
|
||||
os_strncmp(pos, "true", 4) == 0) ||
|
||||
(end - pos >= 5 &&
|
||||
os_strncmp(pos, "false", 5) == 0) ||
|
||||
(end - pos >= 4 &&
|
||||
os_strncmp(pos, "null", 4) == 0))) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"JSON: Invalid literal name");
|
||||
goto fail;
|
||||
}
|
||||
if (!curr_token) {
|
||||
token = json_alloc_token(&tokens);
|
||||
if (!token)
|
||||
goto fail;
|
||||
curr_token = token;
|
||||
} else if (curr_token->state == JSON_WAITING_VALUE) {
|
||||
wpa_printf(MSG_MSGDUMP,
|
||||
"JSON: Literal name: '%s' = %c",
|
||||
curr_token->name, *pos);
|
||||
} else if (curr_token->parent &&
|
||||
curr_token->parent->type == JSON_ARRAY &&
|
||||
curr_token->parent->state == JSON_STARTED &&
|
||||
curr_token->state == JSON_EMPTY) {
|
||||
wpa_printf(MSG_MSGDUMP,
|
||||
"JSON: Literal name: %c", *pos);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"JSON: Invalid state for a literal name");
|
||||
goto fail;
|
||||
}
|
||||
switch (*pos) {
|
||||
case 't':
|
||||
curr_token->type = JSON_BOOLEAN;
|
||||
curr_token->number = 1;
|
||||
pos += 3;
|
||||
break;
|
||||
case 'f':
|
||||
curr_token->type = JSON_BOOLEAN;
|
||||
curr_token->number = 0;
|
||||
pos += 4;
|
||||
break;
|
||||
case 'n':
|
||||
curr_token->type = JSON_NULL;
|
||||
pos += 3;
|
||||
break;
|
||||
}
|
||||
curr_token->state = JSON_COMPLETED;
|
||||
break;
|
||||
case '-':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
/* number */
|
||||
if (json_parse_number(&pos, end, &num) < 0)
|
||||
goto fail;
|
||||
if (!curr_token) {
|
||||
token = json_alloc_token(&tokens);
|
||||
if (!token)
|
||||
goto fail;
|
||||
token->type = JSON_NUMBER;
|
||||
token->number = num;
|
||||
token->state = JSON_COMPLETED;
|
||||
} else if (curr_token->state == JSON_WAITING_VALUE) {
|
||||
curr_token->number = num;
|
||||
curr_token->state = JSON_COMPLETED;
|
||||
curr_token->type = JSON_NUMBER;
|
||||
wpa_printf(MSG_MSGDUMP,
|
||||
"JSON: Number value: '%s' = '%d'",
|
||||
curr_token->name,
|
||||
curr_token->number);
|
||||
} else if (curr_token->parent &&
|
||||
curr_token->parent->type == JSON_ARRAY &&
|
||||
curr_token->parent->state == JSON_STARTED &&
|
||||
curr_token->state == JSON_EMPTY) {
|
||||
curr_token->number = num;
|
||||
curr_token->state = JSON_COMPLETED;
|
||||
curr_token->type = JSON_NUMBER;
|
||||
wpa_printf(MSG_MSGDUMP,
|
||||
"JSON: Number value: %d",
|
||||
curr_token->number);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"JSON: Invalid state for a number");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"JSON: Unexpected JSON character: %c", *pos);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!root)
|
||||
root = token;
|
||||
if (!curr_token)
|
||||
curr_token = token;
|
||||
}
|
||||
|
||||
if (json_check_tree_state(root) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "JSON: Incomplete token in the tree");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return root;
|
||||
fail:
|
||||
wpa_printf(MSG_DEBUG, "JSON: Parsing failed");
|
||||
json_free(root);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void json_free(struct json_token *json)
|
||||
{
|
||||
if (!json)
|
||||
return;
|
||||
json_free(json->child);
|
||||
json_free(json->sibling);
|
||||
os_free(json->name);
|
||||
os_free(json->string);
|
||||
os_free(json);
|
||||
}
|
||||
|
||||
|
||||
struct json_token * json_get_member(struct json_token *json, const char *name)
|
||||
{
|
||||
struct json_token *token, *ret = NULL;
|
||||
|
||||
if (!json || json->type != JSON_OBJECT)
|
||||
return NULL;
|
||||
/* Return last matching entry */
|
||||
for (token = json->child; token; token = token->sibling) {
|
||||
if (token->name && os_strcmp(token->name, name) == 0)
|
||||
ret = token;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * json_get_member_base64url(struct json_token *json,
|
||||
const char *name)
|
||||
{
|
||||
struct json_token *token;
|
||||
unsigned char *buf;
|
||||
size_t buflen;
|
||||
struct wpabuf *ret;
|
||||
|
||||
token = json_get_member(json, name);
|
||||
if (!token || token->type != JSON_STRING)
|
||||
return NULL;
|
||||
buf = base64_url_decode(token->string, os_strlen(token->string),
|
||||
&buflen);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
ret = wpabuf_alloc_ext_data(buf, buflen);
|
||||
if (!ret)
|
||||
os_free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static const char * json_type_str(enum json_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case JSON_VALUE:
|
||||
return "VALUE";
|
||||
case JSON_OBJECT:
|
||||
return "OBJECT";
|
||||
case JSON_ARRAY:
|
||||
return "ARRAY";
|
||||
case JSON_STRING:
|
||||
return "STRING";
|
||||
case JSON_NUMBER:
|
||||
return "NUMBER";
|
||||
case JSON_BOOLEAN:
|
||||
return "BOOLEAN";
|
||||
case JSON_NULL:
|
||||
return "NULL";
|
||||
}
|
||||
return "??";
|
||||
}
|
||||
|
||||
|
||||
static void json_print_token(struct json_token *token, int depth,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
if (!token)
|
||||
return;
|
||||
len = os_strlen(buf);
|
||||
ret = os_snprintf(buf + len, buflen - len, "[%d:%s:%s]",
|
||||
depth, json_type_str(token->type),
|
||||
token->name ? token->name : "");
|
||||
if (os_snprintf_error(buflen - len, ret)) {
|
||||
buf[len] = '\0';
|
||||
return;
|
||||
}
|
||||
json_print_token(token->child, depth + 1, buf, buflen);
|
||||
json_print_token(token->sibling, depth, buf, buflen);
|
||||
}
|
||||
|
||||
|
||||
void json_print_tree(struct json_token *root, char *buf, size_t buflen)
|
||||
{
|
||||
buf[0] = '\0';
|
||||
json_print_token(root, 1, buf, buflen);
|
||||
}
|
||||
|
||||
|
||||
void json_add_int(struct wpabuf *json, const char *name, int val)
|
||||
{
|
||||
wpabuf_printf(json, "\"%s\":%d", name, val);
|
||||
}
|
||||
|
||||
|
||||
void json_add_string(struct wpabuf *json, const char *name, const char *val)
|
||||
{
|
||||
wpabuf_printf(json, "\"%s\":\"%s\"", name, val);
|
||||
}
|
||||
|
||||
|
||||
int json_add_string_escape(struct wpabuf *json, const char *name,
|
||||
const void *val, size_t len)
|
||||
{
|
||||
char *tmp;
|
||||
size_t tmp_len = 6 * len + 1;
|
||||
|
||||
tmp = os_malloc(tmp_len);
|
||||
if (!tmp)
|
||||
return -1;
|
||||
json_escape_string(tmp, tmp_len, val, len);
|
||||
json_add_string(json, name, tmp);
|
||||
bin_clear_free(tmp, tmp_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int json_add_base64url(struct wpabuf *json, const char *name, const void *val,
|
||||
size_t len)
|
||||
{
|
||||
char *b64;
|
||||
|
||||
b64 = base64_url_encode(val, len, NULL);
|
||||
if (!b64)
|
||||
return -1;
|
||||
json_add_string(json, name, b64);
|
||||
os_free(b64);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void json_start_object(struct wpabuf *json, const char *name)
|
||||
{
|
||||
if (name)
|
||||
wpabuf_printf(json, "\"%s\":", name);
|
||||
wpabuf_put_u8(json, '{');
|
||||
}
|
||||
|
||||
|
||||
void json_end_object(struct wpabuf *json)
|
||||
{
|
||||
wpabuf_put_u8(json, '}');
|
||||
}
|
||||
|
||||
|
||||
void json_start_array(struct wpabuf *json, const char *name)
|
||||
{
|
||||
if (name)
|
||||
wpabuf_printf(json, "\"%s\":", name);
|
||||
wpabuf_put_u8(json, '[');
|
||||
}
|
||||
|
||||
|
||||
void json_end_array(struct wpabuf *json)
|
||||
{
|
||||
wpabuf_put_u8(json, ']');
|
||||
}
|
||||
|
||||
|
||||
void json_value_sep(struct wpabuf *json)
|
||||
{
|
||||
wpabuf_put_u8(json, ',');
|
||||
}
|
53
components/wpa_supplicant/src/utils/json.h
Normal file
53
components/wpa_supplicant/src/utils/json.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* JavaScript Object Notation (JSON) parser (RFC7159)
|
||||
* Copyright (c) 2017, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef JSON_H
|
||||
#define JSON_H
|
||||
|
||||
struct json_token {
|
||||
enum json_type {
|
||||
JSON_VALUE,
|
||||
JSON_OBJECT,
|
||||
JSON_ARRAY,
|
||||
JSON_STRING,
|
||||
JSON_NUMBER,
|
||||
JSON_BOOLEAN,
|
||||
JSON_NULL,
|
||||
} type;
|
||||
enum json_parsing_state {
|
||||
JSON_EMPTY,
|
||||
JSON_STARTED,
|
||||
JSON_WAITING_VALUE,
|
||||
JSON_COMPLETED,
|
||||
} state;
|
||||
char *name;
|
||||
char *string;
|
||||
int number;
|
||||
struct json_token *parent, *child, *sibling;
|
||||
};
|
||||
|
||||
void json_escape_string(char *txt, size_t maxlen, const char *data, size_t len);
|
||||
struct json_token * json_parse(const char *data, size_t data_len);
|
||||
void json_free(struct json_token *json);
|
||||
struct json_token * json_get_member(struct json_token *json, const char *name);
|
||||
struct wpabuf * json_get_member_base64url(struct json_token *json,
|
||||
const char *name);
|
||||
void json_print_tree(struct json_token *root, char *buf, size_t buflen);
|
||||
void json_add_int(struct wpabuf *json, const char *name, int val);
|
||||
void json_add_string(struct wpabuf *json, const char *name, const char *val);
|
||||
int json_add_string_escape(struct wpabuf *json, const char *name,
|
||||
const void *val, size_t len);
|
||||
int json_add_base64url(struct wpabuf *json, const char *name, const void *val,
|
||||
size_t len);
|
||||
void json_start_object(struct wpabuf *json, const char *name);
|
||||
void json_end_object(struct wpabuf *json);
|
||||
void json_start_array(struct wpabuf *json, const char *name);
|
||||
void json_end_array(struct wpabuf *json);
|
||||
void json_value_sep(struct wpabuf *json);
|
||||
|
||||
#endif /* JSON_H */
|
@ -133,7 +133,6 @@ struct wpabuf * wpabuf_alloc(size_t len)
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len)
|
||||
{
|
||||
#ifdef WPA_TRACE
|
||||
@ -285,7 +284,7 @@ struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void wpabuf_printf(struct wpabuf *buf, char *fmt, ...)
|
||||
void wpabuf_printf(struct wpabuf *buf, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf);
|
||||
|
@ -11,3 +11,4 @@ string(SUBSTRING "${WIFI_SUPPLICANT_MD5}" 0 7 WIFI_SUPPLICANT_MD5)
|
||||
|
||||
add_definitions(-DWIFI_SUPPLICANT_MD5=\"${WIFI_SUPPLICANT_MD5}\")
|
||||
add_definitions(-DCONFIG_WPA3_SAE)
|
||||
add_definitions(-DCONFIG_DPP)
|
||||
|
@ -8,3 +8,4 @@ COMPONENT_SRCDIRS := .
|
||||
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
|
||||
|
||||
CFLAGS+= -DCONFIG_WPA3_SAE
|
||||
CFLAGS+= -DCONFIG_DPP
|
||||
|
@ -34,7 +34,7 @@ TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]")
|
||||
crypto_bignum_deinit(bn, 1);
|
||||
|
||||
/* BN - Binary to bignum & bignum to binary*/
|
||||
TEST_ASSERT(!crypto_get_random(buf, 32));
|
||||
TEST_ASSERT(!os_get_random(buf, 32));
|
||||
|
||||
bn = crypto_bignum_init_set(buf, 32);
|
||||
TEST_ASSERT_NOT_NULL(bn);
|
||||
@ -366,7 +366,7 @@ TEST_CASE("Test crypto lib ECC apis", "[wpa_crypto]")
|
||||
|
||||
/* Note this is just testing coversion & not whether point is
|
||||
* in the group or not*/
|
||||
TEST_ASSERT(!crypto_get_random(pt1, 64));
|
||||
TEST_ASSERT(!os_get_random(pt1, 64));
|
||||
|
||||
p = crypto_ec_point_from_bin(e, pt1);
|
||||
|
||||
|
177
components/wpa_supplicant/test/test_dpp.c
Normal file
177
components/wpa_supplicant/test/test_dpp.c
Normal file
@ -0,0 +1,177 @@
|
||||
/* Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "unity.h"
|
||||
#include <string.h>
|
||||
#include "crypto/crypto.h"
|
||||
#include "../src/common/defs.h"
|
||||
#include "../src/common/dpp.h"
|
||||
|
||||
#ifdef CONFIG_WPA_TESTING_OPTIONS
|
||||
struct dpp_global {
|
||||
void *msg_ctx;
|
||||
struct dl_list bootstrap; /* struct dpp_bootstrap_info */
|
||||
struct dl_list configurator; /* struct dpp_configurator */
|
||||
};
|
||||
|
||||
extern u8 dpp_protocol_key_override[600];
|
||||
extern size_t dpp_protocol_key_override_len;
|
||||
extern u8 dpp_nonce_override[DPP_MAX_NONCE_LEN];
|
||||
extern size_t dpp_nonce_override_len;
|
||||
#define MAX_FRAME_SIZE 1200
|
||||
|
||||
TEST_CASE("Test vectors DPP responder p256", "[wpa_dpp]")
|
||||
{
|
||||
/* Global variables */
|
||||
char command[1200] = {0};
|
||||
const u8 *frame;
|
||||
int len = 0;
|
||||
struct dpp_authentication *auth_instance = NULL;
|
||||
u8 auth[MAX_FRAME_SIZE] = {0};
|
||||
char prefix[] = "30310201010420";
|
||||
char postfix[] = "a00a06082a8648ce3d030107";
|
||||
size_t hex_len;
|
||||
int ret = 0;
|
||||
int id;
|
||||
|
||||
/* DPP global config initialization */
|
||||
struct dpp_global_config dpp_conf;
|
||||
memset(&dpp_conf, 0, sizeof(dpp_conf));
|
||||
struct dpp_global *dpp = dpp_global_init(&dpp_conf);
|
||||
|
||||
/* bootstrap generation test */
|
||||
ESP_LOGI("DPP Test", "bootstrap generation test");
|
||||
{
|
||||
char key[1000] = {0};
|
||||
const char *uri;
|
||||
|
||||
char private_bootstrap_key[] = "54ce181a98525f217216f59b245f60e9df30ac7f6b26c939418cfc3c42d1afa0";
|
||||
char bootstrap_info[] = "DPP:K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgACCcWFqRtN+f0loEUgGIXDnMXPrjl92u2pV97Ff6DjUD8=;;";
|
||||
|
||||
sprintf(key, "%s%s%s", prefix, private_bootstrap_key, postfix);
|
||||
|
||||
sprintf(command, "type=qrcode key=%s", key);
|
||||
id = dpp_bootstrap_gen(dpp, command);
|
||||
uri = dpp_bootstrap_get_uri(dpp, id);
|
||||
printf("uri is =%s\n", uri);
|
||||
printf("is be =%s\n", bootstrap_info);
|
||||
TEST_ASSERT((strcmp(uri, bootstrap_info) == 0));
|
||||
}
|
||||
ESP_LOGI("DPP Test", "bootstap generation passed");
|
||||
ESP_LOGI("DPP Test", "Overwrite Protocol key, responder nounce");
|
||||
{
|
||||
char protocol_key[] = "f798ed2e19286f6a6efe210b1863badb99af2a14b497634dbfd2a97394fb5aa5";
|
||||
char nounce[] = "3d0cfb011ca916d796f7029ff0b43393";
|
||||
|
||||
/* Overwrite protocol key */
|
||||
memset(command, 0, 1200);
|
||||
sprintf(command, "%s%s%s", prefix, protocol_key, postfix);
|
||||
|
||||
hex_len = os_strlen(command);
|
||||
ret = 0;
|
||||
|
||||
if (hex_len > 2 * sizeof(dpp_protocol_key_override))
|
||||
ret = -1;
|
||||
else if (hexstr2bin(command, dpp_protocol_key_override,
|
||||
hex_len / 2))
|
||||
ret = -1;
|
||||
else
|
||||
dpp_protocol_key_override_len = hex_len / 2;
|
||||
|
||||
TEST_ASSERT(ret == 0);
|
||||
|
||||
/* Overwrite nounce */
|
||||
hex_len = os_strlen(nounce);
|
||||
|
||||
if (hex_len > 2 * sizeof(dpp_nonce_override))
|
||||
ret = -1;
|
||||
else if (hexstr2bin(nounce, dpp_nonce_override, hex_len / 2))
|
||||
ret = -1;
|
||||
else
|
||||
dpp_nonce_override_len = hex_len / 2;
|
||||
|
||||
TEST_ASSERT(ret == 0);
|
||||
|
||||
}
|
||||
ESP_LOGI("DPP Test", "Overwritten Protocol key, responder nounce.. ");
|
||||
ESP_LOGI("DPP Test", "Enqueue Auth request");
|
||||
{
|
||||
char auth_req[] = "d00012001ac459c40d649f8664c1b8771ac459c40d6400120409506f9a1a010002102000922ddd7a3ed69f46125d772bbe6017cd4e03870dc014509e38b54628e157a87d011020005d467a09760292fc15d31792b0a5b050db8bf6ad807d71b2d93f4d1c2e65d8810310400050a532ae2a07207276418d2fa630295d45569be425aa634f02014d00a7d1f61ae14f35a5a858bccad90d126c46594c49ef82655e78888e15a32d916ac217249118100200510104102900868f478fc599ac3fa8152b975eff8be4e71b189dbefbc3185b1d7f3864e896f913cba3d9601326f278";
|
||||
|
||||
char auth_resp[] = "d00012349f8664c1b8771ac459c40d649f8664c1b87712340409506f9a1a0101001001000002102000922ddd7a3ed69f46125d772bbe6017cd4e03870dc014509e38b54628e157a87d091040005e3fb3576884887f17c3203d8a3a6c2fac722ef0e2201b61ac73bc655c709a902d4b030669fb9eff8b0a79fa7c1a172ac2a92c626256963f9274dc90682c81e504107500da553cdf80da3e27054c5e1f809ac303c63948b9bb5690ad12f357d75dfbc362cbae89e472dd6851925534024310aff5ae403831e98a7efc7deb9516164329c227039ae73c509147d156ae085f56c242bf7decc1f3b68d81697c6197453cb6faff7b062f7861073148052db539895bc6583d08b4aa";
|
||||
u8 *tmp;
|
||||
|
||||
hex_len = os_strlen(auth_req);
|
||||
if (hex_len > 2 * MAX_FRAME_SIZE)
|
||||
ret = -1;
|
||||
else if (hexstr2bin(auth_req, auth, hex_len / 2))
|
||||
ret = -1;
|
||||
else
|
||||
len = hex_len / 2;
|
||||
frame = auth;
|
||||
frame += 26;
|
||||
len -= 26;
|
||||
auth_instance = dpp_auth_req_rx(NULL, 1, 0 , NULL,
|
||||
dpp_bootstrap_get_id(dpp, id), 2412, frame, frame+6, len-6);
|
||||
|
||||
/* auth response u8 */
|
||||
hex_len = os_strlen(auth_resp);
|
||||
if (hex_len > 2 * MAX_FRAME_SIZE)
|
||||
ret = -1;
|
||||
else if (hexstr2bin(auth_resp, auth, hex_len / 2))
|
||||
ret = -1;
|
||||
else
|
||||
len = hex_len / 2;
|
||||
tmp = auth;
|
||||
tmp += 26;
|
||||
len -= 26;
|
||||
|
||||
frame = wpabuf_head_u8(auth_instance->resp_msg);
|
||||
len = wpabuf_len(auth_instance->resp_msg);
|
||||
|
||||
TEST_ASSERT(memcmp(frame + 28, tmp + 26, len - 26) == 0);
|
||||
}
|
||||
ESP_LOGI("DPP Test", "Auth request parsing passed");
|
||||
ESP_LOGI("DPP Test", "Enqueue Auth confirm parsing passed");
|
||||
{
|
||||
char auth_confirm[] = "d00012341ac459c40d649f8664c1b8771ac459c40d6412340409506f9a1a0102001001000002102000922ddd7a3ed69f46125d772bbe6017cd4e03870dc014509e38b54628e157a87d0410340054e07e62c74526dfd97e029dc781e0771e573ebc73c94227b5de8350fc6a1974b40f54c9fe1a1c9288a91fce4ee6c1f2ff069741";
|
||||
hex_len = os_strlen(auth_confirm);
|
||||
os_memset(auth, 0, 1200);
|
||||
if (hex_len > 2 * MAX_FRAME_SIZE)
|
||||
ret = -1;
|
||||
else if (hexstr2bin(auth_confirm, auth, hex_len / 2))
|
||||
ret = -1;
|
||||
else
|
||||
len = hex_len / 2;
|
||||
frame = auth;
|
||||
frame = auth + 26;
|
||||
len = len - 26;
|
||||
dpp_auth_conf_rx(auth_instance, frame, frame+6, len-6);
|
||||
TEST_ASSERT(auth_instance->auth_success == 1);
|
||||
}
|
||||
ESP_LOGI("DPP Test", "Auth confirm parsing passed");
|
||||
/* deinit for memory passing */
|
||||
{
|
||||
dpp_auth_deinit(auth_instance);
|
||||
dpp_global_deinit(dpp);
|
||||
}
|
||||
ESP_LOGI("DPP Test", "Test case passed");
|
||||
}
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user