aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls
diff options
context:
space:
mode:
authorPali Rohár <pali.rohar@gmail.com>2015-11-22 01:02:56 (GMT)
committerJouni Malinen <j@w1.fi>2015-11-29 09:45:59 (GMT)
commitfdc16142642b702105bf769cbe95db3370690ff1 (patch)
tree3c924658874a3d4b12129ffa7b2eb19d86b7de2d /src/tls
parent3665776e4e0ea42989517ca4cb2699e8ee91b35f (diff)
downloadhostap-fdc16142642b702105bf769cbe95db3370690ff1.zip
hostap-fdc16142642b702105bf769cbe95db3370690ff1.tar.gz
hostap-fdc16142642b702105bf769cbe95db3370690ff1.tar.bz2
TLS client: Add support for validating server certificate hash
This commit adds support for "hash://server/sha256/cert_hash_in_hex" scheme in ca_cert property for the internal TLS implementation. Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Diffstat (limited to 'src/tls')
-rw-r--r--src/tls/tlsv1_client_read.c30
-rw-r--r--src/tls/tlsv1_cred.c28
-rw-r--r--src/tls/tlsv1_cred.h2
3 files changed, 56 insertions, 4 deletions
diff --git a/src/tls/tlsv1_client_read.c b/src/tls/tlsv1_client_read.c
index 4fe9580..48120b6 100644
--- a/src/tls/tlsv1_client_read.c
+++ b/src/tls/tlsv1_client_read.c
@@ -364,10 +364,32 @@ static int tls_process_certificate(struct tlsv1_client *conn, u8 ct,
pos += cert_len;
}
- if (conn->cred && conn->cred->ca_cert_verify &&
- x509_certificate_chain_validate(conn->cred->trusted_certs, chain,
- &reason, conn->disable_time_checks)
- < 0) {
+ if (conn->cred && conn->cred->server_cert_only && chain) {
+ u8 hash[SHA256_MAC_LEN];
+ char buf[128];
+
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Validate server certificate hash");
+ x509_name_string(&chain->subject, buf, sizeof(buf));
+ wpa_printf(MSG_DEBUG, "TLSv1: 0: %s", buf);
+ if (sha256_vector(1, &chain->cert_start, &chain->cert_len,
+ hash) < 0 ||
+ os_memcmp(conn->cred->srv_cert_hash, hash,
+ SHA256_MAC_LEN) != 0) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Server certificate hash mismatch");
+ wpa_hexdump(MSG_MSGDUMP, "TLSv1: SHA256 hash",
+ hash, SHA256_MAC_LEN);
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_BAD_CERTIFICATE);
+ x509_certificate_chain_free(chain);
+ return -1;
+ }
+ } else if (conn->cred && conn->cred->ca_cert_verify &&
+ x509_certificate_chain_validate(conn->cred->trusted_certs,
+ chain, &reason,
+ conn->disable_time_checks)
+ < 0) {
int tls_reason;
wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain "
"validation failed (reason=%d)", reason);
diff --git a/src/tls/tlsv1_cred.c b/src/tls/tlsv1_cred.c
index fbac965..3ed21ec 100644
--- a/src/tls/tlsv1_cred.c
+++ b/src/tls/tlsv1_cred.c
@@ -190,6 +190,34 @@ int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert,
const u8 *cert_blob, size_t cert_blob_len,
const char *path)
{
+ if (cert && os_strncmp(cert, "hash://", 7) == 0) {
+ const char *pos = cert + 7;
+ if (os_strncmp(pos, "server/sha256/", 14) != 0) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Unsupported ca_cert hash value '%s'",
+ cert);
+ return -1;
+ }
+ pos += 14;
+ if (os_strlen(pos) != 32 * 2) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Unexpected SHA256 hash length in ca_cert '%s'",
+ cert);
+ return -1;
+ }
+ if (hexstr2bin(pos, cred->srv_cert_hash, 32) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Invalid SHA256 hash value in ca_cert '%s'",
+ cert);
+ return -1;
+ }
+ cred->server_cert_only = 1;
+ cred->ca_cert_verify = 0;
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Checking only server certificate match");
+ return 0;
+ }
+
cred->ca_cert_verify = cert || cert_blob || path;
if (tlsv1_set_cert_chain(&cred->trusted_certs, cert,
diff --git a/src/tls/tlsv1_cred.h b/src/tls/tlsv1_cred.h
index b1e3e00..ac72b8c 100644
--- a/src/tls/tlsv1_cred.h
+++ b/src/tls/tlsv1_cred.h
@@ -15,6 +15,8 @@ struct tlsv1_credentials {
struct crypto_private_key *key;
unsigned int ca_cert_verify:1;
+ unsigned int server_cert_only:1;
+ u8 srv_cert_hash[32];
/* Diffie-Hellman parameters */
u8 *dh_p; /* prime */