summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2003-12-26 11:42:44 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2003-12-26 11:42:44 +0000
commit647c0a87ec285f1426e512de977c7e1a94c189d6 (patch)
tree83635934c73b47c225b6efe198dfc066b5e6b5a7 /lib
parent705c60685882fb25fffcfc2c71c2e4a4eab233e0 (diff)
downloadgnutls-647c0a87ec285f1426e512de977c7e1a94c189d6.tar.gz
Added support for the Subject Key ID PKIX extension.
Diffstat (limited to 'lib')
-rw-r--r--lib/gnutls_mpi.h1
-rw-r--r--lib/pkix.asn8
-rw-r--r--lib/pkix_asn1_tab.c4
-rw-r--r--lib/x509/extensions.c58
-rw-r--r--lib/x509/extensions.h3
-rw-r--r--lib/x509/privkey.c20
-rw-r--r--lib/x509/x509.c111
-rw-r--r--lib/x509/x509.h10
-rw-r--r--lib/x509/x509_write.c63
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 */