summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-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
8 files changed, 295 insertions, 9 deletions
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 */