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>
This commit is contained in:
parent
3665776e4e
commit
fdc1614264
3 changed files with 56 additions and 4 deletions
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue