mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-01 19:35:56 +00:00
wpa_supplicant: Fix IOT issue with latest freeradius
Fix inter operability issue with freeradius version 3.0.21 and openssl 1.1.1f when internal tls client is used which requires extension elements in client hello. closes https://github.com/espressif/esp-idf/issues/5273 closes https://github.com/espressif/esp-idf/issues/5627
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "crypto/md5.h"
|
||||
#include "crypto/sha1.h"
|
||||
#include "crypto/sha256.h"
|
||||
#include "tls/tls.h"
|
||||
@@ -333,3 +334,184 @@ int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label,
|
||||
return tls_prf_sha1_md5(secret, secret_len, label, seed, seed_len, out,
|
||||
outlen);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_TLSV12
|
||||
int tlsv12_key_x_server_params_hash(u16 tls_version, u8 hash_alg,
|
||||
const u8 *client_random,
|
||||
const u8 *server_random,
|
||||
const u8 *server_params,
|
||||
size_t server_params_len, u8 *hash)
|
||||
{
|
||||
size_t hlen;
|
||||
struct crypto_hash *ctx;
|
||||
enum crypto_hash_alg alg;
|
||||
|
||||
switch (hash_alg) {
|
||||
case TLS_HASH_ALG_SHA256:
|
||||
alg = CRYPTO_HASH_ALG_SHA256;
|
||||
hlen = SHA256_MAC_LEN;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
ctx = crypto_hash_init(alg, NULL, 0);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_params, server_params_len);
|
||||
if (crypto_hash_finish(ctx, hash, &hlen) < 0)
|
||||
return -1;
|
||||
|
||||
return hlen;
|
||||
}
|
||||
#endif /* CONFIG_TLSV12 */
|
||||
|
||||
|
||||
int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
|
||||
const u8 *server_random,
|
||||
const u8 *server_params,
|
||||
size_t server_params_len, u8 *hash)
|
||||
{
|
||||
u8 *hpos;
|
||||
size_t hlen;
|
||||
struct crypto_hash *ctx;
|
||||
|
||||
hpos = hash;
|
||||
|
||||
ctx = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_params, server_params_len);
|
||||
hlen = MD5_MAC_LEN;
|
||||
if (crypto_hash_finish(ctx, hash, &hlen) < 0)
|
||||
return -1;
|
||||
hpos += hlen;
|
||||
|
||||
ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_params, server_params_len);
|
||||
hlen = hash + sizeof(hash) - hpos;
|
||||
if (crypto_hash_finish(ctx, hpos, &hlen) < 0)
|
||||
return -1;
|
||||
hpos += hlen;
|
||||
return hpos - hash;
|
||||
}
|
||||
|
||||
|
||||
int tls_verify_signature(u16 tls_version, struct crypto_public_key *pk,
|
||||
const u8 *data, size_t data_len,
|
||||
const u8 *pos, size_t len, u8 *alert)
|
||||
{
|
||||
u8 *buf;
|
||||
const u8 *end = pos + len;
|
||||
const u8 *decrypted;
|
||||
u16 slen;
|
||||
size_t buflen;
|
||||
|
||||
if (end - pos < 2) {
|
||||
*alert = TLS_ALERT_DECODE_ERROR;
|
||||
return -1;
|
||||
}
|
||||
slen = WPA_GET_BE16(pos);
|
||||
pos += 2;
|
||||
if (end - pos < slen) {
|
||||
*alert = TLS_ALERT_DECODE_ERROR;
|
||||
return -1;
|
||||
}
|
||||
if (end - pos > slen) {
|
||||
wpa_hexdump(MSG_MSGDUMP, "Additional data after Signature",
|
||||
pos + slen, end - pos - slen);
|
||||
end = pos + slen;
|
||||
}
|
||||
|
||||
wpa_hexdump(MSG_MSGDUMP, "TLSv1: Signature", pos, end - pos);
|
||||
if (pk == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "TLSv1: No public key to verify signature");
|
||||
*alert = TLS_ALERT_INTERNAL_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
buflen = end - pos;
|
||||
buf = os_malloc(end - pos);
|
||||
if (buf == NULL) {
|
||||
*alert = TLS_ALERT_INTERNAL_ERROR;
|
||||
return -1;
|
||||
}
|
||||
if (crypto_public_key_decrypt_pkcs1(pk, pos, end - pos, buf, &buflen) <
|
||||
0) {
|
||||
wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt signature");
|
||||
os_free(buf);
|
||||
*alert = TLS_ALERT_DECRYPT_ERROR;
|
||||
return -1;
|
||||
}
|
||||
decrypted = buf;
|
||||
|
||||
wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature",
|
||||
decrypted, buflen);
|
||||
|
||||
#ifdef CONFIG_TLSV12
|
||||
if (tls_version >= TLS_VERSION_1_2) {
|
||||
/*
|
||||
* RFC 3447, A.2.4 RSASSA-PKCS1-v1_5
|
||||
*
|
||||
* DigestInfo ::= SEQUENCE {
|
||||
* digestAlgorithm DigestAlgorithm,
|
||||
* digest OCTET STRING
|
||||
* }
|
||||
*
|
||||
* SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11}
|
||||
*
|
||||
* DER encoded DigestInfo for SHA256 per RFC 3447:
|
||||
* 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 ||
|
||||
* H
|
||||
*/
|
||||
if (buflen >= 19 + 32 &&
|
||||
os_memcmp(buf, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01"
|
||||
"\x65\x03\x04\x02\x01\x05\x00\x04\x20", 19) == 0)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithm = SHA-256");
|
||||
decrypted = buf + 19;
|
||||
buflen -= 19;
|
||||
} else if (buflen >= 19 + 48 &&
|
||||
os_memcmp(buf, "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01"
|
||||
"\x65\x03\x04\x02\x02\x05\x00\x04\x30", 19) == 0)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithm = SHA-384");
|
||||
decrypted = buf + 19;
|
||||
buflen -= 19;
|
||||
} else if (buflen >= 19 + 64 &&
|
||||
os_memcmp(buf, "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01"
|
||||
"\x65\x03\x04\x02\x03\x05\x00\x04\x40", 19) == 0)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithm = SHA-512");
|
||||
decrypted = buf + 19;
|
||||
buflen -= 19;
|
||||
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "TLSv1.2: Unrecognized DigestInfo");
|
||||
os_free(buf);
|
||||
*alert = TLS_ALERT_DECRYPT_ERROR;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_TLSV12 */
|
||||
|
||||
if (buflen != data_len ||
|
||||
os_memcmp_const(decrypted, data, data_len) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in CertificateVerify - did not match calculated hash");
|
||||
os_free(buf);
|
||||
*alert = TLS_ALERT_DECRYPT_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_free(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user