Skip to content

Commit 50b4cf9

Browse files
kapilkedawatespressif-bot
authored andcommitted
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 espressif/esp-idf#5273 closes espressif/esp-idf#5627
1 parent 59347d6 commit 50b4cf9

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)