diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-10-25 15:29:01 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-10-25 15:29:01 +0000 |
commit | 0fba2d908da6d0df821991ea5fdbeeda0f4ff089 (patch) | |
tree | 87901f6b84472227b4ad23bde4efabe462658154 | |
parent | 4a288531e874f10a0c250ca52d1cd102bce4ffa6 (diff) | |
download | gnutls-0fba2d908da6d0df821991ea5fdbeeda0f4ff089.tar.gz |
Improved the certificate generation stuff.
-rw-r--r-- | includes/gnutls/x509.h | 2 | ||||
-rw-r--r-- | lib/x509/common.c | 97 | ||||
-rw-r--r-- | lib/x509/common.h | 3 | ||||
-rw-r--r-- | lib/x509/crl.c | 139 | ||||
-rw-r--r-- | lib/x509/dn.c | 4 | ||||
-rw-r--r-- | lib/x509/extensions.c | 78 | ||||
-rw-r--r-- | lib/x509/extensions.h | 2 | ||||
-rw-r--r-- | lib/x509/mpi.c | 1 | ||||
-rw-r--r-- | lib/x509/verify.c | 148 | ||||
-rw-r--r-- | lib/x509/x509.c | 139 | ||||
-rw-r--r-- | lib/x509/x509.h | 20 | ||||
-rw-r--r-- | lib/x509/x509_write.c | 70 |
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; } |