From 2be2aecf9ec3dc662b2df27494862121f9b0ee0b Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Fri, 2 Nov 2012 13:46:25 +0100 Subject: [PATCH] check pathlen constraints. --- NEWS | 8 ++++++-- lib/gnutls_cert.c | 25 +++++++++++++----------- lib/gnutls_int.h | 1 + lib/x509/verify.c | 45 +++++++++++++++++++++++++++++++------------- tests/suite/chain | 2 +- tests/suite/x509paths/README | 1 - 6 files changed, 54 insertions(+), 28 deletions(-) diff --git a/NEWS b/NEWS index ef4f7035e..79a07b385 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,10 @@ See the end for copying conditions. ** libgnutls: gnutls_certificate_verify_peers2() will set flags depending on the available revocation data validity. +** libgnutls: Added gnutls_certificate_verification_status_print(), +a function to print the verification status code in human +readable text. + ** libgnutls: Added priority string %VERIFY_DISABLE_CRL_CHECKS. ** libgnutls: Simplified certificate verification by adding @@ -16,8 +20,8 @@ gnutls_certificate_verify_peers3(). for SRTP. ** libgnutls: The X.509 verification functions check the key -usage bits and output @GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE -if check fails. +usage bits and pathlen constraints and on failure output +GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE. ** libgnutls: gnutls_x509_crl_verify() includes the time checks. diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index 8c2d27d42..f784cc5f8 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -934,14 +934,14 @@ gnutls_certificate_verification_status_print (unsigned int status, _gnutls_buffer_init (&str); if (status == 0) - _gnutls_buffer_append_str (&str, _("Peer's certificate is trusted. ")); + _gnutls_buffer_append_str (&str, _("The certificate is trusted. ")); else - _gnutls_buffer_append_str (&str, _("Peer's certificate is NOT trusted. ")); + _gnutls_buffer_append_str (&str, _("The certificate is NOT trusted. ")); if (type == GNUTLS_CRT_X509) { if (status & GNUTLS_CERT_REVOKED) - _gnutls_buffer_append_str (&str, _("Peer's certificate chain revoked. ")); + _gnutls_buffer_append_str (&str, _("The certificate chain revoked. ")); if (status & GNUTLS_CERT_REVOCATION_DATA_TOO_OLD) _gnutls_buffer_append_str (&str, _("The revocation data are too old. ")); @@ -953,30 +953,33 @@ gnutls_certificate_verification_status_print (unsigned int status, _gnutls_buffer_append_str (&str, _("The revocation data are issued with a future date. ")); if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) - _gnutls_buffer_append_str (&str, _("Peer's certificate issuer is unknown. ")); + _gnutls_buffer_append_str (&str, _("The certificate issuer is unknown. ")); if (status & GNUTLS_CERT_SIGNER_NOT_CA) - _gnutls_buffer_append_str (&str, _("Peer's certificate issuer is not a CA. ")); + _gnutls_buffer_append_str (&str, _("The certificate issuer is not a CA. ")); } else if (type == GNUTLS_CRT_OPENPGP) { - _gnutls_buffer_append_str (&str, _("Peer's certificate is not trusted. ")); + _gnutls_buffer_append_str (&str, _("The certificate is not trusted. ")); if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) - _gnutls_buffer_append_str (&str, _("Could not find a signer of the peer's certificate. ")); + _gnutls_buffer_append_str (&str, _("Could not find a signer of the certificate. ")); if (status & GNUTLS_CERT_REVOKED) - _gnutls_buffer_append_str (&str, _("Peer's certificate is revoked. ")); + _gnutls_buffer_append_str (&str, _("The certificate is revoked. ")); } if (status & GNUTLS_CERT_INSECURE_ALGORITHM) - _gnutls_buffer_append_str (&str, _("Peer's certificate chain uses insecure algorithm. ")); + _gnutls_buffer_append_str (&str, _("The certificate chain uses insecure algorithm. ")); + + if (status & GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE) + _gnutls_buffer_append_str (&str, _("The certificate chain violates the signer's constraints. ")); if (status & GNUTLS_CERT_NOT_ACTIVATED) - _gnutls_buffer_append_str (&str, _("Peer's certificate chain uses not yet valid certificate. ")); + _gnutls_buffer_append_str (&str, _("The certificate chain uses not yet valid certificate. ")); if (status & GNUTLS_CERT_EXPIRED) - _gnutls_buffer_append_str (&str, _("Peer's certificate chain uses expired certificate. ")); + _gnutls_buffer_append_str (&str, _("The certificate chain uses expired certificate. ")); if (status & GNUTLS_CERT_SIGNATURE_FAILURE) _gnutls_buffer_append_str (&str, _("The signature in the certificate is invalid. ")); diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 68a176ee3..108113581 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -202,6 +202,7 @@ typedef enum transport_t */ #define DEFAULT_MAX_VERIFY_DEPTH 16 #define DEFAULT_MAX_VERIFY_BITS 16*1024 +#define MAX_VERIFY_DEPTH 4096 #include diff --git a/lib/x509/verify.c b/lib/x509/verify.c index 0a61869cd..7cbbb6329 100644 --- a/lib/x509/verify.c +++ b/lib/x509/verify.c @@ -113,13 +113,15 @@ cleanup: */ static int check_if_ca (gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer, + unsigned int *max_path, unsigned int flags) { gnutls_datum_t cert_signed_data = { NULL, 0 }; gnutls_datum_t issuer_signed_data = { NULL, 0 }; gnutls_datum_t cert_signature = { NULL, 0 }; gnutls_datum_t issuer_signature = { NULL, 0 }; - int result; + int pathlen, result; + unsigned int ca_status; /* Check if the issuer is the same with the * certificate. This is added in order for trusted @@ -176,9 +178,21 @@ check_if_ca (gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer, goto cleanup; } } + + result = gnutls_x509_crt_get_basic_constraints( issuer, NULL, &ca_status, &pathlen); + if (result < 0) + { + ca_status = 0; + pathlen = -1; + } + + if (ca_status != 0 && pathlen != -1) + { + if ((unsigned)pathlen < *max_path) + *max_path = pathlen; + } - result = gnutls_x509_crt_get_ca_status (issuer, NULL); - if (result == 1) + if (ca_status != 0) { result = 1; goto cleanup; @@ -392,6 +406,7 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert, unsigned int *output, gnutls_x509_crt_t * _issuer, time_t now, + unsigned int *max_path, gnutls_verify_output_function func) { gnutls_datum_t cert_signed_data = { NULL, 0 }; @@ -402,18 +417,20 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert, if (output) *output = 0; - - if (tcas_size >= 1) - issuer = find_issuer (cert, trusted_cas, tcas_size); - else + + if (*max_path == 0) { - gnutls_assert (); - out = GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; + out = GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE | GNUTLS_CERT_INVALID; if (output) *output |= out; + gnutls_assert (); result = 0; goto cleanup; } + (*max_path)--; + + if (tcas_size >= 1) + issuer = find_issuer (cert, trusted_cas, tcas_size); /* issuer is not in trusted certificate * authorities. @@ -437,12 +454,12 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert, gnutls_assert (); return issuer_version; } - + if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN) && ((flags & GNUTLS_VERIFY_DO_NOT_ALLOW_X509_V1_CA_CRT) || issuer_version != 1)) { - if (check_if_ca (cert, issuer, flags) == 0) + if (check_if_ca (cert, issuer, max_path, flags) == 0) { gnutls_assert (); out = GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID; @@ -603,6 +620,7 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * certificate_list, unsigned int status = 0, output; time_t now = gnutls_time (0); gnutls_x509_crt_t issuer = NULL; + unsigned int max_path; if (clist_size > 1) { @@ -676,9 +694,10 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * certificate_list, * in self signed etc certificates. */ output = 0; + max_path = MAX_VERIFY_DEPTH; ret = _gnutls_verify_certificate2 (certificate_list[clist_size - 1], trusted_cas, tcas_size, flags, &output, - &issuer, now, func); + &issuer, now, &max_path, func); if (ret == 0) { /* if the last certificate in the certificate @@ -707,7 +726,7 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * certificate_list, if ((ret = _gnutls_verify_certificate2 (certificate_list[i - 1], &certificate_list[i], 1, flags, - &output, NULL, now, func)) == 0) + &output, NULL, now, &max_path, func)) == 0) { status |= output; status |= GNUTLS_CERT_INVALID; diff --git a/tests/suite/chain b/tests/suite/chain index 35bc541c9..f1967c981 100755 --- a/tests/suite/chain +++ b/tests/suite/chain @@ -24,7 +24,7 @@ CERTTOOL=../../../src/certtool SUCCESS=" 1 4 7 12 15 16 17 18 24 26 27 30 33 56 57 62 63 " FAILURE=" 2 3 5 6 8 9 10 11 13 14 19 20 21 22 23 25 28 29 31 32 54 55 58 59 60 61 " -KNOWN_BUGS=" 15 16 17 18 19 31 32 54 55 58 59 60 61 " +KNOWN_BUGS=" 15 16 17 18 19 31 32 " cd x509paths diff --git a/tests/suite/x509paths/README b/tests/suite/x509paths/README index 0d5d892b1..d56032dce 100644 --- a/tests/suite/x509paths/README +++ b/tests/suite/x509paths/README @@ -27,4 +27,3 @@ that can verify CRLs on addition. (there is an issue there since the CRLs that are being added are typically of an intermediate CA which is not in the trust list to verify them) -Chain 54-55,58-61: We don't check path length constraints properly. XXX -- 2.11.4.GIT