mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/eap_client_iot_issue' into 'master'
wpa_supplicant: Fix IOT issue with freeradius & internal eap agent See merge request espressif/esp-idf!9766
This commit is contained in:
commit
b613f90cb9
@ -706,18 +706,16 @@ int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type,
|
||||
if (data == NULL || data_len == 0)
|
||||
return 0;
|
||||
|
||||
pos = conn->client_hello_ext = os_malloc(6 + data_len);
|
||||
pos = conn->client_hello_ext = os_malloc(4 + data_len);
|
||||
if (pos == NULL)
|
||||
return -1;
|
||||
|
||||
WPA_PUT_BE16(pos, 4 + data_len);
|
||||
pos += 2;
|
||||
WPA_PUT_BE16(pos, ext_type);
|
||||
pos += 2;
|
||||
WPA_PUT_BE16(pos, data_len);
|
||||
pos += 2;
|
||||
os_memcpy(pos, data, data_len);
|
||||
conn->client_hello_ext_len = 6 + data_len;
|
||||
conn->client_hello_ext_len = 4 + data_len;
|
||||
|
||||
if (ext_type == TLS_EXT_PAC_OPAQUE) {
|
||||
conn->session_ticket_included = 1;
|
||||
|
@ -409,9 +409,11 @@ static int tls_process_certificate(struct tlsv1_client *conn, u8 ct,
|
||||
|
||||
|
||||
static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
|
||||
const u8 *buf, size_t len)
|
||||
const u8 *buf, size_t len,
|
||||
tls_key_exchange key_exchange)
|
||||
{
|
||||
const u8 *pos, *end;
|
||||
const u8 *pos, *end, *server_params, *server_params_end;
|
||||
u8 alert;
|
||||
|
||||
tlsv1_client_free_dh(conn);
|
||||
|
||||
@ -420,6 +422,7 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
|
||||
|
||||
if (end - pos < 3)
|
||||
goto fail;
|
||||
server_params = pos;
|
||||
conn->dh_p_len = WPA_GET_BE16(pos);
|
||||
pos += 2;
|
||||
if (conn->dh_p_len == 0 || end - pos < (int) conn->dh_p_len) {
|
||||
@ -464,6 +467,60 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
|
||||
pos += conn->dh_ys_len;
|
||||
wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
|
||||
conn->dh_ys, conn->dh_ys_len);
|
||||
server_params_end = pos;
|
||||
|
||||
if (key_exchange == TLS_KEY_X_DHE_RSA) {
|
||||
u8 hash[64];
|
||||
int hlen;
|
||||
|
||||
if (conn->rl.tls_version == TLS_VERSION_1_2) {
|
||||
#ifdef CONFIG_TLSV12
|
||||
/*
|
||||
* RFC 5246, 4.7:
|
||||
* TLS v1.2 adds explicit indication of the used
|
||||
* signature and hash algorithms.
|
||||
*
|
||||
* struct {
|
||||
* HashAlgorithm hash;
|
||||
* SignatureAlgorithm signature;
|
||||
* } SignatureAndHashAlgorithm;
|
||||
*/
|
||||
if (end - pos < 2)
|
||||
goto fail;
|
||||
if ((pos[0] != TLS_HASH_ALG_SHA256) ||
|
||||
pos[1] != TLS_SIGN_ALG_RSA) {
|
||||
wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/signature(%u) algorithm",
|
||||
pos[0], pos[1]);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hlen = tlsv12_key_x_server_params_hash(
|
||||
conn->rl.tls_version, pos[0],
|
||||
conn->client_random,
|
||||
conn->server_random, server_params,
|
||||
server_params_end - server_params, hash);
|
||||
pos += 2;
|
||||
#else /* CONFIG_TLSV12 */
|
||||
goto fail;
|
||||
#endif /* CONFIG_TLSV12 */
|
||||
} else {
|
||||
hlen = tls_key_x_server_params_hash(
|
||||
conn->rl.tls_version, conn->client_random,
|
||||
conn->server_random, server_params,
|
||||
server_params_end - server_params, hash);
|
||||
}
|
||||
|
||||
if (hlen < 0)
|
||||
goto fail;
|
||||
wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerKeyExchange hash",
|
||||
hash, hlen);
|
||||
|
||||
if (tls_verify_signature(conn->rl.tls_version,
|
||||
conn->server_rsa_key,
|
||||
hash, hlen, pos, end - pos,
|
||||
&alert) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -542,8 +599,10 @@ static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len);
|
||||
suite = tls_get_cipher_suite(conn->rl.cipher_suite);
|
||||
if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) {
|
||||
if (tlsv1_process_diffie_hellman(conn, pos, len) < 0) {
|
||||
if (suite && (suite->key_exchange == TLS_KEY_X_DH_anon ||
|
||||
suite->key_exchange == TLS_KEY_X_DHE_RSA)) {
|
||||
if (tlsv1_process_diffie_hellman(conn, pos, len,
|
||||
suite->key_exchange) < 0) {
|
||||
tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||
TLS_ALERT_DECODE_ERROR);
|
||||
return -1;
|
||||
|
@ -48,6 +48,7 @@ u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len)
|
||||
u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr;
|
||||
struct os_time now;
|
||||
size_t len, i;
|
||||
u8 *ext_start;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello");
|
||||
*out_len = 0;
|
||||
@ -62,7 +63,7 @@ u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len)
|
||||
wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random",
|
||||
conn->client_random, TLS_RANDOM_LEN);
|
||||
|
||||
len = 100 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len;
|
||||
len = 150 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len;
|
||||
hello = os_malloc(len);
|
||||
if (hello == NULL)
|
||||
return NULL;
|
||||
@ -102,12 +103,42 @@ u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len)
|
||||
*pos++ = 1;
|
||||
*pos++ = TLS_COMPRESSION_NULL;
|
||||
|
||||
/* Extension */
|
||||
ext_start = pos;
|
||||
pos += 2;
|
||||
|
||||
#ifdef CONFIG_TLSV12
|
||||
if (conn->rl.tls_version >= TLS_VERSION_1_2) {
|
||||
/*
|
||||
* Add signature_algorithms extension since we support only
|
||||
* SHA256 (and not the default SHA1) with TLSv1.2.
|
||||
*/
|
||||
/* ExtensionsType extension_type = signature_algorithms(13) */
|
||||
WPA_PUT_BE16(pos, TLS_EXT_SIGNATURE_ALGORITHMS);
|
||||
pos += 2;
|
||||
/* opaque extension_data<0..2^16-1> length */
|
||||
WPA_PUT_BE16(pos, 4);
|
||||
pos += 2;
|
||||
/* supported_signature_algorithms<2..2^16-2> length */
|
||||
WPA_PUT_BE16(pos, 2);
|
||||
pos += 2;
|
||||
/* supported_signature_algorithms */
|
||||
*pos++ = TLS_HASH_ALG_SHA256;
|
||||
*pos++ = TLS_SIGN_ALG_RSA;
|
||||
}
|
||||
#endif /* CONFIG_TLSV12 */
|
||||
|
||||
if (conn->client_hello_ext) {
|
||||
os_memcpy(pos, conn->client_hello_ext,
|
||||
conn->client_hello_ext_len);
|
||||
pos += conn->client_hello_ext_len;
|
||||
}
|
||||
|
||||
if (pos == ext_start + 2)
|
||||
pos -= 2; /* no extensions */
|
||||
else
|
||||
WPA_PUT_BE16(ext_start, pos - ext_start - 2);
|
||||
|
||||
WPA_PUT_BE24(hs_length, pos - hs_length - 3);
|
||||
tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -169,6 +169,7 @@ enum {
|
||||
#define TLS_EXT_TRUSTED_CA_KEYS 3 /* RFC 4366 */
|
||||
#define TLS_EXT_TRUNCATED_HMAC 4 /* RFC 4366 */
|
||||
#define TLS_EXT_STATUS_REQUEST 5 /* RFC 4366 */
|
||||
#define TLS_EXT_SIGNATURE_ALGORITHMS 13 /* RFC 5246 */
|
||||
#define TLS_EXT_SESSION_TICKET 35 /* RFC 4507 */
|
||||
|
||||
#define TLS_EXT_PAC_OPAQUE TLS_EXT_SESSION_TICKET /* EAP-FAST terminology */
|
||||
@ -257,5 +258,17 @@ int tls_version_ok(u16 ver);
|
||||
const char * tls_version_str(u16 ver);
|
||||
int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label,
|
||||
const u8 *seed, size_t seed_len, u8 *out, size_t outlen);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
#endif /* TLSV1_COMMON_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user