summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2003-12-23 21:47:11 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2003-12-23 21:47:11 +0000
commitc10891c3ee5a37ba4a1f22d4443cadf8c3240a7b (patch)
treefa6fecd78c272ae5cdff759671eaa92a7627055e
parent9ed56d8896141d63f5bc3d8f68c2d5c3b6c26d65 (diff)
downloadgnutls-c10891c3ee5a37ba4a1f22d4443cadf8c3240a7b.tar.gz
Added support for reading and generating CRL distribution
points extensions in certificates (not working yet).
-rw-r--r--NEWS2
-rw-r--r--doc/TODO1
-rw-r--r--includes/gnutls/x509.h3
-rw-r--r--lib/pkix.asn17
-rw-r--r--lib/pkix_asn1_tab.c17
-rw-r--r--lib/x509/common.c5
-rw-r--r--lib/x509/dsa.c5
-rw-r--r--lib/x509/extensions.c72
-rw-r--r--lib/x509/extensions.h2
-rw-r--r--lib/x509/x509.c130
-rw-r--r--lib/x509/x509_write.c56
-rw-r--r--src/certtool.c39
12 files changed, 338 insertions, 11 deletions
diff --git a/NEWS b/NEWS
index b5de615f49..b0386aa63d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,7 @@
Version 1.1.1
- Added PKCS #7 support to certtool utility.
+- Added support for reading and generating CRL distribution
+ points extensions in certificates.
Version 1.1.0 (21/12/2003)
- The error codes GNUTLS_E_NO_TEMPORARY_DH_PARAMS and GNUTLS_E_NO_TEMPORARY_RSA_PARAMS
diff --git a/doc/TODO b/doc/TODO
index bb36ca853f..b5b327684f 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -10,7 +10,6 @@ Current list:
* Add function to extract the signers of an openpgp key. Should
be similar to gnutls_x509_crt_get_dn_oid().
* Add function to verify an openpgp key against a plain key.
-* Add support for extracting CRL distribution points.
* Add support for generating CRLs.
* Add support for TLS 1.1
* Drop the compatibility functions.
diff --git a/includes/gnutls/x509.h b/includes/gnutls/x509.h
index f594379656..3beda03cba 100644
--- a/includes/gnutls/x509.h
+++ b/includes/gnutls/x509.h
@@ -73,7 +73,8 @@ int gnutls_x509_crt_get_signature_algorithm(gnutls_x509_crt cert);
int gnutls_x509_crt_get_version(gnutls_x509_crt cert);
int gnutls_x509_crt_get_key_id( gnutls_x509_crt crt, unsigned int flags,
unsigned char* output_data, size_t* output_data_size);
-
+int gnutls_x509_crt_get_crl_dist_points(gnutls_x509_crt cert,
+ unsigned int seq, void *ret, size_t *ret_size, unsigned int *critical);
time_t gnutls_x509_crt_get_activation_time(gnutls_x509_crt cert);
time_t gnutls_x509_crt_get_expiration_time(gnutls_x509_crt cert);
diff --git a/lib/pkix.asn b/lib/pkix.asn
index 01b1e7e940..446f5b5455 100644
--- a/lib/pkix.asn
+++ b/lib/pkix.asn
@@ -184,7 +184,7 @@ SkipCerts ::= INTEGER (0..MAX)
id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= {id-ce 31}
-CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
+CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
DistributionPoint ::= SEQUENCE {
distributionPoint [0] DistributionPointName OPTIONAL,
@@ -195,6 +195,21 @@ DistributionPointName ::= CHOICE {
fullName [0] GeneralNames,
nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
+-- Those are used to raw write a fullname.
+
+WritableCRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF WritableDistributionPoint
+
+WritableDistributionPoint ::= SEQUENCE {
+ distributionPoint [0] WriteableDistributionPointName OPTIONAL,
+ reasons [1] ReasonFlags OPTIONAL,
+ cRLIssuer [2] GeneralNames OPTIONAL }
+
+WriteableDistributionPointName ::= CHOICE {
+ fullName [0] ANY,
+ nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
+
+
+
ReasonFlags ::= BIT STRING {
diff --git a/lib/pkix_asn1_tab.c b/lib/pkix_asn1_tab.c
index 26d8ef9942..c773aba042 100644
--- a/lib/pkix_asn1_tab.c
+++ b/lib/pkix_asn1_tab.c
@@ -171,7 +171,7 @@ const ASN1_ARRAY_TYPE pkix_asn1_tab[]={
{"id-ce-cRLDistributionPoints",1879048204,0},
{0,1073741825,"id-ce"},
{0,1,"31"},
- {"CRLDistPointsSyntax",1612709899,0},
+ {"CRLDistributionPoints",1612709899,0},
{"MAX",1074266122,"1"},
{0,2,"DistributionPoint"},
{"DistributionPoint",1610612741,0},
@@ -186,6 +186,21 @@ const ASN1_ARRAY_TYPE pkix_asn1_tab[]={
{0,4104,"0"},
{"nameRelativeToCRLIssuer",536879106,"RelativeDistinguishedName"},
{0,4104,"1"},
+ {"WritableCRLDistributionPoints",1612709899,0},
+ {"MAX",1074266122,"1"},
+ {0,2,"WritableDistributionPoint"},
+ {"WritableDistributionPoint",1610612741,0},
+ {"distributionPoint",1610637314,"WriteableDistributionPointName"},
+ {0,4104,"0"},
+ {"reasons",1610637314,"ReasonFlags"},
+ {0,4104,"1"},
+ {"cRLIssuer",536895490,"GeneralNames"},
+ {0,4104,"2"},
+ {"WriteableDistributionPointName",1610612754,0},
+ {"fullName",1610620941,0},
+ {0,4104,"0"},
+ {"nameRelativeToCRLIssuer",536879106,"RelativeDistinguishedName"},
+ {0,4104,"1"},
{"ReasonFlags",1610874886,0},
{"unused",1073741825,"0"},
{"keyCompromise",1073741825,"1"},
diff --git a/lib/x509/common.c b/lib/x509/common.c
index 4e95651b85..003857a716 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -598,12 +598,13 @@ int _gnutls_x509_set_time(ASN1_TYPE c2, const char *where, time_t tim)
}
-gnutls_x509_subject_alt_name _gnutls_x509_san_find_type( char* str_type) {
+gnutls_x509_subject_alt_name _gnutls_x509_san_find_type( char* str_type)
+{
if (strcmp( str_type, "dNSName")==0) return GNUTLS_SAN_DNSNAME;
if (strcmp( str_type, "rfc822Name")==0) return GNUTLS_SAN_RFC822NAME;
if (strcmp( str_type, "uniformResourceIdentifier")==0) return GNUTLS_SAN_URI;
if (strcmp( str_type, "iPAddress")==0) return GNUTLS_SAN_IPADDRESS;
- return -1;
+ return (gnutls_x509_subject_alt_name)-1;
}
/* A generic export function. Will export the given ASN.1 encoded data
diff --git a/lib/x509/dsa.c b/lib/x509/dsa.c
index b5e35b94da..174c0b31b2 100644
--- a/lib/x509/dsa.c
+++ b/lib/x509/dsa.c
@@ -35,7 +35,10 @@ int _gnutls_dsa_generate_params(GNUTLS_MPI* resarr, int* resarr_len, int bits)
int ret;
gcry_sexp_t parms, key, list;
- if (bits > 1024) bits = 1024;
+ if (bits > 1024) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
ret = gcry_sexp_build( &parms, NULL, "(genkey(dsa(nbits %d)))", bits);
if (ret != 0) {
diff --git a/lib/x509/extensions.c b/lib/x509/extensions.c
index d290e95f91..e639e61d0c 100644
--- a/lib/x509/extensions.c
+++ b/lib/x509/extensions.c
@@ -29,6 +29,7 @@
#include <common.h>
#include <x509.h>
#include <extensions.h>
+#include <gnutls_datum.h>
/* This function will attempt to return the requested extension found in
* the given X509v3 certificate. The return value is allocated and stored into
@@ -564,3 +565,74 @@ int _gnutls_x509_ext_gen_subject_alt_name(gnutls_x509_subject_alt_name type,
return 0;
}
+
+int _gnutls_x509_ext_gen_crl_dist_points(gnutls_x509_subject_alt_name type,
+ const char* data_string, gnutls_datum* der_ext)
+{
+ ASN1_TYPE ext = ASN1_TYPE_EMPTY;
+ gnutls_datum name = {NULL, 0};
+ int result;
+
+ result = _gnutls_x509_ext_gen_subject_alt_name( type, data_string, &name);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.WritableCRLDistributionPoints", &ext);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ result = asn1_write_value( ext, "", "NEW", 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ result = asn1_write_value( ext, "?LAST.reasons", NULL, 0);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ result = asn1_write_value( ext, "?LAST.cRLIssuer", NULL, 0);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ result = asn1_write_value( ext, "?LAST.distributionPoint", "fullName", 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ result = asn1_write_value( ext, "?LAST.distributionPoint.fullName", name.data, name.size);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_der_encode( ext, "", der_ext, 0);
+
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = 0;
+
+cleanup:
+ _gnutls_free_datum( &name);
+ asn1_delete_structure(&ext);
+
+ return result;
+}
diff --git a/lib/x509/extensions.h b/lib/x509/extensions.h
index 84ea5752f8..7b90d452ee 100644
--- a/lib/x509/extensions.h
+++ b/lib/x509/extensions.h
@@ -13,3 +13,5 @@ int _gnutls_x509_ext_gen_basicConstraints(int CA, gnutls_datum* der_ext);
int _gnutls_x509_ext_gen_keyUsage(uint16 usage, gnutls_datum* der_ext);
int _gnutls_x509_ext_gen_subject_alt_name(gnutls_x509_subject_alt_name type,
const char* data_string, gnutls_datum* der_ext);
+int _gnutls_x509_ext_gen_crl_dist_points(gnutls_x509_subject_alt_name type,
+ const char* data_string, gnutls_datum* der_ext);
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index fccbd302f6..e2f30adb1a 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -623,7 +623,6 @@ int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt cert,
if ((result =
_gnutls_x509_crt_get_extension(cert, "2.5.29.17", 0, &dnsname, critical)) < 0) {
- gnutls_assert();
return result;
}
@@ -632,9 +631,9 @@ int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt cert,
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
- if ((result=asn1_create_element
- (_gnutls_get_pkix(), "PKIX1.SubjectAltName", &c2))
- != ASN1_SUCCESS) {
+ result=asn1_create_element
+ (_gnutls_get_pkix(), "PKIX1.SubjectAltName", &c2);
+ if (result != ASN1_SUCCESS) {
gnutls_assert();
_gnutls_free_datum( &dnsname);
return _gnutls_asn2err(result);
@@ -1305,4 +1304,127 @@ int result;
return result;
}
+/**
+ * gnutls_x509_crt_get_crl_dist_points - This function returns the CRL distribution points
+ * @cert: should contain a gnutls_x509_crt structure
+ * @seq: specifies the sequence number of the distribution point (0 for the first one, 1 for the second etc.)
+ * @ret: is the place where the distribution point will be copied to
+ * @ret_size: holds the size of ret.
+ * @critical: will be non zero if the extension is marked as critical (may be null)
+ *
+ * This function will return the CRL distribution points (2.5.29.31), contained in the
+ * given certificate.
+ *
+ * This is specified in X509v3 Certificate Extensions. GNUTLS will return the
+ * distribution point type, or a negative error code on error.
+ *
+ * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if ret_size is not enough to hold the distribution
+ * point, or the type of the distribution point if everything was ok. The type is
+ * one of the enumerated gnutls_x509_subject_alt_name.
+ *
+ * If the certificate does not have an Alternative name with the specified
+ * sequence number then returns GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ *
+ **/
+int gnutls_x509_crt_get_crl_dist_points(gnutls_x509_crt cert,
+ unsigned int seq, void *ret, size_t *ret_size, unsigned int *critical)
+{
+ int result;
+ gnutls_datum dist_points = {NULL, 0};
+ ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+ char name[128];
+ char ext_data[256];
+ int len;
+ char num[MAX_INT_DIGITS];
+ gnutls_x509_subject_alt_name type;
+
+ if (cert==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ if (ret) memset(ret, 0, *ret_size);
+ else *ret_size = 0;
+
+ result =
+ _gnutls_x509_crt_get_extension(cert, "2.5.29.31", 0, &dist_points, critical);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ if (dist_points.size == 0 || dist_points.data==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ result=asn1_create_element
+ (_gnutls_get_pkix(), "PKIX1.CRLDistributionPoints", &c2);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ _gnutls_free_datum( &dist_points);
+ return _gnutls_asn2err(result);
+ }
+
+ result = asn1_der_decoding(&c2, dist_points.data, dist_points.size, NULL);
+ _gnutls_free_datum( &dist_points);
+
+ if (result != ASN1_SUCCESS) {
+ /* couldn't decode DER */
+
+ _gnutls_x509_log("X509 certificate: Decoding error %d\n", result);
+ gnutls_assert();
+ asn1_delete_structure(&c2);
+ return _gnutls_asn2err(result);
+ }
+
+ seq++; /* 0->1, 1->2 etc */
+ _gnutls_int2str( seq, num);
+ _gnutls_str_cpy( name, sizeof(name), "dn.?");
+ _gnutls_str_cat( name, sizeof(name), num);
+ _gnutls_str_cat( name, sizeof(name), ".distributionPoint.fullName");
+
+ len = sizeof(ext_data);
+ result =
+ asn1_read_value(c2, name, ext_data, &len);
+
+ if (result == ASN1_VALUE_NOT_FOUND) {
+ asn1_delete_structure(&c2);
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ asn1_delete_structure(&c2);
+ return _gnutls_asn2err(result);
+ }
+
+ type = _gnutls_x509_san_find_type( ext_data);
+ if (type == (gnutls_x509_subject_alt_name)-1) {
+ asn1_delete_structure(&c2);
+ gnutls_assert();
+ return GNUTLS_E_X509_UNKNOWN_SAN;
+ }
+
+ _gnutls_str_cat( name, sizeof(name), ".");
+ _gnutls_str_cat( name, sizeof(name), ext_data);
+
+ len = *ret_size;
+ result =
+ asn1_read_value(c2, name, ret, &len);
+ asn1_delete_structure(&c2);
+
+ *ret_size = len;
+
+ if (result==ASN1_MEM_ERROR)
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ return type;
+}
+
#endif
diff --git a/lib/x509/x509_write.c b/lib/x509/x509_write.c
index 0bd9e9d9df..4ab52ade99 100644
--- a/lib/x509/x509_write.c
+++ b/lib/x509/x509_write.c
@@ -561,5 +561,61 @@ static void disable_optional_stuff( gnutls_x509_crt cert)
return;
}
+/**
+ * gnutls_x509_crt_set_crl_dist_points - This function will set the CRL dist points
+ * @crt: should contain a gnutls_x509_crt structure
+ * @type: is one of the gnutls_x509_subject_alt_name enumerations
+ * @data_string: The data to be set
+ *
+ * This function will set the CRL distribution points certificate extension.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int gnutls_x509_crt_set_crl_dist_points(gnutls_x509_crt crt, gnutls_x509_subject_alt_name type,
+ const char* data_string)
+{
+int result;
+gnutls_datum der_data;
+gnutls_datum oldname;
+unsigned int critical;
+
+ if (crt==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* Check if the extension already exists.
+ */
+ result = _gnutls_x509_crt_get_extension(crt, "2.5.29.31", 0, &oldname, &critical);
+
+ if (result >= 0) _gnutls_free_datum( &oldname);
+ if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* generate the extension.
+ */
+ result = _gnutls_x509_ext_gen_crl_dist_points( type, data_string, &der_data);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ result = _gnutls_x509_crt_set_extension( crt, "2.5.29.31", &der_data, 0);
+
+ _gnutls_free_datum( &der_data);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ crt->use_extensions = 1;
+
+ return 0;
+}
+
#endif /* ENABLE_PKI */
diff --git a/src/certtool.c b/src/certtool.c
index 9fdc2663b9..c968ce49ca 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -183,6 +183,11 @@ const char* msg;
if (info.dsa) {
msg = "DSA";
key_type = GNUTLS_PK_DSA;
+
+ if (info.bits > 1024) {
+ fprintf(stderr, "The DSA algorithm cannot be used with primes over 1024 bits.\n");
+ exit(1);
+ }
} else {
msg = "RSA";
key_type = GNUTLS_PK_RSA;
@@ -685,10 +690,13 @@ const char* get_algorithm( int a)
}
}
+/* OIDs that are handled by the gnutls' functions.
+ */
static inline int known_oid( const char* oid)
{
if (strcmp(oid, "2.5.29.17") == 0 ||
strcmp( oid, "2.5.29.19") == 0 ||
+ strcmp( oid, "2.5.29.31") == 0 ||
strcmp( oid, "2.5.29.15") == 0)
return 1;
@@ -818,6 +826,37 @@ void certificate_info( void)
break;
}
}
+
+ /* CRL dist points.
+ */
+ ret = 0;
+ for (i = 0; !(ret < 0); i++) {
+ size = sizeof(buffer);
+ ret = gnutls_x509_crt_get_crl_dist_points(crt, i, buffer, &size, &critical);
+
+ if (i==0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ fprintf(outfile, "\tCRL Distribution points:");
+ if (critical) fprintf(outfile, " (critical)");
+ fprintf(outfile, "\n");
+ }
+
+ if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ fprintf(outfile, "\t\tFound unsupported name.\n");
+ } else switch (ret) {
+ case GNUTLS_SAN_DNSNAME:
+ fprintf(outfile, "\t\tDNSname: %s\n", buffer);
+ break;
+ case GNUTLS_SAN_RFC822NAME:
+ fprintf(outfile, "\t\tRFC822name: %s\n", buffer);
+ break;
+ case GNUTLS_SAN_URI:
+ fprintf(outfile, "\t\tURI: %s\n", buffer);
+ break;
+ case GNUTLS_SAN_IPADDRESS:
+ fprintf(outfile, "\t\tIPAddress: %s\n", buffer);
+ break;
+ }
+ }
/* check for basicConstraints
*/