]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Backported several things from the development branch.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Tue, 10 Feb 2004 20:03:26 +0000 (20:03 +0000)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Tue, 10 Feb 2004 20:03:26 +0000 (20:03 +0000)
46 files changed:
NEWS
configure.in
includes/gnutls/x509.h
lib/Makefile.am
lib/gnutls.h.in.in
lib/gnutls_cipher.c
lib/gnutls_errors.c
lib/gnutls_errors_int.h
lib/gnutls_hash_int.c
lib/gnutls_int.h
lib/gnutls_mpi.h
lib/gnutls_rsa_export.c
lib/gnutls_rsa_export.h
lib/gnutls_ui.h
lib/rsa_compat.c
lib/x509/Makefile.am
lib/x509/common.c
lib/x509/common.h
lib/x509/crl.c
lib/x509/crl_write.c [new file with mode: 0644]
lib/x509/crq.c
lib/x509/dn.c
lib/x509/extensions.c
lib/x509/extensions.h
lib/x509/mpi.c
lib/x509/mpi.h
lib/x509/pkcs12.c
lib/x509/pkcs12_bag.c
lib/x509/pkcs12_encr.c
lib/x509/pkcs5.c
lib/x509/pkcs7.c
lib/x509/privkey.c
lib/x509/privkey_pkcs8.c
lib/x509/rc2.c
lib/x509/rfc2818_hostname.c
lib/x509/sign.c
lib/x509/sign.h
lib/x509/verify.c
lib/x509/x509.c
lib/x509/x509.h
lib/x509/x509_write.c
lib/x509/xml.c
src/certtool-gaa.c
src/certtool-gaa.h
src/certtool.c
src/certtool.gaa

diff --git a/NEWS b/NEWS
index 579846612e3e7fb74b12ff9e39c03bf59df96e58..4c78bb6c1e7981112eca6b8a082c37f82dddf0dd 100644 (file)
--- 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
index 9fbd9129867f82c988ab5c9e1fc9e61e9b1c03b9..bbe83478291d7fda235afc07151298f340829482 100644 (file)
@@ -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
 
index bdc7a9f0c754171bae02ea3f92160d89ef182d9f..ab8346d3c9a9e1de2b6fca093f42dd6aee85f265 100644 (file)
@@ -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);
index c5ff61952fa187f51ceddd7edccd909a079cd402..39aa7f011557996e480d673dfe18e8842efcf94e 100644 (file)
@@ -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) \
index 1d89595bd1ad7d84b1f5aac663dd77a9f0c25415..b39d7bcc16bc63779ddfae54d25580d3dc2e264e 100644 (file)
@@ -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.
  */
index cca6a8fed4d3c23193063d9fd2e604739c2c9058..cf32bcd43518d7660604dbeaa55a9522c7a225f9 100644 (file)
@@ -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 {
index 0ea3581416d0b7e83df05f0e4abb3d39ed4b1eaa..23670e13bf7b166d685805fe738c0ab503564f82 100644 (file)
@@ -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 ), 
index 3f64c626d721ad5b027d89ff93240c58aa63246b..e5d181e01fa442cf7f8956b05deb62f42dbb1900 100644 (file)
 
 #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
 
index 1746f963dc542e0ec44bd5ba8fa2d0500cccded7..cea75de4d0278ad850c01cb66f239c5ae928165e 100644 (file)
@@ -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;
index ef95fee29c0e5023ecceef021d3caa22632a1525..00868356f886ef6c64f4b98257bf06c14cf1d41e 100644 (file)
@@ -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*);
index 2ac9eae663b76109069ffcf3913ffa85f2148bc0..357cc0a7bd1e577fe51e3ec2593a904d4307010c 100644 (file)
@@ -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);
 
index bc7104fb9251f0df46bcc04c3e096dce3c59e9b7..b772a2312c65a7df2c3c5a7be9b6f7ea8ca3be72 100644 (file)
@@ -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;
 
index 49fec266b9126cff133b34e7c39d30b1d80a98e1..57897d32bbb70b225235dea993395a517d236453 100644 (file)
@@ -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);
 
index ef050f9aba8c08b36a118b991b9f84996b308abc..007690182ce30fbf5e0995a7acadc979d05eea26 100644 (file)
@@ -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 */
index 67e4d101418a407c94d569c3c70c75e61887b8ba..18a33a2a3f472a65d3837330cd505dc74ef00e00 100644 (file)
@@ -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;
index 206617b223b90466d8be75467419f02e95435355..de9bc28e11c0735afe4f475da267ffa1812444a3 100644 (file)
@@ -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
 
index 7af2a068f02c4c3a3cb0cfa7014f0f58ffde4b52..b466ce192c3cbd73a6bbc00e5b183fd2230002b0 100644 (file)
@@ -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");
 
index 34d07d9a23eeabb7dfcbc321a8fd6ff0f760c412..f29a28f27be7ff48416e0905bcd9f8942dbddcaf 100644 (file)
@@ -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);
 
index d4e05b6cd26031b9698ff9899879212e0f608b13..3ae42dced9dd7751fbbe094e5841419ffeeb6712 100644 (file)
@@ -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 (file)
index 0000000..7545f2c
--- /dev/null
@@ -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 */
index 07938ccab164faf467bd066f311e86e76b810065..e6d4d1669cdc910eebe07c169d8a4e05c6385ddf 100644 (file)
@@ -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;
index 755f72ec558637b803541972c9aefdd15fbd71ed..ef0e6401cc81b4960ac6b805fa5b6aa8123d8815 100644 (file)
@@ -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)");
                                }
                        }
                        
index c88a69c250ccc5d9303c6b51af87f485302bb564..fc6e07a2dfaed2d965e9bba912764e4e371334ee 100644 (file)
@@ -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;
+}
index 12f8f70c88f3aae755b6e8addb76c16e4ed81985..ce2e70a67b150297b712f8fa4406fb1fdf9ec0da 100644 (file)
@@ -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);
index 2eb76bb064b16b8847cd20d60981130df59a0c03..d2d260f63d13140a8050a78142c896a6ab8f11b7 100644 (file)
@@ -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
index 471a01c8de08caf580437b26c59e1d7cbe2d9f71..cfa92918f761d5a3a52771f1929c6d48d2dd8d06 100644 (file)
@@ -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);
index 9f61e21d0d553b98907da024b6d47fb1d8e310d2..27bbe41218bbeb1749a099ada242e60ed73c1a4c 100644 (file)
@@ -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;
index 6b9ab32ba1055d3094a19006bc51a4f3dc07c2d7..466f4e7970c11422649f84ed5e1f47a0ad9ce94a 100644 (file)
@@ -1,5 +1,6 @@
 /*
  *  Copyright (C) 2003 Nikos Mavroyanopoulos
+ *  Copyright (C) 2004 Free Software Foundation
  *
  *  This file is part of GNUTLS.
  *
index c1501e62dbbfc9b56e6bc147e99b8583db04f1fc..921bff9b86ebcec9df58fe511d38661fb9ec6577 100644 (file)
@@ -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.
index 15ce59c05c04d96ffc7c8c8a65370b474cafe0e0..c1c745b71e25000a424ab5ada705c0b797a4e2f2 100644 (file)
@@ -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
index eb12fc12127dd82ce38a1dc1d1eb9d0c39bb0fda..3b969f32fb64fceb8686af20c8376ac71787db20 100644 (file)
@@ -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 */
index b1dbeec0869679f9f1b516d726826dbf57571d0b..4798e221dd09a316be409115c5d22c1cfc50647d 100644 (file)
@@ -1,5 +1,6 @@
 /*
  *  Copyright (C) 2003 Nikos Mavroyanopoulos
+ *  Copyright (C) 2004 Free Software Foundation
  *
  *  This file is part of GNUTLS.
  *
 #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;
index 433436fa3bd26c773a03e5cf1affa83855feb7a2..93a67d41d6cea091f449e950ed24381457c66132 100644 (file)
@@ -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;
index b993d4479356b839b86939a8672b992fdb9a9c33..982d556f255fd2010464291b2ea76e371480ad0e 100644 (file)
@@ -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.
  *
index 7c19c228db4ac9906d6977c24447caceb4bf1f96..d07b113e9c8e5af12cba39d2bbae074eb7aa2f87 100644 (file)
@@ -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.
  *
 #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;
       }
    }
 
index 3a45b0ecb1949f06407c01343ebc63fdf9e7bb13..b63724e060f19edb0035016fdc380b986ac7d49a 100644 (file)
@@ -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
index dd6936f346441f9852da9009853303631f045d7b..08e0475f72d29e1e150483e48123ee3ad960f67f 100644 (file)
@@ -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);
index 24c7cdb702e4556d8e2c1ac09cf65735483e40b3..9b3f658b00608f83be1ba483f242f734ffcbe9fa 100644 (file)
@@ -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;
                        }
index d6d78592aff66855ae4f6db03da08b5bc2832cf9..96096d6aaf4ea01aea50c4d9a18558a5ed86a171 100644 (file)
@@ -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
index 72e66c21ed96167f36804eda5a6260171efdd813..ee5c949e1ad8b5dcc3a17901b6d14f3408a50af3 100644 (file)
@@ -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
index 77e59d2b1016903e783bd47d5d7e2c1b21d30b18..d458c252f2a142243608621576ec2c6e4d1bb4c7 100644 (file)
@@ -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. 
   *
@@ -261,6 +256,48 @@ gnutls_datum der_data;
        return 0;
 }
 
+/**
+  * 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
@@ -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 */
index 5c3ec65f941a6565a91b5e880cf083537641d1b7..4cac03abe4cba272b68fcd1accec32ae63e9f67c 100644 (file)
@@ -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.
   *
   **/
index 707ee10ed0544c0c2d4265cdfb75037d2995f5fe..fac7e054ef77ea41f891221486f749d2f809beca 100644 (file)
@@ -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,44 +879,58 @@ 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:
@@ -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;
index 15210d0aac539b1d06bea3b40610d4f0551cca21..2bef4af05b9ba569dea353921a39d108494b3470 100644 (file)
@@ -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;
index 7d488711a110b95e3ed62065196b7ef11b2f6a6e..6546765cb0e914f87750968ca139cd52b34ee3c6 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
  *
  * This file is part of GNUTLS.
  *
 #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);
 
-       fprintf(outfile, "X.509 certificate info:\n\n");
+       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, "Version: %d\n", gnutls_x509_crt_get_version(crt));
+       fprintf(outfile, "\n%s\n", buffer);
+}
+
+static void print_certificate_info( gnutls_x509_crt crt, FILE* out, unsigned int all)
+{
+       int ret;
+       unsigned int i, indx, j;
+       unsigned int critical, key_usage;
+       time_t tim;
+       char serial[40];
+       size_t serial_size = sizeof(serial), dn_size, size;
+       char printable[256];
+       char *print;
+       const char* cprint;
+       char dn[256];
+       char oid[128] = "";
+       char old_oid[128] = "";
+       
+       fprintf( out, "\n\nX.509 certificate info:\n\n");
+       
+       fprintf(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,263 +1086,173 @@ 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");
-                               else
-                                       fprintf(outfile, "\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);
-                       
-                       }
-       
-                       ret = 0;
-                       strcpy( old_oid, oid);
-               }
-       }
-
-
-       /* 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(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);
-       } else {
-               print = printable;
-               for (i = 0; i < size; i++) {
-                       sprintf(print, "%.2x ", (unsigned char) buffer[i]);
-                       print += 3;
-               }
-               fprintf(outfile, "Public Key ID: %s\n", printable);
-       }
-
-       fprintf(outfile, "\n");
-}
-
-static void print_certificate_info( gnutls_x509_crt crt)
-{
-       int ret;
-       unsigned int i;
-       unsigned int critical, key_usage;
-       time_t tim;
-       char serial[40];
-       size_t serial_size = sizeof(serial), dn_size, size;
-       char printable[256];
-       char *print;
-       const char* cprint;
-       char dn[256];
-       
-       fprintf( stderr, "\n\nX.509 certificate info:\n\n");
-       
-       fprintf(stderr, "Version: %d\n", gnutls_x509_crt_get_version(crt));
-
-       /* serial number
-        */
-       if (gnutls_x509_crt_get_serial(crt, serial, &serial_size) >= 0) {
-               print = printable;
-               for (i = 0; i < serial_size; i++) {
-                       sprintf(print, "%.2x ",
-                               (unsigned char) serial[i]);
-                       print += 3;
-               }
-               fprintf(stderr, "Serial Number (hex): %s\n", printable);
-       }
-       
-       /* Validity
-        */
-       fprintf(stderr, "Validity:\n");
-
-       tim = gnutls_x509_crt_get_activation_time(crt);
-       fprintf(stderr, "\tNot Before: %s", ctime(&tim));
-
-       tim = gnutls_x509_crt_get_expiration_time(crt);
-       fprintf(stderr, "\tNot After: %s", ctime(&tim));
-
-       /* Subject
-        */
-       dn_size = sizeof(dn);
-       ret = gnutls_x509_crt_get_dn(crt, dn, &dn_size);
-       if (ret >= 0)
-               fprintf(stderr, "Subject: %s\n", dn);
-
-       /* Public key algorithm
-        */
-       fprintf(stderr, "Subject Public Key Info:\n");
-       ret = gnutls_x509_crt_get_pk_algorithm(crt, NULL);
-       fprintf(stderr, "\tPublic Key Algorithm: ");
-
-       cprint = get_algorithm( ret);
-       fprintf(stderr,  "%s\n", cprint);
-
-
-       
-       fprintf(stderr, "\nX.509 Extensions:\n");
-       
-       /* subject alternative name
-        */
-       for (i = 0; !(ret < 0); i++) {
-               size = sizeof(buffer);
-               ret = gnutls_x509_crt_get_subject_alt_name(crt, i, buffer, &size, &critical);
-
-               if (i==0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
-                       fprintf(stderr, "\tSubject Alternative name:");
-                       if (critical) fprintf(stderr, " (critical)");
-                       fprintf(stderr, "\n");
-               }
-               
-               if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
-                       fprintf(stderr, "\t\tFound unsupported alternative name.\n");
-               } else switch (ret) {
-                       case GNUTLS_SAN_DNSNAME:
-                               fprintf(stderr, "\t\tDNSname: %s\n", buffer);
-                               break;
-                       case GNUTLS_SAN_RFC822NAME:
-                               fprintf(stderr, "\t\tRFC822name: %s\n", buffer);
-                               break;
-                       case GNUTLS_SAN_URI:
-                               fprintf(stderr, "\t\tURI: %s\n", buffer);
-                               break;
-                       case GNUTLS_SAN_IPADDRESS:
-                               fprintf(stderr, "\t\tIPAddress: %s\n", buffer);
-                               break;
+                       ret = gnutls_x509_crt_get_extension_by_oid( crt, oid, indx, buffer, &size, &critical);
+                       if (ret >= 0) {
+                               if (critical)
+                                       fprintf(out, "(critical)\n");
+                               else
+                                       fprintf(out, "\n");
+
+                               print = printable;
+                               for (j = 0; j < size; j++) {
+                                       sprintf(print, "%.2x", (unsigned char) buffer[j]);
+                                       print += 2;
+                               }
+                               fprintf(out, "\t\tDER Data: %s\n", printable);
+                       
+                       }
+       
+                       ret = 0;
+                       strcpy( old_oid, oid);
                }
        }
-       
-       /* 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.
+
+       /* fingerprint
         */
-       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( 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);
+               }
+       }
+
+       size = sizeof(buffer);
+       if ((ret=gnutls_x509_crt_get_key_id(crt, 0, buffer, &size)) < 0) 
+       {
+               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(out, "\tPublic Key ID: %s\n", printable);
        }
 
-       fprintf(stderr, "\n");
+       fprintf(out, "\n");
 
+       if (out==stderr) /* interactive */
        if (read_yesno( "Is the above information ok? (Y/N): ")==0) {
                exit(1);
        }
 }
 
-void crl_info(void)
+static void print_crl_info( gnutls_x509_crl crl, FILE* out, int all)
 {
-       gnutls_x509_crl crl;
        int ret, rc;
-       size_t size;
        time_t tim;
-       unsigned int i;
-       gnutls_datum pem;
-       unsigned char serial[40];
+       unsigned int i, j;
+       char serial[128];
        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;
 
-       gnutls_x509_crl_init(&crl);
-       
-       pem.data = buffer;
-       pem.size = size;
-       
-       ret = gnutls_x509_crl_import(crl, &pem, in_cert_format);
-       if (ret < 0) {
-               fprintf(stderr, "Decoding error: %s\n", gnutls_strerror(ret));
-               exit(1);
-       }
-       
-       fprintf(outfile, "Version: %d\n", gnutls_x509_crl_get_version(crl));
+       fprintf(out, "CRL information:\n");
+       fprintf(out, "Version: %d\n", gnutls_x509_crl_get_version(crl));
 
        /* Issuer
         */
-       dn_size = sizeof(dn);
+       if (all) {
+               dn_size = sizeof(dn);
 
-       ret = gnutls_x509_crl_get_issuer_dn(crl, dn, &dn_size);
-       if (ret >= 0)
-               fprintf(outfile, "Issuer: %s\n", dn);
+               ret = gnutls_x509_crl_get_issuer_dn(crl, dn, &dn_size);
+               if (ret >= 0)
+                       fprintf(out, "Issuer: %s\n", dn);
 
-       fprintf(outfile, "Signature Algorithm: ");
-       ret = gnutls_x509_crl_get_signature_algorithm(crl);
+               fprintf(out, "Signature Algorithm: ");
+               ret = gnutls_x509_crl_get_signature_algorithm(crl);
 
-       cprint = get_algorithm( ret);
-       fprintf(outfile,  "%s\n", cprint);
+               cprint = get_sign_algorithm( ret);
+               fprintf(out,  "%s\n", cprint);
+       }
 
        /* Validity
         */
-       fprintf(outfile, "Update dates:\n");
+       fprintf(out, "Update dates:\n");
 
        tim = gnutls_x509_crl_get_this_update(crl);
-       fprintf(outfile, "\tIssued at: %s", ctime(&tim));
+       fprintf(out, "\tIssued at: %s", ctime(&tim));
 
        tim = gnutls_x509_crl_get_next_update(crl);
-       fprintf(outfile, "\tNext at: %s", ctime(&tim));
+       fprintf(out, "\tNext at: %s", ctime(&tim));
 
-       fprintf(outfile, "\n");
+       fprintf(out, "\n");
        
        /* Count the certificates.
         */
         
        rc = gnutls_x509_crl_get_crt_count( crl);
-       fprintf(outfile, "Revoked certificates: %d\n", rc);
+       fprintf(out, "Revoked certificates: %d\n", rc);
 
-       for (i=0;i<(unsigned int)rc;i++) {
+       for (j=0;j<(unsigned int)rc;j++) {
                /* serial number
                 */
                serial_size = sizeof(serial);
-               if (gnutls_x509_crl_get_crt_serial(crl, i, serial, &serial_size, &tim) >= 0) {
+               ret = gnutls_x509_crl_get_crt_serial(crl, j, serial, &serial_size, &tim);
+               
+               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(outfile, "\tCertificate SN: %s\n", printable);
-                       fprintf(outfile, "\tRevoked at: %s\n", ctime( &tim));
+                       fprintf(out, "\tCertificate SN: %s\n", printable);
+                       fprintf(out, "\tRevoked at: %s\n", ctime( &tim));
                }
+       }
+
+}
+
+void crl_info()
+{
+       gnutls_x509_crl crl;
+       int ret;
+       size_t size;
+       gnutls_datum pem;
+               
+       size = fread( buffer, 1, sizeof(buffer)-1, infile);
+       buffer[size] = 0;
+
+       gnutls_x509_crl_init(&crl);
+       
+       pem.data = buffer;
+       pem.size = size;
+       
+       ret = gnutls_x509_crl_import(crl, &pem, in_cert_format);
+       if (ret < 0) {
+               fprintf(stderr, "Decoding error: %s\n", gnutls_strerror(ret));
+               exit(1);
+       }
        
+       print_crl_info( crl, outfile, 1);
+
+       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);
        }
+       
+       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>
 
@@ -2059,6 +2366,103 @@ void pkcs12_info( void)
        } while( ret == 0);
 
        
+}
+
+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 */
@@ -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);
 }
index 007200952aea6ab744811b89c4306c31f326f2b8..9fb257e93f13e1a468747d547fb3990897f02c84 100644 (file)
@@ -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."