diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-02-08 20:25:03 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-02-08 20:25:03 +0000 |
commit | 3f08429200ccfcab06ef151d5ebd5c57431cf284 (patch) | |
tree | 30f2677f698a1fe972db39fb834b6bdc40d3b7d8 | |
parent | 00aef08f3f6446d82dcf0a884ab56e2146b36e82 (diff) | |
download | gnutls-3f08429200ccfcab06ef151d5ebd5c57431cf284.tar.gz |
Certificate revocation support is almost complete.
-rw-r--r-- | includes/gnutls/x509.h | 14 | ||||
-rw-r--r-- | lib/x509/Makefile.am | 2 | ||||
-rw-r--r-- | lib/x509/common.c | 4 | ||||
-rw-r--r-- | lib/x509/crl.c | 182 | ||||
-rw-r--r-- | lib/x509/crl.h | 19 | ||||
-rw-r--r-- | lib/x509/dn.c | 23 | ||||
-rw-r--r-- | lib/x509/dn.h | 5 | ||||
-rw-r--r-- | lib/x509/pkcs7.c | 13 | ||||
-rw-r--r-- | lib/x509/verify.c | 63 | ||||
-rw-r--r-- | lib/x509/x509.c | 105 | ||||
-rw-r--r-- | lib/x509/x509.h | 23 | ||||
-rw-r--r-- | tests/test20.pem | 192 | ||||
-rw-r--r-- | tests/test21.pem | 163 | ||||
-rw-r--r-- | tests/x509_test.c | 77 |
14 files changed, 731 insertions, 154 deletions
diff --git a/includes/gnutls/x509.h b/includes/gnutls/x509.h index b9e94897c8..64bad19450 100644 --- a/includes/gnutls/x509.h +++ b/includes/gnutls/x509.h @@ -83,10 +83,10 @@ int gnutls_x509_certificate_get_key_usage( gnutls_x509_certificate cert, unsigne */ #define GNUTLS_KEY_DIGITAL_SIGNATURE 256 #define GNUTLS_KEY_NON_REPUDIATION 128 -#define GNUTLS_KEY_GNUTLS_KEY_ENCIPHERMENT 64 +#define GNUTLS_KEY_KEY_ENCIPHERMENT 64 #define GNUTLS_KEY_DATA_ENCIPHERMENT 32 -#define GNUTLS_KEY_GNUTLS_KEY_AGREEMENT 16 -#define GNUTLS_KEY_GNUTLS_KEY_CERT_SIGN 8 +#define GNUTLS_KEY_KEY_AGREEMENT 16 +#define GNUTLS_KEY_KEY_CERT_SIGN 8 #define GNUTLS_KEY_CRL_SIGN 4 #define GNUTLS_KEY_ENCIPHER_ONLY 2 #define GNUTLS_KEY_DECIPHER_ONLY 1 @@ -137,6 +137,8 @@ int gnutls_x509_crl_get_certificate_count(gnutls_x509_crl crl); int gnutls_x509_crl_get_certificate(gnutls_x509_crl crl, int index, unsigned char* serial, int* serial_size, time_t* time); +int gnutls_x509_crl_check_issuer( gnutls_x509_crl crl, + gnutls_x509_certificate issuer); /* PKCS7 structures handling */ @@ -166,7 +168,7 @@ typedef enum gnutls_certificate_verify_flags { */ } gnutls_certificate_verify_flags; -int gnutls_x509_certificate_is_issuer( gnutls_x509_certificate cert, +int gnutls_x509_certificate_check_issuer( gnutls_x509_certificate cert, gnutls_x509_certificate issuer); int gnutls_x509_certificate_list_verify( gnutls_x509_certificate* cert_list, int cert_list_length, @@ -181,6 +183,10 @@ int gnutls_x509_crl_verify( gnutls_x509_crl crl, gnutls_x509_certificate *CA_list, int CA_list_length, unsigned int flags, unsigned int *verify); +int gnutls_x509_certificate_check_revocation(gnutls_x509_certificate cert, + gnutls_x509_crl * crl_list, + int crl_list_length); + #ifdef __cplusplus } diff --git a/lib/x509/Makefile.am b/lib/x509/Makefile.am index 357dbf8a89..cedcc7fcb8 100644 --- a/lib/x509/Makefile.am +++ b/lib/x509/Makefile.am @@ -1,5 +1,5 @@ INCLUDES = -I../ -I../minitasn1/ -I../../includes/ -EXTRA_DIST = crl.h dn.h common.h x509.h extensions.h pkcs7.h \ +EXTRA_DIST = dn.h common.h x509.h extensions.h pkcs7.h \ x509-api.tex compat.h verify.h mpi.h noinst_LTLIBRARIES = libx509.la diff --git a/lib/x509/common.c b/lib/x509/common.c index bdc7c22d53..3b9fcb32a6 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -122,7 +122,7 @@ int result; char str[1024], tmpname[1024]; const char* ANAME = NULL; int CHOICE = -1, len = -1; -ASN1_TYPE tmpasn; +ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY; if (value==NULL || value_size <=0 || res_size == NULL) { gnutls_assert(); @@ -150,7 +150,7 @@ ASN1_TYPE tmpasn; _gnutls_str_cat( tmpname, sizeof(tmpname), ANAME); if ((result = - _gnutls_asn1_create_element(_gnutls_get_pkix(), str, + asn1_create_element(_gnutls_get_pkix(), str, &tmpasn, tmpname)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); diff --git a/lib/x509/crl.c b/lib/x509/crl.c index c13aa7caec..1b4aad67ff 100644 --- a/lib/x509/crl.c +++ b/lib/x509/crl.c @@ -26,7 +26,7 @@ #include <gnutls_errors.h> #include <common.h> #include <x509_b64.h> -#include <crl.h> +#include <x509.h> #include <dn.h> /** @@ -41,9 +41,12 @@ **/ int gnutls_x509_crl_init(gnutls_x509_crl * crl) { - *crl = gnutls_calloc( 1, sizeof(gnutls_x509_crl_int)); + *crl = gnutls_calloc(1, sizeof(gnutls_x509_crl_int)); - if (*crl) return 0; /* success */ + if (*crl) { + (*crl)->crl = ASN1_TYPE_EMPTY; + return 0; /* success */ + } return GNUTLS_E_MEMORY_ERROR; } @@ -80,7 +83,7 @@ void gnutls_x509_crl_deinit(gnutls_x509_crl crl) * **/ int gnutls_x509_crl_import(gnutls_x509_crl crl, const gnutls_datum * data, - gnutls_x509_certificate_format format) + gnutls_x509_certificate_format format) { int result = 0, need_free = 0; int start, end; @@ -90,19 +93,21 @@ int gnutls_x509_crl_import(gnutls_x509_crl crl, const gnutls_datum * data, */ if (format == GNUTLS_X509_FMT_PEM) { opaque *out; - - result = _gnutls_fbase64_decode(PEM_CRL, data->data, data->size, - &out); + + result = + _gnutls_fbase64_decode(PEM_CRL, data->data, data->size, + &out); if (result <= 0) { - if (result==0) result = GNUTLS_E_INTERNAL_ERROR; + if (result == 0) + result = GNUTLS_E_INTERNAL_ERROR; gnutls_assert(); return result; } - + _data.data = out; _data.size = result; - + need_free = 1; } @@ -116,7 +121,8 @@ int gnutls_x509_crl_import(gnutls_x509_crl crl, const gnutls_datum * data, return _gnutls_asn2err(result); } - result = asn1_der_decoding(&crl->crl, _data.data, _data.size, NULL); + result = + asn1_der_decoding(&crl->crl, _data.data, _data.size, NULL); if (result != ASN1_SUCCESS) { result = _gnutls_asn2err(result); gnutls_assert(); @@ -125,9 +131,9 @@ int gnutls_x509_crl_import(gnutls_x509_crl crl, const gnutls_datum * data, /* Get the signed data */ - result = asn1_der_decoding_startEnd(crl->crl, _data.data, _data.size, - "crl2.tbsCertList", &start, - &end); + result = + asn1_der_decoding_startEnd(crl->crl, _data.data, _data.size, + "crl2.tbsCertList", &start, &end); if (result != ASN1_SUCCESS) { result = _gnutls_asn2err(result); gnutls_assert(); @@ -142,62 +148,70 @@ int gnutls_x509_crl_import(gnutls_x509_crl crl, const gnutls_datum * data, gnutls_assert(); goto cleanup; } - + /* Read the signature */ { opaque signature[640]; int len; - + /* read the bit string of the signature */ len = sizeof(signature); - result = asn1_read_value( crl->crl, "crl2.signature", signature, - &len); - + result = + asn1_read_value(crl->crl, "crl2.signature", signature, + &len); + if (result != ASN1_SUCCESS) { result = _gnutls_asn2err(result); gnutls_assert(); goto cleanup; } - + if (len % 8 != 0) { gnutls_assert(); result = GNUTLS_E_UNIMPLEMENTED_FEATURE; goto cleanup; } - - if ((result=_gnutls_set_datum(&crl->signature, signature, len/8)) < 0) { + + if ((result = + _gnutls_set_datum(&crl->signature, signature, + len / 8)) < 0) { gnutls_assert(); goto cleanup; } - + /* Read the signature algorithm. Note that parameters are not * read. They will be read from the issuer's certificate if needed. */ - + len = sizeof(signature); - result = asn1_read_value( crl->crl, "crl2.signatureAlgorithm.algorithm", - signature, &len); - + result = + asn1_read_value(crl->crl, + "crl2.signatureAlgorithm.algorithm", + signature, &len); + if (result != ASN1_SUCCESS) { result = _gnutls_asn2err(result); gnutls_assert(); goto cleanup; } - - crl->signature_algorithm = _gnutls_x509_oid2pk_algorithm( signature); + + crl->signature_algorithm = + _gnutls_x509_oid2pk_algorithm(signature); } - if (need_free) _gnutls_free_datum( &_data); + if (need_free) + _gnutls_free_datum(&_data); return 0; cleanup: - if (crl->crl) + if (crl->crl) asn1_delete_structure(&crl->crl); _gnutls_free_datum(&crl->signed_data); _gnutls_free_datum(&crl->signature); - if (need_free) _gnutls_free_datum( &_data); + if (need_free) + _gnutls_free_datum(&_data); return result; } @@ -219,16 +233,17 @@ int gnutls_x509_crl_import(gnutls_x509_crl crl, const gnutls_datum * data, * **/ int gnutls_x509_crl_get_issuer_dn(gnutls_x509_crl crl, char *buf, - int *sizeof_buf) + int *sizeof_buf) { if (sizeof_buf == 0 || crl == NULL) { return GNUTLS_E_INVALID_REQUEST; } - - return _gnutls_x509_parse_dn( crl->crl, "crl2.tbsCertList.issuer.rdnSequence", - buf, sizeof_buf); - + return _gnutls_x509_parse_dn(crl->crl, + "crl2.tbsCertList.issuer.rdnSequence", + buf, sizeof_buf); + + } /** @@ -251,17 +266,19 @@ int gnutls_x509_crl_get_issuer_dn(gnutls_x509_crl crl, char *buf, * On success zero is returned. * **/ -int gnutls_x509_crl_get_issuer_dn_by_oid(gnutls_x509_crl crl, const char* oid, - int indx, char *buf, int *sizeof_buf) +int gnutls_x509_crl_get_issuer_dn_by_oid(gnutls_x509_crl crl, + const char *oid, int indx, + char *buf, int *sizeof_buf) { if (sizeof_buf == 0 || crl == NULL) { return GNUTLS_E_INVALID_REQUEST; } - - return _gnutls_x509_parse_dn_oid( crl->crl, "crl2.tbsCertList.issuer.rdnSequence", oid, - indx, buf, sizeof_buf); - + return _gnutls_x509_parse_dn_oid(crl->crl, + "crl2.tbsCertList.issuer.rdnSequence", + oid, indx, buf, sizeof_buf); + + } /** @@ -275,7 +292,8 @@ int gnutls_x509_crl_get_issuer_dn_by_oid(gnutls_x509_crl crl, const char* oid, * Returns 0 on success. * **/ -int gnutls_x509_crl_get_signed_data(gnutls_x509_crl crl, gnutls_const_datum *data) +int gnutls_x509_crl_get_signed_data(gnutls_x509_crl crl, + gnutls_const_datum * data) { data->data = crl->signed_data.data; data->size = crl->signed_data.size; @@ -294,7 +312,8 @@ int gnutls_x509_crl_get_signed_data(gnutls_x509_crl crl, gnutls_const_datum *dat * Returns 0 on success. * **/ -int gnutls_x509_crl_get_signature(gnutls_x509_crl crl, gnutls_const_datum *data) +int gnutls_x509_crl_get_signature(gnutls_x509_crl crl, + gnutls_const_datum * data) { data->data = crl->signature.data; data->size = crl->signature.size; @@ -332,10 +351,11 @@ int gnutls_x509_crl_get_version(gnutls_x509_crl crl) { opaque version[5]; int len, result; - + len = sizeof(version); - if ((result = asn1_read_value(crl->crl, "crl2.tbsCertList.version", version, &len)) != - ASN1_SUCCESS) { + if ((result = + asn1_read_value(crl->crl, "crl2.tbsCertList.version", version, + &len)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } @@ -354,7 +374,8 @@ int gnutls_x509_crl_get_version(gnutls_x509_crl crl) **/ time_t gnutls_x509_crl_get_this_update(gnutls_x509_crl crl) { - return _gnutls_x509_get_time( crl->crl, "crl2.tbsCertList.thisUpdate"); + return _gnutls_x509_get_time(crl->crl, + "crl2.tbsCertList.thisUpdate"); } /** @@ -370,7 +391,8 @@ time_t gnutls_x509_crl_get_this_update(gnutls_x509_crl crl) **/ time_t gnutls_x509_crl_get_next_update(gnutls_x509_crl crl) { - return _gnutls_x509_get_time( crl->crl, "crl2.tbsCertList.nextUpdate"); + return _gnutls_x509_get_time(crl->crl, + "crl2.tbsCertList.nextUpdate"); } /** @@ -387,12 +409,15 @@ int gnutls_x509_crl_get_certificate_count(gnutls_x509_crl crl) { int count, result; - - result = asn1_number_of_elements( crl->crl, "crl2.tbsCertList.revokedCertificates", &count); + + result = + asn1_number_of_elements(crl->crl, + "crl2.tbsCertList.revokedCertificates", + &count); if (result != ASN1_SUCCESS) { gnutls_assert(); - return 0; /* no certificates */ + return 0; /* no certificates */ } return count; @@ -412,37 +437,42 @@ int gnutls_x509_crl_get_certificate_count(gnutls_x509_crl crl) * Returns a negative value on failure. * **/ -int gnutls_x509_crl_get_certificate(gnutls_x509_crl crl, int index, unsigned char* serial, - int* serial_size, time_t* time) +int gnutls_x509_crl_get_certificate(gnutls_x509_crl crl, int index, + unsigned char *serial, + int *serial_size, time_t * time) { int result; char str_index[MAX_INT_DIGITS]; char serial_name[64]; char date_name[64]; - - _gnutls_int2str(index+1, str_index); - _gnutls_str_cpy( serial_name, sizeof(serial_name), "crl2.tbsCertList.revokedCertificates.?"); - _gnutls_str_cat( serial_name, sizeof(serial_name), str_index); - _gnutls_str_cat( serial_name, sizeof(serial_name), ".userCertificate"); - _gnutls_str_cpy( date_name, sizeof(date_name), "crl2.tbsCertList.revokedCertificates.?"); - _gnutls_str_cat( date_name, sizeof(date_name), str_index); - _gnutls_str_cat( date_name, sizeof(date_name), ".revocationDate"); + _gnutls_int2str(index + 1, str_index); + _gnutls_str_cpy(serial_name, sizeof(serial_name), + "crl2.tbsCertList.revokedCertificates.?"); + _gnutls_str_cat(serial_name, sizeof(serial_name), str_index); + _gnutls_str_cat(serial_name, sizeof(serial_name), + ".userCertificate"); + _gnutls_str_cpy(date_name, sizeof(date_name), + "crl2.tbsCertList.revokedCertificates.?"); + _gnutls_str_cat(date_name, sizeof(date_name), str_index); + _gnutls_str_cat(date_name, sizeof(date_name), ".revocationDate"); - if ((result = asn1_read_value(crl->crl, serial_name, serial, serial_size)) != ASN1_SUCCESS) - { + + if ((result = + asn1_read_value(crl->crl, serial_name, serial, + serial_size)) != ASN1_SUCCESS) { gnutls_assert(); if (result == ASN1_ELEMENT_NOT_FOUND) return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; return _gnutls_asn2err(result); } - + if (time) { - *time = _gnutls_x509_get_time( crl->crl, date_name); + *time = _gnutls_x509_get_time(crl->crl, date_name); } - + return 0; } @@ -457,8 +487,8 @@ int gnutls_x509_crl_get_certificate(gnutls_x509_crl crl, int index, unsigned cha * Returns a negative value on error, and zero on success. * -*/ -int _gnutls_x509_crl_get_raw_issuer_dn( gnutls_x509_crl crl, - gnutls_const_datum* dn) +int _gnutls_x509_crl_get_raw_issuer_dn(gnutls_x509_crl crl, + gnutls_const_datum * dn) { ASN1_TYPE c2 = ASN1_TYPE_EMPTY; int result, len1; @@ -468,12 +498,14 @@ int _gnutls_x509_crl_get_raw_issuer_dn( gnutls_x509_crl crl, */ if ((result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.TBSCertList", - &c2, "c2")) != ASN1_SUCCESS) { + &c2, "c2")) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } - result = asn1_der_decoding(&c2, crl->signed_data.data, crl->signed_data.size, NULL); + result = + asn1_der_decoding(&c2, crl->signed_data.data, + crl->signed_data.size, NULL); if (result != ASN1_SUCCESS) { /* couldn't decode DER */ gnutls_assert(); @@ -482,8 +514,9 @@ int _gnutls_x509_crl_get_raw_issuer_dn( gnutls_x509_crl crl, } result = - asn1_der_decoding_startEnd(c2, crl->signed_data.data, crl->signed_data.size, - "c2.issuer", &start1, &end1); + asn1_der_decoding_startEnd(c2, crl->signed_data.data, + crl->signed_data.size, "c2.issuer", + &start1, &end1); asn1_delete_structure(&c2); if (result != ASN1_SUCCESS) { @@ -499,3 +532,4 @@ int _gnutls_x509_crl_get_raw_issuer_dn( gnutls_x509_crl crl, return 0; } + diff --git a/lib/x509/crl.h b/lib/x509/crl.h deleted file mode 100644 index afb7c57d1d..0000000000 --- a/lib/x509/crl.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef CRL_H -# define CRL_H - -#include "x509.h" - -typedef struct gnutls_x509_crl_int { - ASN1_TYPE crl; - gnutls_datum signed_data; /* Holds the signed data of the CRL. - */ - gnutls_datum signature; - gnutls_pk_algorithm signature_algorithm; -} gnutls_x509_crl_int; - -typedef struct gnutls_x509_crl_int *gnutls_x509_crl; - -int _gnutls_x509_crl_get_raw_issuer_dn( gnutls_x509_crl crl, - gnutls_const_datum* dn); - -#endif diff --git a/lib/x509/dn.c b/lib/x509/dn.c index 67df0def11..72f213d21b 100644 --- a/lib/x509/dn.c +++ b/lib/x509/dn.c @@ -584,3 +584,26 @@ int gnutls_x509_rdn_get_by_oid(const gnutls_datum * idn, const char* oid, int in return result; } + +/* + * Compares the DER encoded part of a DN. + * + * FIXME: use a real DN comparison algorithm. + * + * Returns 1 if the DN's match and zero if they don't match. Otherwise + * a negative value is returned to indicate error. + */ +int _gnutls_x509_compare_raw_dn(const gnutls_const_datum * dn1, + const gnutls_const_datum * dn2) +{ + + if (dn1->size != dn2->size) { + gnutls_assert(); + return 0; + } + if (memcmp(dn1->data, dn2->data, dn2->size) != 0) { + gnutls_assert(); + return 0; + } + return 1; /* they match */ +} diff --git a/lib/x509/dn.h b/lib/x509/dn.h index 65483375ed..d6b0fff4d0 100644 --- a/lib/x509/dn.h +++ b/lib/x509/dn.h @@ -1,3 +1,6 @@ +#ifndef DN_H +# define DN_H + /* Some OIDs usually found in Distinguished names */ #define OID_X520_COUNTRY_NAME "2 5 4 6" @@ -17,3 +20,5 @@ int _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct, int _gnutls_x509_parse_dn_oid(ASN1_TYPE asn1_struct, const char* asn1_rdn_name, const char* oid, int indx, char *buf, int* sizeof_buf); + +#endif diff --git a/lib/x509/pkcs7.c b/lib/x509/pkcs7.c index df84ca84c2..36583c83ed 100644 --- a/lib/x509/pkcs7.c +++ b/lib/x509/pkcs7.c @@ -43,7 +43,10 @@ int gnutls_pkcs7_init(gnutls_pkcs7 * pkcs7) { *pkcs7 = gnutls_calloc( 1, sizeof(gnutls_pkcs7_int)); - if (*pkcs7) return 0; /* success */ + if (*pkcs7) { + (*pkcs7)->pkcs7 = ASN1_TYPE_EMPTY; + return 0; /* success */ + } return GNUTLS_E_MEMORY_ERROR; } @@ -150,7 +153,7 @@ int gnutls_pkcs7_import(gnutls_pkcs7 pkcs7, const gnutls_datum * data, int gnutls_pkcs7_get_certificate(gnutls_pkcs7 pkcs7, int indx, char* certificate, int* certificate_size) { - ASN1_TYPE c2 = NULL; + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; int result, len; char oid[128]; opaque *tmp = NULL; @@ -205,7 +208,7 @@ int gnutls_pkcs7_get_certificate(gnutls_pkcs7 pkcs7, /* Step 1. In case of a signed structure extract certificate set. */ - if ((result=_gnutls_asn1_create_element + if ((result=asn1_create_element (_gnutls_get_pkix(), "PKIX1.SignedData", &c2, "c2")) != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); @@ -292,7 +295,7 @@ int gnutls_pkcs7_get_certificate(gnutls_pkcs7 pkcs7, **/ int gnutls_pkcs7_get_certificate_count(gnutls_pkcs7 pkcs7) { - ASN1_TYPE c2; + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; int result, len, count; char oid[64]; opaque *tmp = NULL; @@ -344,7 +347,7 @@ int gnutls_pkcs7_get_certificate_count(gnutls_pkcs7 pkcs7) /* Step 1. In case of a signed structure count the certificate set. */ - if ((result=_gnutls_asn1_create_element + if ((result=asn1_create_element (_gnutls_get_pkix(), "PKIX1.SignedData", &c2, "c2")) != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); diff --git a/lib/x509/verify.c b/lib/x509/verify.c index 42547029df..2c105f2425 100644 --- a/lib/x509/verify.c +++ b/lib/x509/verify.c @@ -32,8 +32,8 @@ #include <gnutls_sig.h> #include <gnutls_str.h> #include <gnutls_datum.h> +#include <dn.h> #include <x509.h> -#include <crl.h> #include <mpi.h> #include <verify.h> @@ -83,8 +83,6 @@ static int check_if_ca(gnutls_x509_certificate cert, * This does a straight (DER) compare of the issuer/subject fields in * the given certificates. * - * FIXME: use a real DN comparison algorithm. - * * Returns 1 if the match and zero if they don't match. Otherwise * a negative value is returned to indicate error. */ @@ -106,17 +104,7 @@ int is_issuer(gnutls_x509_certificate cert, gnutls_x509_certificate issuer_cert) return ret; } - if (dn1.size != dn2.size) { - gnutls_assert(); - return 0; - } - if (memcmp(dn1.data, dn2.data, dn2.size) != 0) { - gnutls_assert(); - return 0; - } - - /* they match */ - return 1; + return _gnutls_x509_compare_raw_dn( &dn1, &dn2); } @@ -140,17 +128,7 @@ int is_crl_issuer(gnutls_x509_crl crl, gnutls_x509_certificate issuer_cert) return ret; } - if (dn1.size != dn2.size) { - gnutls_assert(); - return 0; - } - if (memcmp(dn1.data, dn2.data, dn2.size) != 0) { - gnutls_assert(); - return 0; - } - - /* they match */ - return 1; + return _gnutls_x509_compare_raw_dn( &dn1, &dn2); } @@ -224,7 +202,7 @@ static int _gnutls_verify_certificate2(gnutls_x509_certificate cert, return 0; } - if (flags & GNUTLS_VERIFY_DISABLE_CA_SIGN) { + if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN)) { if (check_if_ca(cert, issuer)==0) { gnutls_assert(); return 0; @@ -271,7 +249,7 @@ static int _gnutls_verify_crl2(gnutls_x509_crl crl, return 0; } - if (flags & GNUTLS_VERIFY_DISABLE_CA_SIGN) { + if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN)) { if (gnutls_x509_certificate_get_ca_status(issuer, NULL) != 1) { gnutls_assert(); @@ -313,7 +291,18 @@ unsigned int _gnutls_x509_verify_certificate(gnutls_x509_certificate * certifica int i = 0, ret; unsigned int status = 0; - /* Verify the certificate path */ + /* Check for revoked certificates in the chain + */ + for (i = 0; i < clist_size; i++) { + ret = gnutls_x509_certificate_check_revocation( certificate_list[i], + CRLs, crls_size); + if (ret == 1) { /* revoked */ + status |= GNUTLS_CERT_REVOKED; + } + } + + /* Verify the certificate path + */ for (i = 0; i < clist_size; i++) { if (i + 1 >= clist_size) break; @@ -326,10 +315,12 @@ unsigned int _gnutls_x509_verify_certificate(gnutls_x509_certificate * certifica } } - if (status != 0) { /* If there is any problem in the - * certificate chain then mark as not trusted - * and return immediately. - */ + if (status != 0) { + /* If there is any problem in the + * certificate chain then mark as not trusted + * and return immediately. + */ + gnutls_assert(); return (status | GNUTLS_CERT_NOT_TRUSTED); } @@ -624,7 +615,7 @@ int gnutls_x509_certificate_verify( gnutls_x509_certificate cert, } /** - * gnutls_x509_certificate_is_issuer - This function checks if the certificate given has the given issuer + * gnutls_x509_certificate_check_issuer - This function checks if the certificate given has the given issuer * @cert: is the certificate to be checked * @issuer: is the certificate of a possible issuer * @@ -635,14 +626,14 @@ int gnutls_x509_certificate_verify( gnutls_x509_certificate cert, * A negative value is returned in case of an error. * **/ -int gnutls_x509_certificate_is_issuer( gnutls_x509_certificate cert, +int gnutls_x509_certificate_check_issuer( gnutls_x509_certificate cert, gnutls_x509_certificate issuer) { return is_issuer(cert, issuer); } /** - * gnutls_x509_crl_is_issuer - This function checks if the CRL given has the given issuer + * gnutls_x509_crl_check_issuer - This function checks if the CRL given has the given issuer * @crl: is the CRL to be checked * @issuer: is the certificate of a possible issuer * @@ -653,7 +644,7 @@ int gnutls_x509_certificate_is_issuer( gnutls_x509_certificate cert, * A negative value is returned in case of an error. * **/ -int gnutls_x509_crl_is_issuer( gnutls_x509_crl cert, +int gnutls_x509_crl_check_issuer( gnutls_x509_crl cert, gnutls_x509_certificate issuer) { return is_crl_issuer(cert, issuer); diff --git a/lib/x509/x509.c b/lib/x509/x509.c index 30b26d821a..fc45dd872d 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -44,7 +44,10 @@ int gnutls_x509_certificate_init(gnutls_x509_certificate * cert) { *cert = gnutls_calloc( 1, sizeof(gnutls_x509_certificate_int)); - if (*cert) return 0; /* success */ + if (*cert) { + (*cert)->cert = ASN1_TYPE_EMPTY; + return 0; /* success */ + } return GNUTLS_E_MEMORY_ERROR; } @@ -726,8 +729,8 @@ int gnutls_x509_certificate_get_ca_status(gnutls_x509_certificate cert, int* cri * This function will return certificate's key usage, by reading the * keyUsage X.509 extension. The key usage value will ORed values of the: * GNUTLS_KEY_DIGITAL_SIGNATURE, GNUTLS_KEY_NON_REPUDIATION, - * GNUTLS_KEY_GNUTLS_KEY_ENCIPHERMENT, GNUTLS_KEY_DATA_ENCIPHERMENT, - * GNUTLS_KEY_GNUTLS_KEY_AGREEMENT, GNUTLS_KEY_GNUTLS_KEY_CERT_SIGN, + * GNUTLS_KEY_KEY_ENCIPHERMENT, GNUTLS_KEY_DATA_ENCIPHERMENT, + * GNUTLS_KEY_KEY_AGREEMENT, GNUTLS_KEY_KEY_CERT_SIGN, * GNUTLS_KEY_CRL_SIGN, GNUTLS_KEY_ENCIPHER_ONLY, * GNUTLS_KEY_DECIPHER_ONLY. * @@ -896,3 +899,99 @@ int _gnutls_x509_certificate_get_raw_dn( gnutls_x509_certificate cert, { return _gnutls_x509_certificate_get_raw_dn2( cert, "c2.subject", start); } + + +/** + * gnutls_x509_certificate_check_revocation - This function checks if the given certificate is revoked + * @cert: should contain a gnutls_x509_certificate structure + * @crl_list: should contain a list of gnutls_x509_crl structures + * @crl_list_length: the length of the crl_list + * + * This function will return check if the given certificate is revoked. + * It is assumed that the CRLs have been verified before. + * + * Returns 0 if the certificate is NOT revoked, and 1 if it is. + * A negative value is returned on error. + * + **/ +int gnutls_x509_certificate_check_revocation(gnutls_x509_certificate cert, + gnutls_x509_crl * crl_list, + int crl_list_length) +{ + opaque serial[64]; + opaque cert_serial[64]; + int serial_size, cert_serial_size; + int ncerts, ret, i, j; + gnutls_const_datum dn1, dn2; + + for (j = 0; j < crl_list_length; j++) { /* do for all the crls */ + + /* Step 1. check if issuer's DN match + */ + ret = _gnutls_x509_crl_get_raw_issuer_dn(crl_list[j], &dn1); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = + _gnutls_x509_certificate_get_raw_issuer_dn(cert, &dn2); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = _gnutls_x509_compare_raw_dn(&dn1, &dn2); + if (ret == 0) { + /* issuers do not match so don't even + * bother checking. + */ + continue; + } + + /* Step 2. Read the certificate's serial number + */ + cert_serial_size = sizeof(cert_serial); + ret = + gnutls_x509_certificate_get_serial(cert, cert_serial, + &cert_serial_size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + /* Step 3. cycle through the CRL serials and compare with + * certificate serial we have. + */ + + ncerts = gnutls_x509_crl_get_certificate_count(crl_list[j]); + if (ncerts < 0) { + gnutls_assert(); + return ncerts; + } + + for (i = 0; i < ncerts; i++) { + serial_size = sizeof(serial); + ret = + gnutls_x509_crl_get_certificate(crl_list[j], i, serial, + &serial_size, + NULL); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + if (serial_size == cert_serial_size) { + if (memcmp + (serial, cert_serial, + serial_size) == 0) { + /* serials match */ + return 1; /* revoked! */ + } + } + } + + } + return 0; /* not revoked. */ +} diff --git a/lib/x509/x509.h b/lib/x509/x509.h index f1a3aa16cb..31f06e4918 100644 --- a/lib/x509/x509.h +++ b/lib/x509/x509.h @@ -1,6 +1,14 @@ #ifndef X509_H # define X509_H +typedef struct gnutls_x509_crl_int { + ASN1_TYPE crl; + gnutls_datum signed_data; /* Holds the signed data of the CRL. + */ + gnutls_datum signature; + gnutls_pk_algorithm signature_algorithm; +} gnutls_x509_crl_int; + typedef struct gnutls_x509_certificate_int { ASN1_TYPE cert; gnutls_datum signed_data; /* Holds the signed data of the CRL. @@ -10,6 +18,7 @@ typedef struct gnutls_x509_certificate_int { } gnutls_x509_certificate_int; typedef struct gnutls_x509_certificate_int *gnutls_x509_certificate; +typedef struct gnutls_x509_crl_int *gnutls_x509_crl; int gnutls_x509_certificate_get_issuer_dn_by_oid(gnutls_x509_certificate cert, const char* oid, int indx, char *buf, int *sizeof_buf); @@ -25,5 +34,19 @@ int _gnutls_x509_certificate_get_raw_issuer_dn( gnutls_x509_certificate cert, int _gnutls_x509_certificate_get_raw_dn( gnutls_x509_certificate cert, gnutls_const_datum* start); +int gnutls_x509_certificate_get_serial(gnutls_x509_certificate cert, char* result, int* result_size); + +int _gnutls_x509_compare_raw_dn(const gnutls_const_datum * dn1, + const gnutls_const_datum * dn2); + +int gnutls_x509_certificate_check_revocation(gnutls_x509_certificate cert, gnutls_x509_crl * crl_list, int crl_list_length); + + +int _gnutls_x509_crl_get_raw_issuer_dn( gnutls_x509_crl crl, + gnutls_const_datum* dn); +int gnutls_x509_crl_get_certificate_count(gnutls_x509_crl crl); +int gnutls_x509_crl_get_certificate(gnutls_x509_crl crl, int index, + unsigned char *serial, + int *serial_size, time_t * time); #endif diff --git a/tests/test20.pem b/tests/test20.pem new file mode 100644 index 0000000000..957832d1e9 --- /dev/null +++ b/tests/test20.pem @@ -0,0 +1,192 @@ +[ The intermediate certificate has been revoked ] + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 40 (0x28) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=U.S. Government, OU=Dod, OU=Testing, CN=CA1-CP.06.01 + Validity + Not Before: Jan 1 12:01:00 1998 GMT + Not After : Jan 1 12:01:00 2048 GMT + Subject: C=US, O=U.S. Government, OU=DoD, OU=Testing, CN=User1-CP.06.01 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e8:7b:95:4c:0c:45:eb:7b:b7:f0:01:23:a9:a8: + db:b0:ac:9d:1c:d0:eb:85:f1:ed:fd:5d:ab:1a:c9: + 36:eb:92:46:c9:55:4a:16:96:9f:08:86:1e:37:3e: + e7:f4:d2:ed:4a:df:8f:d5:4e:d1:db:1e:04:2c:cf: + b3:26:05:a0:85:f5:ab:b4:39:ce:50:2b:c3:2d:b8: + aa:95:d3:18:c9:a5:a4:41:81:cb:38:bb:8e:45:ce: + f3:0e:7e:c2:a8:77:fb:c4:45:ad:04:33:af:bd:73: + 2e:d0:15:57:fa:8f:53:29:5e:b8:5f:0c:f2:3c:e4: + c1:f3:ef:6b:0b:a7:9b:07:4b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Certificate Policies: + Policy: 2.16.840.1.101.3.1.48.1 + + X509v3 Subject Key Identifier: + 6B:20:B4:3C:F5:3D:CF:2B + X509v3 Authority Key Identifier: + keyid:08:80:26:97:3E:BE:09:CD + + Signature Algorithm: sha1WithRSAEncryption + 3f:3e:db:52:f6:84:57:b3:32:8e:17:bc:2c:93:bf:b2:88:fc: + e1:7e:f5:ae:f5:4f:b4:13:eb:85:88:d6:4c:9e:a9:eb:d1:82: + 7c:94:72:86:8d:ef:01:42:2d:f1:11:5a:97:51:85:6f:bd:9c: + e3:90:d0:1a:47:15:cc:b2:c9:c3:c7:03:3f:76:a3:b5:66:9c: + e4:76:7d:74:d3:c9:91:6f:8a:87:5d:a5:f6:0a:a3:9f:4e:b5: + 5c:08:d0:e1:79:db:6f:04:03:60:2b:97:86:0b:8f:13:db:f7: + 93:30:db:8a:6c:15:c0:81:0e:07:fe:12:01:15:f7:ef:2e:d3: + 51:69 +-----BEGIN CERTIFICATE----- +MIIChjCCAe+gAwIBAgIBKDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsT +B1Rlc3RpbmcxFTATBgNVBAMTDENBMS1DUC4wNi4wMTAeFw05ODAxMDExMjAxMDBa +Fw00ODAxMDExMjAxMDBaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdv +dmVybm1lbnQxDDAKBgNVBAsTA0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UE +AxMOVXNlcjEtQ1AuMDYuMDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOh7 +lUwMRet7t/ABI6mo27CsnRzQ64Xx7f1dqxrJNuuSRslVShaWnwiGHjc+5/TS7Urf +j9VO0dseBCzPsyYFoIX1q7Q5zlArwy24qpXTGMmlpEGByzi7jkXO8w5+wqh3+8RF +rQQzr71zLtAVV/qPUyleuF8M8jzkwfPvawunmwdLAgMBAAGjUjBQMA4GA1UdDwEB +/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECgQIayC0PPU9 +zyswEwYDVR0jBAwwCoAICIAmlz6+Cc0wDQYJKoZIhvcNAQEFBQADgYEAPz7bUvaE +V7Myjhe8LJO/soj84X71rvVPtBPrhYjWTJ6p69GCfJRyho3vAUIt8RFal1GFb72c +45DQGkcVzLLJw8cDP3ajtWac5HZ9dNPJkW+Kh12l9gqjn061XAjQ4XnbbwQDYCuX +hguPE9v3kzDbimwVwIEOB/4SARX37y7TUWk= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 39 (0x27) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=U.S. Government, OU=DoD, OU=Testing, CN=Trust Anchor + Validity + Not Before: Jan 1 12:01:00 1998 GMT + Not After : Jan 1 12:01:00 2048 GMT + Subject: C=US, O=U.S. Government, OU=Dod, OU=Testing, CN=CA1-CP.06.01 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c8:e0:c5:d9:07:4f:01:7d:41:f1:a3:ff:f8:45: + ee:c0:c7:4a:96:90:78:32:ea:76:fe:fd:76:8b:43: + 61:70:3d:bb:e9:6f:99:a4:84:b8:6a:0d:90:52:5f: + 72:90:2f:46:22:27:ca:7c:d6:d9:9d:bd:14:07:fc: + b6:c5:cd:7f:f7:38:a0:53:51:f5:79:8a:66:32:f7: + bf:40:d8:d1:1b:e2:8b:45:a7:a1:03:4a:c9:19:86: + db:58:dd:dd:88:cd:42:02:a0:25:94:5e:13:9b:9e: + 69:07:27:68:c4:73:cd:5b:82:01:64:2b:92:e2:af: + 59:bf:b4:aa:b6:20:e3:c5:25 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Certificate Policies: + Policy: 2.16.840.1.101.3.1.48.1 + + X509v3 Subject Key Identifier: + 08:80:26:97:3E:BE:09:CD + X509v3 Authority Key Identifier: + keyid:AB:9A:EB:F9:C2:E7:54:8F + + Signature Algorithm: sha1WithRSAEncryption + d1:9b:c8:1b:67:27:93:7d:a9:ea:ec:6a:1b:0f:01:bb:8d:0d: + ad:f1:ee:f6:03:64:24:be:4c:84:31:c9:5c:0e:8e:c5:4e:41: + 5f:96:d6:66:92:e7:29:72:e8:1e:2a:92:76:d1:1d:9b:2e:5c: + 2d:9c:37:92:08:31:9d:dc:63:b2:74:45:33:20:9a:c1:a6:2e: + a4:90:61:96:0a:ae:15:bb:af:06:d0:3c:ac:cb:64:73:91:f8: + ce:e7:4f:65:c3:9c:bd:7b:bb:5f:0e:7c:2b:ed:5c:69:21:94: + 44:bf:80:ea:e5:c5:3e:73:14:05:dd:7e:93:e7:a3:6e:d3:bc: + 3e:da +-----BEGIN CERTIFICATE----- +MIIClTCCAf6gAwIBAgIBJzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsT +B1Rlc3RpbmcxFTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBa +Fw00ODAxMDExMjAxMDBaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdv +dmVybm1lbnQxDDAKBgNVBAsTA0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UE +AxMMQ0ExLUNQLjA2LjAxMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI4MXZ +B08BfUHxo//4Re7Ax0qWkHgy6nb+/XaLQ2FwPbvpb5mkhLhqDZBSX3KQL0YiJ8p8 +1tmdvRQH/LbFzX/3OKBTUfV5imYy979A2NEb4otFp6EDSskZhttY3d2IzUICoCWU +XhObnmkHJ2jEc81bggFkK5Lir1m/tKq2IOPFJQIDAQABo2MwYTAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATAR +BgNVHQ4ECgQICIAmlz6+Cc0wEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcN +AQEFBQADgYEA0ZvIG2cnk32p6uxqGw8Bu40NrfHu9gNkJL5MhDHJXA6OxU5BX5bW +ZpLnKXLoHiqSdtEdmy5cLZw3kggxndxjsnRFMyCawaYupJBhlgquFbuvBtA8rMtk +c5H4zudPZcOcvXu7Xw58K+1caSGURL+A6uXFPnMUBd1+k+ejbtO8Pto= +-----END CERTIFICATE----- +Certificate Revocation List (CRL): + Version 2 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: /C=US/O=U.S. Government/OU=Dod/OU=Testing/CN=CA1-CP.06.01 + Last Update: Jan 1 12:01:00 1999 GMT + Next Update: Jan 1 12:01:00 2048 GMT + CRL extensions: + X509v3 CRL Number: + 1 + X509v3 Authority Key Identifier: + keyid:08:80:26:97:3E:BE:09:CD + +No Revoked Certificates. + Signature Algorithm: sha1WithRSAEncryption + 6e:42:5e:8d:f7:35:af:3b:42:6e:d0:ba:c4:96:77:89:91:03: + 0c:c5:b6:0b:11:6f:3a:f4:b0:86:60:a3:3e:a5:58:de:5a:c2: + 3c:d4:90:cd:d8:e6:a9:ea:62:a0:29:ee:ee:89:e0:3f:e1:c0: + 03:b8:4c:ed:b9:be:4a:83:7b:2b:35:ca:b9:f4:3b:0b:63:8d: + a0:0c:2f:a0:f6:60:9e:88:9d:83:b4:55:10:2c:54:07:20:fa: + 00:9b:b4:e3:27:76:c0:22:d8:46:90:9f:4b:6b:43:b5:72:e1: + 1c:40:e9:7b:e1:0b:c2:fd:f9:a5:b9:02:32:50:8e:da:ee:c9: + f9:37 +-----BEGIN X509 CRL----- +MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UE +ChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rp +bmcxFTATBgNVBAMTDENBMS1DUC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAx +MTIwMTAwWqAjMCEwCgYDVR0UBAMCAQEwEwYDVR0jBAwwCoAICIAmlz6+Cc0wDQYJ +KoZIhvcNAQEFBQADgYEAbkJejfc1rztCbtC6xJZ3iZEDDMW2CxFvOvSwhmCjPqVY +3lrCPNSQzdjmqepioCnu7ongP+HAA7hM7bm+SoN7KzXKufQ7C2ONoAwvoPZgnoid +g7RVECxUByD6AJu04yd2wCLYRpCfS2tDtXLhHEDpe+ELwv35pbkCMlCO2u7J+Tc= +-----END X509 CRL----- + +Certificate Revocation List (CRL): + Version 2 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: /C=US/O=U.S. Government/OU=DoD/OU=Testing/CN=Trust Anchor + Last Update: Jan 1 12:01:00 1999 GMT + Next Update: Jan 1 12:01:00 2048 GMT + CRL extensions: + X509v3 CRL Number: + 1 + X509v3 Authority Key Identifier: + keyid:AB:9A:EB:F9:C2:E7:54:8F + +Revoked Certificates: + Serial Number: 27 + Revocation Date: Jan 1 12:00:00 1999 GMT + X509v3 CRL Reason Code: + Key Compromise + Signature Algorithm: sha1WithRSAEncryption + 0b:b9:6a:67:07:a3:25:15:bb:42:fc:c7:d7:5f:fb:71:87:0b: + de:b6:9c:80:cc:47:dc:f4:94:fe:e7:ef:c8:b9:3b:6a:14:7e: + f9:1b:47:6a:bc:bf:59:e0:af:45:dc:b3:9c:b8:88:38:0f:19: + 06:28:2e:5a:d5:4f:aa:c3:72:b0:d9:fb:58:ba:1f:40:85:5a: + fb:f4:c3:dd:3f:a5:79:c7:b8:7b:53:70:19:0b:e3:e5:0f:9e: + db:04:6d:19:78:3e:80:2b:93:8d:32:94:15:f2:91:9d:6c:fb: + 3b:b4:72:88:92:8a:8a:6d:23:b4:01:78:46:40:a9:2d:e6:cd: + 0a:16 +-----BEGIN X509 CRL----- +MIIBbzCB2QIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UE +ChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rp +bmcxFTATBgNVBAMTDFRydXN0IEFuY2hvchcNOTkwMTAxMTIwMTAwWhcNNDgwMTAx +MTIwMTAwWjAiMCACAScXDTk5MDEwMTEyMDAwMFowDDAKBgNVHRUEAwoBAaAjMCEw +CgYDVR0UBAMCAQEwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcNAQEFBQAD +gYEAC7lqZwejJRW7QvzH11/7cYcL3racgMxH3PSU/ufvyLk7ahR++RtHary/WeCv +RdyznLiIOA8ZBiguWtVPqsNysNn7WLofQIVa+/TD3T+lece4e1NwGQvj5Q+e2wRt +GXg+gCuTjTKUFfKRnWz7O7RyiJKKim0jtAF4RkCpLebNChY= +-----END X509 CRL----- diff --git a/tests/test21.pem b/tests/test21.pem new file mode 100644 index 0000000000..2a3b253043 --- /dev/null +++ b/tests/test21.pem @@ -0,0 +1,163 @@ +[ The end certificate has been revoked ] + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 42 (0x2a) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=U.S. Government, OU=Dod, OU=Testing, CN=CA1-CP.06.02 + Validity + Not Before: Jan 1 12:01:00 1998 GMT + Not After : Jan 1 12:01:00 2048 GMT + Subject: C=US, O=U.S. Government, OU=DoD, OU=Testing, CN=User1-CP.06.02 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ae:03:f4:7f:09:c5:e2:2b:16:e3:a6:c7:47:12: + 90:86:0d:4b:4a:7b:70:34:81:95:c7:39:ec:d6:b7: + fb:59:3b:94:90:fb:98:4f:59:3f:af:f8:ed:8b:03: + 54:ad:9b:c1:ee:1a:4c:a0:93:5e:d3:e4:fe:41:90: + e9:bb:0b:b3:02:57:6f:25:b8:93:8f:9f:e4:b7:80: + 62:85:e0:6e:66:57:8c:05:85:f8:12:88:97:cb:8a: + 7a:db:2a:0b:71:e4:09:ea:a1:05:a6:35:00:65:2a: + 79:fe:28:38:09:1a:90:43:fe:d6:36:05:ba:63:58: + b4:c6:81:fb:dc:7f:d2:77:01 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Certificate Policies: + Policy: 2.16.840.1.101.3.1.48.1 + + X509v3 Subject Key Identifier: + 0B:D3:22:24:D2:3B:D5:13 + X509v3 Authority Key Identifier: + keyid:68:7C:56:39:D1:EC:2D:B5 + + Signature Algorithm: sha1WithRSAEncryption + a3:f8:9b:98:8c:6d:7a:2b:72:8d:99:6c:ce:30:9c:fe:ce:f2: + 33:fd:2c:9c:be:fc:a5:8a:4c:39:9d:cf:d9:33:ca:91:88:76: + 4e:1e:3e:07:0f:09:a9:7d:74:f8:cf:f3:c0:50:63:e4:1c:3b: + 22:6c:c2:21:17:d2:dc:61:6e:2a:67:15:73:21:c1:e0:e6:4b: + 31:c4:19:b5:75:80:f0:63:99:f7:86:2f:5a:ae:53:04:83:65: + 56:d4:e1:42:db:ac:42:3d:79:28:1a:b6:4c:93:4d:15:4c:83: + a4:17:6f:ca:8d:39:02:71:2c:45:8d:07:6c:84:2e:e9:98:4d: + 43:8d +-----BEGIN CERTIFICATE----- +MIIChjCCAe+gAwIBAgIBKjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsT +B1Rlc3RpbmcxFTATBgNVBAMTDENBMS1DUC4wNi4wMjAeFw05ODAxMDExMjAxMDBa +Fw00ODAxMDExMjAxMDBaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdv +dmVybm1lbnQxDDAKBgNVBAsTA0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UE +AxMOVXNlcjEtQ1AuMDYuMDIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK4D +9H8JxeIrFuOmx0cSkIYNS0p7cDSBlcc57Na3+1k7lJD7mE9ZP6/47YsDVK2bwe4a +TKCTXtPk/kGQ6bsLswJXbyW4k4+f5LeAYoXgbmZXjAWF+BKIl8uKetsqC3HkCeqh +BaY1AGUqef4oOAkakEP+1jYFumNYtMaB+9x/0ncBAgMBAAGjUjBQMA4GA1UdDwEB +/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECgQIC9MiJNI7 +1RMwEwYDVR0jBAwwCoAIaHxWOdHsLbUwDQYJKoZIhvcNAQEFBQADgYEAo/ibmIxt +eityjZlszjCc/s7yM/0snL78pYpMOZ3P2TPKkYh2Th4+Bw8JqX10+M/zwFBj5Bw7 +ImzCIRfS3GFuKmcVcyHB4OZLMcQZtXWA8GOZ94YvWq5TBINlVtThQtusQj15KBq2 +TJNNFUyDpBdvyo05AnEsRY0HbIQu6ZhNQ40= +-----END CERTIFICATE----- + + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 41 (0x29) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=U.S. Government, OU=DoD, OU=Testing, CN=Trust Anchor + Validity + Not Before: Jan 1 12:01:00 1998 GMT + Not After : Jan 1 12:01:00 2048 GMT + Subject: C=US, O=U.S. Government, OU=Dod, OU=Testing, CN=CA1-CP.06.02 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bf:21:e8:d5:dc:39:9e:68:b5:bc:3b:03:1f:00: + 6c:ab:e7:ef:0d:3b:13:35:0b:e5:01:62:c9:5b:39: + f5:a3:29:41:9d:86:55:fa:4f:11:5c:e4:03:89:54: + 90:69:4b:f4:23:78:0f:91:5a:85:02:c6:7c:4a:6f: + d4:12:94:ea:c1:98:00:eb:72:71:b3:f3:35:74:fd: + cd:09:0c:b6:94:de:84:a0:b1:51:16:64:4d:12:7b: + 10:55:5a:b2:9c:97:58:fb:c0:dd:11:bb:13:1e:02: + 9d:f8:db:f6:28:ca:f0:70:79:ad:d5:7a:a2:64:99: + 20:9c:ed:8d:93:8e:bb:96:11 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Certificate Policies: + Policy: 2.16.840.1.101.3.1.48.1 + + X509v3 Subject Key Identifier: + 68:7C:56:39:D1:EC:2D:B5 + X509v3 Authority Key Identifier: + keyid:AB:9A:EB:F9:C2:E7:54:8F + + Signature Algorithm: sha1WithRSAEncryption + bb:37:aa:fe:5a:a9:d2:ab:3a:da:4a:ca:e8:40:3c:d5:28:a5: + 87:2e:36:97:f2:a6:ca:71:37:99:5b:bd:18:f0:60:41:2d:01: + 50:38:bb:fa:b4:10:fa:6d:14:c5:81:25:ce:3d:92:34:ee:09: + e5:a0:58:78:2f:7c:95:52:45:08:75:fb:40:4f:32:54:ea:0f: + 05:07:79:ac:0f:ab:af:3e:07:0f:d4:28:3f:b8:25:c5:3a:8b: + 53:a4:dc:f5:51:5d:fa:26:85:a6:ab:15:b5:28:76:6f:11:f6: + 06:d5:01:d8:04:60:79:b4:e4:95:a3:65:e5:53:db:bb:4f:b2: + 73:62 +-----BEGIN CERTIFICATE----- +MIIClTCCAf6gAwIBAgIBKTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsT +B1Rlc3RpbmcxFTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBa +Fw00ODAxMDExMjAxMDBaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdv +dmVybm1lbnQxDDAKBgNVBAsTA0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UE +AxMMQ0ExLUNQLjA2LjAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/IejV +3DmeaLW8OwMfAGyr5+8NOxM1C+UBYslbOfWjKUGdhlX6TxFc5AOJVJBpS/QjeA+R +WoUCxnxKb9QSlOrBmADrcnGz8zV0/c0JDLaU3oSgsVEWZE0SexBVWrKcl1j7wN0R +uxMeAp342/YoyvBwea3VeqJkmSCc7Y2TjruWEQIDAQABo2MwYTAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATAR +BgNVHQ4ECgQIaHxWOdHsLbUwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcN +AQEFBQADgYEAuzeq/lqp0qs62krK6EA81Silhy42l/KmynE3mVu9GPBgQS0BUDi7 ++rQQ+m0UxYElzj2SNO4J5aBYeC98lVJFCHX7QE8yVOoPBQd5rA+rrz4HD9QoP7gl +xTqLU6Tc9VFd+iaFpqsVtSh2bxH2BtUB2ARgebTklaNl5VPbu0+yc2I= +-----END CERTIFICATE----- + +Certificate Revocation List (CRL): + Version 2 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: /C=US/O=U.S. Government/OU=Dod/OU=Testing/CN=CA1-CP.06.02 + Last Update: Jan 1 12:01:00 1999 GMT + Next Update: Jan 1 12:01:00 2048 GMT + CRL extensions: + X509v3 CRL Number: + 1 + X509v3 Authority Key Identifier: + keyid:68:7C:56:39:D1:EC:2D:B5 + +Revoked Certificates: + Serial Number: 2A + Revocation Date: Jan 1 12:00:00 1999 GMT + X509v3 CRL Reason Code: + Key Compromise + Signature Algorithm: sha1WithRSAEncryption + 60:66:80:cd:5a:14:76:54:99:de:e1:8a:89:13:df:1c:01:48: + a0:a4:fb:f6:13:4e:be:d3:b1:68:60:34:68:87:a4:f4:ec:a9: + 0e:b0:ea:60:08:7f:b3:68:ec:5d:28:5e:2f:4a:6b:fe:ff:56: + 44:81:ef:b4:2b:7b:ca:d5:c3:c5:5c:a7:e0:dc:63:a5:fb:fb: + 06:40:0c:32:27:1c:75:4c:75:38:7d:55:12:54:d1:92:69:ad: + 31:ee:d1:3b:35:1e:1d:41:b3:5c:93:4f:7b:1d:41:73:d0:6f: + 48:28:47:d7:c6:d6:61:c9:32:39:97:58:24:18:dc:b4:22:89: + 16:0c +-----BEGIN X509 CRL----- +MIIBbzCB2QIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UE +ChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rp +bmcxFTATBgNVBAMTDENBMS1DUC4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAx +MTIwMTAwWjAiMCACASoXDTk5MDEwMTEyMDAwMFowDDAKBgNVHRUEAwoBAaAjMCEw +CgYDVR0UBAMCAQEwEwYDVR0jBAwwCoAIaHxWOdHsLbUwDQYJKoZIhvcNAQEFBQAD +gYEAYGaAzVoUdlSZ3uGKiRPfHAFIoKT79hNOvtOxaGA0aIek9OypDrDqYAh/s2js +XSheL0pr/v9WRIHvtCt7ytXDxVyn4Nxjpfv7BkAMMiccdUx1OH1VElTRkmmtMe7R +OzUeHUGzXJNPex1Bc9BvSChH18bWYckyOZdYJBjctCKJFgw= +-----END X509 CRL----- diff --git a/tests/x509_test.c b/tests/x509_test.c index 7df91202ba..f093387243 100644 --- a/tests/x509_test.c +++ b/tests/x509_test.c @@ -3,8 +3,6 @@ #include <string.h> #include <gnutls/x509.h> -#include <dmalloc.h> - #define MAX_FILE_SIZE 16*1024 struct file_res { @@ -18,6 +16,8 @@ static struct file_res test_files[] = { { "test3.pem", GNUTLS_CERT_INVALID | GNUTLS_CERT_NOT_TRUSTED }, { "test10.pem", 0 }, { "test13.pem", GNUTLS_CERT_INVALID | GNUTLS_CERT_NOT_TRUSTED }, + { "test20.pem", GNUTLS_CERT_REVOKED | GNUTLS_CERT_NOT_TRUSTED }, + { "test21.pem", GNUTLS_CERT_REVOKED | GNUTLS_CERT_NOT_TRUSTED }, { "test22.pem", GNUTLS_CERT_INVALID | GNUTLS_CERT_NOT_TRUSTED }, { "test23.pem", GNUTLS_CERT_INVALID | GNUTLS_CERT_NOT_TRUSTED }, { "test24.pem", 0 }, @@ -41,8 +41,13 @@ static void print_res( int x) printf("- certificate is NOT trusted\n"); else printf("- certificate is trusted\n"); + if (x&GNUTLS_CERT_CORRUPTED) printf("- Found a corrupted certificate.\n"); + + if (x&GNUTLS_CERT_REVOKED) + printf("- certificate is revoked.\n"); + return; } @@ -92,13 +97,13 @@ int i = 0, exp_result; } -#define PEM_SEP "-----BEGIN CERT" -#define PEM_SEP_SIZE (sizeof(PEM_SEP)-1) +#define CERT_SEP "-----BEGIN CERT" +#define CRL_SEP "-----BEGIN X509 CRL" /* Verifies a base64 encoded certificate list from memory */ int _verify_x509_mem( const char* cert, int cert_size, - const char *ca, int ca_size) + const char *ca, int ca_size, const char* crl, int crl_size) { int siz, i; const char *ptr; @@ -107,7 +112,8 @@ int _verify_x509_mem( const char* cert, int cert_size, gnutls_datum tmp; gnutls_x509_certificate *x509_cert_list = NULL; gnutls_x509_certificate x509_ca; - int x509_ncerts; + gnutls_x509_crl *x509_crl_list = NULL; + int x509_ncerts, x509_ncrls; /* Decode the CA certificate */ @@ -127,6 +133,50 @@ int _verify_x509_mem( const char* cert, int cert_size, exit(1); } + /* Decode the CRL list + */ + siz = crl_size; + ptr = crl; + + i = 1; + + if (strstr(ptr, CRL_SEP)!=NULL) /* if CRLs exist */ + do { + x509_crl_list = + (gnutls_x509_crl *) realloc( x509_crl_list, + i * + sizeof(gnutls_x509_crl)); + if (x509_crl_list == NULL) { + fprintf(stderr, "memory error\n"); + exit(1); + } + + tmp.data = (char*)ptr; + tmp.size = siz; + + ret = gnutls_x509_crl_init( &x509_crl_list[i-1]); + if (ret < 0) { + fprintf(stderr, "Error parsing the CRL[%d]: %s\n", i, gnutls_strerror(ret)); + exit(1); + } + + ret = gnutls_x509_crl_import( x509_crl_list[i-1], &tmp, GNUTLS_X509_FMT_PEM); + if (ret < 0) { + fprintf(stderr, "Error parsing the CRL[%d]: %s\n", i, gnutls_strerror(ret)); + exit(1); + } + + /* now we move ptr after the pem header */ + ptr = strstr(ptr, CRL_SEP); + if (ptr!=NULL) + ptr++; + + i++; + } while ((ptr = strstr(ptr, CRL_SEP)) != NULL); + + x509_ncrls = i - 1; + + /* Decode the certificate chain. */ siz = cert_size; @@ -160,23 +210,30 @@ int _verify_x509_mem( const char* cert, int cert_size, } /* now we move ptr after the pem header */ - ptr = strstr(ptr, PEM_SEP); + ptr = strstr(ptr, CERT_SEP); if (ptr!=NULL) ptr++; i++; - } while ((ptr = strstr(ptr, PEM_SEP)) != NULL); + } while ((ptr = strstr(ptr, CERT_SEP)) != NULL); x509_ncerts = i - 1; ret = gnutls_x509_certificate_list_verify( x509_cert_list, x509_ncerts, - &x509_ca, 1, NULL, 0, &output); + &x509_ca, 1, x509_crl_list, x509_ncrls, 0, &output); gnutls_x509_certificate_deinit( x509_ca); + for (i=0;i<x509_ncerts;i++) { gnutls_x509_certificate_deinit( x509_cert_list[i]); } + + for (i=0;i<x509_ncrls;i++) { + gnutls_x509_crl_deinit( x509_crl_list[i]); + } + free( x509_cert_list); + free( x509_crl_list); if ( ret < 0) { fprintf(stderr, "Error in verification: %s\n", gnutls_strerror(ret)); @@ -220,6 +277,6 @@ int _verify_x509_file( const char* certfile, const char *cafile) ca[ca_size] = 0; - return _verify_x509_mem( cert, cert_size, ca, ca_size); + return _verify_x509_mem( cert, cert_size, ca, ca_size, cert, cert_size); } |