From: Jouni Malinen Date: Sun, 29 Nov 2015 16:16:07 +0000 (+0200) Subject: TLS: Add TLS v1.2 signature algorithm support for SHA384 and SHA512 X-Git-Tag: hostap_2_6~1288 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b115eebe01ca23848d3af786a6b22803a1b2fafc;p=thirdparty%2Fhostap.git TLS: Add TLS v1.2 signature algorithm support for SHA384 and SHA512 This extends the internal TLS client implementation to support signature algorithms SHA384 and SHA512 in addition to the previously supported SHA256. Signed-off-by: Jouni Malinen --- diff --git a/src/tls/tlsv1_client_read.c b/src/tls/tlsv1_client_read.c index 48120b683..294ae0081 100644 --- a/src/tls/tlsv1_client_read.c +++ b/src/tls/tlsv1_client_read.c @@ -529,7 +529,7 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn, server_params_end = pos; if (key_exchange == TLS_KEY_X_DHE_RSA) { - u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; + u8 hash[64]; int hlen; if (conn->rl.tls_version == TLS_VERSION_1_2) { @@ -546,18 +546,21 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn, */ if (end - pos < 2) goto fail; - if (pos[0] != TLS_HASH_ALG_SHA256 || + if ((pos[0] != TLS_HASH_ALG_SHA256 && + pos[0] != TLS_HASH_ALG_SHA384 && + pos[0] != TLS_HASH_ALG_SHA512) || pos[1] != TLS_SIGN_ALG_RSA) { wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/signature(%u) algorithm", pos[0], pos[1]); goto fail; } - pos += 2; hlen = tlsv12_key_x_server_params_hash( - conn->rl.tls_version, conn->client_random, + 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 */ diff --git a/src/tls/tlsv1_client_write.c b/src/tls/tlsv1_client_write.c index e02437172..6f1e0522b 100644 --- a/src/tls/tlsv1_client_write.c +++ b/src/tls/tlsv1_client_write.c @@ -116,12 +116,16 @@ u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len) WPA_PUT_BE16(pos, TLS_EXT_SIGNATURE_ALGORITHMS); pos += 2; /* opaque extension_data<0..2^16-1> length */ - WPA_PUT_BE16(pos, 4); + WPA_PUT_BE16(pos, 8); pos += 2; /* supported_signature_algorithms<2..2^16-2> length */ - WPA_PUT_BE16(pos, 2); + WPA_PUT_BE16(pos, 6); pos += 2; /* supported_signature_algorithms */ + *pos++ = TLS_HASH_ALG_SHA512; + *pos++ = TLS_SIGN_ALG_RSA; + *pos++ = TLS_HASH_ALG_SHA384; + *pos++ = TLS_SIGN_ALG_RSA; *pos++ = TLS_HASH_ALG_SHA256; *pos++ = TLS_SIGN_ALG_RSA; } diff --git a/src/tls/tlsv1_common.c b/src/tls/tlsv1_common.c index dabc12a12..6b28417e4 100644 --- a/src/tls/tlsv1_common.c +++ b/src/tls/tlsv1_common.c @@ -335,7 +335,7 @@ int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label, #ifdef CONFIG_TLSV12 -int tlsv12_key_x_server_params_hash(u16 tls_version, +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, @@ -343,14 +343,30 @@ int tlsv12_key_x_server_params_hash(u16 tls_version, { size_t hlen; struct crypto_hash *ctx; - - ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, 0); + enum crypto_hash_alg alg; + + switch (hash_alg) { + case TLS_HASH_ALG_SHA256: + alg = CRYPTO_HASH_ALG_SHA256; + hlen = SHA256_MAC_LEN; + break; + case TLS_HASH_ALG_SHA384: + alg = CRYPTO_HASH_ALG_SHA384; + hlen = 48; + break; + case TLS_HASH_ALG_SHA512: + alg = CRYPTO_HASH_ALG_SHA512; + hlen = 64; + 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); - hlen = SHA256_MAC_LEN; if (crypto_hash_finish(ctx, hash, &hlen) < 0) return -1; @@ -469,6 +485,21 @@ int tls_verify_signature(u16 tls_version, struct crypto_public_key *pk, wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithn = 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: DigestAlgorithn = 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: DigestAlgorithn = SHA-512"); + decrypted = buf + 19; + buflen -= 19; + } else { wpa_printf(MSG_DEBUG, "TLSv1.2: Unrecognized DigestInfo"); os_free(buf); diff --git a/src/tls/tlsv1_common.h b/src/tls/tlsv1_common.h index e2a5d4ce2..7a252feec 100644 --- a/src/tls/tlsv1_common.h +++ b/src/tls/tlsv1_common.h @@ -258,7 +258,8 @@ 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, const u8 *client_random, +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); diff --git a/src/tls/tlsv1_server_write.c b/src/tls/tlsv1_server_write.c index 65cda3c24..e7c5e2254 100644 --- a/src/tls/tlsv1_server_write.c +++ b/src/tls/tlsv1_server_write.c @@ -448,7 +448,8 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn, if (conn->rl.tls_version >= TLS_VERSION_1_2) { #ifdef CONFIG_TLSV12 hlen = tlsv12_key_x_server_params_hash( - conn->rl.tls_version, conn->client_random, + conn->rl.tls_version, TLS_HASH_ALG_SHA256, + conn->client_random, conn->server_random, server_params, pos - server_params, hash + 19);