summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2004-02-10 20:03:26 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2004-02-10 20:03:26 +0000
commitc05ec8d781434991a800bb6d626638151c62ddb6 (patch)
tree01610a2e5b9477ce1c393dfa5fab62a52b0d9900
parent773197f2b0320f0097325a60ff19c29187c67a33 (diff)
downloadgnutls-c05ec8d781434991a800bb6d626638151c62ddb6.tar.gz
Backported several things from the development branch.
-rw-r--r--NEWS12
-rw-r--r--configure.in4
-rw-r--r--includes/gnutls/x509.h88
-rw-r--r--lib/Makefile.am3
-rw-r--r--lib/gnutls.h.in.in5
-rw-r--r--lib/gnutls_cipher.c6
-rw-r--r--lib/gnutls_errors.c1
-rw-r--r--lib/gnutls_errors_int.h1
-rw-r--r--lib/gnutls_hash_int.c2
-rw-r--r--lib/gnutls_int.h5
-rw-r--r--lib/gnutls_mpi.h1
-rw-r--r--lib/gnutls_rsa_export.c4
-rw-r--r--lib/gnutls_rsa_export.h2
-rw-r--r--lib/gnutls_ui.h17
-rw-r--r--lib/rsa_compat.c4
-rw-r--r--lib/x509/Makefile.am4
-rw-r--r--lib/x509/common.c171
-rw-r--r--lib/x509/common.h15
-rw-r--r--lib/x509/crl.c16
-rw-r--r--lib/x509/crl_write.c259
-rw-r--r--lib/x509/crq.c49
-rw-r--r--lib/x509/dn.c11
-rw-r--r--lib/x509/extensions.c215
-rw-r--r--lib/x509/extensions.h4
-rw-r--r--lib/x509/mpi.c117
-rw-r--r--lib/x509/mpi.h6
-rw-r--r--lib/x509/pkcs12.c6
-rw-r--r--lib/x509/pkcs12_bag.c1
-rw-r--r--lib/x509/pkcs12_encr.c5
-rw-r--r--lib/x509/pkcs5.c1
-rw-r--r--lib/x509/pkcs7.c2
-rw-r--r--lib/x509/privkey.c362
-rw-r--r--lib/x509/privkey_pkcs8.c5
-rw-r--r--lib/x509/rc2.c1
-rw-r--r--lib/x509/rfc2818_hostname.c86
-rw-r--r--lib/x509/sign.c116
-rw-r--r--lib/x509/sign.h2
-rw-r--r--lib/x509/verify.c31
-rw-r--r--lib/x509/x509.c347
-rw-r--r--lib/x509/x509.h12
-rw-r--r--lib/x509/x509_write.c309
-rw-r--r--lib/x509/xml.c3
-rw-r--r--src/certtool-gaa.c189
-rw-r--r--src/certtool-gaa.h30
-rw-r--r--src/certtool.c965
-rw-r--r--src/certtool.gaa9
46 files changed, 2695 insertions, 809 deletions
diff --git a/NEWS b/NEWS
index 579846612e..4c78bb6c1e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,15 @@
+Version 1.0.5
+- Backported several things from the development branch:
+ - Added CRL verification functionality to certtool.
+ - Corrected the CRL distribution point extension handling.
+ - Added PKCS #7 support to certtool utility.
+ - Added support for reading and generating CRL distribution
+ points extensions in certificates.
+ - Added support for generating CRLs in the library and the
+ certtool utility.
+ - Added support for the Subject Key ID PKIX extension.
+ - Added the gnutls_sign_algorithm type.
+
Version 1.0.4 (04/01/2004)
- Changed handshake behaviour to send the lowest TLS version
when an unsupported version was advertized. The current behaviour
diff --git a/configure.in b/configure.in
index 9fbd912986..bbe8347829 100644
--- a/configure.in
+++ b/configure.in
@@ -12,7 +12,7 @@ AC_DEFINE_UNQUOTED(T_OS, "$target_os", [OS name])
dnl Gnutls Version
GNUTLS_MAJOR_VERSION=1
GNUTLS_MINOR_VERSION=0
-GNUTLS_MICRO_VERSION=4
+GNUTLS_MICRO_VERSION=5
GNUTLS_VERSION=$GNUTLS_MAJOR_VERSION.$GNUTLS_MINOR_VERSION.$GNUTLS_MICRO_VERSION
AC_DEFINE_UNQUOTED(GNUTLS_VERSION, "$GNUTLS_VERSION", [version of gnutls])
@@ -28,7 +28,7 @@ AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
dnl This is the library version
-GNUTLS_MOST_RECENT_INTERFACE=11
+GNUTLS_MOST_RECENT_INTERFACE=12
GNUTLS_CURRENT_INTERFACE_IMPLEMENTATION_NUMBER=$GNUTLS_MICRO_VERSION
GNUTLS_OLDEST_INTERFACE=10
diff --git a/includes/gnutls/x509.h b/includes/gnutls/x509.h
index bdc7a9f0c7..ab8346d3c9 100644
--- a/includes/gnutls/x509.h
+++ b/includes/gnutls/x509.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -32,7 +33,8 @@ extern "C" {
#include <gnutls/gnutls.h>
-/* Some OIDs usually found in Distinguished names
+/* Some OIDs usually found in Distinguished names, or
+ * in Subject Directory Attribute extensions.
*/
#define GNUTLS_OID_X520_COUNTRY_NAME "2.5.4.6"
#define GNUTLS_OID_X520_ORGANIZATION_NAME "2.5.4.10"
@@ -40,6 +42,21 @@ extern "C" {
#define GNUTLS_OID_X520_COMMON_NAME "2.5.4.3"
#define GNUTLS_OID_X520_LOCALITY_NAME "2.5.4.7"
#define GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME "2.5.4.8"
+
+#define GNUTLS_OID_X520_INITIALS "2.5.4.43"
+#define GNUTLS_OID_X520_GENERATION_QUALIFIER "2.5.4.44"
+#define GNUTLS_OID_X520_SURNAME "2.5.4.4"
+#define GNUTLS_OID_X520_GIVEN_NAME "2.5.4.42"
+#define GNUTLS_OID_X520_TITLE "2.5.4.12"
+#define GNUTLS_OID_X520_DN_QUALIFIER "2.5.4.46"
+#define GNUTLS_OID_X520_PSEUDONYM "2.5.4.65"
+
+#define GNUTLS_OID_PKIX_DATE_OF_BIRTH "1.3.6.1.5.5.7.9.1"
+#define GNUTLS_OID_PKIX_PLACE_OF_BIRTH "1.3.6.1.5.5.7.9.2"
+#define GNUTLS_OID_PKIX_GENDER "1.3.6.1.5.5.7.9.3"
+#define GNUTLS_OID_PKIX_COUNTRY_OF_CITIZENSHIP "1.3.6.1.5.5.7.9.4"
+#define GNUTLS_OID_PKIX_COUNTRY_OF_RESIDENCE "1.3.6.1.5.5.7.9.5"
+
#define GNUTLS_OID_LDAP_DC "0.9.2342.19200300.100.1.25"
#define GNUTLS_OID_LDAP_UID "0.9.2342.19200300.100.1.1"
#define GNUTLS_OID_PKCS9_EMAIL "1.2.840.113549.1.9.1"
@@ -74,6 +91,26 @@ 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* 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);
+int gnutls_x509_crt_cpy_crl_dist_points(gnutls_x509_crt dst,
+ gnutls_x509_crt src);
time_t gnutls_x509_crt_get_activation_time(gnutls_x509_crt cert);
time_t gnutls_x509_crt_get_expiration_time(gnutls_x509_crt cert);
@@ -81,30 +118,18 @@ int gnutls_x509_crt_get_serial(gnutls_x509_crt cert, void* result, size_t* resul
int gnutls_x509_crt_get_pk_algorithm( gnutls_x509_crt cert, unsigned int* bits);
int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt cert,
- int seq, void *ret, size_t *ret_size, unsigned int* critical);
+ unsigned int seq, void *ret, size_t *ret_size, unsigned int* critical);
int gnutls_x509_crt_get_ca_status(gnutls_x509_crt cert, unsigned int* critical);
+/* The key_usage flags are defined in gnutls.h. They are
+ * the GNUTLS_KEY_* definitions.
+ */
int gnutls_x509_crt_get_key_usage( gnutls_x509_crt cert, unsigned int* key_usage,
unsigned int* critical);
+int gnutls_x509_crt_set_key_usage(gnutls_x509_crt crt, unsigned int usage);
int gnutls_x509_dn_oid_known(const char* oid);
-/* key_usage will be an OR of the following values:
- */
-#define GNUTLS_KEY_DIGITAL_SIGNATURE 128 /* when the key is to be
- * used for signing.
- */
-#define GNUTLS_KEY_NON_REPUDIATION 64
-#define GNUTLS_KEY_KEY_ENCIPHERMENT 32 /* when the key is to be
- * used for encryption.
- */
-#define GNUTLS_KEY_DATA_ENCIPHERMENT 16
-#define GNUTLS_KEY_KEY_AGREEMENT 8
-#define GNUTLS_KEY_KEY_CERT_SIGN 4
-#define GNUTLS_KEY_CRL_SIGN 2
-#define GNUTLS_KEY_ENCIPHER_ONLY 1
-#define GNUTLS_KEY_DECIPHER_ONLY 32768
-
int gnutls_x509_crt_get_extension_oid(gnutls_x509_crt cert, int indx,
void* oid, size_t * sizeof_oid);
int gnutls_x509_crt_get_extension_by_oid(gnutls_x509_crt cert,
@@ -133,9 +158,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
*/
@@ -182,6 +210,19 @@ int gnutls_x509_crl_get_crt_serial(gnutls_x509_crl crl, int index, unsigned char
int gnutls_x509_crl_check_issuer( gnutls_x509_crl crl,
gnutls_x509_crt issuer);
+/* CRL writing.
+ */
+int gnutls_x509_crl_set_version(gnutls_x509_crl crl, unsigned int version);
+int gnutls_x509_crl_sign(gnutls_x509_crl crl, gnutls_x509_crt issuer,
+ gnutls_x509_privkey issuer_key);
+int gnutls_x509_crl_set_this_update(gnutls_x509_crl crl, time_t act_time);
+int gnutls_x509_crl_set_next_update(gnutls_x509_crl crl, time_t exp_time);
+int gnutls_x509_crl_set_crt_serial(gnutls_x509_crl crl, const void* serial,
+ size_t serial_size, time_t revocation_time);
+int gnutls_x509_crl_set_crt(gnutls_x509_crl crl, gnutls_x509_crt crt,
+ time_t revocation_time);
+
+
/* PKCS7 structures handling
*/
@@ -278,6 +319,15 @@ int gnutls_x509_privkey_import_rsa_raw(gnutls_x509_privkey privkey,
const gnutls_datum *m, const gnutls_datum *e,
const gnutls_datum *d, const gnutls_datum *p, const gnutls_datum *q,
const gnutls_datum *u);
+
+int gnutls_x509_privkey_export_dsa_raw(gnutls_x509_privkey key,
+ gnutls_datum * p, gnutls_datum *q,
+ gnutls_datum *g, gnutls_datum *y, gnutls_datum* x);
+int gnutls_x509_privkey_import_dsa_raw(gnutls_x509_privkey key,
+ const gnutls_datum* p, const gnutls_datum* q,
+ const gnutls_datum* g, const gnutls_datum* y,
+ const gnutls_datum* x);
+
int gnutls_x509_privkey_get_pk_algorithm( gnutls_x509_privkey key);
int gnutls_x509_privkey_get_key_id( gnutls_x509_privkey key, unsigned int flags,
unsigned char* output_data, size_t* output_data_size);
diff --git a/lib/Makefile.am b/lib/Makefile.am
index c5ff61952f..39aa7f0115 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -56,7 +56,8 @@ libgnutls_la_LIBADD = $(MINITASN1_OBJECTS) x509/dn.lo x509/crl.lo x509/common.lo
x509/x509.lo x509/extensions.lo x509/compat.lo x509/verify.lo \
x509/mpi.lo x509/privkey.lo x509/pkcs7.lo x509/crq.lo x509/xml.lo x509/sign.lo \
x509/pkcs5.lo x509/privkey_pkcs8.lo x509/pkcs12.lo x509/pkcs12_bag.lo \
- x509/pkcs12_encr.lo x509/rfc2818_hostname.lo x509/rc2.lo x509/x509_write.lo
+ x509/pkcs12_encr.lo x509/rfc2818_hostname.lo x509/rc2.lo x509/x509_write.lo \
+ x509/crl_write.lo x509/dsa.lo
libgnutls_la_LDFLAGS = $(LIBASN1_LINK) $(LIBGCRYPT_LIBS) \
$(libgnutls_version_script_cmd) \
diff --git a/lib/gnutls.h.in.in b/lib/gnutls.h.in.in
index 1d89595bd1..b39d7bcc16 100644
--- a/lib/gnutls.h.in.in
+++ b/lib/gnutls.h.in.in
@@ -157,6 +157,11 @@ typedef enum gnutls_pk_algorithm { GNUTLS_PK_RSA = 1, GNUTLS_PK_DSA,
GNUTLS_PK_UNKNOWN = 0xff
} gnutls_pk_algorithm;
+typedef enum gnutls_sign_algorithm { GNUTLS_SIGN_RSA_SHA = 1, GNUTLS_SIGN_DSA_SHA,
+ GNUTLS_SIGN_RSA_MD5, GNUTLS_SIGN_RSA_MD2,
+ GNUTLS_SIGN_UNKNOWN = 0xff
+} gnutls_sign_algorithm;
+
/* If you want to change this, then also change the
* define in gnutls_int.h, and recompile.
*/
diff --git a/lib/gnutls_cipher.c b/lib/gnutls_cipher.c
index cca6a8fed4..cf32bcd435 100644
--- a/lib/gnutls_cipher.c
+++ b/lib/gnutls_cipher.c
@@ -157,7 +157,8 @@ int _gnutls_decrypt(gnutls_session session, opaque *ciphertext,
}
inline
-static GNUTLS_MAC_HANDLE mac_init( gnutls_mac_algorithm mac, opaque* secret, int secret_size, int ver) {
+static GNUTLS_MAC_HANDLE mac_init( gnutls_mac_algorithm mac, opaque* secret, int secret_size, int ver)
+{
GNUTLS_MAC_HANDLE td;
if ( ver == GNUTLS_SSL3) { /* SSL 3.0 */
@@ -173,7 +174,8 @@ GNUTLS_MAC_HANDLE td;
}
inline
-static void mac_deinit( GNUTLS_MAC_HANDLE td, opaque* res, int ver) {
+static void mac_deinit( GNUTLS_MAC_HANDLE td, opaque* res, int ver)
+{
if ( ver == GNUTLS_SSL3) { /* SSL 3.0 */
_gnutls_mac_deinit_ssl3(td, res);
} else {
diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c
index 0ea3581416..23670e13bf 100644
--- a/lib/gnutls_errors.c
+++ b/lib/gnutls_errors.c
@@ -54,6 +54,7 @@ static gnutls_error_entry error_algorithms[] = {
ERROR_ENTRY("The Diffie Hellman prime sent by the server is not acceptable (not long enough).", GNUTLS_E_DH_PRIME_UNACCEPTABLE, 1 ),
ERROR_ENTRY("A TLS packet with unexpected length was received.", GNUTLS_E_UNEXPECTED_PACKET_LENGTH, 1 ),
ERROR_ENTRY("The specified session has been invalidated for some reason.", GNUTLS_E_INVALID_SESSION, 1 ),
+ ERROR_ENTRY("The specified name does not match the name in the certificate.", GNUTLS_E_NAME_DOES_NOT_MATCH, 1 ),
ERROR_ENTRY("GnuTLS internal error.", GNUTLS_E_INTERNAL_ERROR, 1 ),
ERROR_ENTRY("An illegal TLS extension was received.", GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION, 1 ),
diff --git a/lib/gnutls_errors_int.h b/lib/gnutls_errors_int.h
index 3f64c626d7..e5d181e01f 100644
--- a/lib/gnutls_errors_int.h
+++ b/lib/gnutls_errors_int.h
@@ -122,6 +122,7 @@
#define GNUTLS_E_OPENPGP_KEYRING_ERROR -204
#define GNUTLS_E_X509_UNSUPPORTED_OID -205
+#define GNUTLS_E_NAME_DOES_NOT_MATCH -206
#define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250
diff --git a/lib/gnutls_hash_int.c b/lib/gnutls_hash_int.c
index 1746f963dc..cea75de4d0 100644
--- a/lib/gnutls_hash_int.c
+++ b/lib/gnutls_hash_int.c
@@ -78,7 +78,7 @@ int _gnutls_hash_get_algo_len(gnutls_mac_algorithm algorithm)
ret = gcry_md_get_algo_dlen(GCRY_MD_MD5);
break;
case GNUTLS_MAC_RMD160:
- ret = gcry_md_get_algo_dlen(GCRY_MD_MD5);
+ ret = gcry_md_get_algo_dlen(GCRY_MD_RMD160);
break;
default:
ret = 0; break;
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index ef95fee29c..00868356f8 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -212,6 +212,11 @@ typedef enum gnutls_pk_algorithm { GNUTLS_PK_RSA = 1, GNUTLS_PK_DSA,
GNUTLS_PK_UNKNOWN = 0xff
} gnutls_pk_algorithm;
+typedef enum gnutls_sign_algorithm { GNUTLS_SIGN_RSA_SHA = 1, GNUTLS_SIGN_DSA_SHA,
+ GNUTLS_SIGN_RSA_MD5, GNUTLS_SIGN_RSA_MD2,
+ GNUTLS_SIGN_UNKNOWN = 0xff
+} gnutls_sign_algorithm;
+
/* STATE (stop) */
typedef void (*LOG_FUNC)( int, const char*);
diff --git a/lib/gnutls_mpi.h b/lib/gnutls_mpi.h
index 2ac9eae663..357cc0a7bd 100644
--- a/lib/gnutls_mpi.h
+++ b/lib/gnutls_mpi.h
@@ -26,6 +26,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/gnutls_rsa_export.c b/lib/gnutls_rsa_export.c
index bc7104fb92..b772a2312c 100644
--- a/lib/gnutls_rsa_export.c
+++ b/lib/gnutls_rsa_export.c
@@ -54,7 +54,7 @@ const GNUTLS_MPI* _gnutls_get_rsa_params(gnutls_rsa_params rsa_params)
/* resarr will contain: modulus(0), public exponent(1), private exponent(2),
* prime1 - p (3), prime2 - q(4), u (5).
*/
-int _gnutls_rsa_generate_params(GNUTLS_MPI* resarr, int bits)
+int _gnutls_rsa_generate_params(GNUTLS_MPI* resarr, int* resarr_len, int bits)
{
int ret;
@@ -145,6 +145,8 @@ int _gnutls_rsa_generate_params(GNUTLS_MPI* resarr, int bits)
_gnutls_dump_mpi( "p: ", resarr[3]);
_gnutls_dump_mpi( "q: ", resarr[4]);
_gnutls_dump_mpi( "u: ", resarr[5]);
+
+ *resarr_len = 6;
return 0;
diff --git a/lib/gnutls_rsa_export.h b/lib/gnutls_rsa_export.h
index 49fec266b9..57897d32bb 100644
--- a/lib/gnutls_rsa_export.h
+++ b/lib/gnutls_rsa_export.h
@@ -20,5 +20,5 @@
const GNUTLS_MPI* _gnutls_get_rsa_params(gnutls_rsa_params);
int _gnutls_peers_cert_less_512( gnutls_session session);
-int _gnutls_rsa_generate_params(GNUTLS_MPI* resarr, int bits);
+int _gnutls_rsa_generate_params(GNUTLS_MPI* resarr, int* resarr_len, int bits);
diff --git a/lib/gnutls_ui.h b/lib/gnutls_ui.h
index ef050f9aba..007690182c 100644
--- a/lib/gnutls_ui.h
+++ b/lib/gnutls_ui.h
@@ -72,6 +72,23 @@ int gnutls_pem_base64_encode_alloc( const char* header, const gnutls_datum *data
int gnutls_pem_base64_decode_alloc( const char* header, const gnutls_datum *b64_data,
gnutls_datum* result);
+/* key_usage will be an OR of the following values:
+ */
+#define GNUTLS_KEY_DIGITAL_SIGNATURE 128 /* when the key is to be
+ * used for signing.
+ */
+#define GNUTLS_KEY_NON_REPUDIATION 64
+#define GNUTLS_KEY_KEY_ENCIPHERMENT 32 /* when the key is to be
+ * used for encryption.
+ */
+#define GNUTLS_KEY_DATA_ENCIPHERMENT 16
+#define GNUTLS_KEY_KEY_AGREEMENT 8
+#define GNUTLS_KEY_KEY_CERT_SIGN 4
+#define GNUTLS_KEY_CRL_SIGN 2
+#define GNUTLS_KEY_ENCIPHER_ONLY 1
+#define GNUTLS_KEY_DECIPHER_ONLY 32768
+
+
# endif /* LIBGNUTLS_VERSION */
#endif /* GNUTLS_UI_H */
diff --git a/lib/rsa_compat.c b/lib/rsa_compat.c
index 67e4d10141..18a33a2a3f 100644
--- a/lib/rsa_compat.c
+++ b/lib/rsa_compat.c
@@ -162,14 +162,14 @@ int gnutls_rsa_params_generate(gnutls_datum * m, gnutls_datum *e,
GNUTLS_MPI rsa_params[RSA_PRIVATE_PARAMS];
size_t siz;
uint i;
- int ret;
+ int ret, params_len;
if (check_bits(bits) < 0) {
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
- ret = _gnutls_rsa_generate_params( rsa_params, bits);
+ ret = _gnutls_rsa_generate_params( rsa_params, &params_len, bits);
if (ret < 0) {
gnutls_assert();
return ret;
diff --git a/lib/x509/Makefile.am b/lib/x509/Makefile.am
index 206617b223..de9bc28e11 100644
--- a/lib/x509/Makefile.am
+++ b/lib/x509/Makefile.am
@@ -1,7 +1,7 @@
INCLUDES = -I../ -I../minitasn1/ -I../../includes/
EXTRA_DIST = dn.h common.h x509.h extensions.h pkcs7.h \
x509-api.tex compat.h verify.h mpi.h crq.h sign.h pkcs5.h \
- privkey.h pkcs12.h rc2.h rfc2818.h
+ privkey.h pkcs12.h rc2.h rfc2818.h dsa.h
noinst_LTLIBRARIES = libx509.la
#lib_LTLIBRARIES = libgnutls-x509.la
@@ -9,7 +9,7 @@ noinst_LTLIBRARIES = libx509.la
COBJECTS = crl.c dn.c common.c x509.c extensions.c \
rfc2818_hostname.c verify.c mpi.c privkey.c pkcs7.c \
crq.c xml.c sign.c pkcs5.c privkey_pkcs8.c pkcs12.c \
- pkcs12_bag.c pkcs12_encr.c rc2.c x509_write.c
+ pkcs12_bag.c pkcs12_encr.c rc2.c x509_write.c crl_write.c dsa.c
COMPAT_OBJECTS = compat.c
diff --git a/lib/x509/common.c b/lib/x509/common.c
index 7af2a068f0..b466ce192c 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -35,7 +36,7 @@
typedef struct _oid2string {
const char * oid;
const char * ldap_desc;
- int choice;
+ int choice; /* of type DirectoryString */
int printable;
} oid2string;
@@ -43,18 +44,34 @@ typedef struct _oid2string {
* contained in a rdnSequence and are printable.
*/
static const oid2string _oid2str[] = {
+ /* PKIX
+ */
+ {"1.3.6.1.5.5.7.9.1", "dateOfBirth", 0, 1},
+ {"1.3.6.1.5.5.7.9.2", "placeOfBirth", 0, 1},
+ {"1.3.6.1.5.5.7.9.3", "gender", 0, 1},
+ {"1.3.6.1.5.5.7.9.4", "countryOfCitizenship", 0, 1},
+ {"1.3.6.1.5.5.7.9.5", "countryOfResidence", 0, 1},
+
{"2.5.4.6", "C", 0, 1},
+ {"2.5.4.9", "STREET", 1, 1},
{"2.5.4.12", "T", 1, 1},
{"2.5.4.10", "O", 1, 1},
{"2.5.4.11", "OU", 1, 1},
{"2.5.4.3", "CN", 1, 1},
{"2.5.4.7", "L", 1, 1},
{"2.5.4.8", "ST", 1, 1},
+
{"2.5.4.5", "serialNumber", 0, 1},
{"2.5.4.20", "telephoneNumber", 0, 1},
+ {"2.5.4.4", "surName", 1, 1},
+ {"2.5.4.43", "initials", 1, 1},
+ {"2.5.4.44", "generationQualifier", 1, 1},
+ {"2.5.4.42", "givenName", 1, 1},
+ {"2.5.4.65", "pseudonym", 1, 1},
+ {"2.5.4.46", "dnQualifier", 0, 1},
{"0.9.2342.19200300.100.1.25", "DC", 0, 1},
- {"0.9.2342.19200300.100.1.1", "UID", 0, 1}, /* FIXME: CHOICE? */
+ {"0.9.2342.19200300.100.1.1", "UID", 0, 1},
{"1.2.840.113549.1.9.1", "EMAIL", 0, 1},
{"1.2.840.113549.1.9.7", NULL, 1, 1},
@@ -244,23 +261,21 @@ gnutls_pk_algorithm _gnutls_x509_oid2pk_algorithm( const char* oid)
return GNUTLS_PK_UNKNOWN;
}
-gnutls_pk_algorithm _gnutls_x509_oid2sign_algorithm( const char* oid,
- gnutls_mac_algorithm * mac)
+gnutls_sign_algorithm _gnutls_x509_oid2sign_algorithm( const char* oid)
{
if (strcmp( oid, RSA_MD5_OID) == 0) {
- if (mac) *mac = GNUTLS_MAC_MD5;
- return GNUTLS_PK_RSA;
+ return GNUTLS_SIGN_RSA_MD5;
} else if (strcmp( oid, RSA_SHA1_OID) == 0) {
- if (mac) *mac = GNUTLS_MAC_SHA;
- return GNUTLS_PK_RSA;
+ return GNUTLS_SIGN_RSA_SHA;
+ } else if (strcmp( oid, RSA_MD2_OID) == 0) {
+ return GNUTLS_SIGN_RSA_MD2;
} else if (strcmp( oid, DSA_SHA1_OID) == 0) {
- if (mac) *mac = GNUTLS_MAC_SHA;
- return GNUTLS_PK_DSA;
+ return GNUTLS_SIGN_DSA_SHA;
}
_gnutls_x509_log("Unknown SIGN OID: '%s'\n", oid);
- return GNUTLS_PK_UNKNOWN;
+ return GNUTLS_SIGN_UNKNOWN;
}
@@ -276,28 +291,41 @@ gnutls_mac_algorithm _gnutls_x509_oid2mac_algorithm( const char* oid)
return GNUTLS_MAC_UNKNOWN;
}
-const char* _gnutls_x509_mac2oid( gnutls_mac_algorithm mac)
+const char* _gnutls_x509_mac_to_oid( gnutls_mac_algorithm mac)
{
if (mac == GNUTLS_MAC_SHA) return OID_SHA1;
else if (mac == GNUTLS_MAC_MD5) return OID_MD5;
else return NULL;
}
-const char* _gnutls_x509_pk2oid( gnutls_pk_algorithm pk)
+const char* _gnutls_x509_pk_to_oid( gnutls_pk_algorithm pk)
{
if (pk == GNUTLS_PK_RSA) return PKIX1_RSA_OID;
else if (pk == GNUTLS_PK_DSA) return DSA_OID;
else return NULL;
}
-const char* _gnutls_x509_sign2oid( gnutls_pk_algorithm pk, gnutls_mac_algorithm mac)
+gnutls_sign_algorithm _gnutls_x509_pk_to_sign(
+ gnutls_pk_algorithm pk, gnutls_mac_algorithm mac)
{
if (pk == GNUTLS_PK_RSA) {
- if (mac == GNUTLS_MAC_SHA) return RSA_SHA1_OID;
- else if (mac == GNUTLS_MAC_MD5) return RSA_MD5_OID;
+ if (mac == GNUTLS_MAC_SHA) return GNUTLS_SIGN_RSA_SHA;
+ else if (mac == GNUTLS_MAC_MD5) return GNUTLS_SIGN_RSA_MD5;
} else if (pk == GNUTLS_PK_DSA) {
- if (mac == GNUTLS_MAC_SHA) return DSA_SHA1_OID;
+ if (mac == GNUTLS_MAC_SHA) return GNUTLS_SIGN_DSA_SHA;
}
+ return GNUTLS_SIGN_UNKNOWN;
+}
+
+const char* _gnutls_x509_sign_to_oid( gnutls_pk_algorithm pk, gnutls_mac_algorithm mac)
+{
+gnutls_sign_algorithm sign;
+
+ sign = _gnutls_x509_pk_to_sign( pk, mac);
+
+ if (sign == GNUTLS_SIGN_RSA_SHA) return RSA_SHA1_OID;
+ else if (sign == GNUTLS_SIGN_RSA_MD5) return RSA_MD5_OID;
+ else if (sign == GNUTLS_SIGN_DSA_SHA) return DSA_SHA1_OID;
return NULL;
}
@@ -569,7 +597,7 @@ time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *when)
*/
int _gnutls_x509_set_time(ASN1_TYPE c2, const char *where, time_t tim)
{
- opaque str_time[MAX_TIME];
+ char str_time[MAX_TIME];
char name[1024];
int result, len;
@@ -598,12 +626,13 @@ int _gnutls_x509_set_time(ASN1_TYPE c2, const char *where, time_t tim)
}
-gnutls_x509_subject_alt_name _gnutls_x509_san_find_type( char* str_type) {
+gnutls_x509_subject_alt_name _gnutls_x509_san_find_type( char* str_type)
+{
if (strcmp( str_type, "dNSName")==0) return GNUTLS_SAN_DNSNAME;
if (strcmp( str_type, "rfc822Name")==0) return GNUTLS_SAN_RFC822NAME;
if (strcmp( str_type, "uniformResourceIdentifier")==0) return GNUTLS_SAN_URI;
if (strcmp( str_type, "iPAddress")==0) return GNUTLS_SAN_IPADDRESS;
- return -1;
+ return (gnutls_x509_subject_alt_name)-1;
}
/* A generic export function. Will export the given ASN.1 encoded data
@@ -626,7 +655,6 @@ int _gnutls_x509_export_int( ASN1_TYPE asn1_data,
{
*output_data_size = len;
if (result == ASN1_MEM_ERROR) {
- gnutls_assert();
return GNUTLS_E_SHORT_MEMORY_BUFFER;
}
gnutls_assert();
@@ -949,7 +977,6 @@ gnutls_datum val;
/* Encodes and copies the private key parameters into a
* subjectPublicKeyInfo structure.
*
- * FIXME: can only support RSA parameters.
*/
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)
@@ -959,18 +986,13 @@ gnutls_datum der = {NULL, 0};
int result;
char name[128];
- if (pk_algorithm != GNUTLS_PK_RSA) {
- gnutls_assert();
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
- }
-
- pk = _gnutls_x509_pk2oid( pk_algorithm);
+ pk = _gnutls_x509_pk_to_oid( pk_algorithm);
if (pk == NULL) {
gnutls_assert();
return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
}
- /* write the RSA OID
+ /* write the OID
*/
_gnutls_str_cpy( name, sizeof(name), dst_name);
_gnutls_str_cat( name, sizeof(name), ".algorithm.algorithm");
@@ -980,34 +1002,74 @@ char name[128];
return _gnutls_asn2err(result);
}
- /* disable parameters, which are not used in RSA.
- */
- _gnutls_str_cpy( name, sizeof(name), dst_name);
- _gnutls_str_cat( name, sizeof(name), ".algorithm.parameters");
- result = asn1_write_value( dst, name, NULL, 0);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
+ if (pk_algorithm == GNUTLS_PK_RSA) {
+ /* disable parameters, which are not used in RSA.
+ */
+ _gnutls_str_cpy( name, sizeof(name), dst_name);
+ _gnutls_str_cat( name, sizeof(name), ".algorithm.parameters");
+ result = asn1_write_value( dst, name, NULL, 0);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
- result = _gnutls_x509_write_rsa_params( params, params_size, &der);
- if (result < 0) {
- gnutls_assert();
- return result;
- }
+ result = _gnutls_x509_write_rsa_params( params, params_size, &der);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
- /* Write the DER parameters. (in bits)
- */
- _gnutls_str_cpy( name, sizeof(name), dst_name);
- _gnutls_str_cat( name, sizeof(name), ".subjectPublicKey");
- result = asn1_write_value( dst, name, der.data, der.size*8);
+ /* Write the DER parameters. (in bits)
+ */
+ _gnutls_str_cpy( name, sizeof(name), dst_name);
+ _gnutls_str_cat( name, sizeof(name), ".subjectPublicKey");
+ result = asn1_write_value( dst, name, der.data, der.size*8);
- _gnutls_free_datum(&der);
+ _gnutls_free_datum(&der);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+ } else if (pk_algorithm == GNUTLS_PK_DSA) {
+
+ result = _gnutls_x509_write_dsa_params( params, params_size, &der);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ /* Write the DER parameters.
+ */
+ _gnutls_str_cpy( name, sizeof(name), dst_name);
+ _gnutls_str_cat( name, sizeof(name), ".algorithm.parameters");
+ result = asn1_write_value( dst, name, der.data, der.size);
+
+ _gnutls_free_datum(&der);
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ result = _gnutls_x509_write_dsa_public_key( params, params_size, &der);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ _gnutls_str_cpy( name, sizeof(name), dst_name);
+ _gnutls_str_cat( name, sizeof(name), ".subjectPublicKey");
+ result = asn1_write_value( dst, name, der.data, der.size*8);
+
+ _gnutls_free_datum(&der);
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ } else return GNUTLS_E_UNIMPLEMENTED_FEATURE;
return 0;
}
@@ -1044,7 +1106,8 @@ char name[128];
return algo;
}
- /* Now read the parameters' bits */
+ /* Now read the parameters' bits
+ */
_gnutls_str_cpy( name, sizeof(name), src_name);
_gnutls_str_cat( name, sizeof(name), ".subjectPublicKey");
diff --git a/lib/x509/common.h b/lib/x509/common.h
index 34d07d9a23..f29a28f27b 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -13,8 +13,11 @@ void _gnutls_int2str(unsigned int k, char *data);
#define PKIX1_RSA_OID "1.2.840.113549.1.1.1"
#define DSA_OID "1.2.840.10040.4.1"
+/* signature OIDs
+ */
#define DSA_SHA1_OID "1.2.840.10040.4.3"
#define RSA_MD5_OID "1.2.840.113549.1.1.4"
+#define RSA_MD2_OID "1.2.840.113549.1.1.2"
#define RSA_SHA1_OID "1.2.840.113549.1.1.5"
time_t _gnutls_x509_utcTime2gtime(const char *ttime);
@@ -31,12 +34,14 @@ int _gnutls_x509_oid_data_printable( const char* OID);
gnutls_pk_algorithm _gnutls_x509_oid2pk_algorithm( const char* oid);
gnutls_mac_algorithm _gnutls_x509_oid2mac_algorithm( const char* oid);
-gnutls_pk_algorithm _gnutls_x509_oid2sign_algorithm( const char* oid,
- gnutls_mac_algorithm * mac);
+gnutls_sign_algorithm _gnutls_x509_oid2sign_algorithm( const char* oid);
-const char* _gnutls_x509_pk2oid( gnutls_pk_algorithm pk);
-const char* _gnutls_x509_sign2oid( gnutls_pk_algorithm pk, gnutls_mac_algorithm mac);
-const char* _gnutls_x509_mac2oid( gnutls_mac_algorithm mac);
+const char* _gnutls_x509_pk_to_oid( gnutls_pk_algorithm pk);
+
+gnutls_sign_algorithm _gnutls_x509_pk_to_sign(
+ gnutls_pk_algorithm pk, gnutls_mac_algorithm mac);
+const char* _gnutls_x509_sign_to_oid( gnutls_sign_algorithm, gnutls_mac_algorithm mac);
+const char* _gnutls_x509_mac_to_oid( gnutls_mac_algorithm mac);
time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *when);
diff --git a/lib/x509/crl.c b/lib/x509/crl.c
index d4e05b6cd2..3ae42dced9 100644
--- a/lib/x509/crl.c
+++ b/lib/x509/crl.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -55,6 +56,7 @@ int gnutls_x509_crl_init(gnutls_x509_crl * crl)
&(*crl)->crl);
if (result != ASN1_SUCCESS) {
gnutls_assert();
+ gnutls_free( *crl);
return _gnutls_asn2err(result);
}
return 0; /* success */
@@ -154,7 +156,7 @@ int gnutls_x509_crl_import(gnutls_x509_crl crl, const gnutls_datum * data,
* gnutls_x509_crl_get_issuer_dn - This function returns the CRL's issuer distinguished name
* @crl: should contain a gnutls_x509_crl structure
* @buf: a pointer to a structure to hold the peer's name (may be null)
- * @sizeof_buf: initialy holds the size of 'buf'
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will copy the name of the CRL issuer in the provided buffer. The name
* will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output
@@ -187,7 +189,7 @@ int gnutls_x509_crl_get_issuer_dn(gnutls_x509_crl crl, char *buf,
* @indx: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one.
* @raw_flag: If non zero returns the raw DER data of the DN part.
* @buf: a pointer to a structure to hold the peer's name (may be null)
- * @sizeof_buf: initialy holds the size of 'buf'
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will extract the part of the name of the CRL issuer specified
* by the given OID. The output will be encoded as described in RFC2253. The output
@@ -224,7 +226,7 @@ int gnutls_x509_crl_get_issuer_dn_by_oid(gnutls_x509_crl crl,
* @crl: should contain a gnutls_x509_crl structure
* @indx: Specifies which DN OID to send. Use zero to get the first one.
* @oid: a pointer to a structure to hold the name (may be null)
- * @sizeof_oid: initialy holds the size of 'oid'
+ * @sizeof_oid: initially holds the size of 'oid'
*
* This function will extract the requested OID of the name of the CRL issuer, specified
* by the given index.
@@ -253,7 +255,7 @@ int gnutls_x509_crl_get_dn_oid(gnutls_x509_crl crl,
* gnutls_x509_crl_get_signature_algorithm - This function returns the CRL's signature algorithm
* @crl: should contain a gnutls_x509_crl structure
*
- * This function will return a value of the gnutls_pk_algorithm enumeration that
+ * This function will return a value of the gnutls_sign_algorithm enumeration that
* is the signature algorithm.
*
* Returns a negative value on error.
@@ -280,7 +282,7 @@ int gnutls_x509_crl_get_signature_algorithm(gnutls_x509_crl crl)
return result;
}
- result = _gnutls_x509_oid2sign_algorithm( (const char*)sa.data, NULL);
+ result = _gnutls_x509_oid2sign_algorithm( (const char*)sa.data);
_gnutls_free_datum( &sa);
@@ -393,11 +395,11 @@ int gnutls_x509_crl_get_crt_count(gnutls_x509_crl crl)
}
/**
- * gnutls_x509_crl_get_crt - This function returns the serial number of a revoked certificate
+ * gnutls_x509_crl_get_crt_serial - This function returns the serial number of a revoked certificate
* @crl: should contain a gnutls_x509_crl structure
* @index: the index of the certificate to extract (starting from 0)
* @serial: where the serial number will be copied
- * @serial_size: initialy holds the size of serial
+ * @serial_size: initially holds the size of serial
* @time: if non null, will hold the time this certificate was revoked
*
* This function will return the serial number of the specified, by the index,
diff --git a/lib/x509/crl_write.c b/lib/x509/crl_write.c
new file mode 100644
index 0000000000..7545f2c6a8
--- /dev/null
+++ b/lib/x509/crl_write.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* This file contains functions to handle CRL generation.
+ */
+
+#include <gnutls_int.h>
+
+#ifdef ENABLE_PKI
+
+#include <gnutls_datum.h>
+#include <gnutls_global.h>
+#include <gnutls_errors.h>
+#include <common.h>
+#include <gnutls_x509.h>
+#include <x509_b64.h>
+#include <crq.h>
+#include <dn.h>
+#include <mpi.h>
+#include <sign.h>
+#include <extensions.h>
+#include <libtasn1.h>
+#include <gnutls_ui.h>
+
+static void disable_optional_stuff( gnutls_x509_crl crl);
+
+/**
+ * gnutls_x509_crl_set_version - This function will set the CRL version
+ * @crl: should contain a gnutls_x509_crl structure
+ * @version: holds the version number. For CRLv1 crls must be 1.
+ *
+ * This function will set the version of the CRL. This
+ * must be one for CRL version 1, and so on. The CRLs generated
+ * by gnutls should have a version number of 2.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int gnutls_x509_crl_set_version(gnutls_x509_crl crl, unsigned int version)
+{
+int result;
+char null = version;
+
+ if (crl==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ null -= 1;
+ if (null < 0) null = 0;
+
+ result = asn1_write_value( crl->crl, "tbsCertList.version", &null, 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_x509_crl_sign - This function will sign a CRL with a key
+ * @crl: should contain a gnutls_x509_crl structure
+ * @issuer: is the certificate of the certificate issuer
+ * @issuer_key: holds the issuer's private key
+ *
+ * This function will sign the CRL with the issuer's private key, and
+ * will copy the issuer's information into the CRL.
+ *
+ * This must be the last step in a certificate CRL since all
+ * the previously set parameters are now signed.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int gnutls_x509_crl_sign(gnutls_x509_crl crl, gnutls_x509_crt issuer,
+ gnutls_x509_privkey issuer_key)
+{
+int result;
+
+ if (crl==NULL || issuer == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* disable all the unneeded OPTIONAL fields.
+ */
+ disable_optional_stuff( crl);
+
+ result = _gnutls_x509_pkix_sign( crl->crl, "tbsCertList", issuer,
+ issuer_key);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_x509_crl_set_this_update - This function will set the CRL's issuing time
+ * @crl: should contain a gnutls_x509_crl structure
+ * @act_time: The actual time
+ *
+ * This function will set the time this CRL was issued.
+ *
+ * Returns 0 on success, or a negative value in case of an error.
+ *
+ **/
+int gnutls_x509_crl_set_this_update(gnutls_x509_crl crl, time_t act_time)
+{
+ if (crl==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ return _gnutls_x509_set_time( crl->crl, "tbsCertList.thisUpdate", act_time);
+}
+
+/**
+ * gnutls_x509_crl_set_next_update - This function will set the CRL next update time
+ * @crl: should contain a gnutls_x509_crl structure
+ * @exp_time: The actual time
+ *
+ * This function will set the time this CRL will be updated.
+ *
+ * Returns 0 on success, or a negative value in case of an error.
+ *
+ **/
+int gnutls_x509_crl_set_next_update(gnutls_x509_crl crl, time_t exp_time)
+{
+ if (crl==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+ return _gnutls_x509_set_time( crl->crl, "tbsCertList.nextUpdate", exp_time);
+}
+
+/**
+ * gnutls_x509_crl_set_crt_serial - This function will set a revoked certificate's serial number
+ * @crl: should contain a gnutls_x509_crl structure
+ * @serial: The revoked certificate's serial number
+ * @serial_size: Holds the size of the serial field.
+ * @revocation_time: The time this certificate was revoked
+ *
+ * This function will set a revoked certificate's serial number to the CRL.
+ *
+ * Returns 0 on success, or a negative value in case of an error.
+ *
+ **/
+int gnutls_x509_crl_set_crt_serial(gnutls_x509_crl crl, const void* serial,
+ size_t serial_size, time_t revocation_time)
+{
+ int ret;
+
+ if (crl==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ ret = asn1_write_value(crl->crl, "tbsCertList.revokedCertificates", "NEW", 1);
+ if (ret != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(ret);
+ }
+
+ ret = asn1_write_value(crl->crl, "tbsCertList.revokedCertificates.?LAST.userCertificate", serial, serial_size);
+ if (ret != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(ret);
+ }
+
+ ret = _gnutls_x509_set_time( crl->crl, "tbsCertList.revokedCertificates.?LAST.revocationDate",
+ revocation_time);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret = asn1_write_value(crl->crl, "tbsCertList.revokedCertificates.?LAST.crlEntryExtensions", NULL, 0);
+ if (ret != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(ret);
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_x509_crl_set_crt - This function will set a revoked certificate's serial number
+ * @crl: should contain a gnutls_x509_crl structure
+ * @crt: should contain a gnutls_x509_crt structure with the revoked certificate
+ * @revocation_time: The time this certificate was revoked
+ *
+ * This function will set a revoked certificate's serial number to the CRL.
+ *
+ * Returns 0 on success, or a negative value in case of an error.
+ *
+ **/
+int gnutls_x509_crl_set_crt(gnutls_x509_crl crl, gnutls_x509_crt crt,
+ time_t revocation_time)
+{
+ int ret;
+ opaque serial[128];
+ size_t serial_size;
+
+ if (crl==NULL || crt == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ serial_size = sizeof(serial);
+ ret = gnutls_x509_crt_get_serial(crt, serial, &serial_size);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret = gnutls_x509_crl_set_crt_serial( crl, serial, serial_size, revocation_time);
+ if (ret < 0) {
+ gnutls_assert();
+ return _gnutls_asn2err(ret);
+ }
+
+ return 0;
+}
+
+
+/* If OPTIONAL fields have not been initialized then
+ * disable them.
+ */
+static void disable_optional_stuff( gnutls_x509_crl crl)
+{
+
+ asn1_write_value( crl->crl, "tbsCertList.crlExtensions", NULL, 0);
+
+ return;
+}
+
+#endif /* ENABLE_PKI */
diff --git a/lib/x509/crq.c b/lib/x509/crq.c
index 07938ccab1..e6d4d1669c 100644
--- a/lib/x509/crq.c
+++ b/lib/x509/crq.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -59,6 +60,7 @@ int gnutls_x509_crq_init(gnutls_x509_crq * crq)
&((*crq)->crq));
if (result != ASN1_SUCCESS) {
gnutls_assert();
+ gnutls_free( *crq);
return _gnutls_asn2err(result);
}
return 0; /* success */
@@ -146,9 +148,7 @@ int gnutls_x509_crq_import(gnutls_x509_crq crq, const gnutls_datum * data,
goto cleanup;
}
- if (need_free) _gnutls_free_datum( &_data);
-
- return 0;
+ result = 0;
cleanup:
if (need_free) _gnutls_free_datum( &_data);
@@ -161,7 +161,7 @@ int gnutls_x509_crq_import(gnutls_x509_crq crq, const gnutls_datum * data,
* gnutls_x509_crq_get_dn - This function returns the Certificate request subject's distinguished name
* @crq: should contain a gnutls_x509_crq structure
* @buf: a pointer to a structure to hold the name (may be null)
- * @sizeof_buf: initialy holds the size of @buf
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will copy the name of the Certificate request subject in the provided buffer. The name
* will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output
@@ -193,7 +193,7 @@ int gnutls_x509_crq_get_dn(gnutls_x509_crq crq, char *buf,
* @indx: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one.
* @raw_flag: If non zero returns the raw DER data of the DN part.
* @buf: a pointer to a structure to hold the name (may be null)
- * @sizeof_buf: initialy holds the size of @buf
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will extract the part of the name of the Certificate request subject, specified
* by the given OID. The output will be encoded as described in RFC2253. The output
@@ -228,7 +228,7 @@ int gnutls_x509_crq_get_dn_by_oid(gnutls_x509_crq crq, const char* oid,
* @crq: should contain a gnutls_x509_crq structure
* @indx: Specifies which DN OID to send. Use zero to get the first one.
* @oid: a pointer to a structure to hold the name (may be null)
- * @sizeof_oid: initialy holds the size of @oid
+ * @sizeof_oid: initially holds the size of @oid
*
* This function will extract the requested OID of the name of the Certificate request subject, specified
* by the given index.
@@ -395,7 +395,7 @@ static int parse_attribute(ASN1_TYPE asn1_struct,
* gnutls_x509_crq_get_challenge_password - This function will get the challenge password
* @crq: should contain a gnutls_x509_crq structure
* @pass: will hold a null terminated password
- * @sizeof_pass: Initialy holds the size of pass.
+ * @sizeof_pass: Initially holds the size of @pass.
*
* This function will return the challenge password in the
* request.
@@ -460,15 +460,14 @@ int gnutls_x509_crq_set_dn_by_oid(gnutls_x509_crq crq, const char* oid,
int gnutls_x509_crq_set_version(gnutls_x509_crq crq, unsigned int version)
{
int result;
-char null = version;
+unsigned char null = version;
if (crq==NULL) {
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
- null -= 1;
- if (null < 0) null = 0;
+ if (null > 0) null--;
result = asn1_write_value( crq->crq, "certificationRequestInfo.version", &null, 1);
if (result != ASN1_SUCCESS) {
@@ -599,18 +598,12 @@ int gnutls_x509_crq_sign(gnutls_x509_crq crq, gnutls_x509_privkey key)
{
int result;
gnutls_datum signature;
-const char* pk;
if (crq==NULL) {
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
- if (key->pk_algorithm != GNUTLS_PK_RSA) {
- gnutls_assert();
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
- }
-
/* Step 1. Self sign the request.
*/
result = _gnutls_x509_sign_tbs( crq->crq, "certificationRequestInfo", GNUTLS_MAC_SHA,
@@ -634,26 +627,11 @@ const char* pk;
/* Step 3. Write the signatureAlgorithm field.
*/
- pk = _gnutls_x509_sign2oid( key->pk_algorithm, GNUTLS_MAC_SHA);
- if (pk == NULL) {
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- /* write the RSA OID
- */
- result = asn1_write_value( crq->crq, "signatureAlgorithm.algorithm", pk, 1);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- /* disable parameters, which are not used in RSA.
- */
- result = asn1_write_value( crq->crq, "signatureAlgorithm.parameters", NULL, 0);
- if (result != ASN1_SUCCESS) {
+ result = _gnutls_x509_write_sig_params( crq->crq, "signatureAlgorithm",
+ key->pk_algorithm, key->params, key->params_size);
+ if (result < 0) {
gnutls_assert();
- return _gnutls_asn2err(result);
+ return result;
}
return 0;
@@ -720,7 +698,6 @@ int result;
bits);
if (result < 0) {
gnutls_assert();
- return result;
}
return result;
diff --git a/lib/x509/dn.c b/lib/x509/dn.c
index 755f72ec55..ef0e6401cc 100644
--- a/lib/x509/dn.c
+++ b/lib/x509/dn.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -244,7 +245,7 @@ int _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct,
ldap_desc = oid2ldap_string(oid);
printable = _gnutls_x509_oid_data_printable(oid);
- sizeof_escaped = 2*len;
+ sizeof_escaped = 2*len + 1;
escaped = gnutls_malloc( sizeof_escaped);
if (escaped == NULL) {
@@ -272,6 +273,7 @@ int _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct,
len,
string,
&sizeof_string);
+
if (result < 0) {
gnutls_assert();
_gnutls_x509_log
@@ -290,10 +292,13 @@ int _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct,
res =
_gnutls_bin2hex(value2, len, escaped,
sizeof_escaped);
+
+ STR_APPEND(ldap_desc);
+ STR_APPEND("=#");
if (res) {
- STR_APPEND(ldap_desc);
- STR_APPEND("=#");
STR_APPEND(res);
+ } else {
+ STR_APPEND("(null)");
}
}
diff --git a/lib/x509/extensions.c b/lib/x509/extensions.c
index c88a69c250..fc6e07a2df 100644
--- a/lib/x509/extensions.c
+++ b/lib/x509/extensions.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -28,6 +29,8 @@
#include <libtasn1.h>
#include <common.h>
#include <x509.h>
+#include <extensions.h>
+#include <gnutls_datum.h>
/* This function will attempt to return the requested extension found in
* the given X509v3 certificate. The return value is allocated and stored into
@@ -103,7 +106,7 @@ int _gnutls_x509_crt_get_extension( gnutls_x509_crt cert, const char* extension_
return _gnutls_asn2err(result);
}
- if (strcmp( str_critical, "TRUE")==0)
+ if (str_critical[0] == 'T')
critical = 1;
else critical = 0;
@@ -339,9 +342,10 @@ int _gnutls_x509_ext_extract_keyUsage(uint16 *keyUsage, opaque * extnValue,
int extnValueLen)
{
ASN1_TYPE ext = ASN1_TYPE_EMPTY;
- uint8 str[2];
int len, result;
+ uint8 str[2];
+ str[0] = str[1] = 0;
*keyUsage = 0;
if ((result=asn1_create_element
@@ -356,7 +360,7 @@ int _gnutls_x509_ext_extract_keyUsage(uint16 *keyUsage, opaque * extnValue,
if (result != ASN1_SUCCESS) {
gnutls_assert();
asn1_delete_structure(&ext);
- return 0;
+ return _gnutls_asn2err(result);
}
len = sizeof(str);
@@ -366,7 +370,7 @@ int _gnutls_x509_ext_extract_keyUsage(uint16 *keyUsage, opaque * extnValue,
asn1_delete_structure(&ext);
return 0;
}
-
+
*keyUsage = str[0] | (str[1] << 8);
asn1_delete_structure(&ext);
@@ -397,13 +401,14 @@ int _gnutls_x509_ext_extract_basicConstraints(int *CA, opaque * extnValue,
if (result != ASN1_SUCCESS) {
gnutls_assert();
asn1_delete_structure(&ext);
- return 0;
+ return _gnutls_asn2err(result);
}
len = sizeof(str) - 1;
+ /* the default value of cA is false.
+ */
result = asn1_read_value(ext, "cA", str, &len);
if (result != ASN1_SUCCESS) {
- gnutls_assert();
asn1_delete_structure(&ext);
return 0;
}
@@ -458,23 +463,51 @@ int _gnutls_x509_ext_gen_basicConstraints(int CA, gnutls_datum* der_ext)
return 0;
}
-/* generate the subject alternative name in a DER encoded extension
+/* generate the keyUsage in a DER encoded extension
+ * Use an ORed SEQUENCE of GNUTLS_KEY_* for usage.
*/
-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_keyUsage(uint16 usage, gnutls_datum* der_ext)
{
ASN1_TYPE ext = ASN1_TYPE_EMPTY;
- const char *str;
- char name[128];
int result;
+ uint8 str[2];
- result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.SubjectAltName", &ext);
+ result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.KeyUsage", &ext);
if (result != ASN1_SUCCESS) {
gnutls_assert();
return _gnutls_asn2err(result);
}
- result = asn1_write_value( ext, "", "NEW", 1);
+ str[0] = usage & 0xff;
+ str[1] = usage >> 8;
+
+ result = asn1_write_value(ext, "", str, 9);
+ 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;
+}
+
+static int write_new_general_name( ASN1_TYPE ext, const char* ext_name,
+ gnutls_x509_subject_alt_name type, const char* data_string)
+{
+const char* str;
+int result;
+char name[128];
+
+ result = asn1_write_value( ext, ext_name, "NEW", 1);
if (result != ASN1_SUCCESS) {
gnutls_assert();
return _gnutls_asn2err(result);
@@ -498,13 +531,20 @@ int _gnutls_x509_ext_gen_subject_alt_name(gnutls_x509_subject_alt_name type,
return GNUTLS_E_INTERNAL_ERROR;
}
- result = asn1_write_value( ext, "?LAST", str, 1);
+ if (ext_name[0] == 0) { /* no dot */
+ _gnutls_str_cpy( name, sizeof(name), "?LAST");
+ } else {
+ _gnutls_str_cpy( name, sizeof(name), ext_name);
+ _gnutls_str_cat( name, sizeof(name), ".?LAST");
+ }
+
+ result = asn1_write_value( ext, name, 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), ".");
_gnutls_str_cat( name, sizeof(name), str);
result = asn1_write_value(ext, name, data_string, strlen(data_string));
@@ -514,6 +554,31 @@ int _gnutls_x509_ext_gen_subject_alt_name(gnutls_x509_subject_alt_name type,
return _gnutls_asn2err(result);
}
+ return 0;
+}
+
+/* Convert the given name to GeneralNames in a DER encoded extension.
+ * This is the same as subject alternative name.
+ */
+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;
+ int result;
+
+ result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.GeneralNames", &ext);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ result = write_new_general_name(ext, "", type, data_string);
+ if (result < 0) {
+ gnutls_assert();
+ asn1_delete_structure(&ext);
+ return result;
+ }
+
result = _gnutls_x509_der_encode( ext, "", der_ext, 0);
asn1_delete_structure(&ext);
@@ -525,3 +590,123 @@ 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;
+}
+
+/* Creates and encodes the CRL Distribution points. data_string should be a name
+ * and type holds the type of the name.
+ * reason_flags should be an or'ed sequence of GNUTLS_CRL_REASON_*.
+ *
+ */
+int _gnutls_x509_ext_gen_crl_dist_points(gnutls_x509_subject_alt_name type,
+ const void* data_string, unsigned int reason_flags, gnutls_datum* der_ext)
+{
+ ASN1_TYPE ext = ASN1_TYPE_EMPTY;
+ gnutls_datum gnames = {NULL, 0};
+ int result;
+ uint8 reasons[2];
+
+ reasons[0] = reason_flags & 0xff;
+ reasons[1] = reason_flags >> 8;
+
+ result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.CRLDistributionPoints", &ext);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ result = asn1_write_value( ext, "", "NEW", 1);
+ 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);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+#if 0
+ /* When used as type CHOICE.
+ */
+ result = asn1_write_value( ext, "?LAST.distributionPoint", "fullName", 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+#endif
+
+ asn1_write_value( ext, "?LAST.distributionPoint.nameRelativeToCRLIssuer", NULL, 0);
+
+ result = write_new_general_name(ext, "?LAST.distributionPoint.fullName", type, data_string);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_der_encode( ext, "", der_ext, 0);
+
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = 0;
+
+cleanup:
+ _gnutls_free_datum( &gnames);
+ asn1_delete_structure(&ext);
+
+ return result;
+}
diff --git a/lib/x509/extensions.h b/lib/x509/extensions.h
index 12f8f70c88..ce2e70a67b 100644
--- a/lib/x509/extensions.h
+++ b/lib/x509/extensions.h
@@ -10,5 +10,9 @@ 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_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 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/mpi.c b/lib/x509/mpi.c
index 2eb76bb064..d2d260f63d 100644
--- a/lib/x509/mpi.c
+++ b/lib/x509/mpi.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -141,7 +142,7 @@ int _gnutls_x509_read_dsa_params(opaque * der, int dersize, GNUTLS_MPI * params)
/* reads DSA's Y
* from the certificate
- * params[3]
+ * only sets params[3]
*/
int _gnutls_x509_read_dsa_pubkey(opaque * der, int dersize, GNUTLS_MPI * params)
{
@@ -163,7 +164,7 @@ int _gnutls_x509_read_dsa_pubkey(opaque * der, int dersize, GNUTLS_MPI * params)
return _gnutls_asn2err(result);
}
- /* Read p */
+ /* Read Y */
if ( (result=_gnutls_x509_read_int( spk, "", &params[3])) < 0) {
gnutls_assert();
@@ -331,7 +332,69 @@ cleanup:
}
/*
- * This function writes the BIT STRING subjectPublicKey for DSS keys.
+ * This function writes and encodes the parameters for DSS or RSA keys.
+ * This is the "signatureAlgorithm" fields.
+ */
+int _gnutls_x509_write_sig_params( ASN1_TYPE dst, const char* dst_name,
+ gnutls_pk_algorithm pk_algorithm, GNUTLS_MPI * params, int params_size)
+{
+gnutls_datum der;
+int result;
+char name[128];
+const char* pk;
+
+ _gnutls_str_cpy( name, sizeof(name), dst_name);
+ _gnutls_str_cat( name, sizeof(name), ".algorithm");
+
+ pk = _gnutls_x509_sign_to_oid( pk_algorithm, GNUTLS_MAC_SHA);
+ if (pk == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* write the OID.
+ */
+ result = asn1_write_value( dst, name, pk, 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+
+ _gnutls_str_cpy( name, sizeof(name), dst_name);
+ _gnutls_str_cat( name, sizeof(name), ".parameters");
+
+ if (pk_algorithm == GNUTLS_PK_DSA) {
+ result = _gnutls_x509_write_dsa_params( params, params_size, &der);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ result = asn1_write_value( dst, name, der.data, der.size);
+ _gnutls_free_datum( &der);
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+ } else { /* RSA */
+ result = asn1_write_value( dst, name, NULL, 0);
+
+ if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) {
+ /* Here we ignore the element not found error, since this
+ * may have been disabled before.
+ */
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * This function writes the parameters for DSS keys.
* Needs 3 parameters (p,q,g).
*
* Allocates the space used to store the DER data.
@@ -390,6 +453,54 @@ cleanup:
return result;
}
+/*
+ * This function writes the public parameters for DSS keys.
+ * Needs 1 parameter (y).
+ *
+ * Allocates the space used to store the DER data.
+ */
+int _gnutls_x509_write_dsa_public_key( GNUTLS_MPI * params, int params_size,
+ gnutls_datum* der)
+{
+ int result;
+ ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+
+ der->data = NULL;
+ der->size = 0;
+
+ if (params_size < 3) {
+ gnutls_assert();
+ result = GNUTLS_E_INVALID_REQUEST;
+ goto cleanup;
+ }
+
+ if ((result=asn1_create_element
+ (_gnutls_get_gnutls_asn(), "GNUTLS.DSAPublicKey", &spk))
+ != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ result = _gnutls_x509_write_int( spk, "", params[3], 0);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_der_encode( spk, "", der, 0);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ asn1_delete_structure(&spk);
+ return 0;
+
+cleanup:
+ asn1_delete_structure(&spk);
+ return result;
+}
+
/* this function reads a (small) unsigned integer
* from asn1 structs. Combines the read and the convertion
diff --git a/lib/x509/mpi.h b/lib/x509/mpi.h
index 471a01c8de..cfa92918f7 100644
--- a/lib/x509/mpi.h
+++ b/lib/x509/mpi.h
@@ -1,3 +1,4 @@
+#include <gnutls_int.h>
#include "x509.h"
int _gnutls_x509_crt_get_mpis( gnutls_x509_crt cert,
@@ -10,6 +11,8 @@ int _gnutls_x509_write_rsa_params( GNUTLS_MPI * params, int params_size,
gnutls_datum* der);
int _gnutls_x509_write_dsa_params( GNUTLS_MPI * params, int params_size,
gnutls_datum* der);
+int _gnutls_x509_write_dsa_public_key( GNUTLS_MPI * params, int params_size,
+ gnutls_datum* der);
int _gnutls_x509_read_uint( ASN1_TYPE node, const char* value,
unsigned int* ret);
@@ -18,3 +21,6 @@ int _gnutls_x509_read_int( ASN1_TYPE node, const char* value,
GNUTLS_MPI* ret_mpi);
int _gnutls_x509_write_int( ASN1_TYPE node, const char* value, GNUTLS_MPI mpi, int lz);
int _gnutls_x509_write_uint32( ASN1_TYPE node, const char* value, uint32 num);
+
+int _gnutls_x509_write_sig_params( ASN1_TYPE dst, const char* dst_name,
+ gnutls_pk_algorithm pk_algorithm, GNUTLS_MPI * params, int params_size);
diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c
index 9f61e21d0d..27bbe41218 100644
--- a/lib/x509/pkcs12.c
+++ b/lib/x509/pkcs12.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -129,6 +130,7 @@ int gnutls_pkcs12_init(gnutls_pkcs12 * pkcs12)
&(*pkcs12)->pkcs12);
if (result != ASN1_SUCCESS) {
gnutls_assert();
+ gnutls_free( *pkcs12);
return _gnutls_asn2err(result);
}
return 0; /* success */
@@ -264,7 +266,7 @@ static int oid2bag( const char* oid)
return GNUTLS_BAG_UNKNOWN;
}
-static const char* bag2oid( int bag)
+static const char* bag_to_oid( int bag)
{
switch (bag) {
case GNUTLS_BAG_PKCS8_KEY:
@@ -1050,7 +1052,7 @@ const char* oid;
for (i=0;i<bag->bag_elements;i++) {
- oid = bag2oid( bag->element[i].type);
+ oid = bag_to_oid( bag->element[i].type);
if (oid==NULL) {
gnutls_assert();
continue;
diff --git a/lib/x509/pkcs12_bag.c b/lib/x509/pkcs12_bag.c
index 6b9ab32ba1..466f4e7970 100644
--- a/lib/x509/pkcs12_bag.c
+++ b/lib/x509/pkcs12_bag.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/x509/pkcs12_encr.c b/lib/x509/pkcs12_encr.c
index c1501e62db..921bff9b86 100644
--- a/lib/x509/pkcs12_encr.c
+++ b/lib/x509/pkcs12_encr.c
@@ -1,7 +1,4 @@
-/* This is based on minip12.
- */
-
-/* minip12.c - A minilam pkcs-12 implementation.
+/* minip12.c - A mini pkcs-12 implementation (modified for gnutls)
* Copyright (C) 2002 Free Software Foundation, Inc.
*
* This file some day was part of GnuPG.
diff --git a/lib/x509/pkcs5.c b/lib/x509/pkcs5.c
index 15ce59c05c..c1c745b71e 100644
--- a/lib/x509/pkcs5.c
+++ b/lib/x509/pkcs5.c
@@ -1,5 +1,6 @@
/* pkcs5.c Implementation of Password-Based Cryptography as per PKCS#5
* Copyright (C) 2002,2003 Simon Josefsson
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/lib/x509/pkcs7.c b/lib/x509/pkcs7.c
index eb12fc1212..3b969f32fb 100644
--- a/lib/x509/pkcs7.c
+++ b/lib/x509/pkcs7.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -145,6 +146,7 @@ int gnutls_pkcs7_init(gnutls_pkcs7 * pkcs7)
&(*pkcs7)->pkcs7);
if (result != ASN1_SUCCESS) {
gnutls_assert();
+ gnutls_free( *pkcs7);
return _gnutls_asn2err(result);
}
return 0; /* success */
diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c
index b1dbeec086..4798e221dd 100644
--- a/lib/x509/privkey.c
+++ b/lib/x509/privkey.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -32,9 +33,11 @@
#include <mpi.h>
#include <extensions.h>
#include <sign.h>
+#include <dsa.h>
#include <verify.h>
static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params);
+static int _encode_dsa( ASN1_TYPE* c2, GNUTLS_MPI* params);
/**
* gnutls_x509_privkey_init - This function initializes a gnutls_crl structure
@@ -356,7 +359,9 @@ int gnutls_x509_privkey_import(gnutls_x509_privkey key, const gnutls_datum * dat
return result;
}
-#define FREE_PRIVATE_PARAMS for (i=0;i<RSA_PRIVATE_PARAMS;i++) \
+#define FREE_RSA_PRIVATE_PARAMS for (i=0;i<RSA_PRIVATE_PARAMS;i++) \
+ _gnutls_mpi_release(&key->params[i])
+#define FREE_DSA_PRIVATE_PARAMS for (i=0;i<DSA_PRIVATE_PARAMS;i++) \
_gnutls_mpi_release(&key->params[i])
/**
@@ -389,49 +394,49 @@ int gnutls_x509_privkey_import_rsa_raw(gnutls_x509_privkey key,
siz = m->size;
if (_gnutls_mpi_scan(&key->params[0], m->data, &siz)) {
gnutls_assert();
- FREE_PRIVATE_PARAMS;
+ FREE_RSA_PRIVATE_PARAMS;
return GNUTLS_E_MPI_SCAN_FAILED;
}
siz = e->size;
if (_gnutls_mpi_scan(&key->params[1], e->data, &siz)) {
gnutls_assert();
- FREE_PRIVATE_PARAMS;
+ FREE_RSA_PRIVATE_PARAMS;
return GNUTLS_E_MPI_SCAN_FAILED;
}
siz = d->size;
if (_gnutls_mpi_scan(&key->params[2], d->data, &siz)) {
gnutls_assert();
- FREE_PRIVATE_PARAMS;
+ FREE_RSA_PRIVATE_PARAMS;
return GNUTLS_E_MPI_SCAN_FAILED;
}
siz = p->size;
if (_gnutls_mpi_scan(&key->params[3], p->data, &siz)) {
gnutls_assert();
- FREE_PRIVATE_PARAMS;
+ FREE_RSA_PRIVATE_PARAMS;
return GNUTLS_E_MPI_SCAN_FAILED;
}
siz = q->size;
if (_gnutls_mpi_scan(&key->params[4], q->data, &siz)) {
gnutls_assert();
- FREE_PRIVATE_PARAMS;
+ FREE_RSA_PRIVATE_PARAMS;
return GNUTLS_E_MPI_SCAN_FAILED;
}
siz = u->size;
if (_gnutls_mpi_scan(&key->params[5], u->data, &siz)) {
gnutls_assert();
- FREE_PRIVATE_PARAMS;
+ FREE_RSA_PRIVATE_PARAMS;
return GNUTLS_E_MPI_SCAN_FAILED;
}
ret = _encode_rsa( &key->key, key->params);
if (ret < 0) {
gnutls_assert();
- FREE_PRIVATE_PARAMS;
+ FREE_RSA_PRIVATE_PARAMS;
return ret;
}
@@ -442,6 +447,81 @@ int gnutls_x509_privkey_import_rsa_raw(gnutls_x509_privkey key,
}
+/**
+ * gnutls_x509_privkey_import_dsa_raw - This function will import a raw DSA key
+ * @key: The structure to store the parsed key
+ * @p: holds the p
+ * @q: holds the q
+ * @g: holds the g
+ * @y: holds the y
+ * @x: holds the x
+ *
+ * This function will convert the given DSA raw parameters
+ * to the native gnutls_x509_privkey format. The output will be stored in @key.
+ *
+ **/
+int gnutls_x509_privkey_import_dsa_raw(gnutls_x509_privkey key,
+ const gnutls_datum* p, const gnutls_datum* q,
+ const gnutls_datum* g, const gnutls_datum* y,
+ const gnutls_datum* x)
+{
+ int i = 0, ret;
+ size_t siz = 0;
+
+ if (key == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ siz = p->size;
+ if (_gnutls_mpi_scan(&key->params[0], p->data, &siz)) {
+ gnutls_assert();
+ FREE_DSA_PRIVATE_PARAMS;
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ siz = q->size;
+ if (_gnutls_mpi_scan(&key->params[1], q->data, &siz)) {
+ gnutls_assert();
+ FREE_DSA_PRIVATE_PARAMS;
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ siz = g->size;
+ if (_gnutls_mpi_scan(&key->params[2], g->data, &siz)) {
+ gnutls_assert();
+ FREE_DSA_PRIVATE_PARAMS;
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ siz = y->size;
+ if (_gnutls_mpi_scan(&key->params[3], y->data, &siz)) {
+ gnutls_assert();
+ FREE_DSA_PRIVATE_PARAMS;
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ siz = x->size;
+ if (_gnutls_mpi_scan(&key->params[4], x->data, &siz)) {
+ gnutls_assert();
+ FREE_DSA_PRIVATE_PARAMS;
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ ret = _encode_dsa( &key->key, key->params);
+ if (ret < 0) {
+ gnutls_assert();
+ FREE_DSA_PRIVATE_PARAMS;
+ return ret;
+ }
+
+ key->params_size = DSA_PRIVATE_PARAMS;
+ key->pk_algorithm = GNUTLS_PK_DSA;
+
+ return 0;
+
+}
+
/**
* gnutls_x509_privkey_get_pk_algorithm - This function returns the key's PublicKey algorithm
@@ -623,6 +703,106 @@ int gnutls_x509_privkey_export_rsa_raw(gnutls_x509_privkey key,
}
+/**
+ * gnutls_x509_privkey_export_dsa_raw - This function will export the DSA private key
+ * @params: a structure that holds the DSA parameters
+ * @p: will hold the p
+ * @q: will hold the q
+ * @g: will hold the g
+ * @y: will hold the y
+ * @x: will hold the x
+ *
+ * This function will export the DSA private key's parameters found in the given
+ * structure. The new parameters will be allocated using
+ * gnutls_malloc() and will be stored in the appropriate datum.
+ *
+ **/
+int gnutls_x509_privkey_export_dsa_raw(gnutls_x509_privkey key,
+ gnutls_datum * p, gnutls_datum *q,
+ gnutls_datum *g, gnutls_datum *y, gnutls_datum* x)
+{
+ size_t siz;
+
+ if (key == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* P */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, key->params[0]);
+
+ p->data = gnutls_malloc(siz);
+ if (p->data == NULL) {
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ p->size = siz;
+ _gnutls_mpi_print( p->data, &siz, key->params[0]);
+
+ /* Q */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, key->params[1]);
+
+ q->data = gnutls_malloc(siz);
+ if (q->data == NULL) {
+ _gnutls_free_datum( p);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ q->size = siz;
+ _gnutls_mpi_print( q->data, &siz, key->params[1]);
+
+ /* G */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, key->params[2]);
+
+ g->data = gnutls_malloc(siz);
+ if (g->data == NULL) {
+ _gnutls_free_datum( q);
+ _gnutls_free_datum( p);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ g->size = siz;
+ _gnutls_mpi_print( g->data, &siz, key->params[2]);
+
+ /* Y */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, key->params[3]);
+
+ y->data = gnutls_malloc(siz);
+ if (y->data == NULL) {
+ _gnutls_free_datum( g);
+ _gnutls_free_datum( q);
+ _gnutls_free_datum( p);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ y->size = siz;
+ _gnutls_mpi_print(y->data, &siz, key->params[3]);
+
+ /* X */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, key->params[4]);
+
+ x->data = gnutls_malloc(siz);
+ if (x->data == NULL) {
+ _gnutls_free_datum( p);
+ _gnutls_free_datum( q);
+ _gnutls_free_datum( g);
+ _gnutls_free_datum( y);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ x->size = siz;
+ _gnutls_mpi_print(x->data, &siz, key->params[4]);
+
+ return 0;
+
+}
+
+
/* Encodes the RSA parameters into an ASN.1 RSA private key structure.
*/
static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params)
@@ -644,28 +824,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;
@@ -689,13 +869,13 @@ 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;
goto cleanup;
}
-
+
p = all_data;
m_data = p; p+= size[0];
pube_data = p; p+= size[1];
@@ -704,7 +884,7 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params)
p2_data = p; p+= size[4];
u_data = p; p+= size[5];
exp1_data = p; p+= size[6];
- exp2_data = p;
+ exp2_data = p;
_gnutls_mpi_print_lz( m_data, &size[0], params[0]);
_gnutls_mpi_print_lz( pube_data, &size[1], params[1]);
@@ -792,7 +972,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) {
@@ -816,7 +996,118 @@ 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;
+}
+
+/* Encodes the DSA parameters into an ASN.1 DSAPrivateKey structure.
+ */
+static int _encode_dsa( ASN1_TYPE* c2, GNUTLS_MPI* params)
+{
+ int result, i;
+ size_t size[DSA_PRIVATE_PARAMS], total;
+ opaque* p_data, *q_data, *g_data, *x_data, *y_data;
+ opaque * all_data = NULL, *p;
+ opaque null = '\0';
+
+ /* Read all the sizes */
+ total = 0;
+ for (i=0;i<DSA_PRIVATE_PARAMS;i++) {
+ _gnutls_mpi_print_lz( NULL, &size[i], params[i]);
+ total += size[i];
+ }
+
+ /* Encoding phase.
+ * allocate data enough to hold everything
+ */
+ all_data = gnutls_secure_malloc( total);
+ if (all_data == NULL) {
+ gnutls_assert();
+ result = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
+
+ p = all_data;
+ p_data = p; p += size[0];
+ q_data = p; p += size[1];
+ g_data = p; p += size[2];
+ y_data = p; p += size[3];
+ x_data = p;
+
+ _gnutls_mpi_print_lz( p_data, &size[0], params[0]);
+ _gnutls_mpi_print_lz( q_data, &size[1], params[1]);
+ _gnutls_mpi_print_lz( g_data, &size[2], params[2]);
+ _gnutls_mpi_print_lz( y_data, &size[3], params[3]);
+ _gnutls_mpi_print_lz( x_data, &size[4], params[4]);
+
+ /* Ok. Now we have the data. Create the asn1 structures
+ */
+
+ if ((result = asn1_create_element
+ (_gnutls_get_gnutls_asn(), "GNUTLS.DSAPrivateKey", c2))
+ != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ /* Write PRIME
+ */
+ if ((result = asn1_write_value(*c2, "p",
+ p_data, size[0])) != ASN1_SUCCESS)
+ {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if ((result = asn1_write_value(*c2, "q",
+ q_data, size[1])) != ASN1_SUCCESS)
+ {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if ((result = asn1_write_value(*c2, "g",
+ g_data, size[2])) != ASN1_SUCCESS)
+ {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if ((result = asn1_write_value(*c2, "Y",
+ y_data, size[3])) != ASN1_SUCCESS)
+ {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if ((result = asn1_write_value(*c2, "priv",
+ x_data, size[4])) != ASN1_SUCCESS)
+ {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ gnutls_free(all_data);
+
+ if ((result = asn1_write_value(*c2, "version",
+ &null, 1)) != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ return 0;
+
+ cleanup:
+ asn1_delete_structure(c2);
+ gnutls_free( all_data);
return result;
}
@@ -830,8 +1121,7 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params)
* @flags: unused for now. Must be 0.
*
* This function will generate a random private key. Note that
- * this function must be called on an empty private key. Currently only RSA
- * keys can be generated.
+ * this function must be called on an empty private key.
*
* Returns 0 on success or a negative value on error.
*
@@ -839,7 +1129,8 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params)
int gnutls_x509_privkey_generate( gnutls_x509_privkey key, gnutls_pk_algorithm algo,
unsigned int bits, unsigned int flags)
{
-int ret;
+int ret, params_len;
+int i;
if (key == NULL) {
gnutls_assert();
@@ -848,10 +1139,23 @@ int ret;
switch( algo) {
case GNUTLS_PK_DSA:
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
- case GNUTLS_PK_RSA:
- ret = _gnutls_rsa_generate_params( key->params, bits);
+ ret = _gnutls_dsa_generate_params( key->params, &params_len, bits);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+ ret = _encode_dsa( &key->key, key->params);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+ key->params_size = params_len;
+ key->pk_algorithm = GNUTLS_PK_DSA;
+
+ break;
+ case GNUTLS_PK_RSA:
+ ret = _gnutls_rsa_generate_params( key->params, &params_len, bits);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -862,7 +1166,7 @@ int ret;
gnutls_assert();
goto cleanup;
}
- key->params_size = 6;
+ key->params_size = params_len;
key->pk_algorithm = GNUTLS_PK_RSA;
break;
@@ -876,12 +1180,8 @@ int ret;
cleanup:
key->pk_algorithm = GNUTLS_PK_UNKNOWN;
key->params_size = 0;
- _gnutls_mpi_release(&key->params[0]);
- _gnutls_mpi_release(&key->params[1]);
- _gnutls_mpi_release(&key->params[2]);
- _gnutls_mpi_release(&key->params[3]);
- _gnutls_mpi_release(&key->params[4]);
- _gnutls_mpi_release(&key->params[5]);
+ for (i=0;i<params_len;i++)
+ _gnutls_mpi_release(&key->params[i]);
return ret;
}
@@ -930,7 +1230,7 @@ gnutls_datum der = { NULL, 0 };
goto cleanup;
}
} else if (key->pk_algorithm == GNUTLS_PK_DSA) {
- result = _gnutls_x509_write_dsa_params( key->params, key->params_size, &der);
+ result = _gnutls_x509_write_dsa_public_key( key->params, key->params_size, &der);
if (result < 0) {
gnutls_assert();
goto cleanup;
diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c
index 433436fa3b..93a67d41d6 100644
--- a/lib/x509/privkey_pkcs8.c
+++ b/lib/x509/privkey_pkcs8.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -605,7 +606,7 @@ int decode_pkcs8_key(const gnutls_datum * raw_key,
gnutls_x509_privkey pkey, ASN1_TYPE* out)
{
int result, len;
- opaque enc_oid[64];
+ char enc_oid[64];
gnutls_datum tmp;
ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY, pkcs8_asn = ASN1_TYPE_EMPTY;
ASN1_TYPE ret_asn;
@@ -1701,7 +1702,7 @@ int _gnutls_pkcs7_decrypt_data(const gnutls_datum * data,
gnutls_datum * dec)
{
int result, len;
- opaque enc_oid[64];
+ char enc_oid[64];
gnutls_datum tmp;
ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY, pkcs7_asn = ASN1_TYPE_EMPTY;
int params_start, params_end, params_len;
diff --git a/lib/x509/rc2.c b/lib/x509/rc2.c
index b993d44793..982d556f25 100644
--- a/lib/x509/rc2.c
+++ b/lib/x509/rc2.c
@@ -1,5 +1,6 @@
/* rc2.c - The RC2 stream cipher
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/x509/rfc2818_hostname.c b/lib/x509/rfc2818_hostname.c
index 7c19c228db..d07b113e9c 100644
--- a/lib/x509/rfc2818_hostname.c
+++ b/lib/x509/rfc2818_hostname.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2002 Andrew McDonald
* Portions Copyright 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -25,80 +26,8 @@
#include <x509.h>
#include <dn.h>
#include <common.h>
-#include <gnutls/compat8.h>
#include <rfc2818.h>
-
-/*-
- * gnutls_x509_check_certificates_hostname - This function compares the given hostname with the hostname in the certificate
- * @cert: should contain a DER encoded certificate
- * @hostname: A null terminated string that contains a DNS name
- *
- * This function will check if the given certificate's subject matches
- * the given hostname. This is a basic implementation of the matching
- * described in RFC2818 (HTTPS), which takes into account wildcards.
- *
- * Returns non zero on success, and zero on failure.
- *
- -*/
-int gnutls_x509_check_certificates_hostname(const gnutls_datum * cert,
- const char *hostname)
-{
- char dnsname[MAX_CN];
- int dnsnamesize;
- int found_dnsname = 0;
- int ret = 0;
- gnutls_x509_dn dn;
- int i = 0;
-
- /* try matching against:
- * 1) a DNS name as an alternative name (subjectAltName) extension
- * in the certificate
- * 2) the common name (CN) in the certificate
- *
- * either of these may be of the form: *.domain.tld
- *
- * only try (2) if there is no subjectAltName extension of
- * type dNSName
- */
-
- /* Check through all included subjectAltName extensions, comparing
- * against all those of type dNSName.
- */
- for (i = 0; !(ret < 0); i++) {
-
- dnsnamesize = MAX_CN;
- ret =
- gnutls_x509_extract_certificate_subject_alt_name(cert, i,
- dnsname,
- &dnsnamesize);
-
- if (ret == GNUTLS_SAN_DNSNAME) {
- found_dnsname = 1;
- if (_gnutls_hostname_compare(dnsname, hostname)) {
- return 1;
- }
- }
-
- }
-
- if (!found_dnsname) {
- /* not got the necessary extension, use CN instead
- */
- if (gnutls_x509_extract_certificate_dn(cert, &dn) != 0) {
- /* got an error, can't find a name
- */
- return 0;
- }
-
- if (_gnutls_hostname_compare(dn.common_name, hostname)) {
- return 1;
- }
- }
-
- /* not found a matching name
- */
- return 0;
-}
+#include <gnutls_errors.h>
/* compare hostname against certificate, taking account of wildcards
* return 1 on success or 0 on error
@@ -144,7 +73,8 @@ int _gnutls_hostname_compare(const char *certname, const char *hostname)
*
* This function will check if the given certificate's subject matches
* the given hostname. This is a basic implementation of the matching
- * described in RFC2818 (HTTPS), which takes into account wildcards.
+ * described in RFC2818 (HTTPS), which takes into account wildcards,
+ * and the subject alternative name PKIX extension.
*
* Returns non zero on success, and zero on failure.
*
@@ -183,7 +113,7 @@ int gnutls_x509_crt_check_hostname(gnutls_x509_crt cert,
if (ret == GNUTLS_SAN_DNSNAME) {
found_dnsname = 1;
if (_gnutls_hostname_compare(dnsname, hostname)) {
- return 1;
+ return GNUTLS_E_NAME_DOES_NOT_MATCH;
}
}
@@ -194,14 +124,14 @@ int gnutls_x509_crt_check_hostname(gnutls_x509_crt cert,
*/
dnsnamesize = sizeof(dnsname);
if (gnutls_x509_crt_get_dn_by_oid(cert, OID_X520_COMMON_NAME, 0,
- 0, dnsname, &dnsnamesize) != 0) {
+ 0, dnsname, &dnsnamesize) < 0) {
/* got an error, can't find a name
*/
- return 0;
+ return GNUTLS_E_NAME_DOES_NOT_MATCH;
}
if (_gnutls_hostname_compare(dnsname, hostname)) {
- return 1;
+ return GNUTLS_E_NAME_DOES_NOT_MATCH;
}
}
diff --git a/lib/x509/sign.c b/lib/x509/sign.c
index 3a45b0ecb1..b63724e060 100644
--- a/lib/x509/sign.c
+++ b/lib/x509/sign.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos <nmav@hellug.gr>
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -52,7 +53,7 @@ ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
int result;
const char* algo;
- algo = _gnutls_x509_mac2oid( hash);
+ algo = _gnutls_x509_mac_to_oid( hash);
if (algo == NULL) {
gnutls_assert();
return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
@@ -116,7 +117,7 @@ const char* algo;
* params[1] is public key
*/
static int
-_pkcs1_rsa_sign( gnutls_mac_algorithm hash, const gnutls_datum* text,
+pkcs1_rsa_sign( gnutls_mac_algorithm hash, const gnutls_datum* text,
GNUTLS_MPI *params, int params_len, gnutls_datum* signature)
{
int ret;
@@ -154,6 +155,35 @@ _pkcs1_rsa_sign( gnutls_mac_algorithm hash, const gnutls_datum* text,
return 0;
}
+static int
+dsa_sign( const gnutls_datum* text,
+ GNUTLS_MPI *params, int params_len, gnutls_datum* signature)
+{
+ int ret;
+ opaque _digest[MAX_HASH_SIZE];
+ GNUTLS_HASH_HANDLE hd;
+ gnutls_datum digest;
+
+ hd = _gnutls_hash_init( GNUTLS_MAC_SHA);
+ if (hd == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ _gnutls_hash( hd, text->data, text->size);
+ _gnutls_hash_deinit( hd, _digest);
+
+ digest.data = _digest;
+ digest.size = 20;
+
+ if ( (ret=_gnutls_sign( GNUTLS_PK_DSA, params, params_len, &digest, signature)) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ return 0;
+}
+
/* Signs the given data using the parameters from the signer's
* private key.
*
@@ -171,7 +201,7 @@ int ret;
switch( signer->pk_algorithm)
{
case GNUTLS_PK_RSA:
- ret = _pkcs1_rsa_sign( hash, tbs, signer->params, signer->params_size,
+ ret = pkcs1_rsa_sign( hash, tbs, signer->params, signer->params_size,
signature);
if (ret < 0) {
gnutls_assert();
@@ -180,7 +210,7 @@ int ret;
return 0;
break;
case GNUTLS_PK_DSA:
- ret = _gnutls_dsa_sign( signature, tbs, signer->params, signer->params_size);
+ ret = dsa_sign( tbs, signer->params, signer->params_size, signature);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -233,4 +263,82 @@ gnutls_datum tbs;
return result;
}
+/*-
+ * _gnutls_x509_pkix_sign - This function will sign a CRL or a certificate with a key
+ * @src: should contain an ASN1_TYPE
+ * @issuer: is the certificate of the certificate issuer
+ * @issuer_key: holds the issuer's private key
+ *
+ * This function will sign a CRL or a certificate with the issuer's private key, and
+ * will copy the issuer's information into the CRL or certificate.
+ *
+ * Returns 0 on success.
+ *
+ -*/
+int _gnutls_x509_pkix_sign(ASN1_TYPE src, const char* src_name,
+ gnutls_x509_crt issuer, gnutls_x509_privkey issuer_key)
+{
+int result;
+gnutls_datum signature;
+char name[128];
+
+ /* Step 1. Copy the issuer's name into the certificate.
+ */
+ _gnutls_str_cpy( name, sizeof(name), src_name);
+ _gnutls_str_cat( name, sizeof(name), ".issuer");
+
+ result = _gnutls_asn1_copy_node( &src, name,
+ issuer->cert, "tbsCertificate.subject");
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ /* Step 1.5. Write the signature stuff in the tbsCertificate.
+ */
+ _gnutls_str_cpy( name, sizeof(name), src_name);
+ _gnutls_str_cat( name, sizeof(name), ".signature");
+
+ result = _gnutls_x509_write_sig_params( src, name,
+ issuer_key->pk_algorithm, issuer_key->params, issuer_key->params_size);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ /* Step 2. Sign the certificate.
+ */
+ result = _gnutls_x509_sign_tbs( src, src_name, GNUTLS_MAC_SHA,
+ issuer_key, &signature);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ /* write the signature (bits)
+ */
+ result = asn1_write_value( src, "signature", signature.data, signature.size*8);
+
+ _gnutls_free_datum( &signature);
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ /* Step 3. Move up and write the AlgorithmIdentifier, which is also
+ * the same.
+ */
+
+ result = _gnutls_x509_write_sig_params( src, "signatureAlgorithm",
+ issuer_key->pk_algorithm, issuer_key->params, issuer_key->params_size);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ return 0;
+}
+
#endif
diff --git a/lib/x509/sign.h b/lib/x509/sign.h
index dd6936f346..08e0475f72 100644
--- a/lib/x509/sign.h
+++ b/lib/x509/sign.h
@@ -2,3 +2,5 @@ int _gnutls_x509_sign( const gnutls_datum* tbs, gnutls_mac_algorithm hash,
gnutls_x509_privkey signer, gnutls_datum* signature);
int _gnutls_x509_sign_tbs( ASN1_TYPE cert, const char* tbs_name,
gnutls_mac_algorithm hash, gnutls_x509_privkey signer, gnutls_datum* signature);
+int _gnutls_x509_pkix_sign(ASN1_TYPE src, const char* src_name,
+ gnutls_x509_crt issuer, gnutls_x509_privkey issuer_key);
diff --git a/lib/x509/verify.c b/lib/x509/verify.c
index 24c7cdb702..9b3f658b00 100644
--- a/lib/x509/verify.c
+++ b/lib/x509/verify.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos <nmav@hellug.gr>
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -459,6 +460,34 @@ _pkcs1_rsa_verify_sig( const gnutls_datum* text, const gnutls_datum* signature,
return 0;
}
+/* Hashes input data and verifies a DSA signature.
+ */
+static int
+dsa_verify_sig( const gnutls_datum* text, const gnutls_datum* signature,
+ GNUTLS_MPI *params, int params_len)
+{
+ int ret;
+ opaque _digest[MAX_HASH_SIZE];
+ gnutls_datum digest;
+ GNUTLS_HASH_HANDLE hd;
+
+ hd = _gnutls_hash_init( GNUTLS_MAC_SHA);
+ if (hd == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ _gnutls_hash( hd, text->data, text->size);
+ _gnutls_hash_deinit( hd, _digest);
+
+ digest.data = _digest;
+ digest.size = 20;
+
+ ret = _gnutls_dsa_verify( &digest, signature, params, params_len);
+
+ return ret;
+}
+
/* Verifies the signature data, and returns 0 if not verified,
* or 1 otherwise.
*/
@@ -479,7 +508,7 @@ static int verify_sig( const gnutls_datum* tbs, const gnutls_datum* signature,
break;
case GNUTLS_PK_DSA:
- if (_gnutls_dsa_verify( tbs, signature, issuer_params, issuer_params_size)!=0) {
+ if (dsa_verify_sig( tbs, signature, issuer_params, issuer_params_size)!=0) {
gnutls_assert();
return 0;
}
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index d6d78592af..96096d6aaf 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -57,6 +58,7 @@ int gnutls_x509_crt_init(gnutls_x509_crt * cert)
&(*cert)->cert);
if (result != ASN1_SUCCESS) {
gnutls_assert();
+ gnutls_free( *cert);
return _gnutls_asn2err(result);
}
return 0; /* success */
@@ -214,7 +216,7 @@ int gnutls_x509_crt_import(gnutls_x509_crt cert, const gnutls_datum * data,
* gnutls_x509_crt_get_issuer_dn - This function returns the Certificate's issuer distinguished name
* @cert: should contain a gnutls_x509_crt structure
* @buf: a pointer to a structure to hold the name (may be null)
- * @sizeof_buf: initialy holds the size of 'buf'
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will copy the name of the Certificate issuer in the provided buffer. The name
* will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output
@@ -246,7 +248,7 @@ int gnutls_x509_crt_get_issuer_dn(gnutls_x509_crt cert, char *buf,
* @indx: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one.
* @raw_flag: If non zero returns the raw DER data of the DN part.
* @buf: a pointer to a structure to hold the name (may be null)
- * @sizeof_buf: initialy holds the size of @buf
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will extract the part of the name of the Certificate issuer specified
* by the given OID. The output will be encoded as described in RFC2253. The output
@@ -281,7 +283,7 @@ int gnutls_x509_crt_get_issuer_dn_by_oid(gnutls_x509_crt cert, const char* oid,
* @cert: should contain a gnutls_x509_crt structure
* @indx: This specifies which OID to return. Use zero to get the first one.
* @oid: a pointer to a buffer to hold the OID (may be null)
- * @sizeof_oid: initialy holds the size of @oid
+ * @sizeof_oid: initially holds the size of @oid
*
* This function will extract the OIDs of the name of the Certificate issuer specified
* by the given index.
@@ -309,7 +311,7 @@ int gnutls_x509_crt_get_issuer_dn_oid(gnutls_x509_crt cert,
* gnutls_x509_crt_get_dn - This function returns the Certificate's distinguished name
* @cert: should contain a gnutls_x509_crt structure
* @buf: a pointer to a structure to hold the name (may be null)
- * @sizeof_buf: initialy holds the size of @buf
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will copy the name of the Certificate in the provided buffer. The name
* will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output
@@ -341,7 +343,7 @@ int gnutls_x509_crt_get_dn(gnutls_x509_crt cert, char *buf,
* @indx: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one.
* @raw_flag: If non zero returns the raw DER data of the DN part.
* @buf: a pointer to a structure to hold the name (may be null)
- * @sizeof_buf: initialy holds the size of @buf
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will extract the part of the name of the Certificate subject, specified
* by the given OID. The output
@@ -376,7 +378,7 @@ int gnutls_x509_crt_get_dn_by_oid(gnutls_x509_crt cert, const char* oid,
* @cert: should contain a gnutls_x509_crt structure
* @indx: This specifies which OID to return. Use zero to get the first one.
* @oid: a pointer to a buffer to hold the OID (may be null)
- * @sizeof_oid: initialy holds the size of @oid
+ * @sizeof_oid: initially holds the size of @oid
*
* This function will extract the OIDs of the name of the Certificate subject specified
* by the given index.
@@ -404,7 +406,7 @@ int gnutls_x509_crt_get_dn_oid(gnutls_x509_crt cert,
* gnutls_x509_crt_get_signature_algorithm - This function returns the Certificate's signature algorithm
* @cert: should contain a gnutls_x509_crt structure
*
- * This function will return a value of the gnutls_pk_algorithm enumeration that
+ * This function will return a value of the gnutls_sign_algorithm enumeration that
* is the signature algorithm.
*
* Returns a negative value on error.
@@ -430,7 +432,7 @@ int gnutls_x509_crt_get_signature_algorithm(gnutls_x509_crt cert)
return result;
}
- result = _gnutls_x509_oid2sign_algorithm( sa.data, NULL);
+ result = _gnutls_x509_oid2sign_algorithm( sa.data);
_gnutls_free_datum( &sa);
@@ -537,7 +539,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;
}
/**
@@ -578,6 +655,66 @@ int gnutls_x509_crt_get_pk_algorithm( gnutls_x509_crt cert, unsigned int* bits)
}
+/* returns the type and the name.
+ */
+static int parse_general_name( ASN1_TYPE src, const char* src_name,
+ int seq, void* name, size_t *name_size)
+{
+int len;
+char num[MAX_INT_DIGITS];
+char nptr[128];
+int result;
+opaque choice_type[128];
+gnutls_x509_subject_alt_name type;
+
+ seq++; /* 0->1, 1->2 etc */
+ _gnutls_int2str( seq, num);
+
+ _gnutls_str_cpy( nptr, sizeof(nptr), src_name);
+ if (src_name[0] != 0) _gnutls_str_cat( nptr, sizeof(nptr), ".");
+
+ _gnutls_str_cat( nptr, sizeof(nptr), "?");
+ _gnutls_str_cat( nptr, sizeof(nptr), num);
+
+ len = sizeof(choice_type);
+ result =
+ asn1_read_value(src, nptr, choice_type, &len);
+
+ 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);
+ }
+
+
+ type = _gnutls_x509_san_find_type( choice_type);
+ if (type == (gnutls_x509_subject_alt_name)-1) {
+ gnutls_assert();
+ return GNUTLS_E_X509_UNKNOWN_SAN;
+ }
+
+ _gnutls_str_cat( nptr, sizeof(nptr), ".");
+ _gnutls_str_cat( nptr, sizeof(nptr), choice_type);
+
+ len = *name_size;
+ result =
+ asn1_read_value(src, nptr, name, &len);
+ *name_size = len;
+
+ if (result==ASN1_MEM_ERROR)
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ return type;
+}
+
/**
* gnutls_x509_crt_get_subject_alt_name - This function returns the certificate's alternative name, if any
* @cert: should contain a gnutls_x509_crt structure
@@ -602,15 +739,11 @@ int gnutls_x509_crt_get_pk_algorithm( gnutls_x509_crt cert, unsigned int* bits)
*
**/
int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt cert,
- int seq, void *ret, size_t *ret_size, unsigned int *critical)
+ unsigned int seq, void *ret, size_t *ret_size, unsigned int *critical)
{
int result;
gnutls_datum dnsname;
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
- char nptr[128];
- char ext_data[256];
- int len;
- char num[MAX_INT_DIGITS];
gnutls_x509_subject_alt_name type;
if (cert==NULL) {
@@ -623,7 +756,6 @@ int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt cert,
if ((result =
_gnutls_x509_crt_get_extension(cert, "2.5.29.17", 0, &dnsname, critical)) < 0) {
- gnutls_assert();
return result;
}
@@ -632,9 +764,9 @@ int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt cert,
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
- if ((result=asn1_create_element
- (_gnutls_get_pkix(), "PKIX1.SubjectAltName", &c2))
- != ASN1_SUCCESS) {
+ result=asn1_create_element
+ (_gnutls_get_pkix(), "PKIX1.SubjectAltName", &c2);
+ if (result != ASN1_SUCCESS) {
gnutls_assert();
_gnutls_free_datum( &dnsname);
return _gnutls_asn2err(result);
@@ -644,59 +776,21 @@ 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);
}
- seq++; /* 0->1, 1->2 etc */
- _gnutls_int2str( seq, num);
- _gnutls_str_cpy( nptr, sizeof(nptr), "?");
- _gnutls_str_cat( nptr, sizeof(nptr), num);
-
- len = sizeof(ext_data);
- result =
- asn1_read_value(c2, nptr, ext_data, &len);
+ result = parse_general_name( c2, "", seq, ret, ret_size);
- if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND) {
- asn1_delete_structure(&c2);
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
-
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- asn1_delete_structure(&c2);
- return _gnutls_asn2err(result);
- }
-
-
- type = _gnutls_x509_san_find_type( ext_data);
- if (type == (gnutls_x509_subject_alt_name)-1) {
- asn1_delete_structure(&c2);
- gnutls_assert();
- return GNUTLS_E_X509_UNKNOWN_SAN;
- }
-
- _gnutls_str_cat( nptr, sizeof(nptr), ".");
- _gnutls_str_cat( nptr, sizeof(nptr), ext_data);
-
- len = *ret_size;
- result =
- asn1_read_value(c2, nptr, ret, &len);
asn1_delete_structure(&c2);
- *ret_size = len;
- if (result==ASN1_MEM_ERROR)
- return GNUTLS_E_SHORT_MEMORY_BUFFER;
-
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
+ if (result < 0) {
+ return result;
}
+ type = result;
+
return type;
}
@@ -810,7 +904,7 @@ int gnutls_x509_crt_get_key_usage(gnutls_x509_crt cert, unsigned int *key_usage,
* @oid: holds an Object Identified in null terminated string
* @indx: In case multiple same OIDs exist in the extensions, this specifies which to send. Use zero to get the first one.
* @buf: a pointer to a structure to hold the name (may be null)
- * @sizeof_buf: initialy holds the size of @buf
+ * @sizeof_buf: initially holds the size of @buf
* @critical: will be non zero if the extension is marked as critical
*
* This function will return the extension specified by the OID in the certificate.
@@ -866,7 +960,7 @@ int gnutls_x509_crt_get_extension_by_oid(gnutls_x509_crt cert, const char* oid,
* @cert: should contain a gnutls_x509_crt structure
* @indx: Specifies which extension OID to send. Use zero to get the first one.
* @oid: a pointer to a structure to hold the OID (may be null)
- * @sizeof_oid: initialy holds the size of @oid
+ * @sizeof_oid: initially holds the size of @oid
*
* This function will return the requested extension OID in the certificate.
* The extension OID will be stored as a string in the provided buffer.
@@ -886,9 +980,9 @@ int gnutls_x509_crt_get_extension_oid(gnutls_x509_crt cert, int indx,
return GNUTLS_E_INVALID_REQUEST;
}
- if ((result =
- _gnutls_x509_crt_get_extension_oid(cert, indx, oid, sizeof_oid)) < 0) {
- gnutls_assert();
+ result =
+ _gnutls_x509_crt_get_extension_oid(cert, indx, oid, sizeof_oid);
+ if (result < 0) {
return result;
}
@@ -923,7 +1017,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);
@@ -992,7 +1085,7 @@ int _gnutls_x509_crt_get_raw_dn( gnutls_x509_crt cert,
* @cert: should contain a gnutls_x509_crt structure
* @algo: is a digest algorithm
* @buf: a pointer to a structure to hold the fingerprint (may be null)
- * @sizeof_buf: initialy holds the size of @buf
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will calculate and copy the certificate's fingerprint
* in the provided buffer.
@@ -1136,7 +1229,7 @@ GNUTLS_HASH_HANDLE hd;
goto cleanup;
}
} else if (pk == GNUTLS_PK_DSA) {
- result = _gnutls_x509_write_dsa_params( params, params_size, &der);
+ result = _gnutls_x509_write_dsa_public_key( params, params_size, &der);
if (result < 0) {
gnutls_assert();
goto cleanup;
@@ -1305,4 +1398,122 @@ int result;
return result;
}
+/**
+ * gnutls_x509_crt_get_crl_dist_points - This function returns the CRL distribution points
+ * @cert: should contain a gnutls_x509_crt structure
+ * @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
+ * given certificate.
+ *
+ * @reason_flags should be an ORed sequence of GNUTLS_CRL_REASON_UNUSED,
+ * GNUTLS_CRL_REASON_KEY_COMPROMISE, GNUTLS_CRL_REASON_CA_COMPROMISE,
+ * GNUTLS_CRL_REASON_AFFILIATION_CHANGED, GNUTLS_CRL_REASON_SUPERSEEDED,
+ * GNUTLS_CRL_REASON_CESSATION_OF_OPERATION, GNUTLS_CRL_REASON_CERTIFICATE_HOLD,
+ * GNUTLS_CRL_REASON_PRIVILEGE_WITHDRAWN, GNUTLS_CRL_REASON_AA_COMPROMISE,
+ * or zero for all possible reasons.
+ *
+ * This is specified in X509v3 Certificate Extensions. GNUTLS will return the
+ * distribution point type, or a negative error code on error.
+ *
+ * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if ret_size is not enough to hold the distribution
+ * point, or the type of the distribution point if everything was ok. The type is
+ * one of the enumerated gnutls_x509_subject_alt_name.
+ *
+ * If the certificate does not have an Alternative name with the specified
+ * sequence number then returns GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ *
+ **/
+int gnutls_x509_crt_get_crl_dist_points(gnutls_x509_crt cert,
+ unsigned int seq, void *ret, size_t *ret_size,
+ unsigned int* reason_flags, unsigned int *critical)
+{
+ int result;
+ gnutls_datum dist_points = {NULL, 0};
+ ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+ char name[128];
+ int len;
+ char num[MAX_INT_DIGITS];
+ gnutls_x509_subject_alt_name type;
+ uint8 reasons[2];
+
+ if (cert==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ 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);
+ if (result < 0) {
+ return result;
+ }
+
+ if (dist_points.size == 0 || dist_points.data==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ result=asn1_create_element
+ (_gnutls_get_pkix(), "PKIX1.CRLDistributionPoints", &c2);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ _gnutls_free_datum( &dist_points);
+ return _gnutls_asn2err(result);
+ }
+
+ result = asn1_der_decoding(&c2, dist_points.data, dist_points.size, NULL);
+ _gnutls_free_datum( &dist_points);
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ asn1_delete_structure(&c2);
+ return _gnutls_asn2err(result);
+ }
+
+ /* Return the different names from the first CRLDistr. point.
+ * The whole thing is a mess.
+ */
+ _gnutls_str_cpy( name, sizeof(name), "?1.distributionPoint.fullName");
+
+ result = parse_general_name( c2, name, seq, ret, ret_size);
+ if (result < 0) {
+ asn1_delete_structure(&c2);
+ return result;
+ }
+
+ type = result;
+
+
+ /* Read the CRL reasons.
+ */
+ if (reason_flags) {
+ _gnutls_str_cpy( name, sizeof(name), "?");
+ _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);
+ }
+
+ return type;
+}
+
#endif
diff --git a/lib/x509/x509.h b/lib/x509/x509.h
index 72e66c21ed..ee5c949e1a 100644
--- a/lib/x509/x509.h
+++ b/lib/x509/x509.h
@@ -61,7 +61,7 @@ typedef struct gnutls_x509_privkey_int *gnutls_x509_privkey;
int gnutls_x509_crt_get_issuer_dn_by_oid(gnutls_x509_crt cert, const char* oid,
int indx, unsigned int raw_flag, void *buf, size_t *sizeof_buf);
int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt cert,
- int seq, void *ret, size_t *ret_size, unsigned int* critical);
+ unsigned int seq, void *ret, size_t *ret_size, unsigned int* critical);
int gnutls_x509_crt_get_dn_by_oid(gnutls_x509_crt cert, const char* oid,
int indx, unsigned int raw_flag, void *buf, size_t *sizeof_buf);
int gnutls_x509_crt_get_ca_status(gnutls_x509_crt cert, unsigned int* critical);
@@ -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 77e59d2b10..d458c252f2 100644
--- a/lib/x509/x509_write.c
+++ b/lib/x509/x509_write.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -19,7 +20,7 @@
*
*/
-/* This file contains functions to handle PKCS #10 certificate requests.
+/* This file contains functions to handle X.509 certificate generation.
*/
#include <gnutls_int.h>
@@ -122,15 +123,14 @@ 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 result;
-char null = version;
+unsigned char null = version;
if (crt==NULL) {
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
- null -= 1;
- if (null < 0) null = 0;
+ if (null > 0) null--;
result = asn1_write_value( crt->cert, "tbsCertificate.version", &null, 1);
if (result != ASN1_SUCCESS) {
@@ -196,11 +196,6 @@ int pk_algorithm;
pk_algorithm = gnutls_x509_crq_get_pk_algorithm( crq, NULL);
- if (pk_algorithm != GNUTLS_PK_RSA) {
- gnutls_assert();
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
- }
-
result = _gnutls_asn1_copy_node( &crt->cert, "tbsCertificate.subject",
crq->crq, "certificationRequestInfo.subject");
if (result < 0) {
@@ -222,7 +217,7 @@ int pk_algorithm;
/**
* gnutls_x509_crt_set_ca_status - This function will set the basicConstraints extension
* @crt: should contain a gnutls_x509_crt structure
- * @ca: true(1) or false(0). Depending on the Certificat authority status.
+ * @ca: true(1) or false(0). Depending on the Certificate authority status.
*
* This function will set the basicConstraints certificate extension.
*
@@ -262,6 +257,48 @@ gnutls_datum der_data;
}
/**
+ * gnutls_x509_crt_set_key_usage - This function will set the keyUsage extension
+ * @crt: should contain a gnutls_x509_crt structure
+ * @usage: an ORed sequence of the GNUTLS_KEY_* elements.
+ *
+ * This function will set the keyUsage certificate extension.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int gnutls_x509_crt_set_key_usage(gnutls_x509_crt crt, unsigned int usage)
+{
+int result;
+gnutls_datum der_data;
+
+ if (crt==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* generate the extension.
+ */
+ result = _gnutls_x509_ext_gen_keyUsage( (uint16)usage, &der_data);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ result = _gnutls_x509_crt_set_extension( crt, "2.5.29.15", &der_data, 1);
+
+ _gnutls_free_datum( &der_data);
+
+ if (result < 0) {
+ gnutls_assert();
+ 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
@@ -336,105 +373,23 @@ int gnutls_x509_crt_sign(gnutls_x509_crt crt, gnutls_x509_crt issuer,
gnutls_x509_privkey issuer_key)
{
int result;
-gnutls_datum signature;
-const char* pk;
if (crt==NULL || issuer == NULL) {
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
- if (issuer_key->pk_algorithm != GNUTLS_PK_RSA) {
- gnutls_assert();
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
- }
-
/* disable all the unneeded OPTIONAL fields.
*/
disable_optional_stuff( crt);
-
- /* Step 1. Copy the issuer's name into the certificate.
- */
- result = _gnutls_asn1_copy_node( &crt->cert, "tbsCertificate.issuer",
- issuer->cert, "tbsCertificate.subject");
- if (result < 0) {
- gnutls_assert();
- return result;
- }
-
- /* Step 1.5. Write the signature stuff in the tbsCertificate.
- */
- /* write the RSA OID
- */
- pk = _gnutls_x509_sign2oid( issuer_key->pk_algorithm, GNUTLS_MAC_SHA);
- if (pk == NULL) {
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- result = asn1_write_value( crt->cert, "tbsCertificate.signature.algorithm", pk, 1);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- /* disable parameters, which are not used in RSA.
- */
- result = asn1_write_value( crt->cert, "tbsCertificate.signature.parameters", NULL, 0);
- if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) {
- /* Here we ignore the element not found error, since this
- * may have been disabled before.
- */
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- /* Step 2. Sign the certificate.
- */
- result = _gnutls_x509_sign_tbs( crt->cert, "tbsCertificate", GNUTLS_MAC_SHA,
- issuer_key, &signature);
-
+ result = _gnutls_x509_pkix_sign( crt->cert, "tbsCertificate", issuer,
+ issuer_key);
if (result < 0) {
gnutls_assert();
return result;
}
-
- /* write the signature (bits)
- */
- result = asn1_write_value( crt->cert, "signature", signature.data, signature.size*8);
-
- _gnutls_free_datum( &signature);
-
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- /* Step 2. Move up and write the AlgorithmIdentifier, which is also
- * the same.
- */
-
-
- /* write the RSA OID
- */
- result = asn1_write_value( crt->cert, "signatureAlgorithm.algorithm", pk, 1);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- /* disable parameters, which are not used in RSA.
- */
- result = asn1_write_value( crt->cert, "signatureAlgorithm.parameters", NULL, 0);
- if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) {
- /* Here we ignore the element not found error, since this
- * may have been disabled before.
- */
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
+
return 0;
}
@@ -481,7 +436,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
@@ -491,7 +446,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;
@@ -501,8 +456,8 @@ int gnutls_x509_crt_set_serial(gnutls_x509_crt cert, const unsigned char* serial
return GNUTLS_E_INVALID_REQUEST;
}
- if ((ret = asn1_write_value(cert->cert, "tbsCertificate.serialNumber", serial, serial_size)) < 0)
- {
+ ret = asn1_write_value(cert->cert, "tbsCertificate.serialNumber", serial, serial_size);
+ if (ret != ASN1_SUCCESS) {
gnutls_assert();
return _gnutls_asn2err(ret);
}
@@ -529,5 +484,161 @@ static void disable_optional_stuff( gnutls_x509_crt cert)
return;
}
+/**
+ * gnutls_x509_crt_set_crl_dist_points - This function will set the CRL dist points
+ * @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.
+ *
+ * Returns 0 on success.
+ *
+ **/
+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)
+{
+int result;
+gnutls_datum der_data;
+gnutls_datum oldname;
+unsigned int critical;
+
+ if (crt==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* Check if the extension already exists.
+ */
+ result = _gnutls_x509_crt_get_extension(crt, "2.5.29.31", 0, &oldname, &critical);
+
+ if (result >= 0) _gnutls_free_datum( &oldname);
+ if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* generate the extension.
+ */
+ result = _gnutls_x509_ext_gen_crl_dist_points( type, data_string, reason_flags, &der_data);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ result = _gnutls_x509_crt_set_extension( crt, "2.5.29.31", &der_data, 0);
+
+ _gnutls_free_datum( &der_data);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ crt->use_extensions = 1;
+
+ return 0;
+}
+
+/**
+ * gnutls_x509_crt_cpy_crl_dist_points - This function will copy the CRL dist points
+ * @dst: should contain a gnutls_x509_crt structure
+ * @src: the certificate where the dist points will be copied from
+ *
+ * This function will copy the CRL distribution points certificate
+ * extension, from the source to the destination certificate.
+ * This may be useful to copy from a CA certificate to issued ones.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int gnutls_x509_crt_cpy_crl_dist_points(gnutls_x509_crt dst,
+ gnutls_x509_crt src)
+{
+int result;
+gnutls_datum der_data;
+unsigned int critical;
+
+ if (dst==NULL || src == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* Check if the extension already exists.
+ */
+ result = _gnutls_x509_crt_get_extension(src, "2.5.29.31", 0, &der_data, &critical);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ result = _gnutls_x509_crt_set_extension( dst, "2.5.29.31", &der_data, critical);
+ _gnutls_free_datum( &der_data);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ dst->use_extensions = 1;
+
+ 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/lib/x509/xml.c b/lib/x509/xml.c
index 5c3ec65f94..4cac03abe4 100644
--- a/lib/x509/xml.c
+++ b/lib/x509/xml.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -603,7 +604,7 @@ _gnutls_asn1_get_structure_xml(ASN1_TYPE structure,
* @detail: The detail level (must be GNUTLS_XML_SHOW_ALL or GNUTLS_XML_NORMAL)
*
* This function will return the XML structures of the given X.509 certificate.
- * The XML structures are allocated internaly (with malloc) and stored into res.
+ * The XML structures are allocated internally (with malloc) and stored into res.
* Returns a negative error code in case of an error.
*
**/
diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c
index 707ee10ed0..fac7e054ef 100644
--- a/src/certtool-gaa.c
+++ b/src/certtool-gaa.c
@@ -1,4 +1,4 @@
-/* File generated by GAA 1.6.2
+/* File generated by GAA 1.6.5
*/
#define GAA_NO_WIN32
#line 1 "certtool.gaa"
@@ -132,10 +132,12 @@ void gaa_help(void)
printf("Certtool help\nUsage: certtool [options]\n");
__gaa_helpsingle('s', "generate-self-signed", "", "Generate a self-signed certificate.");
__gaa_helpsingle('c', "generate-certificate", "", "Generate a signed certificate.");
+ __gaa_helpsingle(0, "generate-crl", "", "Generate a CRL.");
__gaa_helpsingle('u', "update-certificate", "", "Update a signed certificate.");
__gaa_helpsingle('p', "generate-privkey", "", "Generate a private key.");
__gaa_helpsingle('q', "generate-request", "", "Generate a PKCS #10 certificate request.");
__gaa_helpsingle('e', "verify-chain", "", "Verify a PEM encoded certificate chain. The last certificate in the chain must be a self signed one.");
+ __gaa_helpsingle(0, "verify-crl", "", "Verify a CRL.");
__gaa_helpsingle(0, "generate-dh-params", "", "Generate PKCS #3 encoded Diffie Hellman parameters.");
__gaa_helpsingle(0, "load-privkey", "FILE ", "Private key file to use.");
__gaa_helpsingle(0, "load-request", "FILE ", "Certificate request file to use.");
@@ -146,9 +148,11 @@ void gaa_help(void)
__gaa_helpsingle('i', "certificate-info", "", "Print information on a certificate.");
__gaa_helpsingle('l', "crl-info", "", "Print information on a CRL.");
__gaa_helpsingle(0, "p12-info", "", "Print information on a PKCS #12 structure.");
+ __gaa_helpsingle(0, "p7-info", "", "Print information on a PKCS #7 structure.");
__gaa_helpsingle('k', "key-info", "", "Print information on a private key.");
__gaa_helpsingle(0, "to-p12", "", "Generate a PKCS #12 structure.");
__gaa_helpsingle('8', "pkcs8", "", "Use PKCS #8 format for private keys.");
+ __gaa_helpsingle(0, "dsa", "", "Use DSA keys.");
__gaa_helpsingle(0, "export-ciphers", "", "Use weak encryption algorithms.");
__gaa_helpsingle(0, "inder", "", "Use DER format for input certificates and private keys.");
__gaa_helpsingle(0, "outder", "", "Use DER format for output certificates and private keys.");
@@ -173,33 +177,35 @@ typedef struct _gaainfo gaainfo;
struct _gaainfo
{
-#line 81 "certtool.gaa"
+#line 90 "certtool.gaa"
int debug;
-#line 78 "certtool.gaa"
+#line 87 "certtool.gaa"
char *infile;
-#line 75 "certtool.gaa"
+#line 84 "certtool.gaa"
char *outfile;
-#line 72 "certtool.gaa"
+#line 81 "certtool.gaa"
int bits;
-#line 69 "certtool.gaa"
+#line 78 "certtool.gaa"
int outcert_format;
-#line 66 "certtool.gaa"
+#line 75 "certtool.gaa"
int incert_format;
-#line 63 "certtool.gaa"
+#line 72 "certtool.gaa"
int export;
-#line 60 "certtool.gaa"
+#line 69 "certtool.gaa"
+ int dsa;
+#line 66 "certtool.gaa"
int pkcs8;
-#line 47 "certtool.gaa"
+#line 51 "certtool.gaa"
char *pass;
-#line 44 "certtool.gaa"
+#line 48 "certtool.gaa"
char *ca;
-#line 41 "certtool.gaa"
+#line 45 "certtool.gaa"
char *ca_privkey;
-#line 38 "certtool.gaa"
+#line 42 "certtool.gaa"
char *cert;
-#line 35 "certtool.gaa"
+#line 39 "certtool.gaa"
char *request;
-#line 32 "certtool.gaa"
+#line 36 "certtool.gaa"
char *privkey;
#line 17 "certtool.gaa"
int action;
@@ -257,7 +263,7 @@ int gaa_error = 0;
#define GAA_MULTIPLE_OPTION 3
#define GAA_REST 0
-#define GAA_NB_OPTION 29
+#define GAA_NB_OPTION 33
#define GAAOPTID_copyright 1
#define GAAOPTID_version 2
#define GAAOPTID_help 3
@@ -268,25 +274,29 @@ int gaa_error = 0;
#define GAAOPTID_outder 8
#define GAAOPTID_inder 9
#define GAAOPTID_export_ciphers 10
-#define GAAOPTID_pkcs8 11
-#define GAAOPTID_to_p12 12
-#define GAAOPTID_key_info 13
-#define GAAOPTID_p12_info 14
-#define GAAOPTID_crl_info 15
-#define GAAOPTID_certificate_info 16
-#define GAAOPTID_password 17
-#define GAAOPTID_load_ca_certificate 18
-#define GAAOPTID_load_ca_privkey 19
-#define GAAOPTID_load_certificate 20
-#define GAAOPTID_load_request 21
-#define GAAOPTID_load_privkey 22
-#define GAAOPTID_generate_dh_params 23
-#define GAAOPTID_verify_chain 24
-#define GAAOPTID_generate_request 25
-#define GAAOPTID_generate_privkey 26
-#define GAAOPTID_update_certificate 27
-#define GAAOPTID_generate_certificate 28
-#define GAAOPTID_generate_self_signed 29
+#define GAAOPTID_dsa 11
+#define GAAOPTID_pkcs8 12
+#define GAAOPTID_to_p12 13
+#define GAAOPTID_key_info 14
+#define GAAOPTID_p7_info 15
+#define GAAOPTID_p12_info 16
+#define GAAOPTID_crl_info 17
+#define GAAOPTID_certificate_info 18
+#define GAAOPTID_password 19
+#define GAAOPTID_load_ca_certificate 20
+#define GAAOPTID_load_ca_privkey 21
+#define GAAOPTID_load_certificate 22
+#define GAAOPTID_load_request 23
+#define GAAOPTID_load_privkey 24
+#define GAAOPTID_generate_dh_params 25
+#define GAAOPTID_verify_crl 26
+#define GAAOPTID_verify_chain 27
+#define GAAOPTID_generate_request 28
+#define GAAOPTID_generate_privkey 29
+#define GAAOPTID_update_certificate 30
+#define GAAOPTID_generate_crl 31
+#define GAAOPTID_generate_certificate 32
+#define GAAOPTID_generate_self_signed 33
#line 168 "gaa.skel"
@@ -580,17 +590,21 @@ int gaa_get_option_num(char *str, int status)
GAA_CHECK1STR("", GAAOPTID_outder);
GAA_CHECK1STR("", GAAOPTID_inder);
GAA_CHECK1STR("", GAAOPTID_export_ciphers);
+ GAA_CHECK1STR("", GAAOPTID_dsa);
GAA_CHECK1STR("8", GAAOPTID_pkcs8);
GAA_CHECK1STR("", GAAOPTID_to_p12);
GAA_CHECK1STR("k", GAAOPTID_key_info);
+ GAA_CHECK1STR("", GAAOPTID_p7_info);
GAA_CHECK1STR("", GAAOPTID_p12_info);
GAA_CHECK1STR("l", GAAOPTID_crl_info);
GAA_CHECK1STR("i", GAAOPTID_certificate_info);
GAA_CHECK1STR("", GAAOPTID_generate_dh_params);
+ GAA_CHECK1STR("", GAAOPTID_verify_crl);
GAA_CHECK1STR("e", GAAOPTID_verify_chain);
GAA_CHECK1STR("q", GAAOPTID_generate_request);
GAA_CHECK1STR("p", GAAOPTID_generate_privkey);
GAA_CHECK1STR("u", GAAOPTID_update_certificate);
+ GAA_CHECK1STR("", GAAOPTID_generate_crl);
GAA_CHECK1STR("c", GAAOPTID_generate_certificate);
GAA_CHECK1STR("s", GAAOPTID_generate_self_signed);
@@ -607,9 +621,11 @@ int gaa_get_option_num(char *str, int status)
GAA_CHECKSTR("outder", GAAOPTID_outder);
GAA_CHECKSTR("inder", GAAOPTID_inder);
GAA_CHECKSTR("export-ciphers", GAAOPTID_export_ciphers);
+ GAA_CHECKSTR("dsa", GAAOPTID_dsa);
GAA_CHECKSTR("pkcs8", GAAOPTID_pkcs8);
GAA_CHECKSTR("to-p12", GAAOPTID_to_p12);
GAA_CHECKSTR("key-info", GAAOPTID_key_info);
+ GAA_CHECKSTR("p7-info", GAAOPTID_p7_info);
GAA_CHECKSTR("p12-info", GAAOPTID_p12_info);
GAA_CHECKSTR("crl-info", GAAOPTID_crl_info);
GAA_CHECKSTR("certificate-info", GAAOPTID_certificate_info);
@@ -620,10 +636,12 @@ int gaa_get_option_num(char *str, int status)
GAA_CHECKSTR("load-request", GAAOPTID_load_request);
GAA_CHECKSTR("load-privkey", GAAOPTID_load_privkey);
GAA_CHECKSTR("generate-dh-params", GAAOPTID_generate_dh_params);
+ GAA_CHECKSTR("verify-crl", GAAOPTID_verify_crl);
GAA_CHECKSTR("verify-chain", GAAOPTID_verify_chain);
GAA_CHECKSTR("generate-request", GAAOPTID_generate_request);
GAA_CHECKSTR("generate-privkey", GAAOPTID_generate_privkey);
GAA_CHECKSTR("update-certificate", GAAOPTID_update_certificate);
+ GAA_CHECKSTR("generate-crl", GAAOPTID_generate_crl);
GAA_CHECKSTR("generate-certificate", GAAOPTID_generate_certificate);
GAA_CHECKSTR("generate-self-signed", GAAOPTID_generate_self_signed);
@@ -670,21 +688,21 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
{
case GAAOPTID_copyright:
OK = 0;
-#line 87 "certtool.gaa"
+#line 96 "certtool.gaa"
{ print_license(); exit(0); ;};
return GAA_OK;
break;
case GAAOPTID_version:
OK = 0;
-#line 86 "certtool.gaa"
+#line 95 "certtool.gaa"
{ certtool_version(); exit(0); ;};
return GAA_OK;
break;
case GAAOPTID_help:
OK = 0;
-#line 84 "certtool.gaa"
+#line 93 "certtool.gaa"
{ gaa_help(); exit(0); ;};
return GAA_OK;
@@ -694,7 +712,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_debug.arg1, gaa_getint, GAATMP_debug.size1);
gaa_index++;
-#line 82 "certtool.gaa"
+#line 91 "certtool.gaa"
{ gaaval->debug = GAATMP_debug.arg1 ;};
return GAA_OK;
@@ -704,7 +722,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_infile.arg1, gaa_getstr, GAATMP_infile.size1);
gaa_index++;
-#line 79 "certtool.gaa"
+#line 88 "certtool.gaa"
{ gaaval->infile = GAATMP_infile.arg1 ;};
return GAA_OK;
@@ -714,7 +732,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_outfile.arg1, gaa_getstr, GAATMP_outfile.size1);
gaa_index++;
-#line 76 "certtool.gaa"
+#line 85 "certtool.gaa"
{ gaaval->outfile = GAATMP_outfile.arg1 ;};
return GAA_OK;
@@ -724,70 +742,84 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_bits.arg1, gaa_getint, GAATMP_bits.size1);
gaa_index++;
-#line 73 "certtool.gaa"
+#line 82 "certtool.gaa"
{ gaaval->bits = GAATMP_bits.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_outder:
OK = 0;
-#line 70 "certtool.gaa"
+#line 79 "certtool.gaa"
{ gaaval->outcert_format=1 ;};
return GAA_OK;
break;
case GAAOPTID_inder:
OK = 0;
-#line 67 "certtool.gaa"
+#line 76 "certtool.gaa"
{ gaaval->incert_format=1 ;};
return GAA_OK;
break;
case GAAOPTID_export_ciphers:
OK = 0;
-#line 64 "certtool.gaa"
+#line 73 "certtool.gaa"
{ gaaval->export=1 ;};
return GAA_OK;
break;
+ case GAAOPTID_dsa:
+ OK = 0;
+#line 70 "certtool.gaa"
+{ gaaval->dsa=1 ;};
+
+ return GAA_OK;
+ break;
case GAAOPTID_pkcs8:
OK = 0;
-#line 61 "certtool.gaa"
+#line 67 "certtool.gaa"
{ gaaval->pkcs8=1 ;};
return GAA_OK;
break;
case GAAOPTID_to_p12:
OK = 0;
-#line 58 "certtool.gaa"
+#line 64 "certtool.gaa"
{ gaaval->action = 8; ;};
return GAA_OK;
break;
case GAAOPTID_key_info:
OK = 0;
-#line 56 "certtool.gaa"
+#line 62 "certtool.gaa"
{ gaaval->action = 6; ;};
return GAA_OK;
break;
+ case GAAOPTID_p7_info:
+ OK = 0;
+#line 60 "certtool.gaa"
+{ gaaval->action = 12; ;};
+
+ return GAA_OK;
+ break;
case GAAOPTID_p12_info:
OK = 0;
-#line 54 "certtool.gaa"
+#line 58 "certtool.gaa"
{ gaaval->action = 9; ;};
return GAA_OK;
break;
case GAAOPTID_crl_info:
OK = 0;
-#line 52 "certtool.gaa"
+#line 56 "certtool.gaa"
{ gaaval->action = 11; ;};
return GAA_OK;
break;
case GAAOPTID_certificate_info:
OK = 0;
-#line 50 "certtool.gaa"
+#line 54 "certtool.gaa"
{ gaaval->action = 2; ;};
return GAA_OK;
@@ -797,7 +829,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_password.arg1, gaa_getstr, GAATMP_password.size1);
gaa_index++;
-#line 48 "certtool.gaa"
+#line 52 "certtool.gaa"
{ gaaval->pass = GAATMP_password.arg1 ;};
return GAA_OK;
@@ -807,7 +839,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_ca_certificate.arg1, gaa_getstr, GAATMP_load_ca_certificate.size1);
gaa_index++;
-#line 45 "certtool.gaa"
+#line 49 "certtool.gaa"
{ gaaval->ca = GAATMP_load_ca_certificate.arg1 ;};
return GAA_OK;
@@ -817,7 +849,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_ca_privkey.arg1, gaa_getstr, GAATMP_load_ca_privkey.size1);
gaa_index++;
-#line 42 "certtool.gaa"
+#line 46 "certtool.gaa"
{ gaaval->ca_privkey = GAATMP_load_ca_privkey.arg1 ;};
return GAA_OK;
@@ -827,7 +859,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_certificate.arg1, gaa_getstr, GAATMP_load_certificate.size1);
gaa_index++;
-#line 39 "certtool.gaa"
+#line 43 "certtool.gaa"
{ gaaval->cert = GAATMP_load_certificate.arg1 ;};
return GAA_OK;
@@ -837,7 +869,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_request.arg1, gaa_getstr, GAATMP_load_request.size1);
gaa_index++;
-#line 36 "certtool.gaa"
+#line 40 "certtool.gaa"
{ gaaval->request = GAATMP_load_request.arg1 ;};
return GAA_OK;
@@ -847,46 +879,60 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_privkey.arg1, gaa_getstr, GAATMP_load_privkey.size1);
gaa_index++;
-#line 33 "certtool.gaa"
+#line 37 "certtool.gaa"
{ gaaval->privkey = GAATMP_load_privkey.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_generate_dh_params:
OK = 0;
-#line 30 "certtool.gaa"
+#line 34 "certtool.gaa"
{ gaaval->action=10; ;};
return GAA_OK;
break;
+ case GAAOPTID_verify_crl:
+ OK = 0;
+#line 32 "certtool.gaa"
+{ gaaval->action=14; ;};
+
+ return GAA_OK;
+ break;
case GAAOPTID_verify_chain:
OK = 0;
-#line 28 "certtool.gaa"
+#line 30 "certtool.gaa"
{ gaaval->action=5; ;};
return GAA_OK;
break;
case GAAOPTID_generate_request:
OK = 0;
-#line 26 "certtool.gaa"
+#line 28 "certtool.gaa"
{ gaaval->action=3; ;};
return GAA_OK;
break;
case GAAOPTID_generate_privkey:
OK = 0;
-#line 24 "certtool.gaa"
+#line 26 "certtool.gaa"
{ gaaval->action=1; ;};
return GAA_OK;
break;
case GAAOPTID_update_certificate:
OK = 0;
-#line 22 "certtool.gaa"
+#line 24 "certtool.gaa"
{ gaaval->action=7; ;};
return GAA_OK;
break;
+ case GAAOPTID_generate_crl:
+ OK = 0;
+#line 22 "certtool.gaa"
+{ gaaval->action=13; ;};
+
+ return GAA_OK;
+ break;
case GAAOPTID_generate_certificate:
OK = 0;
#line 20 "certtool.gaa"
@@ -925,7 +971,7 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
if(inited == 0)
{
-#line 89 "certtool.gaa"
+#line 98 "certtool.gaa"
{ gaaval->bits = 1024; gaaval->pkcs8 = 0; gaaval->privkey = NULL; gaaval->ca=NULL; gaaval->ca_privkey = NULL;
gaaval->debug=1; gaaval->request = NULL; gaaval->infile = NULL; gaaval->outfile = NULL; gaaval->cert = NULL;
gaaval->incert_format = 0; gaaval->outcert_format = 0; gaaval->action=-1; gaaval->pass = NULL;
@@ -1048,7 +1094,8 @@ typedef struct gaastrnode gaa_str_node;
int gaa_internal_get_next_str(FILE *file, gaa_str_node *tmp_str, int argc)
{
int pos_ini;
- char a;
+ int a;
+ char ca;
int i = 0, len = 0, newline = 0;
if(argc == 1) {
@@ -1056,7 +1103,8 @@ int gaa_internal_get_next_str(FILE *file, gaa_str_node *tmp_str, int argc)
len = 2;
}
- if(fscanf(file,"%c", &a) != 1) return 0;
+ a = fgetc( file);
+ if (a == EOF) return 0;
while(a == ' ' || a == 9 || a == '\n')
{
@@ -1065,7 +1113,8 @@ int gaa_internal_get_next_str(FILE *file, gaa_str_node *tmp_str, int argc)
newline=1;
len = 2;
}
- if(fscanf(file,"%c", &a) != 1) return 0;
+ a = fgetc( file);
+ if (a == EOF) return 0;
}
pos_ini = ftell(file) - 1;
@@ -1074,7 +1123,8 @@ int gaa_internal_get_next_str(FILE *file, gaa_str_node *tmp_str, int argc)
{
len++;
- if(fscanf(file,"%c", &a) != 1) a = ' ';
+ a = fgetc( file);
+ if(a==EOF) return 0; //a = ' ';
}
len += 1;
@@ -1094,11 +1144,12 @@ int gaa_internal_get_next_str(FILE *file, gaa_str_node *tmp_str, int argc)
fseek(file,pos_ini, SEEK_SET);
do
{
- if(fscanf(file, "%c", &a) != 1)
+ if(fscanf(file, "%c", &ca) != 1)
{
i+=2;
break;
}
+ a = ca;
tmp_str->str[i] = a;
i++;
}
@@ -1125,7 +1176,7 @@ int gaa_file(char *name, gaainfo *gaaval)
if((file = fopen(name, "r")) == NULL)
{
printf("Couldn't open '%s' configuration file for reading\n", name);
- return 0;
+ return 1;
}
tmp_str = &first_str;
diff --git a/src/certtool-gaa.h b/src/certtool-gaa.h
index 15210d0aac..2bef4af05b 100644
--- a/src/certtool-gaa.h
+++ b/src/certtool-gaa.h
@@ -8,33 +8,35 @@ typedef struct _gaainfo gaainfo;
struct _gaainfo
{
-#line 81 "certtool.gaa"
+#line 90 "certtool.gaa"
int debug;
-#line 78 "certtool.gaa"
+#line 87 "certtool.gaa"
char *infile;
-#line 75 "certtool.gaa"
+#line 84 "certtool.gaa"
char *outfile;
-#line 72 "certtool.gaa"
+#line 81 "certtool.gaa"
int bits;
-#line 69 "certtool.gaa"
+#line 78 "certtool.gaa"
int outcert_format;
-#line 66 "certtool.gaa"
+#line 75 "certtool.gaa"
int incert_format;
-#line 63 "certtool.gaa"
+#line 72 "certtool.gaa"
int export;
-#line 60 "certtool.gaa"
+#line 69 "certtool.gaa"
+ int dsa;
+#line 66 "certtool.gaa"
int pkcs8;
-#line 47 "certtool.gaa"
+#line 51 "certtool.gaa"
char *pass;
-#line 44 "certtool.gaa"
+#line 48 "certtool.gaa"
char *ca;
-#line 41 "certtool.gaa"
+#line 45 "certtool.gaa"
char *ca_privkey;
-#line 38 "certtool.gaa"
+#line 42 "certtool.gaa"
char *cert;
-#line 35 "certtool.gaa"
+#line 39 "certtool.gaa"
char *request;
-#line 32 "certtool.gaa"
+#line 36 "certtool.gaa"
char *privkey;
#line 17 "certtool.gaa"
int action;
diff --git a/src/certtool.c b/src/certtool.c
index 7d488711a1..6546765cb0 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -32,10 +33,13 @@
#include <gnutls/pkcs12.h>
#include <unistd.h>
+static void print_crl_info( gnutls_x509_crl crl, FILE* out, int all);
int generate_prime(int bits);
+void pkcs7_info( void);
void pkcs12_info( void);
void generate_pkcs12( void);
void verify_chain(void);
+void verify_crl(void);
gnutls_x509_privkey load_private_key(int mand);
gnutls_x509_crq load_request(void);
gnutls_x509_privkey load_ca_private_key(void);
@@ -44,10 +48,11 @@ 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);
+gnutls_x509_crt* load_cert_list(int mand, int *size);
static gaainfo info;
FILE* outfile;
@@ -121,27 +126,28 @@ char input[128];
static const char* read_str( const char* input_str)
{
static char input[128];
+int len;
fputs( input_str, stderr);
- fgets( input, sizeof(input), stdin);
+ if (fgets( input, sizeof(input), stdin) == NULL) return NULL;
- input[strlen(input)-1] = 0;
-
- if (strlen(input)==0) return NULL;
+ len = strlen(input);
+ if ( (len > 0) && (input[len-1] == '\n') ) input[len-1] = 0;
+ if (input[0] == 0) return NULL;
return input;
}
static const char* read_pass( const char* input_str)
{
-#ifdef _WIN32
+#ifndef HAVE_GETPASS
static char input[128];
#endif
const char* pass;
if (info.pass) return info.pass;
-#ifdef _WIN32
+#ifndef HAVE_GETPASS
fputs( input_str, stderr);
fgets( input, sizeof(input), stdin);
@@ -176,7 +182,21 @@ char input[128];
static gnutls_x509_privkey generate_private_key_int( void)
{
gnutls_x509_privkey key;
-int ret;
+int ret, key_type;
+const char* msg;
+
+ if (info.dsa) {
+ msg = "DSA";
+ key_type = GNUTLS_PK_DSA;
+
+ if (info.bits > 1024) {
+ fprintf(stderr, "The DSA algorithm cannot be used with primes over 1024 bits.\n");
+ exit(1);
+ }
+ } else {
+ msg = "RSA";
+ key_type = GNUTLS_PK_RSA;
+ }
if (info.privkey)
return load_private_key(1);
@@ -187,8 +207,9 @@ int ret;
exit(1);
}
- fprintf(stderr, "Generating a %d bit RSA private key...\n", info.bits);
- ret = gnutls_x509_privkey_generate( key, GNUTLS_PK_RSA, info.bits, 0);
+ fprintf(stderr, "Generating a %d bit %s private key...\n", info.bits, msg);
+
+ ret = gnutls_x509_privkey_generate( key, key_type, info.bits, 0);
if (ret < 0) {
fprintf(stderr, "privkey_generate: %s\n", gnutls_strerror(ret));
exit(1);
@@ -198,26 +219,26 @@ int ret;
}
-static void print_key_usage( unsigned int x)
+static void print_key_usage( unsigned int x, FILE* out)
{
if (x&GNUTLS_KEY_DIGITAL_SIGNATURE)
- fprintf(outfile,"\t\tDigital signature.\n");
+ fprintf(out,"\t\tDigital signature.\n");
if (x&GNUTLS_KEY_NON_REPUDIATION)
- fprintf(outfile,"\t\tNon repudiation.\n");
+ fprintf(out,"\t\tNon repudiation.\n");
if (x&GNUTLS_KEY_KEY_ENCIPHERMENT)
- fprintf(outfile,"\t\tKey encipherment.\n");
+ fprintf(out,"\t\tKey encipherment.\n");
if (x&GNUTLS_KEY_DATA_ENCIPHERMENT)
- fprintf(outfile,"\t\tData encipherment.\n");
+ fprintf(out,"\t\tData encipherment.\n");
if (x&GNUTLS_KEY_KEY_AGREEMENT)
- fprintf(outfile,"\t\tKey agreement.\n");
+ fprintf(out,"\t\tKey agreement.\n");
if (x&GNUTLS_KEY_KEY_CERT_SIGN)
- fprintf(outfile,"\t\tCertificate signing.\n");
+ fprintf(out,"\t\tCertificate signing.\n");
if (x&GNUTLS_KEY_CRL_SIGN)
- fprintf(outfile,"\t\tCRL signing.\n");
+ fprintf(out,"\t\tCRL signing.\n");
if (x&GNUTLS_KEY_ENCIPHER_ONLY)
- fprintf(outfile,"\t\tKey encipher only.\n");
+ fprintf(out,"\t\tKey encipher only.\n");
if (x&GNUTLS_KEY_DECIPHER_ONLY)
- fprintf(outfile,"\t\tKey decipher only.\n");
+ fprintf(out,"\t\tKey decipher only.\n");
}
static void print_private_key( gnutls_x509_privkey key)
@@ -276,6 +297,7 @@ gnutls_x509_crt generate_certificate( gnutls_x509_privkey *ret_key)
const char* str;
int vers = 3; /* the default version in the certificate
*/
+ unsigned int usage = 0, server;
gnutls_x509_crq crq; /* request */
size = gnutls_x509_crt_init(&crt);
@@ -356,8 +378,8 @@ gnutls_x509_crt generate_certificate( gnutls_x509_privkey *ret_key)
exit(1);
}
- result = read_yesno( "Is this a web server certificate? (Y/N): ");
- if (result != 0) {
+ server = read_yesno( "Is this a web server certificate? (Y/N): ");
+ if (server != 0) {
str = read_str( "Enter the dnsName of the subject of the certificate: ");
if (str != NULL) {
result = gnutls_x509_crt_set_subject_alternative_name( crt, GNUTLS_SAN_DNSNAME, str);
@@ -379,17 +401,121 @@ gnutls_x509_crt generate_certificate( gnutls_x509_privkey *ret_key)
}
}
+
+ if (!ca_status || server) {
+ int pk;
+ const char* msg1, *msg2;
+
+ if (server) msg1 = "Will the certificate be used for signing (DHE and RSA-EXPORT ciphersuites)? (Y/N): ";
+ else msg1 = "Will the certificate be used for signing (required for TLS)? (Y/N): ";
+
+ if (server) msg2 = "Will the certificate be used for encryption (RSA ciphersuites)? (Y/N): ";
+ else msg2 = "Will the certificate be used for encryption (not required for TLS)? (Y/N): ";
+
+ pk = gnutls_x509_crt_get_pk_algorithm( crt, NULL);
+
+ if (pk != GNUTLS_PK_DSA) { /* DSA keys can only sign.
+ */
+ result = read_yesno( msg1);
+ if (result) usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
+
+ result = read_yesno( msg2);
+ if (result) usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
+ } else usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
+ }
+
+
+ if (ca_status) {
+ result = read_yesno( "Will the certificate be used to sign other certificates? (Y/N): ");
+ if (result) usage |= GNUTLS_KEY_KEY_CERT_SIGN;
+
+ result = read_yesno( "Will the certificate be used to sign CRLs? (Y/N): ");
+ if (result) usage |= GNUTLS_KEY_CRL_SIGN;
+ }
+
+ if (usage != 0) {
+ result = gnutls_x509_crt_set_key_usage( crt, usage);
+ if (result < 0) {
+ fprintf(stderr, "key_usage: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+ }
+
+ /* Version.
+ */
result = gnutls_x509_crt_set_version( crt, vers);
if (result < 0) {
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;
}
+gnutls_x509_crl generate_crl( void)
+{
+ gnutls_x509_crl crl;
+ gnutls_x509_crt * crts;
+ int size;
+ int days, result, i;
+ int vers = 2; /* the default version in the CRL
+ */
+
+ result = gnutls_x509_crl_init(&crl);
+ if (result < 0) {
+ fprintf(stderr, "crl_init: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ crts = load_cert_list(1, &size);
+
+ for (i=0;i<size;i++) {
+
+ result = gnutls_x509_crl_set_crt( crl, crts[i], time(0));
+ if (result < 0) {
+ fprintf(stderr, "serial: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+ }
+
+ fprintf(stderr, "\n\nthisUpdate/nextUpdate time.\n");
+ gnutls_x509_crl_set_this_update( crl, time(NULL));
+
+ do {
+ days = read_int( "The next CRL will be issued in (days): ");
+ } while( days==0);
+
+ result = gnutls_x509_crl_set_next_update( crl, time(NULL)+days*24*60*60);
+ if (result < 0) {
+ fprintf(stderr, "next_update: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ /* Version.
+ */
+ result = gnutls_x509_crl_set_version( crl, vers);
+ if (result < 0) {
+ fprintf(stderr, "set_version: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ return crl;
+}
+
gnutls_x509_crt update_certificate( void)
{
gnutls_x509_crt crt;
@@ -428,12 +554,23 @@ void generate_self_signed( void)
gnutls_x509_privkey key;
size_t size;
int result;
+ const char *uri;
fprintf(stderr, "Generating a self signed certificate...\n");
crt = generate_certificate( &key);
- print_certificate_info( crt);
+ uri = read_str( "Enter the URI of the CRL distribution point: ");
+ if (uri) {
+ result = gnutls_x509_crt_set_crl_dist_points( crt, GNUTLS_SAN_URI,
+ uri, 0 /* all reasons */);
+ if (result < 0) {
+ fprintf(stderr, "crl_dist_points: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+ }
+
+ print_certificate_info( crt, stderr, 0);
fprintf(stderr, "\n\nSigning certificate...\n");
@@ -471,8 +608,14 @@ void generate_signed_certificate( void)
ca_crt = load_ca_cert();
crt = generate_certificate( &key);
+
+ /* Copy the CRL distribution points.
+ */
+ gnutls_x509_crt_cpy_crl_dist_points( crt, ca_crt);
+ /* it doesn't matter if we couldn't copy the CRL dist points.
+ */
- print_certificate_info( crt);
+ print_certificate_info( crt, stderr, 0);
fprintf(stderr, "\n\nSigning certificate...\n");
@@ -495,6 +638,43 @@ void generate_signed_certificate( void)
gnutls_x509_privkey_deinit(key);
}
+void generate_signed_crl( void)
+{
+ gnutls_x509_crl crl;
+ size_t size;
+ int result;
+ gnutls_x509_privkey ca_key;
+ gnutls_x509_crt ca_crt;
+
+ fprintf(stderr, "Generating a signed CRL...\n");
+
+ ca_key = load_ca_private_key();
+ ca_crt = load_ca_cert();
+
+ crl = generate_crl();
+
+ print_crl_info( crl, stderr, 0);
+
+ fprintf(stderr, "\n\nSigning CRL...\n");
+
+ result = gnutls_x509_crl_sign( crl, ca_crt, ca_key);
+ if (result < 0) {
+ fprintf(stderr, "crl_sign: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ size = sizeof(buffer);
+ result = gnutls_x509_crl_export( crl, out_cert_format, buffer, &size);
+ if (result < 0) {
+ fprintf(stderr, "crl_export: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ fwrite( buffer, 1, size, outfile);
+
+ gnutls_x509_crl_deinit(crl);
+}
+
void update_signed_certificate( void)
{
gnutls_x509_crt crt;
@@ -541,7 +721,7 @@ int ret;
}
if (info.outfile) {
- outfile = fopen(info.outfile, "w");
+ outfile = fopen(info.outfile, "wb");
if (outfile == NULL) {
fprintf(stderr, "error: could not open '%s'.\n", info.outfile);
exit(1);
@@ -549,7 +729,7 @@ int ret;
} else outfile = stdout;
if (info.infile) {
- infile = fopen(info.infile, "r");
+ infile = fopen(info.infile, "rb");
if (infile == NULL) {
fprintf(stderr, "error: could not open '%s'.\n", info.infile);
exit(1);
@@ -607,6 +787,15 @@ int ret;
case 11:
crl_info();
break;
+ case 12:
+ pkcs7_info();
+ break;
+ case 13:
+ generate_signed_crl();
+ break;
+ case 14:
+ verify_crl();
+ break;
default:
fprintf(stderr, "GnuTLS' certtool utility.\n");
fprintf(stderr, "Please use the --help to get help on this program.\n");
@@ -616,7 +805,7 @@ int ret;
}
-const char* get_algorithm( int a)
+const char* get_pk_algorithm( gnutls_pk_algorithm a)
{
switch (a) {
case GNUTLS_PK_RSA:
@@ -629,10 +818,31 @@ const char* get_algorithm( int a)
}
}
+const char* get_sign_algorithm( gnutls_sign_algorithm a)
+{
+ switch (a) {
+ case GNUTLS_SIGN_RSA_SHA:
+ return "RSA-SHA";
+ case GNUTLS_SIGN_RSA_MD5:
+ return "RSA-MD5";
+ case GNUTLS_SIGN_RSA_MD2:
+ return "RSA-MD2";
+ case GNUTLS_SIGN_DSA_SHA:
+ return "DSA-SHA";
+ break;
+ default:
+ return "UNKNOWN";
+ }
+}
+
+/* OIDs that are handled by the gnutls' functions.
+ */
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;
@@ -642,19 +852,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;
@@ -669,10 +869,37 @@ void certificate_info( void)
fprintf(stderr, "Decoding error: %s\n", gnutls_strerror(ret));
exit(1);
}
+
+ print_certificate_info( crt, outfile, 1);
+
+ size = sizeof(buffer);
+ ret = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, buffer, &size);
+ if (ret < 0) {
+ fprintf(stderr, "Encoding error: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ fprintf(outfile, "\n%s\n", buffer);
+}
- 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(outfile, "Version: %d\n", gnutls_x509_crt_get_version(crt));
+ fprintf( out, "\n\nX.509 certificate info:\n\n");
+
+ fprintf(out, "Version: %d\n", gnutls_x509_crt_get_version(crt));
/* serial number
*/
@@ -683,82 +910,118 @@ 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);
+ else
+ fprintf(stderr, "get_issuer_dn: %s\n", gnutls_strerror(ret));
- 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);
+ else
+ fprintf(stderr, "get_issuer_dn: %s\n", gnutls_strerror(ret));
- 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_sign_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);
+ cprint = get_pk_algorithm( ret);
+ 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(out, "\t\tFound unsupported alternative name.\n");
+ } else switch (ret) {
+ case GNUTLS_SAN_DNSNAME:
+ fprintf(out, "\t\tDNSname: %s\n", buffer);
+ break;
+ case GNUTLS_SAN_RFC822NAME:
+ fprintf(out, "\t\tRFC822name: %s\n", buffer);
+ break;
+ case GNUTLS_SAN_URI:
+ fprintf(out, "\t\tURI: %s\n", buffer);
+ break;
+ case GNUTLS_SAN_IPADDRESS:
+ fprintf(out, "\t\tIPAddress: %s\n", buffer);
+ break;
+ }
+ }
+
+ /* CRL dist points.
+ */
+ ret = 0;
+ for (i = 0; !(ret < 0); i++) {
+ size = sizeof(buffer);
+ 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(out, "\tCRL Distribution points:");
+ 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\tError decoding: %s\n", gnutls_strerror(ret));
} 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;
}
}
@@ -768,12 +1031,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");
}
@@ -782,8 +1045,27 @@ void certificate_info( void)
ret = gnutls_x509_crt_get_key_usage( crt, &key_usage, &critical);
if (ret >= 0) {
- fprintf(outfile, "\tKey usage:\n");
- print_key_usage(key_usage);
+ fprintf(out, "\tKey usage: %s\n", critical?"(critical)":"");
+ print_key_usage(key_usage, out);
+ }
+
+ /* 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)
+ {
+ fprintf(out, "Error getting subject key id: %s\n", gnutls_strerror(ret));
+ }
+
+ 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:
@@ -804,22 +1086,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);
}
@@ -829,173 +1111,122 @@ 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)
+ {
+ fprintf(out, "Error in fingerprint calculation: %s\n", gnutls_strerror(ret));
+ } 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);
if ((ret=gnutls_x509_crt_get_key_id(crt, 0, buffer, &size)) < 0)
{
- 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", gnutls_strerror(ret));
} 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(out, "\tPublic Key ID: %s\n", printable);
}
- fprintf(outfile, "\n");
+ fprintf(out, "\n");
+
+ if (out==stderr) /* interactive */
+ if (read_yesno( "Is the above information ok? (Y/N): ")==0) {
+ exit(1);
+ }
}
-static void print_certificate_info( gnutls_x509_crt crt)
+static void print_crl_info( gnutls_x509_crl crl, FILE* out, int all)
{
- int ret;
- unsigned int i;
- unsigned int critical, key_usage;
+ int ret, rc;
time_t tim;
- char serial[40];
- size_t serial_size = sizeof(serial), dn_size, size;
+ unsigned int i, j;
+ char serial[128];
+ size_t serial_size = sizeof(serial), dn_size;
char printable[256];
- char *print;
+ char *print, dn[256];
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(out, "CRL information:\n");
+ fprintf(out, "Version: %d\n", gnutls_x509_crl_get_version(crl));
+
+ /* Issuer
*/
- fprintf(stderr, "Validity:\n");
+ if (all) {
+ dn_size = sizeof(dn);
- tim = gnutls_x509_crt_get_activation_time(crt);
- fprintf(stderr, "\tNot Before: %s", ctime(&tim));
+ ret = gnutls_x509_crl_get_issuer_dn(crl, dn, &dn_size);
+ if (ret >= 0)
+ fprintf(out, "Issuer: %s\n", dn);
- tim = gnutls_x509_crt_get_expiration_time(crt);
- fprintf(stderr, "\tNot After: %s", ctime(&tim));
+ fprintf(out, "Signature Algorithm: ");
+ ret = gnutls_x509_crl_get_signature_algorithm(crl);
- /* Subject
- */
- dn_size = sizeof(dn);
- ret = gnutls_x509_crt_get_dn(crt, dn, &dn_size);
- if (ret >= 0)
- fprintf(stderr, "Subject: %s\n", dn);
+ cprint = get_sign_algorithm( ret);
+ fprintf(out, "%s\n", cprint);
+ }
- /* Public key algorithm
+ /* Validity
*/
- fprintf(stderr, "Subject Public Key Info:\n");
- ret = gnutls_x509_crt_get_pk_algorithm(crt, NULL);
- fprintf(stderr, "\tPublic Key Algorithm: ");
+ fprintf(out, "Update dates:\n");
- cprint = get_algorithm( ret);
- fprintf(stderr, "%s\n", cprint);
+ tim = gnutls_x509_crl_get_this_update(crl);
+ fprintf(out, "\tIssued at: %s", ctime(&tim));
+ tim = gnutls_x509_crl_get_next_update(crl);
+ fprintf(out, "\tNext at: %s", ctime(&tim));
+ fprintf(out, "\n");
- fprintf(stderr, "\nX.509 Extensions:\n");
-
- /* subject alternative name
+ /* Count the certificates.
*/
- for (i = 0; !(ret < 0); i++) {
- size = sizeof(buffer);
- ret = gnutls_x509_crt_get_subject_alt_name(crt, i, buffer, &size, &critical);
+
+ rc = gnutls_x509_crl_get_crt_count( crl);
+ fprintf(out, "Revoked certificates: %d\n", rc);
- if (i==0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
- fprintf(stderr, "\tSubject Alternative name:");
- if (critical) fprintf(stderr, " (critical)");
- fprintf(stderr, "\n");
- }
+ for (j=0;j<(unsigned int)rc;j++) {
+ /* serial number
+ */
+ serial_size = sizeof(serial);
+ ret = gnutls_x509_crl_get_crt_serial(crl, j, serial, &serial_size, &tim);
- 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;
+ if (ret < 0) {
+ fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
+ } else {
+ print = printable;
+ for (i = 0; i < serial_size; i++) {
+ sprintf(print, "%.2x ",
+ (unsigned char) serial[i]);
+ print += 3;
+ }
+ fprintf(out, "\tCertificate SN: %s\n", printable);
+ fprintf(out, "\tRevoked at: %s\n", ctime( &tim));
}
}
-
- /* 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:\n");
- print_key_usage(key_usage);
- }
- fprintf(stderr, "\n");
-
- if (read_yesno( "Is the above information ok? (Y/N): ")==0) {
- exit(1);
- }
}
-void crl_info(void)
+void crl_info()
{
gnutls_x509_crl crl;
- int ret, rc;
+ int ret;
size_t size;
- time_t tim;
- unsigned int i;
gnutls_datum pem;
- unsigned char serial[40];
- size_t serial_size = sizeof(serial), dn_size;
- char printable[256];
- char *print, dn[256];
- const char* cprint;
size = fread( buffer, 1, sizeof(buffer)-1, infile);
buffer[size] = 0;
@@ -1011,56 +1242,17 @@ void crl_info(void)
exit(1);
}
- fprintf(outfile, "Version: %d\n", gnutls_x509_crl_get_version(crl));
+ print_crl_info( crl, outfile, 1);
- /* Issuer
- */
- dn_size = sizeof(dn);
-
- ret = gnutls_x509_crl_get_issuer_dn(crl, dn, &dn_size);
- if (ret >= 0)
- fprintf(outfile, "Issuer: %s\n", dn);
-
- fprintf(outfile, "Signature Algorithm: ");
- ret = gnutls_x509_crl_get_signature_algorithm(crl);
-
- cprint = get_algorithm( ret);
- fprintf(outfile, "%s\n", cprint);
-
- /* Validity
- */
- fprintf(outfile, "Update dates:\n");
-
- tim = gnutls_x509_crl_get_this_update(crl);
- fprintf(outfile, "\tIssued at: %s", ctime(&tim));
-
- tim = gnutls_x509_crl_get_next_update(crl);
- fprintf(outfile, "\tNext at: %s", ctime(&tim));
-
- fprintf(outfile, "\n");
+ size = sizeof(buffer);
+ ret = gnutls_x509_crl_export(crl, GNUTLS_X509_FMT_PEM, buffer, &size);
+ if (ret < 0) {
+ fprintf(stderr, "Encoding error: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
- /* Count the certificates.
- */
-
- rc = gnutls_x509_crl_get_crt_count( crl);
- fprintf(outfile, "Revoked certificates: %d\n", rc);
-
- for (i=0;i<(unsigned int)rc;i++) {
- /* serial number
- */
- serial_size = sizeof(serial);
- if (gnutls_x509_crl_get_crt_serial(crl, i, serial, &serial_size, &tim) >= 0) {
- print = printable;
- for (i = 0; i < serial_size; i++) {
- sprintf(print, "%.2x ",
- (unsigned char) serial[i]);
- print += 3;
- }
- fprintf(outfile, "\tCertificate SN: %s\n", printable);
- fprintf(outfile, "\tRevoked at: %s\n", ctime( &tim));
- }
+ fprintf(outfile, "\n%s\n", buffer);
- }
}
void privkey_info( void)
@@ -1102,16 +1294,14 @@ void privkey_info( void)
ret = gnutls_x509_privkey_get_pk_algorithm(key);
fprintf(outfile, "\tPublic Key Algorithm: ");
- cprint = get_algorithm( ret);
+ cprint = get_pk_algorithm( ret);
fprintf(outfile, "%s\n", cprint);
size = sizeof(buffer);
if ((ret=gnutls_x509_privkey_get_key_id(key, 0, buffer, &size)) < 0)
{
- const char* str = gnutls_strerror(ret);
- if (str == NULL) str = "unknown error";
- fprintf(stderr, "Error in key id calculation: %s\n", str);
+ fprintf(stderr, "Error in key id calculation: %s\n", gnutls_strerror(ret));
} else {
print = printable;
for (i = 0; i < size; i++) {
@@ -1121,7 +1311,13 @@ void privkey_info( void)
fprintf(outfile, "Public Key ID: %s\n", printable);
}
- fprintf(outfile, "\n");
+ size = sizeof(buffer);
+ ret = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, buffer, &size);
+ if (ret < 0) {
+ fprintf(stderr, "Encoding error: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+ fprintf(outfile, "\n%s\n", buffer);
}
/* mand should be non zero if it is required to read a private key.
@@ -1322,13 +1518,30 @@ size_t size;
*/
gnutls_x509_crt load_cert(int mand)
{
+gnutls_x509_crt *crt;
+int size;
+
+ crt = load_cert_list( mand, &size);
+
+ return crt[0];
+}
+
+#define MAX_CERTS 256
+
+/* Loads a certificate list
+ */
+gnutls_x509_crt* load_cert_list(int mand, int *crt_size)
+{
FILE* fd;
-gnutls_x509_crt crt;
-int ret;
+static gnutls_x509_crt crt[MAX_CERTS];
+char* ptr;
+int ret, i;
gnutls_datum dat;
size_t size;
+int ptr_size;
- fprintf(stderr, "Loading certificate...\n");
+ *crt_size = 0;
+ fprintf(stderr, "Loading certificate list...\n");
if (info.cert==NULL) {
fprintf(stderr, "You must specify a certificate.\n");
@@ -1347,20 +1560,38 @@ size_t size;
fclose(fd);
- ret = gnutls_x509_crt_init(&crt);
- if (ret < 0) {
- fprintf(stderr, "crt_init: %s\n", gnutls_strerror(ret));
- exit(1);
- }
+ ptr = buffer;
+ ptr_size = size;
+
+ for (i=0;i<MAX_CERTS;i++) {
+ ret = gnutls_x509_crt_init(&crt[i]);
+ if (ret < 0) {
+ fprintf(stderr, "crt_init: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
- dat.data = buffer;
- dat.size = size;
+ dat.data = ptr;
+ dat.size = ptr_size;
- ret = gnutls_x509_crt_import( crt, &dat, in_cert_format);
- if (ret < 0) {
- fprintf(stderr, "crt_import: %s\n", gnutls_strerror(ret));
- exit(1);
- }
+ ret = gnutls_x509_crt_import( crt[i], &dat, in_cert_format);
+ if (ret < 0 && *crt_size > 0) break;
+ if (ret < 0) {
+ fprintf(stderr, "crt_import: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ptr = strstr( ptr, "---END");
+ if (ptr==NULL) break;
+ ptr++;
+
+ ptr_size = size;
+ ptr_size -= (unsigned int)((unsigned char*)ptr - (unsigned char*)buffer);
+
+ if (ptr_size < 0) break;
+
+ (*crt_size)++;
+ }
+ fprintf(stderr, "Loaded %d certificates.\n", *crt_size);
return crt;
}
@@ -1666,7 +1897,7 @@ time_t now = time(0);
exit(1);
}
- if (output&GNUTLS_CERT_NOT_TRUSTED) {
+ if (output&GNUTLS_CERT_INVALID) {
fprintf(outfile, "Not verified");
comma = 1;
} else {
@@ -1706,8 +1937,6 @@ time_t now = time(0);
comma = 1;
fprintf(outfile, "Revoked");
}
-
-
}
void verify_chain( void)
@@ -1715,11 +1944,89 @@ void verify_chain( void)
size_t size;
size = fread( buffer, 1, sizeof(buffer)-1, infile);
+ buffer[size] = 0;
_verify_x509_mem( buffer, size);
}
+void verify_crl( void)
+{
+size_t size, dn_size;
+char dn[128];
+unsigned int output;
+int comma=0;
+int ret;
+gnutls_datum pem;
+gnutls_x509_crl crl;
+time_t now = time(0);
+gnutls_x509_crt issuer;
+
+ issuer = load_ca_cert();
+
+ fprintf(outfile, "\nCA certificate:\n");
+ dn_size = sizeof(dn);
+ ret = gnutls_x509_crt_get_dn(issuer, dn, &dn_size);
+ if (ret >= 0)
+ fprintf(outfile, "\tSubject: %s\n\n", dn);
+
+ size = fread( buffer, 1, sizeof(buffer)-1, infile);
+ buffer[size] = 0;
+
+ pem.data = buffer;
+ pem.size = size;
+
+ gnutls_x509_crl_init( &crl);
+
+ ret = gnutls_x509_crl_import(crl, &pem, in_cert_format);
+ if (ret < 0) {
+ fprintf(stderr, "CRL decoding error: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ print_crl_info( crl, outfile, 1);
+
+
+ fprintf(outfile, "Verification output: ");
+ ret = gnutls_x509_crl_verify( crl, &issuer, 1, 0, &output);
+ if (ret < 0) {
+ fprintf(stderr, "Error in verification: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (output&GNUTLS_CERT_INVALID) {
+ fprintf(outfile, "Not verified");
+ comma = 1;
+ } else {
+ fprintf(outfile, "Verified");
+ comma = 1;
+ }
+
+ if (output&GNUTLS_CERT_SIGNER_NOT_CA) {
+ if (comma) fprintf(outfile, ", ");
+ fprintf(outfile, "Issuer is not a CA");
+ comma = 1;
+ }
+
+ /* Check expiration dates.
+ */
+
+ if (gnutls_x509_crl_get_this_update(crl) > now) {
+ if (comma) fprintf(outfile, ", ");
+ comma = 1;
+ fprintf(outfile, "Issued in the future!");
+ }
+
+ if (gnutls_x509_crl_get_next_update(crl) < now) {
+ if (comma) fprintf(outfile, ", ");
+ comma = 1;
+ fprintf(outfile, "CRL is not up to date");
+ }
+
+ fprintf(outfile, "\n");
+
+}
+
#include <gnutls/pkcs12.h>
#include <unistd.h>
@@ -2061,6 +2368,103 @@ void pkcs12_info( void)
}
+void pkcs7_info( void)
+{
+ gnutls_pkcs7 pkcs7;
+ int result;
+ size_t size;
+ gnutls_datum data, b64;
+ int index, count;
+
+ size = fread( buffer, 1, sizeof(buffer)-1, infile);
+ buffer[size] = 0;
+
+ data.data = buffer;
+ data.size = size;
+
+ result = gnutls_pkcs7_init(&pkcs7);
+ if (result < 0) {
+ fprintf(stderr, "p7_init: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ result = gnutls_pkcs7_import( pkcs7, &data, in_cert_format);
+ if (result < 0) {
+ fprintf(stderr, "p7_import: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ /* Read and print the certificates.
+ */
+ result = gnutls_pkcs7_get_crt_count( pkcs7);
+ if (result < 0) {
+ fprintf(stderr, "p7_count: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ count = result;
+
+ if (count > 0)
+ fprintf(outfile, "Certificates: %u\n", count);
+
+ for (index = 0;index < count;index++) {
+ size = sizeof(buffer);
+ result = gnutls_pkcs7_get_crt_raw( pkcs7, index, buffer, &size);
+ if (result < 0) {
+ break;
+ }
+
+ data.data = buffer;
+ data.size = size;
+
+ result = gnutls_pem_base64_encode_alloc( "CERTIFICATE", &data, &b64);
+ if (result < 0) {
+ fprintf(stderr, "error encoding: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ fputs( b64.data, outfile);
+ fputs( "\n", outfile);
+ gnutls_free( b64.data);
+ }
+
+ /* Read the CRLs now.
+ */
+ result = gnutls_pkcs7_get_crl_count( pkcs7);
+ if (result < 0) {
+ fprintf(stderr, "p7_count: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ count = result;
+
+ if (count > 0)
+ fprintf(outfile, "\nCRLs: %u\n", count);
+
+ for (index = 0;index < count;index++) {
+ size = sizeof(buffer);
+ result = gnutls_pkcs7_get_crl_raw( pkcs7, index, buffer, &size);
+ if (result < 0) {
+ break;
+ }
+
+ data.data = buffer;
+ data.size = size;
+
+ result = gnutls_pem_base64_encode_alloc( "X509 CRL", &data, &b64);
+ if (result < 0) {
+ fprintf(stderr, "error encoding: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ fputs( b64.data, outfile);
+ fputs( "\n", outfile);
+ gnutls_free( b64.data);
+ }
+
+
+}
+
#else /* ENABLE_PKI */
#include <stdio.h>
@@ -2082,8 +2486,7 @@ void certtool_version(void)
void print_license(void)
{
- fprintf(stdout,
- "\nCopyright (C) 2001-2003 Nikos Mavroyanopoulos\n"
+ fputs( "\nCopyright (C) 2004 Free Software Foundation\n"
"This program is free software; you can redistribute it and/or modify \n"
"it under the terms of the GNU General Public License as published by \n"
"the Free Software Foundation; either version 2 of the License, or \n"
@@ -2094,5 +2497,5 @@ void print_license(void)
"GNU General Public License for more details. \n" "\n"
"You should have received a copy of the GNU General Public License \n"
"along with this program; if not, write to the Free Software \n"
- "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n");
+ "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n", stdout);
}
diff --git a/src/certtool.gaa b/src/certtool.gaa
index 007200952a..9fb257e93f 100644
--- a/src/certtool.gaa
+++ b/src/certtool.gaa
@@ -19,6 +19,8 @@ option (s, generate-self-signed) { $action=0; } "Generate a self-signed certific
option (c, generate-certificate) { $action=4; } "Generate a signed certificate."
+option (generate-crl) { $action=13; } "Generate a CRL."
+
option (u, update-certificate) { $action=7; } "Update a signed certificate."
option (p, generate-privkey) { $action=1; } "Generate a private key."
@@ -27,6 +29,8 @@ option (q, generate-request) { $action=3; } "Generate a PKCS #10 certificate req
option (e, verify-chain) { $action=5; } "Verify a PEM encoded certificate chain. The last certificate in the chain must be a self signed one."
+option (verify-crl) { $action=14; } "Verify a CRL."
+
option (generate-dh-params) { $action=10; } "Generate PKCS #3 encoded Diffie Hellman parameters."
#char *privkey;
@@ -53,6 +57,8 @@ option (l, crl-info) { $action = 11; } "Print information on a CRL."
option (p12-info) { $action = 9; } "Print information on a PKCS #12 structure."
+option (p7-info) { $action = 12; } "Print information on a PKCS #7 structure."
+
option (k, key-info) { $action = 6; } "Print information on a private key."
option (to-p12) { $action = 8; } "Generate a PKCS #12 structure."
@@ -60,6 +66,9 @@ option (to-p12) { $action = 8; } "Generate a PKCS #12 structure."
#int pkcs8;
option (8, pkcs8) { $pkcs8=1 } "Use PKCS #8 format for private keys."
+#int dsa;
+option (dsa) { $dsa=1 } "Use DSA keys."
+
#int export;
option (export-ciphers) { $export=1 } "Use weak encryption algorithms."