[wpa_supplicant] Cumulative patch from commit 09a281e52
Bug: 237446599
Test: connect/disconnect to WPA2, WPA3 networks
Test: SoftAp & p2p connection
Test: Regression test(b/237480760)
BYPASS_INCLUSIVE_LANGUAGE_REASON=Merged from Open source
09a281e52 Add QCA vendor interface for PASN offload to userspace
809fb96fa Add a vendor attribute to configure concurrency policy for AP interface
a5754f531 Rename QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY
085a3fc76 EHT: Add 320 channel width support
bafe35df0 Move CHANWIDTH_* definitions from ieee80211_defs.h to defs.h
3c2ba98ad Add QCA vendor event to indicate driver recovery after internal failures
6b461f68c Set current_ssid before changing state to ASSOCIATING
8dd826741 QCA vendor attribute to configure direct data path for audio traffic
504be2f9d QCA vendor command support to get WLAN radio combinations
d5905dbc8 OCV: Check the Frequency Segment 1 Channel Number only on 80+80 MHz
4383528e0 P2P: Use weighted preferred channel list for channel selection
f2c5c8d38 QCA vendor attribute to configure RX link speed threshold for roaming
94bc94b20 Add QCA vendor attribute for DO_ACS to allow using existing scan entries
b9e2826b9 P2P: Filter 6 GHz channels if peer doesn't support them
d5a9944b8 Reserve QCA vendor sub command id 206..212
ed63c286f Remove space before tab in QCA vendor commands
e4015440a ProxyARP: Clear bridge parameters on deinit only if hostapd set them
02047e9c8 hs20-osu-client: Explicit checks for snprintf() result
cd92f7f98 FIPS PRF: Avoid duplicate SHA1Init() functionality
5c87fcc15 OpenSSL: Use internal FIPS 186-2 PRF with OpenSSL 3.0
9e305878c SAE-PK: Fix build without AES-SIV
c41004d86 OpenSSL: Convert more crypto_ec_key routines to new EVP API
667a2959c OpenSSL: crypto_ec_key_get_public_key() using new EVP_PKEY API
5b97395b3 OpenSSL: crypto_ec_key_get_private_key() using new EVP_PKEY API
177ebfe10 crypto: Convert crypto_ec_key_get_public_key() to return new ec_point
26780d92f crypto: Convert crypto_ec_key_get_private_key() to return new bignum
c9c2c2d9c OpenSSL: Fix a memory leak on crypto_hash_init() error path
6d19dccf9 OpenSSL: Free OSSL_DECODER_CTX in tls_global_dh()
4f4479ef9 OpenSSL: crypto_ec_key_parse_{priv,pub}() without EC_KEY API
563699174 EAP-SIM/AKA peer: IMSI privacy attribute
1004fb7ee tests: Testing functionality to discard DPP Public Action frames
99165cc4b Rename wpa_supplicant imsi_privacy_key configuration parameter
35eda6e70 EAP-SIM peer: Free imsi_privacy_key on an error path
1328cdeb1 Do not try to use network profile with invalid imsi_privacy_key
d1652dc7c OpenSSL: Refuse to accept expired RSA certificate
866e7b745 OpenSSL: Include rsa.h for OpenSSL 3.0
bc99366f9 OpenSSL: Drop security level to 0 with OpenSSL 3.0 when using TLS 1.0/1.1
ed325ff0f DPP: Allow TCP destination (address/port) to be used from peer URI
37bb4178b DPP: Host information in bootstrapping URI
1142b6e41 EHT: Do not check HE PHY capability info reserved fields
bc3699179 Use Secure=1 in PTK rekeying EAPOL-Key msg 1/4 and 2/4
b859b9bce Simplify wpa_bss_get_vendor_ie_multi_beacon() bounds checking
fc9648a6a DPP: Debug print if not relay is available for PKEX exchange
1739d50c2 FST: More robust bounds checking of local data in fst_dump_mb_ies()
63eb98a8e SAE: Make Anti-Clogging token element parsing simpler
a6e04a067 Simplify DSCP policy parsing
77bb12a60 P2P: Maintain ip_pool bitfield index separately
3f3ce0571 Check sscanf() return value in TWT_SETUP parsing
2982e50c1 EAP-SAKA: Simplify attribute parser for static analyzers
6e8518749 GAS: Limit maximum comeback delay value
fe1dc9ba7 WNM: Try to make bounds checking easier for static analyzers
f8615990e Simplify wpa_parse_kde_ies()
61d37f44b Simplify wpa_parse_generic()
469528a6e BSS coloring: Fix bitmap check
8392c86df Check he_cap pointer in hostapd_set_freq_params() consistently
2227c85a9 DPP: Verify that crypto_ec_point_to_bin() succeeds
a8c319952 nl80211: Verify that nla_put_flag() succeeds for background radar
993eb1240 FST: Make sure get_hw_modes() callback is set for hostapd
4537fe124 P2P: Explicit nul termination of the generated passphrase
79dc7f619 scan: Add option to disable 6 GHz collocated scanning
3b8d9da9b nl80211: Set NL80211_SCAN_FLAG_COLOCATED_6GHZ in scan
96a7f3832 hostapd: Add the destination address of unsolicited Probe Response frame
16e755754 Add -q flag to hostapd in order to control log level
869037443 Discard unencrypted EAPOL/EAP when TK is set and PMF is enabled (AP)
3c2fbe9f5 Discard unencrypted EAPOL-EAP when TK is set and PMF is enabled
872a57500 Discard unencrypted EAPOL-Key msg 1/4 when TK is set and PMF is enabled
e6c0e1215 Do not prevent Michael MIC error report based on disallowed PTK0 rekey
18c0ac890 Provide information about the encryption status of received EAPOL frames
7ee814201 FILS: Set pairwise_set when configuring TK after association
98278c0de Fix no_encrypt flag in control port TX for rekeying
b1172c19e WPA: Discard EAPOL-Key msg 1/4 with corrupted information elements
7a7a4ea57 Check need for SA Query/assoc comeback before updating RSNE parameters
Change-Id: Ifbfe69676b38499a221aeb242cdb3eac3deee375
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index e4f3eb3..67210a0 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -1086,16 +1086,20 @@
* crypto_ec_key_get_public_key - Get EC public key as an EC point
* @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_parse_priv()
* Returns: Public key as an EC point or %NULL on failure
+ *
+ * The caller needs to free the returned value with crypto_ec_point_deinit().
*/
-const struct crypto_ec_point *
+struct crypto_ec_point *
crypto_ec_key_get_public_key(struct crypto_ec_key *key);
/**
* crypto_ec_key_get_private_key - Get EC private key as a bignum
* @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_parse_priv()
* Returns: Private key as a bignum or %NULL on failure
+ *
+ * The caller needs to free the returned value with crypto_bignum_deinit().
*/
-const struct crypto_bignum *
+struct crypto_bignum *
crypto_ec_key_get_private_key(struct crypto_ec_key *key);
/**
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index c6e065f..08e9f26 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -25,6 +25,9 @@
#include <openssl/provider.h>
#include <openssl/core_names.h>
#include <openssl/param_build.h>
+#include <openssl/rsa.h>
+#include <openssl/encoder.h>
+#include <openssl/decoder.h>
#else /* OpenSSL version >= 3.0 */
#include <openssl/cmac.h>
#endif /* OpenSSL version >= 3.0 */
@@ -117,6 +120,19 @@
{
return ASN1_STRING_data((ASN1_STRING *) x);
}
+
+
+static const ASN1_TIME * X509_get0_notBefore(const X509 *x)
+{
+ return X509_get_notBefore(x);
+}
+
+
+static const ASN1_TIME * X509_get0_notAfter(const X509 *x)
+{
+ return X509_get_notAfter(x);
+}
+
#endif /* OpenSSL version < 1.1.0 */
@@ -1347,21 +1363,22 @@
ctx = os_zalloc(sizeof(*ctx));
if (!ctx)
- return NULL;
+ goto fail;
ctx->ctx = EVP_MAC_CTX_new(mac);
if (!ctx->ctx) {
- EVP_MAC_free(mac);
os_free(ctx);
- return NULL;
+ ctx = NULL;
+ goto fail;
}
if (EVP_MAC_init(ctx->ctx, key, key_len, params) != 1) {
EVP_MAC_CTX_free(ctx->ctx);
bin_clear_free(ctx, sizeof(*ctx));
- EVP_MAC_free(mac);
- return NULL;
+ ctx = NULL;
+ goto fail;
}
+fail:
EVP_MAC_free(mac);
return ctx;
#else /* OpenSSL version >= 3.0 */
@@ -2216,6 +2233,7 @@
struct crypto_ec {
EC_GROUP *group;
int nid;
+ int iana_group;
BN_CTX *bnctx;
BIGNUM *prime;
BIGNUM *order;
@@ -2260,6 +2278,44 @@
}
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+static const char * crypto_ec_group_2_name(int group)
+{
+ /* Map from IANA registry for IKE D-H groups to OpenSSL group name */
+ switch (group) {
+ case 19:
+ return "prime256v1";
+ case 20:
+ return "secp384r1";
+ case 21:
+ return "secp521r1";
+ case 25:
+ return "prime192v1";
+ case 26:
+ return "secp224r1";
+#ifdef NID_brainpoolP224r1
+ case 27:
+ return "brainpoolP224r1";
+#endif /* NID_brainpoolP224r1 */
+#ifdef NID_brainpoolP256r1
+ case 28:
+ return "brainpoolP256r1";
+#endif /* NID_brainpoolP256r1 */
+#ifdef NID_brainpoolP384r1
+ case 29:
+ return "brainpoolP384r1";
+#endif /* NID_brainpoolP384r1 */
+#ifdef NID_brainpoolP512r1
+ case 30:
+ return "brainpoolP512r1";
+#endif /* NID_brainpoolP512r1 */
+ default:
+ return NULL;
+ }
+}
+#endif /* OpenSSL version >= 3.0 */
+
+
struct crypto_ec * crypto_ec_init(int group)
{
struct crypto_ec *e;
@@ -2274,6 +2330,7 @@
return NULL;
e->nid = nid;
+ e->iana_group = group;
e->bnctx = BN_CTX_new();
e->group = EC_GROUP_new_by_curve_name(nid);
e->prime = BN_new();
@@ -2936,6 +2993,27 @@
struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len)
{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_PKEY *pkey = NULL;
+ OSSL_DECODER_CTX *ctx;
+
+ ctx = OSSL_DECODER_CTX_new_for_pkey(
+ &pkey, "DER", NULL, "EC",
+ OSSL_KEYMGMT_SELECT_KEYPAIR |
+ OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ NULL, NULL);
+ if (!ctx ||
+ OSSL_DECODER_from_data(ctx, &der, &der_len) != 1) {
+ wpa_printf(MSG_INFO, "OpenSSL: Decoding EC private key (DER) failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto fail;
+ }
+
+ return (struct crypto_ec_key *) pkey;
+fail:
+ crypto_ec_key_deinit((struct crypto_ec_key *) pkey);
+ return NULL;
+#else /* OpenSSL version >= 3.0 */
EVP_PKEY *pkey = NULL;
EC_KEY *eckey;
@@ -2957,6 +3035,7 @@
fail:
crypto_ec_key_deinit((struct crypto_ec_key *) pkey);
return NULL;
+#endif /* OpenSSL version >= 3.0 */
}
@@ -2972,8 +3051,13 @@
}
/* Ensure this is an EC key */
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ if (!EVP_PKEY_is_a(pkey, "EC"))
+ goto fail;
+#else /* OpenSSL version >= 3.0 */
if (!EVP_PKEY_get0_EC_KEY(pkey))
goto fail;
+#endif /* OpenSSL version >= 3.0 */
return (struct crypto_ec_key *) pkey;
fail:
crypto_ec_key_deinit((struct crypto_ec_key *) pkey);
@@ -2984,6 +3068,47 @@
struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *buf_x,
const u8 *buf_y, size_t len)
{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ const char *group_name;
+ OSSL_PARAM params[3];
+ u8 *pub;
+ EVP_PKEY_CTX *ctx;
+ EVP_PKEY *pkey = NULL;
+
+ group_name = crypto_ec_group_2_name(group);
+ if (!group_name)
+ return NULL;
+
+ pub = os_malloc(1 + len * 2);
+ if (!pub)
+ return NULL;
+ pub[0] = 0x04; /* uncompressed */
+ os_memcpy(pub + 1, buf_x, len);
+ os_memcpy(pub + 1 + len, buf_y, len);
+
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
+ (char *) group_name, 0);
+ params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
+ pub, 1 + len * 2);
+ params[2] = OSSL_PARAM_construct_end();
+
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
+ if (!ctx) {
+ os_free(pub);
+ return NULL;
+ }
+ if (EVP_PKEY_fromdata_init(ctx) <= 0 ||
+ EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) {
+ os_free(pub);
+ EVP_PKEY_CTX_free(ctx);
+ return NULL;
+ }
+
+ os_free(pub);
+ EVP_PKEY_CTX_free(ctx);
+
+ return (struct crypto_ec_key *) pkey;
+#else /* OpenSSL version >= 3.0 */
EC_KEY *eckey = NULL;
EVP_PKEY *pkey = NULL;
EC_GROUP *ec_group = NULL;
@@ -3058,6 +3183,7 @@
EVP_PKEY_free(pkey);
pkey = NULL;
goto out;
+#endif /* OpenSSL version >= 3.0 */
}
@@ -3065,9 +3191,28 @@
crypto_ec_key_set_pub_point(struct crypto_ec *ec,
const struct crypto_ec_point *pub)
{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ int len = BN_num_bytes(ec->prime);
+ struct crypto_ec_key *key;
+ u8 *buf;
+
+ buf = os_malloc(2 * len);
+ if (!buf)
+ return NULL;
+ if (crypto_ec_point_to_bin(ec, pub, buf, buf + len) < 0) {
+ os_free(buf);
+ return NULL;
+ }
+
+ key = crypto_ec_key_set_pub(ec->iana_group, buf, buf + len, len);
+ os_free(buf);
+
+ return key;
+#else /* OpenSSL version >= 3.0 */
EC_KEY *eckey;
EVP_PKEY *pkey = NULL;
+ wpa_printf(MSG_INFO, "JKM:%s", __func__);
eckey = EC_KEY_new();
if (!eckey ||
EC_KEY_set_group(eckey, ec->group) != 1 ||
@@ -3093,11 +3238,41 @@
EC_KEY_free(eckey);
pkey = NULL;
goto out;
+#endif /* OpenSSL version >= 3.0 */
}
struct crypto_ec_key * crypto_ec_key_gen(int group)
{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_PKEY_CTX *ctx;
+ OSSL_PARAM params[2];
+ const char *group_name;
+ EVP_PKEY *pkey = NULL;
+
+ group_name = crypto_ec_group_2_name(group);
+ if (!group_name)
+ return NULL;
+
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
+ (char *) group_name, 0);
+ params[1] = OSSL_PARAM_construct_end();
+
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
+ if (!ctx ||
+ EVP_PKEY_keygen_init(ctx) != 1 ||
+ EVP_PKEY_CTX_set_params(ctx, params) != 1 ||
+ EVP_PKEY_generate(ctx, &pkey) != 1) {
+ wpa_printf(MSG_INFO,
+ "OpenSSL: failed to generate EC keypair: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ pkey = NULL;
+ }
+
+ EVP_PKEY_CTX_free(ctx);
+
+ return (struct crypto_ec_key *) pkey;
+#else /* OpenSSL version >= 3.0 */
EVP_PKEY_CTX *kctx = NULL;
EC_KEY *ec_params = NULL, *eckey;
EVP_PKEY *params = NULL, *key = NULL;
@@ -3145,6 +3320,7 @@
EVP_PKEY_free(params);
EVP_PKEY_CTX_free(kctx);
return (struct crypto_ec_key *) key;
+#endif /* OpenSSL version >= 3.0 */
}
@@ -3183,6 +3359,54 @@
struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
{
+ EVP_PKEY *pkey = (EVP_PKEY *) key;
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ OSSL_ENCODER_CTX *ctx;
+ int selection;
+ unsigned char *pdata = NULL;
+ size_t pdata_len = 0;
+ EVP_PKEY *copy = NULL;
+ struct wpabuf *buf = NULL;
+
+ if (EVP_PKEY_get_ec_point_conv_form(pkey) !=
+ POINT_CONVERSION_COMPRESSED) {
+ copy = EVP_PKEY_dup(pkey);
+ if (!copy)
+ return NULL;
+ if (EVP_PKEY_set_utf8_string_param(
+ copy, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
+ OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED) !=
+ 1) {
+ wpa_printf(MSG_INFO,
+ "OpenSSL: Failed to set compressed format");
+ EVP_PKEY_free(copy);
+ return NULL;
+ }
+ pkey = copy;
+ }
+
+ selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS |
+ OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+
+ ctx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "DER",
+ "SubjectPublicKeyInfo",
+ NULL);
+ if (!ctx || OSSL_ENCODER_to_data(ctx, &pdata, &pdata_len) != 1) {
+ wpa_printf(MSG_INFO,
+ "OpenSSL: Failed to encode SubjectPublicKeyInfo: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ pdata = NULL;
+ }
+ OSSL_ENCODER_CTX_free(ctx);
+ if (pdata) {
+ buf = wpabuf_alloc_copy(pdata, pdata_len);
+ OPENSSL_free(pdata);
+ }
+
+ EVP_PKEY_free(copy);
+
+ return buf;
+#else /* OpenSSL version >= 3.0 */
#ifdef OPENSSL_IS_BORINGSSL
unsigned char *der = NULL;
int der_len;
@@ -3196,7 +3420,7 @@
int nid;
ctx = BN_CTX_new();
- eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
+ eckey = EVP_PKEY_get0_EC_KEY(pkey);
if (!ctx || !eckey)
goto fail;
@@ -3249,33 +3473,16 @@
int der_len;
struct wpabuf *buf;
EC_KEY *eckey;
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
- EVP_PKEY *tmp;
-#endif /* OpenSSL version >= 3.0 */
- eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key);
+ eckey = EVP_PKEY_get1_EC_KEY(pkey);
if (!eckey)
return NULL;
/* For now, all users expect COMPRESSED form */
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
- tmp = EVP_PKEY_new();
- if (!tmp)
- return NULL;
- if (EVP_PKEY_set1_EC_KEY(tmp, eckey) != 1) {
- EVP_PKEY_free(tmp);
- return NULL;
- }
- key = (struct crypto_ec_key *) tmp;
-#endif /* OpenSSL version >= 3.0 */
-
der_len = i2d_PUBKEY((EVP_PKEY *) key, &der);
EC_KEY_free(eckey);
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
- EVP_PKEY_free(tmp);
-#endif /* OpenSSL version >= 3.0 */
if (der_len <= 0) {
wpa_printf(MSG_INFO, "OpenSSL: i2d_PUBKEY() failed: %s",
ERR_error_string(ERR_get_error(), NULL));
@@ -3286,19 +3493,58 @@
OPENSSL_free(der);
return buf;
#endif /* OPENSSL_IS_BORINGSSL */
+#endif /* OpenSSL version >= 3.0 */
}
struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key,
bool include_pub)
{
+ EVP_PKEY *pkey = (EVP_PKEY *) key;
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ OSSL_ENCODER_CTX *ctx;
+ int selection;
+ unsigned char *pdata = NULL;
+ size_t pdata_len = 0;
+ struct wpabuf *buf;
+ EVP_PKEY *copy = NULL;
+
+ selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS |
+ OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
+ if (include_pub) {
+ selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+ } else {
+ /* Not including OSSL_KEYMGMT_SELECT_PUBLIC_KEY does not seem
+ * to really be sufficient, so clone the key and explicitly
+ * mark it not to include the public key. */
+ copy = EVP_PKEY_dup(pkey);
+ if (!copy)
+ return NULL;
+ EVP_PKEY_set_int_param(copy, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC,
+ 0);
+ pkey = copy;
+ }
+
+ ctx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "DER",
+ "type-specific", NULL);
+ if (!ctx || OSSL_ENCODER_to_data(ctx, &pdata, &pdata_len) != 1) {
+ OSSL_ENCODER_CTX_free(ctx);
+ EVP_PKEY_free(copy);
+ return NULL;
+ }
+ OSSL_ENCODER_CTX_free(ctx);
+ buf = wpabuf_alloc_copy(pdata, pdata_len);
+ OPENSSL_free(pdata);
+ EVP_PKEY_free(copy);
+ return buf;
+#else /* OpenSSL version >= 3.0 */
EC_KEY *eckey;
unsigned char *der = NULL;
int der_len;
struct wpabuf *buf;
unsigned int key_flags;
- eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key);
+ eckey = EVP_PKEY_get1_EC_KEY(pkey);
if (!eckey)
return NULL;
@@ -3319,18 +3565,53 @@
OPENSSL_free(der);
return buf;
+#endif /* OpenSSL version >= 3.0 */
}
struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key,
int prefix)
{
+ EVP_PKEY *pkey = (EVP_PKEY *) key;
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ struct wpabuf *buf;
+ unsigned char *pos;
+ size_t pub_len = OSSL_PARAM_UNMODIFIED;
+
+ buf = NULL;
+ if (!EVP_PKEY_is_a(pkey, "EC") ||
+ EVP_PKEY_get_octet_string_param(pkey,
+ OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
+ NULL, 0, &pub_len) < 0 ||
+ pub_len == OSSL_PARAM_UNMODIFIED ||
+ !(buf = wpabuf_alloc(pub_len)) ||
+ EVP_PKEY_get_octet_string_param(pkey,
+ OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
+ wpabuf_put(buf, pub_len),
+ pub_len, NULL) != 1 ||
+ wpabuf_head_u8(buf)[0] != 0x04) {
+ wpa_printf(MSG_INFO,
+ "OpenSSL: Failed to get encoded public key: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ wpabuf_free(buf);
+ return NULL;
+ }
+
+ if (!prefix) {
+ /* Remove 0x04 prefix if requested */
+ pos = wpabuf_mhead(buf);
+ os_memmove(pos, pos + 1, pub_len - 1);
+ buf->used--;
+ }
+
+ return buf;
+#else /* OpenSSL version >= 3.0 */
int len, res;
EC_KEY *eckey;
struct wpabuf *buf;
unsigned char *pos;
- eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key);
+ eckey = EVP_PKEY_get1_EC_KEY(pkey);
if (!eckey)
return NULL;
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
@@ -3367,30 +3648,92 @@
}
return buf;
+#endif /* OpenSSL version >= 3.0 */
}
-const struct crypto_ec_point *
+struct crypto_ec_point *
crypto_ec_key_get_public_key(struct crypto_ec_key *key)
{
- const EC_KEY *eckey;
+ EVP_PKEY *pkey = (EVP_PKEY *) key;
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ char group[64];
+ unsigned char pub[256];
+ size_t len;
+ EC_POINT *point = NULL;
+ EC_GROUP *grp;
+ int res = 0;
+ OSSL_PARAM params[2];
- eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
+ if (!EVP_PKEY_is_a(pkey, "EC") ||
+ EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME,
+ group, sizeof(group), &len) != 1 ||
+ EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY,
+ pub, sizeof(pub), &len) != 1)
+ return NULL;
+
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
+ group, 0);
+ params[1] = OSSL_PARAM_construct_end();
+ grp = EC_GROUP_new_from_params(params, NULL, NULL);
+ if (!grp)
+ goto fail;
+ point = EC_POINT_new(grp);
+ if (!point)
+ goto fail;
+ res = EC_POINT_oct2point(grp, point, pub, len, NULL);
+
+fail:
+ if (res != 1) {
+ EC_POINT_free(point);
+ point = NULL;
+ }
+
+ EC_GROUP_free(grp);
+
+ return (struct crypto_ec_point *) point;
+#else /* OpenSSL version >= 3.0 */
+ const EC_KEY *eckey;
+ const EC_POINT *point;
+ const EC_GROUP *group;
+
+ eckey = EVP_PKEY_get0_EC_KEY(pkey);
if (!eckey)
return NULL;
- return (const struct crypto_ec_point *) EC_KEY_get0_public_key(eckey);
+ group = EC_KEY_get0_group(eckey);
+ if (!group)
+ return NULL;
+ point = EC_KEY_get0_public_key(eckey);
+ if (!point)
+ return NULL;
+ return (struct crypto_ec_point *) EC_POINT_dup(point, group);
+#endif /* OpenSSL version >= 3.0 */
}
-const struct crypto_bignum *
+struct crypto_bignum *
crypto_ec_key_get_private_key(struct crypto_ec_key *key)
{
- const EC_KEY *eckey;
+ EVP_PKEY *pkey = (EVP_PKEY *) key;
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ BIGNUM *bn = NULL;
- eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
+ if (!EVP_PKEY_is_a(pkey, "EC") ||
+ EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &bn) != 1)
+ return NULL;
+ return (struct crypto_bignum *) bn;
+#else /* OpenSSL version >= 3.0 */
+ const EC_KEY *eckey;
+ const BIGNUM *bn;
+
+ eckey = EVP_PKEY_get0_EC_KEY(pkey);
if (!eckey)
return NULL;
- return (const struct crypto_bignum *) EC_KEY_get0_private_key(eckey);
+ bn = EC_KEY_get0_private_key(eckey);
+ if (!bn)
+ return NULL;
+ return (struct crypto_bignum *) BN_dup(bn);
+#endif /* OpenSSL version >= 3.0 */
}
@@ -3943,6 +4286,8 @@
{
EVP_PKEY *pkey;
X509 *x509;
+ const ASN1_TIME *not_before, *not_after;
+ int res_before, res_after;
pkey = PEM_read_PUBKEY(f, NULL, NULL, NULL);
if (pkey)
@@ -3953,17 +4298,36 @@
if (!x509)
return NULL;
+ not_before = X509_get0_notBefore(x509);
+ not_after = X509_get0_notAfter(x509);
+ if (!not_before || !not_after)
+ goto fail;
+ res_before = X509_cmp_current_time(not_before);
+ res_after = X509_cmp_current_time(not_after);
+ if (!res_before || !res_after)
+ goto fail;
+ if (res_before > 0 || res_after < 0) {
+ wpa_printf(MSG_INFO,
+ "OpenSSL: Certificate for RSA public key is not valid at this time (%d %d)",
+ res_before, res_after);
+ goto fail;
+ }
+
pkey = X509_get_pubkey(x509);
X509_free(x509);
if (!pkey)
return NULL;
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) {
+ wpa_printf(MSG_INFO, "OpenSSL: No RSA public key found");
EVP_PKEY_free(pkey);
return NULL;
}
return pkey;
+fail:
+ X509_free(x509);
+ return NULL;
}
diff --git a/src/crypto/fips_prf_internal.c b/src/crypto/fips_prf_internal.c
index a4bf50a..f9347d0 100644
--- a/src/crypto/fips_prf_internal.c
+++ b/src/crypto/fips_prf_internal.c
@@ -17,10 +17,11 @@
int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
{
u8 xkey[64];
- u32 t[5], _t[5];
+ u32 _t[5];
int i, j, m, k;
u8 *xpos = x;
u32 carry;
+ struct SHA1Context ctx;
if (seed_len < sizeof(xkey))
os_memset(xkey + seed_len, 0, sizeof(xkey) - seed_len);
@@ -30,11 +31,7 @@
/* FIPS 186-2 + change notice 1 */
os_memcpy(xkey, seed, seed_len);
- t[0] = 0x67452301;
- t[1] = 0xEFCDAB89;
- t[2] = 0x98BADCFE;
- t[3] = 0x10325476;
- t[4] = 0xC3D2E1F0;
+ SHA1Init(&ctx);
m = xlen / 40;
for (j = 0; j < m; j++) {
@@ -43,7 +40,7 @@
/* XVAL = (XKEY + XSEED_j) mod 2^b */
/* w_i = G(t, XVAL) */
- os_memcpy(_t, t, 20);
+ os_memcpy(_t, ctx.state, 20);
SHA1Transform(_t, xkey);
_t[0] = host_to_be32(_t[0]);
_t[1] = host_to_be32(_t[1]);
diff --git a/src/crypto/fips_prf_openssl.c b/src/crypto/fips_prf_openssl.c
index 4697e04..484f772 100644
--- a/src/crypto/fips_prf_openssl.c
+++ b/src/crypto/fips_prf_openssl.c
@@ -7,6 +7,19 @@
*/
#include "includes.h"
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+
+/* OpenSSL 3.0 has deprecated the low-level SHA1 functions and does not
+ * include an upper layer interface that could be used to use the
+ * SHA1_Transform() function. Use the internal SHA-1 implementation instead
+ * as a workaround. */
+#include "sha1-internal.c"
+#include "fips_prf_internal.c"
+
+#else /* OpenSSL version >= 3.0 */
+
#include <openssl/sha.h>
#include "common.h"
@@ -97,3 +110,5 @@
return 0;
}
+
+#endif /* OpenSSL version >= 3.0 */
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index a1b5166..dc8a1b4 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -1584,6 +1584,15 @@
struct tls_connection *conn = arg;
const u8 *pos = buf;
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ if ((SSL_version(ssl) == TLS1_VERSION ||
+ SSL_version(ssl) == TLS1_1_VERSION) &&
+ SSL_get_security_level(ssl) > 0) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Drop security level to 0 to allow TLS 1.0/1.1 use of MD5-SHA1 signature algorithm");
+ SSL_set_security_level(ssl, 0);
+ }
+#endif /* OpenSSL version >= 3.0 */
if (write_p == 2) {
wpa_printf(MSG_DEBUG,
"OpenSSL: session ver=0x%x content_type=%d",
@@ -4180,8 +4189,10 @@
"TLS: Failed to decode domain parameters from '%s': %s",
dh_file, ERR_error_string(ERR_get_error(), NULL));
BIO_free(bio);
+ OSSL_DECODER_CTX_free(ctx);
return -1;
}
+ OSSL_DECODER_CTX_free(ctx);
BIO_free(bio);
if (!tmpkey) {