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:
kapil.gupta
2020-07-23 22:42:37 +05:30
committed by bot
parent 59347d6a63
commit 50b4cf9286
5 changed files with 292 additions and 9 deletions

View File

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