summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2003-10-25 15:29:01 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2003-10-25 15:29:01 +0000
commit0fba2d908da6d0df821991ea5fdbeeda0f4ff089 (patch)
tree87901f6b84472227b4ad23bde4efabe462658154
parent4a288531e874f10a0c250ca52d1cd102bce4ffa6 (diff)
downloadgnutls-0fba2d908da6d0df821991ea5fdbeeda0f4ff089.tar.gz
Improved the certificate generation stuff.
-rw-r--r--includes/gnutls/x509.h2
-rw-r--r--lib/x509/common.c97
-rw-r--r--lib/x509/common.h3
-rw-r--r--lib/x509/crl.c139
-rw-r--r--lib/x509/dn.c4
-rw-r--r--lib/x509/extensions.c78
-rw-r--r--lib/x509/extensions.h2
-rw-r--r--lib/x509/mpi.c1
-rw-r--r--lib/x509/verify.c148
-rw-r--r--lib/x509/x509.c139
-rw-r--r--lib/x509/x509.h20
-rw-r--r--lib/x509/x509_write.c70
12 files changed, 444 insertions, 259 deletions
diff --git a/includes/gnutls/x509.h b/includes/gnutls/x509.h
index f40076e5a6..55a90f9448 100644
--- a/includes/gnutls/x509.h
+++ b/includes/gnutls/x509.h
@@ -114,6 +114,8 @@ int gnutls_x509_crt_set_issuer_dn_by_oid(gnutls_x509_crt crt, const char* oid,
int gnutls_x509_crt_set_version(gnutls_x509_crt crt, unsigned int version);
int gnutls_x509_crt_set_key(gnutls_x509_crt crt, gnutls_x509_privkey key);
int gnutls_x509_crt_set_ca_status(gnutls_x509_crt crt, unsigned int ca);
+int gnutls_x509_crt_set_subject_alternative_name(gnutls_x509_crt crt, gnutls_x509_subject_alt_name type,
+ const char* data_string);
int gnutls_x509_crt_sign(gnutls_x509_crt crt, gnutls_x509_crt issuer,
gnutls_x509_privkey issuer_key);
int gnutls_x509_crt_set_activation_time(gnutls_x509_crt cert, time_t act_time);
diff --git a/lib/x509/common.c b/lib/x509/common.c
index c7ce6fb5c1..01d3048187 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -1126,3 +1126,100 @@ int _gnutls_asn1_copy_node( ASN1_TYPE *dst, const char* dst_name,
return 0;
}
+
+/* Reads the DER signed data from the certificate and allocates space and
+ * returns them into signed_data.
+ */
+int _gnutls_x509_get_signed_data( ASN1_TYPE src, const char* src_name, gnutls_datum * signed_data)
+{
+gnutls_datum der;
+int start, end, result;
+
+ result = _gnutls_x509_der_encode( src, "", &der, 0);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ /* Get the signed data
+ */
+ result = asn1_der_decoding_startEnd( src, der.data, der.size,
+ src_name, &start,
+ &end);
+ if (result != ASN1_SUCCESS) {
+ result = _gnutls_asn2err(result);
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result =
+ _gnutls_set_datum( signed_data, &der.data[start], end - start + 1);
+
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ _gnutls_free_datum(&der);
+
+ return result;
+}
+
+/* Reads the DER signature from the certificate and allocates space and
+ * returns them into signed_data.
+ */
+int _gnutls_x509_get_signature( ASN1_TYPE src, const char* src_name, gnutls_datum * signature)
+{
+int bits, result, len;
+
+ signature->data = NULL;
+ signature->size = 0;
+
+ /* Read the signature
+ */
+ bits = 0;
+ result = asn1_read_value( src, src_name, NULL, &bits);
+
+ if (result != ASN1_MEM_ERROR) {
+ result = _gnutls_asn2err(result);
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ if (bits % 8 != 0) {
+ gnutls_assert();
+ result = GNUTLS_E_CERTIFICATE_ERROR;
+ goto cleanup;
+ }
+
+ len = bits/8;
+
+ signature->data = gnutls_malloc( len);
+ if (signature->data == NULL) {
+ gnutls_assert();
+ result = GNUTLS_E_MEMORY_ERROR;
+ return result;
+ }
+
+ /* read the bit string of the signature
+ */
+ bits = len;
+ result = asn1_read_value( src, src_name, signature->data,
+ &bits);
+
+ if (result != ASN1_SUCCESS) {
+ result = _gnutls_asn2err(result);
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ signature->size = len;
+
+ return 0;
+
+ cleanup:
+ return result;
+}
diff --git a/lib/x509/common.h b/lib/x509/common.h
index 6f286fafb4..0eb81c84d9 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -65,3 +65,6 @@ int _gnutls_x509_encode_and_copy_PKI_params( ASN1_TYPE dst, const char* dst_name
gnutls_pk_algorithm pk_algorithm, GNUTLS_MPI* params, int params_size);
int _gnutls_asn1_copy_node( ASN1_TYPE *dst, const char* dst_name,
ASN1_TYPE src, const char* src_name);
+
+int _gnutls_x509_get_signed_data( ASN1_TYPE src, const char* src_name, gnutls_datum * signed_data);
+int _gnutls_x509_get_signature( ASN1_TYPE src, const char* src_name, gnutls_datum * signature);
diff --git a/lib/x509/crl.c b/lib/x509/crl.c
index 031055d37a..5745e37fbf 100644
--- a/lib/x509/crl.c
+++ b/lib/x509/crl.c
@@ -75,8 +75,6 @@ void gnutls_x509_crl_deinit(gnutls_x509_crl crl)
if (crl->crl)
asn1_delete_structure(&crl->crl);
- _gnutls_free_datum(&crl->signed_data);
- _gnutls_free_datum(&crl->signature);
gnutls_free(crl);
}
@@ -99,9 +97,7 @@ int gnutls_x509_crl_import(gnutls_x509_crl crl, const gnutls_datum * data,
gnutls_x509_crt_fmt format)
{
int result = 0, need_free = 0;
- int start, end, bits, len;
gnutls_datum _data = { data->data, data->size };
- opaque *signature = NULL;
/* If the CRL is in PEM format then decode it
*/
@@ -134,94 +130,12 @@ int gnutls_x509_crl_import(gnutls_x509_crl crl, const gnutls_datum * data,
goto cleanup;
}
- /* Get the signed data
- */
- result =
- asn1_der_decoding_startEnd(crl->crl, _data.data, _data.size,
- "tbsCertList", &start, &end);
- if (result != ASN1_SUCCESS) {
- result = _gnutls_asn2err(result);
- gnutls_assert();
- goto cleanup;
- }
-
-
- result =
- _gnutls_set_datum(&crl->signed_data, &_data.data[start],
- end - start + 1);
- if (result < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- /* Read the signature */
- bits = 0;
- result = asn1_read_value( crl->crl, "signature", NULL, &bits);
-
- if (result != ASN1_MEM_ERROR) {
- result = _gnutls_asn2err(result);
- gnutls_assert();
- goto cleanup;
- }
-
- if (bits % 8 != 0) {
- gnutls_assert();
- result = GNUTLS_E_CERTIFICATE_ERROR;
- goto cleanup;
- }
-
- len = bits/8;
- signature = gnutls_malloc( len);
- if (signature == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- /* read the bit string of the signature
- */
- bits = len;
- result = asn1_read_value( crl->crl, "signature", signature,
- &bits);
-
- if (result != ASN1_SUCCESS) {
- result = _gnutls_asn2err(result);
- gnutls_assert();
- goto cleanup;
- }
-
-
- if ((result=_gnutls_set_datum(&crl->signature, signature, len)) < 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.
- */
-
- result = asn1_read_value( crl->crl, "signatureAlgorithm.algorithm",
- signature, &len);
-
- if (result != ASN1_SUCCESS) {
- result = _gnutls_asn2err(result);
- gnutls_assert();
- goto cleanup;
- }
-
- crl->signature_algorithm = _gnutls_x509_oid2sign_algorithm( signature, NULL);
-
- gnutls_free( signature);
- signature = NULL;
-
if (need_free)
_gnutls_free_datum(&_data);
return 0;
cleanup:
- gnutls_free( signature);
- _gnutls_free_datum(&crl->signed_data);
- _gnutls_free_datum(&crl->signature);
if (need_free)
_gnutls_free_datum(&_data);
return result;
@@ -305,9 +219,25 @@ int gnutls_x509_crl_get_issuer_dn_by_oid(gnutls_x509_crl crl,
**/
int gnutls_x509_crl_get_signature_algorithm(gnutls_x509_crl crl)
{
- return crl->signature_algorithm;
+ int result;
+ gnutls_datum sa;
- return 0;
+ /* Read the signature algorithm. Note that parameters are not
+ * read. They will be read from the issuer's certificate if needed.
+ */
+
+ result = _gnutls_x509_read_value( crl->crl, "signatureAlgorithm.algorithm", &sa, 0);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ result = _gnutls_x509_oid2sign_algorithm( sa.data, NULL);
+
+ _gnutls_free_datum( &sa);
+
+ return result;
}
/**
@@ -460,11 +390,12 @@ int gnutls_x509_crl_get_certificate(gnutls_x509_crl crl, int index,
*
-*/
int _gnutls_x509_crl_get_raw_issuer_dn(gnutls_x509_crl crl,
- gnutls_const_datum * dn)
+ gnutls_datum * dn)
{
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
int result, len1;
int start1, end1;
+ gnutls_datum crl_signed_data;
/* get the issuer of 'crl'
*/
@@ -475,34 +406,44 @@ int _gnutls_x509_crl_get_raw_issuer_dn(gnutls_x509_crl crl,
return _gnutls_asn2err(result);
}
+ result = _gnutls_x509_get_signed_data( crl->crl, "tbsCertList", &crl_signed_data);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
result =
- asn1_der_decoding(&c2, crl->signed_data.data,
- crl->signed_data.size, NULL);
+ asn1_der_decoding(&c2, crl_signed_data.data,
+ crl_signed_data.size, NULL);
if (result != ASN1_SUCCESS) {
/* couldn't decode DER */
gnutls_assert();
asn1_delete_structure(&c2);
- return _gnutls_asn2err(result);
+ result = _gnutls_asn2err(result);
+ goto cleanup;
}
result =
- asn1_der_decoding_startEnd(c2, crl->signed_data.data,
- crl->signed_data.size, "issuer",
+ asn1_der_decoding_startEnd(c2, crl_signed_data.data,
+ crl_signed_data.size, "issuer",
&start1, &end1);
- asn1_delete_structure(&c2);
if (result != ASN1_SUCCESS) {
gnutls_assert();
- return _gnutls_asn2err(result);
+ result = _gnutls_asn2err(result);
+ goto cleanup;
}
len1 = end1 - start1 + 1;
- dn->data = &crl->signed_data.data[start1];
- dn->size = len1;
+ _gnutls_set_datum( dn, &crl_signed_data.data[start1], len1);
- return 0;
+ result = 0;
+cleanup:
+ asn1_delete_structure(&c2);
+ _gnutls_free_datum( &crl_signed_data);
+ return result;
}
/**
diff --git a/lib/x509/dn.c b/lib/x509/dn.c
index 35f6146363..8bfd8e37d7 100644
--- a/lib/x509/dn.c
+++ b/lib/x509/dn.c
@@ -811,8 +811,8 @@ int gnutls_x509_rdn_get_by_oid(const gnutls_datum * idn, const char* oid, int in
* 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)
+int _gnutls_x509_compare_raw_dn(const gnutls_datum * dn1,
+ const gnutls_datum * dn2)
{
if (dn1->size != dn2->size) {
diff --git a/lib/x509/extensions.c b/lib/x509/extensions.c
index 7855590134..c6e4e0e1e9 100644
--- a/lib/x509/extensions.c
+++ b/lib/x509/extensions.c
@@ -34,6 +34,9 @@
* ret.
*
* Critical will be either 0 or 1.
+ *
+ * If the extension does not exist, GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will
+ * be returned.
*/
int _gnutls_x509_crt_get_extension( gnutls_x509_crt cert, const char* extension_id,
int indx, gnutls_datum* ret, unsigned int * _critical)
@@ -303,9 +306,8 @@ int _gnutls_x509_ext_gen_basicConstraints(int CA, gnutls_datum* der_ext)
if (CA == 0) str = "FALSE";
else str = "TRUE";
- if ((result=asn1_create_element
- (_gnutls_get_pkix(), "PKIX1.BasicConstraints", &ext
- )) != ASN1_SUCCESS) {
+ result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.BasicConstraints", &ext);
+ if (result != ASN1_SUCCESS) {
gnutls_assert();
return _gnutls_asn2err(result);
}
@@ -316,6 +318,8 @@ int _gnutls_x509_ext_gen_basicConstraints(int CA, gnutls_datum* der_ext)
asn1_delete_structure(&ext);
return _gnutls_asn2err(result);
}
+
+ asn1_write_value(ext, "pathLenConstraint", NULL, 0);
result = _gnutls_x509_der_encode( ext, "", der_ext, 0);
@@ -328,3 +332,71 @@ int _gnutls_x509_ext_gen_basicConstraints(int CA, gnutls_datum* der_ext)
return 0;
}
+
+/* generate the subject alternative name in a DER encoded extension
+ */
+int _gnutls_x509_ext_gen_subject_alt_name(gnutls_x509_subject_alt_name type,
+ const char* data_string, gnutls_datum* der_ext)
+{
+ ASN1_TYPE ext = ASN1_TYPE_EMPTY;
+ const char *str;
+ char name[128];
+ int result;
+
+ result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.SubjectAltName", &ext);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ result = asn1_write_value( ext, "", "NEW", 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ switch(type) {
+ case GNUTLS_SAN_DNSNAME:
+ str = "dNSName";
+ break;
+ case GNUTLS_SAN_RFC822NAME:
+ str = "rfc822Name";
+ break;
+ case GNUTLS_SAN_URI:
+ str = "uniformResourceIdentifier";
+ break;
+ case GNUTLS_SAN_IPADDRESS:
+ str = "iPAddress";
+ break;
+ default:
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ result = asn1_write_value( ext, "?LAST", str, 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ _gnutls_str_cpy( name, sizeof(name), "?LAST.");
+ _gnutls_str_cat( name, sizeof(name), str);
+
+ result = asn1_write_value(ext, name, data_string, strlen(data_string));
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ asn1_delete_structure(&ext);
+ return _gnutls_asn2err(result);
+ }
+
+ result = _gnutls_x509_der_encode( ext, "", der_ext, 0);
+
+ asn1_delete_structure(&ext);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ return 0;
+}
diff --git a/lib/x509/extensions.h b/lib/x509/extensions.h
index d9fb33dc5f..e457fc231c 100644
--- a/lib/x509/extensions.h
+++ b/lib/x509/extensions.h
@@ -8,3 +8,5 @@ int _gnutls_x509_ext_extract_basicConstraints(int *CA, opaque * extnValue,
int _gnutls_x509_crt_set_extension( gnutls_x509_crt cert, const char* extension_id,
const gnutls_datum* ext_data, unsigned int critical);
int _gnutls_x509_ext_gen_basicConstraints(int CA, 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);
diff --git a/lib/x509/mpi.c b/lib/x509/mpi.c
index 952013324a..181aec9c0c 100644
--- a/lib/x509/mpi.c
+++ b/lib/x509/mpi.c
@@ -314,7 +314,6 @@ int _gnutls_x509_write_rsa_params( GNUTLS_MPI * params, int params_size,
asn1_delete_structure(&spk);
if (result != ASN1_SUCCESS) {
- gnutls_assert();
return _gnutls_asn2err(result);
}
diff --git a/lib/x509/verify.c b/lib/x509/verify.c
index 25715652a1..181a3a858d 100644
--- a/lib/x509/verify.c
+++ b/lib/x509/verify.c
@@ -58,30 +58,69 @@ static int _gnutls_verify_crl2(gnutls_x509_crl crl,
* Returns true or false, if the issuer is a CA,
* or not.
*/
-static int check_if_ca(gnutls_x509_crt cert,
- gnutls_x509_crt issuer)
+static int check_if_ca(gnutls_x509_crt cert, gnutls_x509_crt issuer)
{
+gnutls_datum cert_signed_data = { NULL, 0 };
+gnutls_datum issuer_signed_data = { NULL, 0 };
+gnutls_datum cert_signature = { NULL, 0 };
+gnutls_datum issuer_signature = { NULL, 0 };
+int result;
+
/* Check if the issuer is the same with the
* certificate. This is added in order for trusted
* certificates to be able to verify themselves.
*/
- if (cert->signed_data.size == issuer->signed_data.size) {
+
+ result = _gnutls_x509_get_signed_data( issuer->cert, "tbsCertificate", &issuer_signed_data);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_get_signed_data( cert->cert, "tbsCertificate", &cert_signed_data);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_get_signature( issuer->cert, "signature", &issuer_signature);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_get_signature( cert->cert, "signature", &cert_signature);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ if (cert_signed_data.size == issuer_signed_data.size) {
if (
- (memcmp(cert->signed_data.data, issuer->signed_data.data,
- cert->signed_data.size) == 0) &&
- (cert->signature.size == issuer->signature.size) &&
- (memcmp(cert->signature.data, issuer->signature.data,
- cert->signature.size) == 0))
+ (memcmp(cert_signed_data.data, issuer_signed_data.data,
+ cert_signed_data.size) == 0) &&
+ (cert_signature.size == issuer_signature.size) &&
+ (memcmp(cert_signature.data, issuer_signature.data,
+ cert_signature.size) == 0))
- return 1;
+ result = 1;
+ goto cleanup;
}
if (gnutls_x509_crt_get_ca_status(issuer, NULL) == 1) {
- return 1;
+ result = 1;
+ goto cleanup;
} else
gnutls_assert();
- return 0;
+ result = 0;
+
+cleanup:
+ _gnutls_free_datum( &cert_signed_data);
+ _gnutls_free_datum( &issuer_signed_data);
+ _gnutls_free_datum( &cert_signature);
+ _gnutls_free_datum( &issuer_signature);
+ return result;
}
@@ -95,22 +134,27 @@ static int check_if_ca(gnutls_x509_crt cert,
static
int is_issuer(gnutls_x509_crt cert, gnutls_x509_crt issuer_cert)
{
- gnutls_const_datum dn1, dn2;
+ gnutls_datum dn1 = {NULL, 0}, dn2 = { NULL, 0 };
int ret;
ret = _gnutls_x509_crt_get_raw_issuer_dn( cert, &dn1);
if (ret < 0) {
gnutls_assert();
- return ret;
+ goto cleanup;
}
ret = _gnutls_x509_crt_get_raw_dn( issuer_cert, &dn2);
if (ret < 0) {
gnutls_assert();
- return ret;
+ goto cleanup;
}
- return _gnutls_x509_compare_raw_dn( &dn1, &dn2);
+ ret = _gnutls_x509_compare_raw_dn( &dn1, &dn2);
+
+cleanup:
+ _gnutls_free_datum(&dn1);
+ _gnutls_free_datum(&dn2);
+ return ret;
}
@@ -145,10 +189,10 @@ static int _gnutls_verify_certificate2(gnutls_x509_crt cert,
gnutls_x509_crt *trusted_cas, int tcas_size,
unsigned int flags)
{
-/* CRL is ignored for now */
-
- gnutls_x509_crt issuer;
- int ret, issuer_version;
+gnutls_datum cert_signed_data = { NULL, 0 };
+gnutls_datum cert_signature = { NULL, 0 };
+gnutls_x509_crt issuer;
+int ret, issuer_version, result;
if (tcas_size >= 1)
issuer = find_issuer(cert, trusted_cas, tcas_size);
@@ -179,14 +223,33 @@ static int _gnutls_verify_certificate2(gnutls_x509_crt cert,
}
}
- ret = _gnutls_x509_verify_signature(&cert->signed_data, &cert->signature, issuer);
+
+ result = _gnutls_x509_get_signed_data( cert->cert, "tbsCertificate", &cert_signed_data);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_get_signature( cert->cert, "signature", &cert_signature);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = _gnutls_x509_verify_signature(&cert_signed_data, &cert_signature, issuer);
if (ret < 0) {
gnutls_assert();
/* error. ignore it */
ret = 0;
}
- return ret;
+ result = ret;
+
+cleanup:
+ _gnutls_free_datum( &cert_signed_data);
+ _gnutls_free_datum( &cert_signature);
+
+ return result;
}
@@ -602,13 +665,13 @@ int gnutls_x509_crl_verify( gnutls_x509_crl crl,
static
int is_crl_issuer(gnutls_x509_crl crl, gnutls_x509_crt issuer_cert)
{
- gnutls_const_datum dn1, dn2;
+ gnutls_datum dn1 = {NULL, 0}, dn2 = {NULL, 0};
int ret;
ret = _gnutls_x509_crl_get_raw_issuer_dn( crl, &dn1);
if (ret < 0) {
gnutls_assert();
- return ret;
+ goto cleanup;
}
ret = _gnutls_x509_crt_get_raw_dn( issuer_cert, &dn2);
@@ -617,8 +680,13 @@ int is_crl_issuer(gnutls_x509_crl crl, gnutls_x509_crt issuer_cert)
return ret;
}
- return _gnutls_x509_compare_raw_dn( &dn1, &dn2);
-
+ ret = _gnutls_x509_compare_raw_dn( &dn1, &dn2);
+
+cleanup:
+ _gnutls_free_datum( &dn1);
+ _gnutls_free_datum( &dn2);
+
+ return ret;
}
static inline
@@ -650,9 +718,10 @@ static int _gnutls_verify_crl2(gnutls_x509_crl crl,
unsigned int flags)
{
/* CRL is ignored for now */
-
- gnutls_x509_crt issuer;
- int ret;
+gnutls_datum crl_signed_data = { NULL, 0 };
+gnutls_datum crl_signature = { NULL, 0 };
+gnutls_x509_crt issuer;
+int ret, result;
if (tcas_size >= 1)
issuer = find_crl_issuer(crl, trusted_cas, tcas_size);
@@ -677,14 +746,33 @@ static int _gnutls_verify_crl2(gnutls_x509_crl crl,
}
}
- ret = _gnutls_x509_verify_signature(&crl->signed_data, &crl->signature, issuer);
+ result = _gnutls_x509_get_signed_data( crl->crl, "tbsCertList", &crl_signed_data);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_get_signature( crl->crl, "signature", &crl_signature);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+
+ ret = _gnutls_x509_verify_signature(&crl_signed_data, &crl_signature, issuer);
if (ret < 0) {
gnutls_assert();
/* error. ignore it */
ret = 0;
}
- return ret;
+ result = ret;
+
+cleanup:
+ _gnutls_free_datum( &crl_signed_data);
+ _gnutls_free_datum( &crl_signature);
+
+ return result;
}
#endif
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index 5a1a4cb0f2..bc17f7d06f 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -127,8 +127,6 @@ void gnutls_x509_crt_deinit(gnutls_x509_crt cert)
if (cert->cert)
asn1_delete_structure(&cert->cert);
- _gnutls_free_datum(&cert->signed_data);
- _gnutls_free_datum(&cert->signature);
gnutls_free(cert);
}
@@ -152,7 +150,6 @@ int gnutls_x509_crt_import(gnutls_x509_crt cert, const gnutls_datum * data,
gnutls_x509_crt_fmt format)
{
int result = 0, need_free = 0;
- int start, end, len, bits;
gnutls_datum _data = { data->data, data->size };
opaque *signature = NULL;
@@ -190,85 +187,6 @@ int gnutls_x509_crt_import(gnutls_x509_crt cert, const gnutls_datum * data,
goto cleanup;
}
- /* Get the signed data
- */
- result = asn1_der_decoding_startEnd(cert->cert, _data.data, _data.size,
- "tbsCertificate", &start,
- &end);
- if (result != ASN1_SUCCESS) {
- result = _gnutls_asn2err(result);
- gnutls_assert();
- goto cleanup;
- }
-
-
- result =
- _gnutls_set_datum(&cert->signed_data, &_data.data[start],
- end - start + 1);
- if (result < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- /* Read the signature
- */
- bits = 0;
- result = asn1_read_value( cert->cert, "signature", NULL, &bits);
-
- if (result != ASN1_MEM_ERROR) {
- result = _gnutls_asn2err(result);
- gnutls_assert();
- goto cleanup;
- }
-
- if (bits % 8 != 0) {
- gnutls_assert();
- result = GNUTLS_E_CERTIFICATE_ERROR;
- goto cleanup;
- }
-
- len = bits/8;
- signature = gnutls_malloc( len);
- if (signature == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- /* read the bit string of the signature
- */
- bits = len;
- result = asn1_read_value( cert->cert, "signature", signature,
- &bits);
-
- if (result != ASN1_SUCCESS) {
- result = _gnutls_asn2err(result);
- gnutls_assert();
- goto cleanup;
- }
-
-
- if ((result=_gnutls_set_datum(&cert->signature, signature, len)) < 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.
- */
-
- result = asn1_read_value( cert->cert, "signatureAlgorithm.algorithm",
- signature, &len);
-
- if (result != ASN1_SUCCESS) {
- result = _gnutls_asn2err(result);
- gnutls_assert();
- goto cleanup;
- }
-
- cert->signature_algorithm = _gnutls_x509_oid2sign_algorithm( signature, NULL);
-
- gnutls_free( signature);
- signature = NULL;
if (need_free) _gnutls_free_datum( &_data);
@@ -276,8 +194,6 @@ int gnutls_x509_crt_import(gnutls_x509_crt cert, const gnutls_datum * data,
cleanup:
gnutls_free( signature);
- _gnutls_free_datum(&cert->signed_data);
- _gnutls_free_datum(&cert->signature);
if (need_free) _gnutls_free_datum( &_data);
return result;
}
@@ -419,9 +335,24 @@ int gnutls_x509_crt_get_dn_by_oid(gnutls_x509_crt cert, const char* oid,
**/
int gnutls_x509_crt_get_signature_algorithm(gnutls_x509_crt cert)
{
- return cert->signature_algorithm;
+ int result;
+ gnutls_datum sa;
- return 0;
+ /* Read the signature algorithm. Note that parameters are not
+ * read. They will be read from the issuer's certificate if needed.
+ */
+ result = _gnutls_x509_read_value( cert->cert, "signatureAlgorithm.algorithm", &sa, 0);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ result = _gnutls_x509_oid2sign_algorithm( sa.data, NULL);
+
+ _gnutls_free_datum( &sa);
+
+ return result;
}
/**
@@ -554,6 +485,7 @@ int gnutls_x509_crt_get_pk_algorithm( gnutls_x509_crt cert, unsigned int* bits)
* This is specified in X509v3 Certificate Extensions.
* GNUTLS will return the Alternative name, or a negative
* error code.
+ *
* Returns GNUTLS_E_SHORT_MEMORY_BUFFER if ret_size is not enough to hold the alternative
* name, or the type of alternative name if everything was ok. The type is
* one of the enumerated gnutls_x509_subject_alt_name.
@@ -804,11 +736,12 @@ int gnutls_x509_crt_get_extension_by_oid(gnutls_x509_crt cert, const char* oid,
static
int _gnutls_x509_crt_get_raw_dn2( gnutls_x509_crt cert,
- const char* whom, gnutls_const_datum* start)
+ const char* whom, gnutls_datum* start)
{
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
int result, len1;
int start1, end1;
+ gnutls_datum signed_data;
/* get the issuer of 'cert'
*/
@@ -819,31 +752,41 @@ int _gnutls_x509_crt_get_raw_dn2( gnutls_x509_crt cert,
return _gnutls_asn2err(result);
}
- result = asn1_der_decoding(&c2, cert->signed_data.data, cert->signed_data.size, NULL);
+ result = _gnutls_x509_get_signed_data( cert->cert, "tbsCertificate", &signed_data);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = asn1_der_decoding(&c2, signed_data.data, signed_data.size, NULL);
if (result != ASN1_SUCCESS) {
/* couldn't decode DER */
gnutls_assert();
asn1_delete_structure(&c2);
- return _gnutls_asn2err(result);
+ result = _gnutls_asn2err(result);
+ goto cleanup;
}
result =
- asn1_der_decoding_startEnd(c2, cert->signed_data.data, cert->signed_data.size,
+ asn1_der_decoding_startEnd(c2, signed_data.data, signed_data.size,
whom, &start1, &end1);
- asn1_delete_structure(&c2);
if (result != ASN1_SUCCESS) {
gnutls_assert();
- return _gnutls_asn2err(result);
+ result = _gnutls_asn2err(result);
+ goto cleanup;
}
len1 = end1 - start1 + 1;
- start->data = &cert->signed_data.data[start1];
- start->size = len1;
+ _gnutls_set_datum( start, &signed_data.data[start1], len1);
- return 0;
+ result = 0;
+cleanup:
+ asn1_delete_structure(&c2);
+ _gnutls_free_datum( &signed_data);
+ return result;
}
/*-
@@ -858,7 +801,7 @@ int _gnutls_x509_crt_get_raw_dn2( gnutls_x509_crt cert,
*
-*/
int _gnutls_x509_crt_get_raw_issuer_dn( gnutls_x509_crt cert,
- gnutls_const_datum* start)
+ gnutls_datum* start)
{
return _gnutls_x509_crt_get_raw_dn2( cert, "issuer", start);
}
@@ -875,7 +818,7 @@ int _gnutls_x509_crt_get_raw_issuer_dn( gnutls_x509_crt cert,
*
-*/
int _gnutls_x509_crt_get_raw_dn( gnutls_x509_crt cert,
- gnutls_const_datum * start)
+ gnutls_datum * start)
{
return _gnutls_x509_crt_get_raw_dn2( cert, "subject", start);
}
@@ -1043,7 +986,7 @@ int gnutls_x509_crt_check_revocation(gnutls_x509_crt cert,
opaque cert_serial[64];
int serial_size, cert_serial_size;
int ncerts, ret, i, j;
- gnutls_const_datum dn1, dn2;
+ gnutls_datum dn1, dn2;
for (j = 0; j < crl_list_length; j++) { /* do for all the crls */
diff --git a/lib/x509/x509.h b/lib/x509/x509.h
index 457d835677..9ad73df8c4 100644
--- a/lib/x509/x509.h
+++ b/lib/x509/x509.h
@@ -6,18 +6,11 @@
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_crt_int {
ASN1_TYPE cert;
- gnutls_datum signed_data; /* Holds the signed data of the CRL.
- */
- gnutls_datum signature;
- gnutls_pk_algorithm signature_algorithm;
+ int use_extensions;
} gnutls_x509_crt_int;
@@ -76,21 +69,21 @@ int gnutls_x509_crt_get_pk_algorithm( gnutls_x509_crt cert, unsigned int* bits);
int _gnutls_x509_crt_cpy(gnutls_x509_crt dest, gnutls_x509_crt src);
int _gnutls_x509_crt_get_raw_issuer_dn( gnutls_x509_crt cert,
- gnutls_const_datum* start);
+ gnutls_datum* start);
int _gnutls_x509_crt_get_raw_dn( gnutls_x509_crt cert,
- gnutls_const_datum* start);
+ gnutls_datum* start);
int gnutls_x509_crt_get_serial(gnutls_x509_crt cert, char* result, size_t* result_size);
-int _gnutls_x509_compare_raw_dn(const gnutls_const_datum * dn1,
- const gnutls_const_datum * dn2);
+int _gnutls_x509_compare_raw_dn(const gnutls_datum * dn1,
+ const gnutls_datum * dn2);
int gnutls_x509_crt_check_revocation(gnutls_x509_crt cert, gnutls_x509_crl * crl_list, int crl_list_length);
int _gnutls_x509_crl_cpy(gnutls_x509_crl dest, gnutls_x509_crl src);
int _gnutls_x509_crl_get_raw_issuer_dn( gnutls_x509_crl crl,
- gnutls_const_datum* dn);
+ gnutls_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,
@@ -134,5 +127,4 @@ int gnutls_x509_privkey_export_rsa_raw(gnutls_x509_privkey key,
int gnutls_x509_privkey_export( gnutls_x509_privkey key,
gnutls_x509_crt_fmt format, unsigned char* output_data, size_t* output_data_size);
-
#endif
diff --git a/lib/x509/x509_write.c b/lib/x509/x509_write.c
index a35d4882a2..139729a54b 100644
--- a/lib/x509/x509_write.c
+++ b/lib/x509/x509_write.c
@@ -221,6 +221,59 @@ gnutls_datum der_data;
return result;
}
+ crt->use_extensions = 1;
+
+ return 0;
+}
+
+/**
+ * gnutls_x509_crt_set_subject_alt_name - This function will set the subject Alternative Name
+ * @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 subject alternative name certificate extension.
+ *
+ * On success zero is returned.
+ *
+ **/
+int gnutls_x509_crt_set_subject_alternative_name(gnutls_x509_crt crt, gnutls_x509_subject_alt_name type,
+ const char* data_string)
+{
+int result;
+gnutls_datum der_data;
+gnutls_datum dnsname;
+unsigned int critical;
+
+ /* Check if the extension already exists.
+ */
+ result = _gnutls_x509_crt_get_extension(crt, "2.5.29.17", 0, &dnsname, &critical);
+
+ if (result >= 0) _gnutls_free_datum( &dnsname);
+ if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* generate the extension.
+ */
+ result = _gnutls_x509_ext_gen_subject_alt_name( type, data_string, &der_data);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ result = _gnutls_x509_crt_set_extension( crt, "2.5.29.17", &der_data, 0);
+
+ _gnutls_free_datum( &der_data);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ crt->use_extensions = 1;
+
return 0;
}
@@ -398,22 +451,15 @@ int gnutls_x509_crt_set_serial(gnutls_x509_crt cert, const unsigned char* serial
*/
static void disable_optional_stuff( gnutls_x509_crt cert)
{
-int ret, len = 1;
-opaque tmp;
- ret = asn1_read_value( cert->cert, "tbsCertificate.issuerUniqueID", &tmp, &len);
- if (ret == ASN1_VALUE_NOT_FOUND)
- asn1_write_value( cert->cert, "tbsCertificate.issuerUniqueID", NULL, 0);
+ asn1_write_value( cert->cert, "tbsCertificate.issuerUniqueID", NULL, 0);
- len = 1;
- ret = asn1_read_value( cert->cert, "tbsCertificate.subjectUniqueID", &tmp, &len);
- if (ret == ASN1_VALUE_NOT_FOUND)
- asn1_write_value( cert->cert, "tbsCertificate.subjectUniqueID", NULL, 0);
+ asn1_write_value( cert->cert, "tbsCertificate.subjectUniqueID", NULL, 0);
- len = 1;
- ret = asn1_read_value( cert->cert, "tbsCertificate.extensions", &tmp, &len);
- if (ret == ASN1_VALUE_NOT_FOUND)
+ if (cert->use_extensions == 0) {
+ _gnutls_x509_log( "Disabling X.509 extensions.\n");
asn1_write_value( cert->cert, "tbsCertificate.extensions", NULL, 0);
+ }
return;
}