Skip to content

Commit b613f90

Browse files
committed
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
2 parents 0b9e303 + 50b4cf9 commit b613f90

File tree

5 files changed

+292
-9
lines changed

5 files changed

+292
-9
lines changed

components/wpa_supplicant/src/tls/tlsv1_client.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -706,18 +706,16 @@ int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type,
706706
if (data == NULL || data_len == 0)
707707
return 0;
708708

709-
pos = conn->client_hello_ext = os_malloc(6 + data_len);
709+
pos = conn->client_hello_ext = os_malloc(4 + data_len);
710710
if (pos == NULL)
711711
return -1;
712712

713-
WPA_PUT_BE16(pos, 4 + data_len);
714-
pos += 2;
715713
WPA_PUT_BE16(pos, ext_type);
716714
pos += 2;
717715
WPA_PUT_BE16(pos, data_len);
718716
pos += 2;
719717
os_memcpy(pos, data, data_len);
720-
conn->client_hello_ext_len = 6 + data_len;
718+
conn->client_hello_ext_len = 4 + data_len;
721719

722720
if (ext_type == TLS_EXT_PAC_OPAQUE) {
723721
conn->session_ticket_included = 1;

components/wpa_supplicant/src/tls/tlsv1_client_read.c

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,11 @@ static int tls_process_certificate(struct tlsv1_client *conn, u8 ct,
409409

410410

411411
static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
412-
const u8 *buf, size_t len)
412+
const u8 *buf, size_t len,
413+
tls_key_exchange key_exchange)
413414
{
414-
const u8 *pos, *end;
415+
const u8 *pos, *end, *server_params, *server_params_end;
416+
u8 alert;
415417

416418
tlsv1_client_free_dh(conn);
417419

@@ -420,6 +422,7 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
420422

421423
if (end - pos < 3)
422424
goto fail;
425+
server_params = pos;
423426
conn->dh_p_len = WPA_GET_BE16(pos);
424427
pos += 2;
425428
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,
464467
pos += conn->dh_ys_len;
465468
wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
466469
conn->dh_ys, conn->dh_ys_len);
470+
server_params_end = pos;
471+
472+
if (key_exchange == TLS_KEY_X_DHE_RSA) {
473+
u8 hash[64];
474+
int hlen;
475+
476+
if (conn->rl.tls_version == TLS_VERSION_1_2) {
477+
#ifdef CONFIG_TLSV12
478+
/*
479+
* RFC 5246, 4.7:
480+
* TLS v1.2 adds explicit indication of the used
481+
* signature and hash algorithms.
482+
*
483+
* struct {
484+
* HashAlgorithm hash;
485+
* SignatureAlgorithm signature;
486+
* } SignatureAndHashAlgorithm;
487+
*/
488+
if (end - pos < 2)
489+
goto fail;
490+
if ((pos[0] != TLS_HASH_ALG_SHA256) ||
491+
pos[1] != TLS_SIGN_ALG_RSA) {
492+
wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/signature(%u) algorithm",
493+
pos[0], pos[1]);
494+
goto fail;
495+
}
496+
497+
hlen = tlsv12_key_x_server_params_hash(
498+
conn->rl.tls_version, pos[0],
499+
conn->client_random,
500+
conn->server_random, server_params,
501+
server_params_end - server_params, hash);
502+
pos += 2;
503+
#else /* CONFIG_TLSV12 */
504+
goto fail;
505+
#endif /* CONFIG_TLSV12 */
506+
} else {
507+
hlen = tls_key_x_server_params_hash(
508+
conn->rl.tls_version, conn->client_random,
509+
conn->server_random, server_params,
510+
server_params_end - server_params, hash);
511+
}
512+
513+
if (hlen < 0)
514+
goto fail;
515+
wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerKeyExchange hash",
516+
hash, hlen);
517+
518+
if (tls_verify_signature(conn->rl.tls_version,
519+
conn->server_rsa_key,
520+
hash, hlen, pos, end - pos,
521+
&alert) < 0)
522+
goto fail;
523+
}
467524

468525
return 0;
469526

@@ -542,8 +599,10 @@ static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
542599

543600
wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len);
544601
suite = tls_get_cipher_suite(conn->rl.cipher_suite);
545-
if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) {
546-
if (tlsv1_process_diffie_hellman(conn, pos, len) < 0) {
602+
if (suite && (suite->key_exchange == TLS_KEY_X_DH_anon ||
603+
suite->key_exchange == TLS_KEY_X_DHE_RSA)) {
604+
if (tlsv1_process_diffie_hellman(conn, pos, len,
605+
suite->key_exchange) < 0) {
547606
tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
548607
TLS_ALERT_DECODE_ERROR);
549608
return -1;

components/wpa_supplicant/src/tls/tlsv1_client_write.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len)
4848
u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr;
4949
struct os_time now;
5050
size_t len, i;
51+
u8 *ext_start;
5152

5253
wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello");
5354
*out_len = 0;
@@ -62,7 +63,7 @@ u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len)
6263
wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random",
6364
conn->client_random, TLS_RANDOM_LEN);
6465

65-
len = 100 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len;
66+
len = 150 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len;
6667
hello = os_malloc(len);
6768
if (hello == NULL)
6869
return NULL;
@@ -102,12 +103,42 @@ u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len)
102103
*pos++ = 1;
103104
*pos++ = TLS_COMPRESSION_NULL;
104105

106+
/* Extension */
107+
ext_start = pos;
108+
pos += 2;
109+
110+
#ifdef CONFIG_TLSV12
111+
if (conn->rl.tls_version >= TLS_VERSION_1_2) {
112+
/*
113+
* Add signature_algorithms extension since we support only
114+
* SHA256 (and not the default SHA1) with TLSv1.2.
115+
*/
116+
/* ExtensionsType extension_type = signature_algorithms(13) */
117+
WPA_PUT_BE16(pos, TLS_EXT_SIGNATURE_ALGORITHMS);
118+
pos += 2;
119+
/* opaque extension_data<0..2^16-1> length */
120+
WPA_PUT_BE16(pos, 4);
121+
pos += 2;
122+
/* supported_signature_algorithms<2..2^16-2> length */
123+
WPA_PUT_BE16(pos, 2);
124+
pos += 2;
125+
/* supported_signature_algorithms */
126+
*pos++ = TLS_HASH_ALG_SHA256;
127+
*pos++ = TLS_SIGN_ALG_RSA;
128+
}
129+
#endif /* CONFIG_TLSV12 */
130+
105131
if (conn->client_hello_ext) {
106132
os_memcpy(pos, conn->client_hello_ext,
107133
conn->client_hello_ext_len);
108134
pos += conn->client_hello_ext_len;
109135
}
110136

137+
if (pos == ext_start + 2)
138+
pos -= 2; /* no extensions */
139+
else
140+
WPA_PUT_BE16(ext_start, pos - ext_start - 2);
141+
111142
WPA_PUT_BE24(hs_length, pos - hs_length - 3);
112143
tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
113144

components/wpa_supplicant/src/tls/tlsv1_common.c

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "utils/includes.h"
1010

1111
#include "utils/common.h"
12+
#include "crypto/md5.h"
1213
#include "crypto/sha1.h"
1314
#include "crypto/sha256.h"
1415
#include "tls/tls.h"
@@ -333,3 +334,184 @@ int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label,
333334
return tls_prf_sha1_md5(secret, secret_len, label, seed, seed_len, out,
334335
outlen);
335336
}
337+
338+
339+
#ifdef CONFIG_TLSV12
340+
int tlsv12_key_x_server_params_hash(u16 tls_version, u8 hash_alg,
341+
const u8 *client_random,
342+
const u8 *server_random,
343+
const u8 *server_params,
344+
size_t server_params_len, u8 *hash)
345+
{
346+
size_t hlen;
347+
struct crypto_hash *ctx;
348+
enum crypto_hash_alg alg;
349+
350+
switch (hash_alg) {
351+
case TLS_HASH_ALG_SHA256:
352+
alg = CRYPTO_HASH_ALG_SHA256;
353+
hlen = SHA256_MAC_LEN;
354+
break;
355+
default:
356+
return -1;
357+
}
358+
ctx = crypto_hash_init(alg, NULL, 0);
359+
if (ctx == NULL)
360+
return -1;
361+
crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
362+
crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
363+
crypto_hash_update(ctx, server_params, server_params_len);
364+
if (crypto_hash_finish(ctx, hash, &hlen) < 0)
365+
return -1;
366+
367+
return hlen;
368+
}
369+
#endif /* CONFIG_TLSV12 */
370+
371+
372+
int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
373+
const u8 *server_random,
374+
const u8 *server_params,
375+
size_t server_params_len, u8 *hash)
376+
{
377+
u8 *hpos;
378+
size_t hlen;
379+
struct crypto_hash *ctx;
380+
381+
hpos = hash;
382+
383+
ctx = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
384+
if (ctx == NULL)
385+
return -1;
386+
crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
387+
crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
388+
crypto_hash_update(ctx, server_params, server_params_len);
389+
hlen = MD5_MAC_LEN;
390+
if (crypto_hash_finish(ctx, hash, &hlen) < 0)
391+
return -1;
392+
hpos += hlen;
393+
394+
ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
395+
if (ctx == NULL)
396+
return -1;
397+
crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
398+
crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
399+
crypto_hash_update(ctx, server_params, server_params_len);
400+
hlen = hash + sizeof(hash) - hpos;
401+
if (crypto_hash_finish(ctx, hpos, &hlen) < 0)
402+
return -1;
403+
hpos += hlen;
404+
return hpos - hash;
405+
}
406+
407+
408+
int tls_verify_signature(u16 tls_version, struct crypto_public_key *pk,
409+
const u8 *data, size_t data_len,
410+
const u8 *pos, size_t len, u8 *alert)
411+
{
412+
u8 *buf;
413+
const u8 *end = pos + len;
414+
const u8 *decrypted;
415+
u16 slen;
416+
size_t buflen;
417+
418+
if (end - pos < 2) {
419+
*alert = TLS_ALERT_DECODE_ERROR;
420+
return -1;
421+
}
422+
slen = WPA_GET_BE16(pos);
423+
pos += 2;
424+
if (end - pos < slen) {
425+
*alert = TLS_ALERT_DECODE_ERROR;
426+
return -1;
427+
}
428+
if (end - pos > slen) {
429+
wpa_hexdump(MSG_MSGDUMP, "Additional data after Signature",
430+
pos + slen, end - pos - slen);
431+
end = pos + slen;
432+
}
433+
434+
wpa_hexdump(MSG_MSGDUMP, "TLSv1: Signature", pos, end - pos);
435+
if (pk == NULL) {
436+
wpa_printf(MSG_DEBUG, "TLSv1: No public key to verify signature");
437+
*alert = TLS_ALERT_INTERNAL_ERROR;
438+
return -1;
439+
}
440+
441+
buflen = end - pos;
442+
buf = os_malloc(end - pos);
443+
if (buf == NULL) {
444+
*alert = TLS_ALERT_INTERNAL_ERROR;
445+
return -1;
446+
}
447+
if (crypto_public_key_decrypt_pkcs1(pk, pos, end - pos, buf, &buflen) <
448+
0) {
449+
wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt signature");
450+
os_free(buf);
451+
*alert = TLS_ALERT_DECRYPT_ERROR;
452+
return -1;
453+
}
454+
decrypted = buf;
455+
456+
wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature",
457+
decrypted, buflen);
458+
459+
#ifdef CONFIG_TLSV12
460+
if (tls_version >= TLS_VERSION_1_2) {
461+
/*
462+
* RFC 3447, A.2.4 RSASSA-PKCS1-v1_5
463+
*
464+
* DigestInfo ::= SEQUENCE {
465+
* digestAlgorithm DigestAlgorithm,
466+
* digest OCTET STRING
467+
* }
468+
*
469+
* SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11}
470+
*
471+
* DER encoded DigestInfo for SHA256 per RFC 3447:
472+
* 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 ||
473+
* H
474+
*/
475+
if (buflen >= 19 + 32 &&
476+
os_memcmp(buf, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01"
477+
"\x65\x03\x04\x02\x01\x05\x00\x04\x20", 19) == 0)
478+
{
479+
wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithm = SHA-256");
480+
decrypted = buf + 19;
481+
buflen -= 19;
482+
} else if (buflen >= 19 + 48 &&
483+
os_memcmp(buf, "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01"
484+
"\x65\x03\x04\x02\x02\x05\x00\x04\x30", 19) == 0)
485+
{
486+
wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithm = SHA-384");
487+
decrypted = buf + 19;
488+
buflen -= 19;
489+
} else if (buflen >= 19 + 64 &&
490+
os_memcmp(buf, "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01"
491+
"\x65\x03\x04\x02\x03\x05\x00\x04\x40", 19) == 0)
492+
{
493+
wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithm = SHA-512");
494+
decrypted = buf + 19;
495+
buflen -= 19;
496+
497+
} else {
498+
wpa_printf(MSG_DEBUG, "TLSv1.2: Unrecognized DigestInfo");
499+
os_free(buf);
500+
*alert = TLS_ALERT_DECRYPT_ERROR;
501+
return -1;
502+
}
503+
}
504+
#endif /* CONFIG_TLSV12 */
505+
506+
if (buflen != data_len ||
507+
os_memcmp_const(decrypted, data, data_len) != 0) {
508+
wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in CertificateVerify - did not match calculated hash");
509+
os_free(buf);
510+
*alert = TLS_ALERT_DECRYPT_ERROR;
511+
return -1;
512+
}
513+
514+
os_free(buf);
515+
516+
return 0;
517+
}

components/wpa_supplicant/src/tls/tlsv1_common.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ enum {
169169
#define TLS_EXT_TRUSTED_CA_KEYS 3 /* RFC 4366 */
170170
#define TLS_EXT_TRUNCATED_HMAC 4 /* RFC 4366 */
171171
#define TLS_EXT_STATUS_REQUEST 5 /* RFC 4366 */
172+
#define TLS_EXT_SIGNATURE_ALGORITHMS 13 /* RFC 5246 */
172173
#define TLS_EXT_SESSION_TICKET 35 /* RFC 4507 */
173174

174175
#define TLS_EXT_PAC_OPAQUE TLS_EXT_SESSION_TICKET /* EAP-FAST terminology */
@@ -257,5 +258,17 @@ int tls_version_ok(u16 ver);
257258
const char * tls_version_str(u16 ver);
258259
int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label,
259260
const u8 *seed, size_t seed_len, u8 *out, size_t outlen);
261+
int tlsv12_key_x_server_params_hash(u16 tls_version, u8 hash_Alg,
262+
const u8 *client_random,
263+
const u8 *server_random,
264+
const u8 *server_params,
265+
size_t server_params_len, u8 *hash);
266+
int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
267+
const u8 *server_random,
268+
const u8 *server_params,
269+
size_t server_params_len, u8 *hash);
270+
int tls_verify_signature(u16 tls_version, struct crypto_public_key *pk,
271+
const u8 *data, size_t data_len,
272+
const u8 *pos, size_t len, u8 *alert);
260273

261274
#endif /* TLSV1_COMMON_H */

0 commit comments

Comments
 (0)