diff options
Diffstat (limited to 'src/crypto/tls_gnutls.c')
-rw-r--r-- | src/crypto/tls_gnutls.c | 61 |
1 files changed, 58 insertions, 3 deletions
diff --git a/src/crypto/tls_gnutls.c b/src/crypto/tls_gnutls.c index db66ae15e584..2c5c5a2b6406 100644 --- a/src/crypto/tls_gnutls.c +++ b/src/crypto/tls_gnutls.c @@ -35,8 +35,12 @@ int gnutls_ia_verify_endphase(gnutls_session_t session, char *checksum); #include "tls.h" +#ifndef TLS_RANDOM_SIZE #define TLS_RANDOM_SIZE 32 +#endif +#ifndef TLS_MASTER_SIZE #define TLS_MASTER_SIZE 48 +#endif #if LIBGNUTLS_VERSION_NUMBER < 0x010302 @@ -591,6 +595,17 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, return -1; } } + + if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { + gnutls_certificate_set_verify_flags( + conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); + } + + if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { + gnutls_certificate_set_verify_flags( + conn->xcred, + GNUTLS_VERIFY_DISABLE_TIME_CHECKS); + } } if (params->client_cert && params->private_key) { @@ -711,6 +726,18 @@ int tls_global_set_params(void *tls_ctx, goto fail; } } + + if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { + gnutls_certificate_set_verify_flags( + global->xcred, + GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); + } + + if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { + gnutls_certificate_set_verify_flags( + global->xcred, + GNUTLS_VERIFY_DISABLE_TIME_CHECKS); + } } if (params->client_cert && params->private_key) { @@ -843,7 +870,8 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, } -static int tls_connection_verify_peer(struct tls_connection *conn) +static int tls_connection_verify_peer(struct tls_connection *conn, + gnutls_alert_description_t *err) { unsigned int status, num_certs, i; struct os_time now; @@ -853,22 +881,39 @@ static int tls_connection_verify_peer(struct tls_connection *conn) if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) { wpa_printf(MSG_INFO, "TLS: Failed to verify peer " "certificate chain"); + *err = GNUTLS_A_INTERNAL_ERROR; return -1; } if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) { wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted"); + if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { + wpa_printf(MSG_INFO, "TLS: Certificate uses insecure " + "algorithm"); + *err = GNUTLS_A_INSUFFICIENT_SECURITY; + } + if (status & GNUTLS_CERT_NOT_ACTIVATED) { + wpa_printf(MSG_INFO, "TLS: Certificate not yet " + "activated"); + *err = GNUTLS_A_CERTIFICATE_EXPIRED; + } + if (status & GNUTLS_CERT_EXPIRED) { + wpa_printf(MSG_INFO, "TLS: Certificate expired"); + *err = GNUTLS_A_CERTIFICATE_EXPIRED; + } return -1; } if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a " "known issuer"); + *err = GNUTLS_A_UNKNOWN_CA; return -1; } if (status & GNUTLS_CERT_REVOKED) { wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked"); + *err = GNUTLS_A_CERTIFICATE_REVOKED; return -1; } @@ -878,6 +923,7 @@ static int tls_connection_verify_peer(struct tls_connection *conn) if (certs == NULL) { wpa_printf(MSG_INFO, "TLS: No peer certificate chain " "received"); + *err = GNUTLS_A_UNKNOWN_CA; return -1; } @@ -887,6 +933,7 @@ static int tls_connection_verify_peer(struct tls_connection *conn) if (gnutls_x509_crt_init(&cert) < 0) { wpa_printf(MSG_INFO, "TLS: Certificate initialization " "failed"); + *err = GNUTLS_A_BAD_CERTIFICATE; return -1; } @@ -895,6 +942,7 @@ static int tls_connection_verify_peer(struct tls_connection *conn) wpa_printf(MSG_INFO, "TLS: Could not parse peer " "certificate %d/%d", i + 1, num_certs); gnutls_x509_crt_deinit(cert); + *err = GNUTLS_A_BAD_CERTIFICATE; return -1; } @@ -920,6 +968,7 @@ static int tls_connection_verify_peer(struct tls_connection *conn) "not valid at this time", i + 1, num_certs); gnutls_x509_crt_deinit(cert); + *err = GNUTLS_A_CERTIFICATE_EXPIRED; return -1; } @@ -981,19 +1030,24 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, } } else { size_t size; + gnutls_alert_description_t err; - if (conn->verify_peer && tls_connection_verify_peer(conn)) { + if (conn->verify_peer && + tls_connection_verify_peer(conn, &err)) { wpa_printf(MSG_INFO, "TLS: Peer certificate chain " "failed validation"); conn->failed++; - return NULL; + gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err); + goto out; } +#ifdef CONFIG_GNUTLS_EXTRA if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) { wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation"); conn->failed++; return NULL; } +#endif /* CONFIG_GNUTLS_EXTRA */ if (conn->tls_ia) wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake"); @@ -1021,6 +1075,7 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, } } +out: out_data = conn->push_buf; *out_len = conn->push_buf_len; conn->push_buf = NULL; |