diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gnutls_mpi.h | 1 | ||||
-rw-r--r-- | lib/pkix.asn | 8 | ||||
-rw-r--r-- | lib/pkix_asn1_tab.c | 4 | ||||
-rw-r--r-- | lib/x509/extensions.c | 58 | ||||
-rw-r--r-- | lib/x509/extensions.h | 3 | ||||
-rw-r--r-- | lib/x509/privkey.c | 20 | ||||
-rw-r--r-- | lib/x509/x509.c | 111 | ||||
-rw-r--r-- | lib/x509/x509.h | 10 | ||||
-rw-r--r-- | lib/x509/x509_write.c | 63 |
9 files changed, 243 insertions, 35 deletions
diff --git a/lib/gnutls_mpi.h b/lib/gnutls_mpi.h index 048a10458b..0eafd16c97 100644 --- a/lib/gnutls_mpi.h +++ b/lib/gnutls_mpi.h @@ -28,6 +28,7 @@ #define _gnutls_mpi_mul_ui gcry_mpi_mul_ui # define _gnutls_mpi_alloc_like(x) _gnutls_mpi_new(_gnutls_mpi_get_nbits(x)) +# define _gnutls_mpi_salloc_like(x) _gnutls_mpi_snew(_gnutls_mpi_get_nbits(x)) void _gnutls_mpi_release( GNUTLS_MPI* x); diff --git a/lib/pkix.asn b/lib/pkix.asn index 446f5b5455..37e18060f0 100644 --- a/lib/pkix.asn +++ b/lib/pkix.asn @@ -208,10 +208,6 @@ WriteableDistributionPointName ::= CHOICE { fullName [0] ANY, nameRelativeToCRLIssuer [1] RelativeDistinguishedName } - - - - ReasonFlags ::= BIT STRING { unused (0), keyCompromise (1), @@ -219,7 +215,9 @@ ReasonFlags ::= BIT STRING { affiliationChanged (3), superseded (4), cessationOfOperation (5), - certificateHold (6) } + certificateHold (6), + privilegeWithdrawn (7), + aACompromise (8) } -- extended key usage extension OID and syntax diff --git a/lib/pkix_asn1_tab.c b/lib/pkix_asn1_tab.c index c773aba042..0da13f9504 100644 --- a/lib/pkix_asn1_tab.c +++ b/lib/pkix_asn1_tab.c @@ -208,7 +208,9 @@ const ASN1_ARRAY_TYPE pkix_asn1_tab[]={ {"affiliationChanged",1073741825,"3"}, {"superseded",1073741825,"4"}, {"cessationOfOperation",1073741825,"5"}, - {"certificateHold",1,"6"}, + {"certificateHold",1073741825,"6"}, + {"privilegeWithdrawn",1073741825,"7"}, + {"aACompromise",1,"8"}, {"id-ce-extKeyUsage",1879048204,0}, {0,1073741825,"id-ce"}, {0,1,"37"}, diff --git a/lib/x509/extensions.c b/lib/x509/extensions.c index e639e61d0c..c4dbfe4a6d 100644 --- a/lib/x509/extensions.c +++ b/lib/x509/extensions.c @@ -566,12 +566,49 @@ int _gnutls_x509_ext_gen_subject_alt_name(gnutls_x509_subject_alt_name type, return 0; } +/* generate the SubjectKeyID in a DER encoded extension + */ +int _gnutls_x509_ext_gen_key_id(const void* id, size_t id_size, gnutls_datum* der_ext) +{ + ASN1_TYPE ext = ASN1_TYPE_EMPTY; + int result; + + result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.SubjectKeyIdentifier", &ext); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + result = asn1_write_value(ext, "", id, id_size); + 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; +} + + int _gnutls_x509_ext_gen_crl_dist_points(gnutls_x509_subject_alt_name type, - const char* data_string, gnutls_datum* der_ext) + const void* data_string, unsigned int reason_flags, gnutls_datum* der_ext) { ASN1_TYPE ext = ASN1_TYPE_EMPTY; gnutls_datum name = {NULL, 0}; int result; + uint8 reasons[2]; + + reasons[0] = reason_flags & 0xff; + reasons[1] = reason_flags >> 8; result = _gnutls_x509_ext_gen_subject_alt_name( type, data_string, &name); if (result < 0) { @@ -593,11 +630,20 @@ int _gnutls_x509_ext_gen_crl_dist_points(gnutls_x509_subject_alt_name type, goto cleanup; } - result = asn1_write_value( ext, "?LAST.reasons", NULL, 0); - if (result != ASN1_SUCCESS) { - gnutls_assert(); - result = _gnutls_asn2err(result); - goto cleanup; + if (reason_flags) { + result = asn1_write_value( ext, "?LAST.reasons", reasons, 9); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + } else { + 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); diff --git a/lib/x509/extensions.h b/lib/x509/extensions.h index 7b90d452ee..ce2e70a67b 100644 --- a/lib/x509/extensions.h +++ b/lib/x509/extensions.h @@ -14,4 +14,5 @@ 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); + const void* data_string, unsigned int reason_flags, gnutls_datum* der_ext); +int _gnutls_x509_ext_gen_key_id( const void* id, size_t id_size, gnutls_datum* der_data); diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index 8550026798..930640d6e1 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -823,28 +823,28 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params) /* Now generate exp1 and exp2 */ - exp1 = _gnutls_mpi_alloc_like( params[0]); /* like modulus */ + exp1 = _gnutls_mpi_salloc_like( params[0]); /* like modulus */ if (exp1 == NULL) { gnutls_assert(); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } - exp2 = _gnutls_mpi_alloc_like( params[0]); + exp2 = _gnutls_mpi_salloc_like( params[0]); if (exp2 == NULL) { gnutls_assert(); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } - q1 = _gnutls_mpi_alloc_like( params[4]); + q1 = _gnutls_mpi_salloc_like( params[4]); if (q1 == NULL) { gnutls_assert(); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } - p1 = _gnutls_mpi_alloc_like( params[3]); + p1 = _gnutls_mpi_salloc_like( params[3]); if (p1 == NULL) { gnutls_assert(); result = GNUTLS_E_MEMORY_ERROR; @@ -868,7 +868,7 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params) /* Encoding phase. * allocate data enough to hold everything */ - all_data = gnutls_alloca( total); + all_data = gnutls_secure_malloc( total); if (all_data == NULL) { gnutls_assert(); result = GNUTLS_E_MEMORY_ERROR; @@ -971,7 +971,7 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params) goto cleanup; } - gnutls_afree(all_data); + gnutls_free(all_data); if ((result = asn1_write_value(*c2, "otherPrimeInfos", NULL, 0)) != ASN1_SUCCESS) { @@ -995,7 +995,7 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params) _gnutls_mpi_release( &q1); _gnutls_mpi_release( &p1); asn1_delete_structure(c2); - gnutls_afree( all_data); + gnutls_free( all_data); return result; } @@ -1020,7 +1020,7 @@ static int _encode_dsa( ASN1_TYPE* c2, GNUTLS_MPI* params) /* Encoding phase. * allocate data enough to hold everything */ - all_data = gnutls_alloca( total); + all_data = gnutls_secure_malloc( total); if (all_data == NULL) { gnutls_assert(); result = GNUTLS_E_MEMORY_ERROR; @@ -1093,7 +1093,7 @@ static int _encode_dsa( ASN1_TYPE* c2, GNUTLS_MPI* params) goto cleanup; } - gnutls_afree(all_data); + gnutls_free(all_data); if ((result = asn1_write_value(*c2, "version", &null, 1)) != ASN1_SUCCESS) { @@ -1106,7 +1106,7 @@ static int _encode_dsa( ASN1_TYPE* c2, GNUTLS_MPI* params) cleanup: asn1_delete_structure(c2); - gnutls_afree( all_data); + gnutls_free( all_data); return result; } diff --git a/lib/x509/x509.c b/lib/x509/x509.c index e2f30adb1a..c7f546a7b1 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -537,7 +537,82 @@ int gnutls_x509_crt_get_serial(gnutls_x509_crt cert, void* result, } return 0; +} + +/** + * gnutls_x509_crt_get_subject_key_id - This function returns the certificate's key identifier + * @cert: should contain a gnutls_x509_crt structure + * @result: The place where the identifier will be copied + * @result_size: Holds the size of the result field. + * @critical: will be non zero if the extension is marked as critical (may be null) + * + * This function will return the X.509v3 certificate's subject key identifier. + * This is obtained by the X.509 Subject Key identifier extension + * field (2.5.29.14). + * + * Returns 0 on success and a negative value in case of an error. + * + **/ +int gnutls_x509_crt_get_subject_key_id(gnutls_x509_crt cert, void* ret, + size_t* ret_size, unsigned int* critical) +{ + int result, len; + gnutls_datum id; + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; + + if (cert==NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + + if (ret) memset(ret, 0, *ret_size); + else *ret_size = 0; + + if ((result = + _gnutls_x509_crt_get_extension(cert, "2.5.29.14", 0, &id, critical)) < 0) { + return result; + } + + if (id.size == 0 || id.data==NULL) { + gnutls_assert(); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + result=asn1_create_element + (_gnutls_get_pkix(), "PKIX1.SubjectKeyIdentifier", &c2); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + _gnutls_free_datum( &id); + return _gnutls_asn2err(result); + } + + result = asn1_der_decoding(&c2, id.data, id.size, NULL); + _gnutls_free_datum( &id); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + asn1_delete_structure(&c2); + return _gnutls_asn2err(result); + } + + len = *ret_size; + result = + asn1_read_value(c2, "", ret, &len); + + *ret_size = len; + asn1_delete_structure(&c2); + + if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND) { + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + if (result != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + return 0; } /** @@ -643,9 +718,6 @@ int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt cert, _gnutls_free_datum( &dnsname); 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); @@ -922,7 +994,6 @@ int _gnutls_x509_crt_get_raw_dn2( gnutls_x509_crt cert, 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); result = _gnutls_asn2err(result); @@ -1310,6 +1381,7 @@ int result; * @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. + * @reason_flags: Revocation reasons flags. * @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 @@ -1327,7 +1399,8 @@ int result; * **/ int gnutls_x509_crt_get_crl_dist_points(gnutls_x509_crt cert, - unsigned int seq, void *ret, size_t *ret_size, unsigned int *critical) + unsigned int seq, void *ret, size_t *ret_size, + unsigned int* reason_flags, unsigned int *critical) { int result; gnutls_datum dist_points = {NULL, 0}; @@ -1337,6 +1410,7 @@ int gnutls_x509_crt_get_crl_dist_points(gnutls_x509_crt cert, int len; char num[MAX_INT_DIGITS]; gnutls_x509_subject_alt_name type; + uint8 reasons[2]; if (cert==NULL) { gnutls_assert(); @@ -1345,6 +1419,8 @@ int gnutls_x509_crt_get_crl_dist_points(gnutls_x509_crt cert, if (ret) memset(ret, 0, *ret_size); else *ret_size = 0; + + if (reason_flags) *reason_flags = 0; result = _gnutls_x509_crt_get_extension(cert, "2.5.29.31", 0, &dist_points, critical); @@ -1370,9 +1446,6 @@ int gnutls_x509_crt_get_crl_dist_points(gnutls_x509_crt cert, _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); @@ -1399,6 +1472,28 @@ int gnutls_x509_crt_get_crl_dist_points(gnutls_x509_crt cert, return _gnutls_asn2err(result); } + + /* Read the CRL reasons. + */ + if (reason_flags) { + _gnutls_str_cpy( name, sizeof(name), "dn.?"); + _gnutls_str_cat( name, sizeof(name), num); + _gnutls_str_cat( name, sizeof(name), ".reasons"); + + len = sizeof(reasons); + result = + asn1_read_value(c2, name, reasons, &len); + + if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { + gnutls_assert(); + asn1_delete_structure(&c2); + return _gnutls_asn2err(result); + } + + *reason_flags = reasons[0] | (reasons[1] << 8); + } + + type = _gnutls_x509_san_find_type( ext_data); if (type == (gnutls_x509_subject_alt_name)-1) { asn1_delete_structure(&c2); diff --git a/lib/x509/x509.h b/lib/x509/x509.h index 72e66c21ed..7a56b63fac 100644 --- a/lib/x509/x509.h +++ b/lib/x509/x509.h @@ -127,4 +127,14 @@ 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, void* output_data, size_t* output_data_size); +#define GNUTLS_CRL_REASON_UNUSED 128 +#define GNUTLS_CRL_REASON_KEY_COMPROMISE 64 +#define GNUTLS_CRL_REASON_CA_COMPROMISE 32 +#define GNUTLS_CRL_REASON_AFFILIATION_CHANGED 16 +#define GNUTLS_CRL_REASON_SUPERSEEDED 8 +#define GNUTLS_CRL_REASON_CESSATION_OF_OPERATION 4 +#define GNUTLS_CRL_REASON_CERTIFICATE_HOLD 2 +#define GNUTLS_CRL_REASON_PRIVILEGE_WITHDRAWN 1 +#define GNUTLS_CRL_REASON_AA_COMPROMISE 32768 + #endif diff --git a/lib/x509/x509_write.c b/lib/x509/x509_write.c index 4ab52ade99..403d9997b5 100644 --- a/lib/x509/x509_write.c +++ b/lib/x509/x509_write.c @@ -513,7 +513,7 @@ int gnutls_x509_crt_set_expiration_time(gnutls_x509_crt cert, time_t exp_time) * gnutls_x509_crt_set_serial - This function will set the certificate's serial number * @cert: should contain a gnutls_x509_crt structure * @serial: The serial number - * @result_size: Holds the size of the serial field. + * @serial_size: Holds the size of the serial field. * * This function will set the X.509 certificate's serial number. * Serial is not always a 32 or 64bit number. Some CAs use @@ -523,7 +523,7 @@ int gnutls_x509_crt_set_expiration_time(gnutls_x509_crt cert, time_t exp_time) * Returns 0 on success, or a negative value in case of an error. * **/ -int gnutls_x509_crt_set_serial(gnutls_x509_crt cert, const unsigned char* serial, +int gnutls_x509_crt_set_serial(gnutls_x509_crt cert, const void* serial, size_t serial_size) { int ret; @@ -566,6 +566,7 @@ static void disable_optional_stuff( gnutls_x509_crt cert) * @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 + * @reason_flags: revocation reasons * * This function will set the CRL distribution points certificate extension. * @@ -573,7 +574,7 @@ static void disable_optional_stuff( gnutls_x509_crt cert) * **/ int gnutls_x509_crt_set_crl_dist_points(gnutls_x509_crt crt, gnutls_x509_subject_alt_name type, - const char* data_string) + const void* data_string, unsigned int reason_flags) { int result; gnutls_datum der_data; @@ -597,7 +598,7 @@ unsigned int critical; /* generate the extension. */ - result = _gnutls_x509_ext_gen_crl_dist_points( type, data_string, &der_data); + result = _gnutls_x509_ext_gen_crl_dist_points( type, data_string, reason_flags, &der_data); if (result < 0) { gnutls_assert(); return result; @@ -617,5 +618,59 @@ unsigned int critical; return 0; } +/** + * gnutls_x509_crt_set_subject_key_id - This function will set the certificate's subject key id + * @cert: should contain a gnutls_x509_crt structure + * @id: The key ID + * @id_size: Holds the size of the serial field. + * + * This function will set the X.509 certificate's subject key ID extension. + * + * Returns 0 on success, or a negative value in case of an error. + * + **/ +int gnutls_x509_crt_set_subject_key_id(gnutls_x509_crt cert, const void* id, + size_t id_size) +{ + int result; + gnutls_datum old_id, der_data; + unsigned int critical; + + if (cert==NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + /* Check if the extension already exists. + */ + result = _gnutls_x509_crt_get_extension(cert, "2.5.29.14", 0, &old_id, &critical); + + if (result >= 0) _gnutls_free_datum( &old_id); + if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + /* generate the extension. + */ + result = _gnutls_x509_ext_gen_key_id( id, id_size, &der_data); + if (result < 0) { + gnutls_assert(); + return result; + } + + result = _gnutls_x509_crt_set_extension( cert, "2.5.29.14", &der_data, 0); + + _gnutls_free_datum( &der_data); + + if (result < 0) { + gnutls_assert(); + return result; + } + + cert->use_extensions = 1; + + return 0; +} #endif /* ENABLE_PKI */ |