summaryrefslogtreecommitdiff
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
parent705c60685882fb25fffcfc2c71c2e4a4eab233e0 (diff)
downloadgnutls-647c0a87ec285f1426e512de977c7e1a94c189d6.tar.gz
Added support for the Subject Key ID PKIX extension.
-rw-r--r--NEWS1
-rw-r--r--includes/gnutls/x509.h24
-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
-rw-r--r--src/certtool.c317
12 files changed, 391 insertions, 229 deletions
diff --git a/NEWS b/NEWS
index b0386aa63d..370e953722 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ Version 1.1.1
- Added PKCS #7 support to certtool utility.
- Added support for reading and generating CRL distribution
points extensions in certificates.
+- Added support for the Subject Key ID PKIX extension.
Version 1.1.0 (21/12/2003)
- The error codes GNUTLS_E_NO_TEMPORARY_DH_PARAMS and GNUTLS_E_NO_TEMPORARY_RSA_PARAMS
diff --git a/includes/gnutls/x509.h b/includes/gnutls/x509.h
index 3beda03cba..fc80f9dd5a 100644
--- a/includes/gnutls/x509.h
+++ b/includes/gnutls/x509.h
@@ -73,8 +73,25 @@ int gnutls_x509_crt_get_signature_algorithm(gnutls_x509_crt cert);
int gnutls_x509_crt_get_version(gnutls_x509_crt cert);
int gnutls_x509_crt_get_key_id( gnutls_x509_crt crt, unsigned int flags,
unsigned char* output_data, size_t* output_data_size);
+
+int gnutls_x509_crt_get_subject_key_id(gnutls_x509_crt cert, void* ret,
+ size_t* ret_size, unsigned int* critical);
+
+#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
+
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 gnutls_x509_crt_set_crl_dist_points(gnutls_x509_crt crt, gnutls_x509_subject_alt_name type,
+ const void* data_string, unsigned int reason_flags);
time_t gnutls_x509_crt_get_activation_time(gnutls_x509_crt cert);
time_t gnutls_x509_crt_get_expiration_time(gnutls_x509_crt cert);
@@ -122,9 +139,12 @@ 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);
int gnutls_x509_crt_set_expiration_time(gnutls_x509_crt cert, time_t exp_time);
-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 gnutls_x509_crt_set_subject_key_id(gnutls_x509_crt cert, const void* id,
+ size_t id_size);
+
/* RDN handling
*/
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 */
diff --git a/src/certtool.c b/src/certtool.c
index c968ce49ca..28bb34c908 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -45,7 +45,7 @@ gnutls_x509_crt load_cert(int mand);
void certificate_info( void);
void crl_info( void);
void privkey_info( void);
-static void print_certificate_info( gnutls_x509_crt crt);
+static void print_certificate_info( gnutls_x509_crt crt, FILE* out, unsigned int);
static void gaa_parser(int argc, char **argv);
void generate_self_signed( void);
void generate_request(void);
@@ -442,6 +442,18 @@ gnutls_x509_crt generate_certificate( gnutls_x509_privkey *ret_key)
fprintf(stderr, "set_version: %s\n", gnutls_strerror(result));
exit(1);
}
+
+ /* Subject Key ID.
+ */
+ size = sizeof(buffer);
+ result = gnutls_x509_crt_get_key_id(crt, 0, buffer, &size);
+ if (result >= 0) {
+ result = gnutls_x509_crt_set_subject_key_id( crt, buffer, size);
+ if (result < 0) {
+ fprintf(stderr, "set_subject_key_id: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+ }
*ret_key = key;
return crt;
@@ -491,7 +503,7 @@ void generate_self_signed( void)
crt = generate_certificate( &key);
- print_certificate_info( crt);
+ print_certificate_info( crt, stderr, 0);
fprintf(stderr, "\n\nSigning certificate...\n");
@@ -530,7 +542,7 @@ void generate_signed_certificate( void)
crt = generate_certificate( &key);
- print_certificate_info( crt);
+ print_certificate_info( crt, stderr, 0);
fprintf(stderr, "\n\nSigning certificate...\n");
@@ -697,6 +709,7 @@ static inline int known_oid( const char* oid)
if (strcmp(oid, "2.5.29.17") == 0 ||
strcmp( oid, "2.5.29.19") == 0 ||
strcmp( oid, "2.5.29.31") == 0 ||
+ strcmp( oid, "2.5.29.14") == 0 ||
strcmp( oid, "2.5.29.15") == 0)
return 1;
@@ -706,19 +719,9 @@ static inline int known_oid( const char* oid)
void certificate_info( void)
{
gnutls_x509_crt crt;
+ size_t size;
int ret;
- unsigned int i, indx, j;
- unsigned int critical, key_usage;
- time_t tim;
gnutls_datum pem;
- char serial[40];
- size_t serial_size = sizeof(serial), dn_size, size;
- char printable[256];
- char *print;
- const char* cprint;
- char dn[256];
- char oid[128] = "";
- char old_oid[128] = "";
size = fread( buffer, 1, sizeof(buffer)-1, infile);
buffer[size] = 0;
@@ -733,10 +736,28 @@ void certificate_info( void)
fprintf(stderr, "Decoding error: %s\n", gnutls_strerror(ret));
exit(1);
}
+
+ print_certificate_info( crt, outfile, 1);
+}
- fprintf(outfile, "X.509 certificate info:\n\n");
+static void print_certificate_info( gnutls_x509_crt crt, FILE* out, unsigned int all)
+{
+ int ret;
+ unsigned int i, indx, j;
+ unsigned int critical, key_usage;
+ time_t tim;
+ char serial[40];
+ size_t serial_size = sizeof(serial), dn_size, size;
+ char printable[256];
+ char *print;
+ const char* cprint;
+ char dn[256];
+ char oid[128] = "";
+ char old_oid[128] = "";
+
+ fprintf( out, "\n\nX.509 certificate info:\n\n");
- fprintf(outfile, "Version: %d\n", gnutls_x509_crt_get_version(crt));
+ fprintf(out, "Version: %d\n", gnutls_x509_crt_get_version(crt));
/* serial number
*/
@@ -747,82 +768,83 @@ void certificate_info( void)
(unsigned char) serial[i]);
print += 3;
}
- fprintf(outfile, "Serial Number (hex): %s\n", printable);
+ fprintf(out, "Serial Number (hex): %s\n", printable);
}
-
-
- /* Issuer
+ /* Subject
*/
dn_size = sizeof(dn);
-
- ret = gnutls_x509_crt_get_issuer_dn(crt, dn, &dn_size);
+ ret = gnutls_x509_crt_get_dn(crt, dn, &dn_size);
if (ret >= 0)
- fprintf(outfile, "Issuer: %s\n", dn);
+ fprintf(out, "Subject: %s\n", dn);
- fprintf(outfile, "Signature Algorithm: ");
- ret = gnutls_x509_crt_get_signature_algorithm(crt);
+ /* Issuer
+ */
+ if (all) {
+ dn_size = sizeof(dn);
+ ret = gnutls_x509_crt_get_issuer_dn(crt, dn, &dn_size);
+ if (ret >= 0)
+ fprintf(out, "Issuer: %s\n", dn);
- cprint = get_algorithm( ret);
- fprintf(outfile, "%s\n", cprint);
+
+ /* signature algorithm
+ */
+ fprintf(out, "Signature Algorithm: ");
+ ret = gnutls_x509_crt_get_signature_algorithm(crt);
+
+ cprint = get_algorithm( ret);
+ fprintf(out, "%s\n", cprint);
+ }
/* Validity
*/
- fprintf(outfile, "Validity:\n");
+ fprintf(out, "Validity:\n");
tim = gnutls_x509_crt_get_activation_time(crt);
- fprintf(outfile, "\tNot Before: %s", ctime(&tim));
+ fprintf(out, "\tNot Before: %s", ctime(&tim));
tim = gnutls_x509_crt_get_expiration_time(crt);
- fprintf(outfile, "\tNot After: %s", ctime(&tim));
-
- /* Subject
- */
- dn_size = sizeof(dn);
- ret = gnutls_x509_crt_get_dn(crt, dn, &dn_size);
- if (ret >= 0)
- fprintf(outfile, "Subject: %s\n", dn);
+ fprintf(out, "\tNot After: %s", ctime(&tim));
/* Public key algorithm
*/
- fprintf(outfile, "Subject Public Key Info:\n");
+ fprintf(out, "Subject Public Key Info:\n");
ret = gnutls_x509_crt_get_pk_algorithm(crt, NULL);
- fprintf(outfile, "\tPublic Key Algorithm: ");
+ fprintf(out, "\tPublic Key Algorithm: ");
cprint = get_algorithm( ret);
- fprintf(outfile, "%s\n", cprint);
+ fprintf(out, "%s\n", cprint);
- fprintf(outfile, "\nX.509 Extensions:\n");
+ fprintf(out, "\nX.509 Extensions:\n");
/* subject alternative name
*/
- ret = 0;
for (i = 0; !(ret < 0); i++) {
size = sizeof(buffer);
ret = gnutls_x509_crt_get_subject_alt_name(crt, i, buffer, &size, &critical);
if (i==0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
- fprintf(outfile, "\tSubject Alternative name:");
- if (critical) fprintf(outfile, " (critical)");
- fprintf(outfile, "\n");
+ fprintf(out, "\tSubject Alternative name:");
+ if (critical) fprintf(out, " (critical)");
+ fprintf(out, "\n");
}
if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
- fprintf(outfile, "\t\tFound unsupported alternative name.\n");
+ fprintf(out, "\t\tFound unsupported alternative name.\n");
} else switch (ret) {
case GNUTLS_SAN_DNSNAME:
- fprintf(outfile, "\t\tDNSname: %s\n", buffer);
+ fprintf(out, "\t\tDNSname: %s\n", buffer);
break;
case GNUTLS_SAN_RFC822NAME:
- fprintf(outfile, "\t\tRFC822name: %s\n", buffer);
+ fprintf(out, "\t\tRFC822name: %s\n", buffer);
break;
case GNUTLS_SAN_URI:
- fprintf(outfile, "\t\tURI: %s\n", buffer);
+ fprintf(out, "\t\tURI: %s\n", buffer);
break;
case GNUTLS_SAN_IPADDRESS:
- fprintf(outfile, "\t\tIPAddress: %s\n", buffer);
+ fprintf(out, "\t\tIPAddress: %s\n", buffer);
break;
}
}
@@ -832,7 +854,7 @@ void certificate_info( void)
ret = 0;
for (i = 0; !(ret < 0); i++) {
size = sizeof(buffer);
- ret = gnutls_x509_crt_get_crl_dist_points(crt, i, buffer, &size, &critical);
+ ret = gnutls_x509_crt_get_crl_dist_points(crt, i, buffer, &size, NULL, &critical);
if (i==0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
fprintf(outfile, "\tCRL Distribution points:");
@@ -841,7 +863,7 @@ void certificate_info( void)
}
if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
- fprintf(outfile, "\t\tFound unsupported name.\n");
+ fprintf(outfile, "\t\tError decoding: %s\n", gnutls_strerror(ret));
} else switch (ret) {
case GNUTLS_SAN_DNSNAME:
fprintf(outfile, "\t\tDNSname: %s\n", buffer);
@@ -863,12 +885,12 @@ void certificate_info( void)
ret = gnutls_x509_crt_get_ca_status( crt, &critical);
if (ret >= 0) {
- fprintf(outfile, "\tBasic Constraints:");
- if (critical) fprintf(outfile, " (critical)");
- fprintf(outfile, "\n");
+ fprintf(out, "\tBasic Constraints:");
+ if (critical) fprintf(out, " (critical)");
+ fprintf(out, "\n");
- if (ret==0) fprintf(outfile, "\t\tCA:FALSE\n");
- else fprintf(outfile, "\t\tCA:TRUE\n");
+ if (ret==0) fprintf(out, "\t\tCA:FALSE\n");
+ else fprintf(out, "\t\tCA:TRUE\n");
}
@@ -877,10 +899,31 @@ void certificate_info( void)
ret = gnutls_x509_crt_get_key_usage( crt, &key_usage, &critical);
if (ret >= 0) {
- fprintf(outfile, "\tKey usage:\n");
+ fprintf(out, "\tKey usage: %s\n", critical?"(critical)":"");
print_key_usage(key_usage);
}
+ /* Subject Key ID
+ */
+ size = sizeof(buffer);
+ ret = gnutls_x509_crt_get_subject_key_id(crt, buffer, &size, &critical);
+
+ if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+ {
+ const char* str = gnutls_strerror(ret);
+ if (str == NULL) str = "unknown error";
+ fprintf(out, "Error getting subject key id: %s\n", str);
+ }
+
+ if (ret >= 0) {
+ print = printable;
+ for (i = 0; i < size; i++) {
+ sprintf(print, "%.2x ", (unsigned char) buffer[i]);
+ print += 3;
+ }
+ fprintf(out, "\tSubject Key ID: %s\n\t\t%s\n", critical?"(critical)":"", printable);
+ }
+
/* other extensions:
*/
indx = 0;
@@ -899,22 +942,22 @@ void certificate_info( void)
indx = 0;
}
- fprintf( outfile, "\t%s: ", oid);
+ fprintf( out, "\t%s: ", oid);
size = sizeof(buffer);
ret = gnutls_x509_crt_get_extension_by_oid( crt, oid, indx, buffer, &size, &critical);
if (ret >= 0) {
if (critical)
- fprintf(outfile, "(critical)\n");
+ fprintf(out, "(critical)\n");
else
- fprintf(outfile, "\n");
+ fprintf(out, "\n");
print = printable;
for (j = 0; j < size; j++) {
sprintf(print, "%.2x", (unsigned char) buffer[j]);
print += 2;
}
- fprintf(outfile, "\t\tDER Data: %s\n", printable);
+ fprintf(out, "\t\tDER Data: %s\n", printable);
}
@@ -924,21 +967,25 @@ void certificate_info( void)
}
+
/* fingerprint
*/
- size = sizeof(buffer);
- if ((ret=gnutls_x509_crt_get_fingerprint(crt, GNUTLS_DIG_MD5, buffer, &size)) < 0)
- {
- const char* str = gnutls_strerror(ret);
- if (str == NULL) str = "unknown error";
- fprintf(stderr, "Error in fingerprint calculation: %s\n", str);
- } else {
- print = printable;
- for (i = 0; i < size; i++) {
- sprintf(print, "%.2x ", (unsigned char) buffer[i]);
- print += 3;
+ fprintf( out, "\nOther information:\n");
+ if (all) {
+ size = sizeof(buffer);
+ if ((ret=gnutls_x509_crt_get_fingerprint(crt, GNUTLS_DIG_MD5, buffer, &size)) < 0)
+ {
+ const char* str = gnutls_strerror(ret);
+ if (str == NULL) str = "unknown error";
+ fprintf(out, "Error in fingerprint calculation: %s\n", str);
+ } else {
+ print = printable;
+ for (i = 0; i < size; i++) {
+ sprintf(print, "%.2x ", (unsigned char) buffer[i]);
+ print += 3;
+ }
+ fprintf(out, "\tFingerprint: %s\n", printable);
}
- fprintf(outfile, "\nFingerprint: %s\n", printable);
}
size = sizeof(buffer);
@@ -946,133 +993,19 @@ void certificate_info( void)
{
const char* str = gnutls_strerror(ret);
if (str == NULL) str = "unknown error";
- fprintf(stderr, "Error in key id calculation: %s\n", str);
+ fprintf(out, "Error in key id calculation: %s\n", str);
} else {
print = printable;
for (i = 0; i < size; i++) {
sprintf(print, "%.2x ", (unsigned char) buffer[i]);
print += 3;
}
- fprintf(outfile, "Public Key ID: %s\n", printable);
- }
-
- fprintf(outfile, "\n");
-}
-
-static void print_certificate_info( gnutls_x509_crt crt)
-{
- int ret;
- unsigned int i;
- unsigned int critical, key_usage;
- time_t tim;
- char serial[40];
- size_t serial_size = sizeof(serial), dn_size, size;
- char printable[256];
- char *print;
- const char* cprint;
- char dn[256];
-
- fprintf( stderr, "\n\nX.509 certificate info:\n\n");
-
- fprintf(stderr, "Version: %d\n", gnutls_x509_crt_get_version(crt));
-
- /* serial number
- */
- if (gnutls_x509_crt_get_serial(crt, serial, &serial_size) >= 0) {
- print = printable;
- for (i = 0; i < serial_size; i++) {
- sprintf(print, "%.2x ",
- (unsigned char) serial[i]);
- print += 3;
- }
- fprintf(stderr, "Serial Number (hex): %s\n", printable);
- }
-
- /* Validity
- */
- fprintf(stderr, "Validity:\n");
-
- tim = gnutls_x509_crt_get_activation_time(crt);
- fprintf(stderr, "\tNot Before: %s", ctime(&tim));
-
- tim = gnutls_x509_crt_get_expiration_time(crt);
- fprintf(stderr, "\tNot After: %s", ctime(&tim));
-
- /* Subject
- */
- dn_size = sizeof(dn);
- ret = gnutls_x509_crt_get_dn(crt, dn, &dn_size);
- if (ret >= 0)
- fprintf(stderr, "Subject: %s\n", dn);
-
- /* Public key algorithm
- */
- fprintf(stderr, "Subject Public Key Info:\n");
- ret = gnutls_x509_crt_get_pk_algorithm(crt, NULL);
- fprintf(stderr, "\tPublic Key Algorithm: ");
-
- cprint = get_algorithm( ret);
- fprintf(stderr, "%s\n", cprint);
-
-
-
- fprintf(stderr, "\nX.509 Extensions:\n");
-
- /* subject alternative name
- */
- for (i = 0; !(ret < 0); i++) {
- size = sizeof(buffer);
- ret = gnutls_x509_crt_get_subject_alt_name(crt, i, buffer, &size, &critical);
-
- if (i==0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
- fprintf(stderr, "\tSubject Alternative name:");
- if (critical) fprintf(stderr, " (critical)");
- fprintf(stderr, "\n");
- }
-
- if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
- fprintf(stderr, "\t\tFound unsupported alternative name.\n");
- } else switch (ret) {
- case GNUTLS_SAN_DNSNAME:
- fprintf(stderr, "\t\tDNSname: %s\n", buffer);
- break;
- case GNUTLS_SAN_RFC822NAME:
- fprintf(stderr, "\t\tRFC822name: %s\n", buffer);
- break;
- case GNUTLS_SAN_URI:
- fprintf(stderr, "\t\tURI: %s\n", buffer);
- break;
- case GNUTLS_SAN_IPADDRESS:
- fprintf(stderr, "\t\tIPAddress: %s\n", buffer);
- break;
- }
- }
-
- /* check for basicConstraints
- */
- ret = gnutls_x509_crt_get_ca_status( crt, &critical);
-
- if (ret >= 0) {
- fprintf(stderr, "\tBasic Constraints:");
- if (critical) fprintf(stderr, " (critical)");
- fprintf(stderr, "\n");
-
- if (ret==0) fprintf(stderr, "\t\tCA:FALSE\n");
- else fprintf(stderr, "\t\tCA:TRUE\n");
-
- }
-
- /* Key Usage.
- */
- ret = gnutls_x509_crt_get_key_usage( crt, &key_usage, &critical);
-
- if (ret >= 0) {
- fprintf(stderr, "\tKey usage: %s\n", critical?"(critical)":"");
- print_key_usage(key_usage);
+ fprintf(out, "\tPublic Key ID: %s\n", printable);
}
- fprintf(stderr, "\n");
+ fprintf(out, "\n");
+ if (out==stderr) /* interactive */
if (read_yesno( "Is the above information ok? (Y/N): ")==0) {
exit(1);
}