Merge branch 'feature/dpp_porting' into 'master'

wpa_supplicant: Port DPP crypto functionality from mainline supplicant repository.

See merge request espressif/esp-idf!7513
This commit is contained in:
Jiang Jiang Jian
2020-04-15 13:37:30 +08:00
32 changed files with 10038 additions and 707 deletions

View File

@@ -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
)

View File

@@ -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

View File

@@ -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

View File

@@ -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);
/**

View File

@@ -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 */

File diff suppressed because it is too large Load Diff

View 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 */

View File

@@ -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;

View 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);
}

View 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;
}

View 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 */

View File

@@ -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,

View File

@@ -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 */

View 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);
}

View 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 */

View File

@@ -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 */

View 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;
}

View File

@@ -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);
}
/**

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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 &&

View File

@@ -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);
}

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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

View 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, ',');
}

View 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 */

View File

@@ -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);

View File

@@ -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)

View File

@@ -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

View File

@@ -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);

View 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