diff options
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | doc/TODO | 4 | ||||
-rw-r--r-- | includes/gnutls/x509.h | 9 | ||||
-rw-r--r-- | lib/Makefile.am | 2 | ||||
-rw-r--r-- | lib/gnutls_pk.c | 13 | ||||
-rw-r--r-- | lib/gnutls_rsa_export.c | 4 | ||||
-rw-r--r-- | lib/gnutls_rsa_export.h | 2 | ||||
-rw-r--r-- | lib/gnutls_sig.c | 48 | ||||
-rw-r--r-- | lib/gnutls_ui.h | 2 | ||||
-rw-r--r-- | lib/rsa_compat.c | 3 | ||||
-rw-r--r-- | lib/x509/Makefile.am | 4 | ||||
-rw-r--r-- | lib/x509/common.c | 96 | ||||
-rw-r--r-- | lib/x509/crq.c | 36 | ||||
-rw-r--r-- | lib/x509/dsa.c | 121 | ||||
-rw-r--r-- | lib/x509/dsa.h | 1 | ||||
-rw-r--r-- | lib/x509/mpi.c | 50 | ||||
-rw-r--r-- | lib/x509/mpi.h | 2 | ||||
-rw-r--r-- | lib/x509/privkey.c | 382 | ||||
-rw-r--r-- | lib/x509/sign.c | 35 | ||||
-rw-r--r-- | lib/x509/x509.c | 2 | ||||
-rw-r--r-- | lib/x509/x509_write.c | 10 | ||||
-rw-r--r-- | src/certtool-gaa.c | 104 | ||||
-rw-r--r-- | src/certtool-gaa.h | 16 | ||||
-rw-r--r-- | src/certtool.c | 18 | ||||
-rw-r--r-- | src/certtool.gaa | 3 |
25 files changed, 774 insertions, 194 deletions
@@ -6,6 +6,7 @@ Version 1.1.0 gnutls_certificate_server_retrieve_function(), to allow a client or a server to specify certificates for the handshake without storing them to the credentials structure. +- Added support for generating and exporting DSA private keys. Version 1.0.1 (10/12/2003) - Some minor fixes in the makefiles. They now include CFLAGS @@ -3,9 +3,6 @@ anything), contact the developer's mailing list (gnutls-dev@lists.gnupg.org), in order to avoid having people working on the same thing. Current list: -* Add a callback function in certificate authentication, to receive - the certificate and the private key. This might require a rewrite - of the certificate selection part. * Add gnutls_certificate_set_openpgp_key() and gnutls_certificate_set_openpgp_keyring() functions, similar to gnutls_certificate_set_x509_key(). * Add gnutls_openpgp_key_get_key_usage(). @@ -14,7 +11,6 @@ Current list: * Add function to extract the signers of an openpgp key. Should be similar to gnutls_x509_crt_get_dn_oid(). * Add function to verify an openpgp key against a plain key. -* Add support for generating and handling DSA keys * Add support for extracting CRL distribution points. * Add support for generating CRLs. * Add PKCS #7 support to certtool utility. diff --git a/includes/gnutls/x509.h b/includes/gnutls/x509.h index 143c67abd5..b700726542 100644 --- a/includes/gnutls/x509.h +++ b/includes/gnutls/x509.h @@ -274,6 +274,15 @@ int gnutls_x509_privkey_import_rsa_raw(gnutls_x509_privkey privkey, const gnutls_datum *m, const gnutls_datum *e, const gnutls_datum *d, const gnutls_datum *p, const gnutls_datum *q, const gnutls_datum *u); + +int gnutls_x509_privkey_export_dsa_raw(gnutls_x509_privkey key, + gnutls_datum * p, gnutls_datum *q, + gnutls_datum *g, gnutls_datum *y, gnutls_datum* x); +int gnutls_x509_privkey_import_dsa_raw(gnutls_x509_privkey key, + const gnutls_datum* p, const gnutls_datum* q, + const gnutls_datum* g, const gnutls_datum* y, + const gnutls_datum* x); + int gnutls_x509_privkey_get_pk_algorithm( gnutls_x509_privkey key); int gnutls_x509_privkey_get_key_id( gnutls_x509_privkey key, unsigned int flags, unsigned char* output_data, size_t* output_data_size); diff --git a/lib/Makefile.am b/lib/Makefile.am index c5ff61952f..e72c605a76 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -53,7 +53,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c \ libgnutls_la_SOURCES = $(COBJECTS) 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/x509.lo x509/extensions.lo x509/compat.lo x509/verify.lo x509/dsa.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 diff --git a/lib/gnutls_pk.c b/lib/gnutls_pk.c index 78a294a43d..c6d5db7be1 100644 --- a/lib/gnutls_pk.c +++ b/lib/gnutls_pk.c @@ -491,14 +491,15 @@ int _gnutls_dsa_verify( const gnutls_datum* vdata, const gnutls_datum *sig_value } /* decrypt signature */ - if ( (ret=_gnutls_pk_verify( GCRY_PK_DSA, mdata, rs, params, - params_len)) < 0) { - _gnutls_mpi_release(&mdata); - gnutls_assert(); - return ret; - } + ret=_gnutls_pk_verify( GCRY_PK_DSA, mdata, rs, params, + params_len); _gnutls_mpi_release(&mdata); + if (ret < 0) { + gnutls_assert(); + return ret; + } + return 0; /* ok */ } diff --git a/lib/gnutls_rsa_export.c b/lib/gnutls_rsa_export.c index e030da9658..113867bd32 100644 --- a/lib/gnutls_rsa_export.c +++ b/lib/gnutls_rsa_export.c @@ -53,7 +53,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; @@ -144,6 +144,8 @@ int _gnutls_rsa_generate_params(GNUTLS_MPI* resarr, int bits) _gnutls_dump_mpi( "p: ", resarr[3]); _gnutls_dump_mpi( "q: ", resarr[4]); _gnutls_dump_mpi( "u: ", resarr[5]); + + *resarr_len = 6; return 0; diff --git a/lib/gnutls_rsa_export.h b/lib/gnutls_rsa_export.h index 49fec266b9..57897d32bb 100644 --- a/lib/gnutls_rsa_export.h +++ b/lib/gnutls_rsa_export.h @@ -20,5 +20,5 @@ const GNUTLS_MPI* _gnutls_get_rsa_params(gnutls_rsa_params); int _gnutls_peers_cert_less_512( gnutls_session session); -int _gnutls_rsa_generate_params(GNUTLS_MPI* resarr, int bits); +int _gnutls_rsa_generate_params(GNUTLS_MPI* resarr, int* resarr_len, int bits); diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c index 277db2aacc..87a541d473 100644 --- a/lib/gnutls_sig.c +++ b/lib/gnutls_sig.c @@ -147,30 +147,6 @@ opaque concat[36]; } -/* This will create a PKCS1 or DSA signature, as defined in the TLS protocol. - * Cert is the certificate of the corresponding private key. It is only checked if - * it supports signing. - */ -static -int _gnutls_tls_sign( gnutls_cert* cert, gnutls_privkey* pkey, const gnutls_datum* hash_concat, gnutls_datum *signature) -{ - - /* If our certificate supports signing - */ - - if ( cert != NULL) - if ( cert->keyUsage != 0) - if ( !(cert->keyUsage & KEY_DIGITAL_SIGNATURE)) { - gnutls_assert(); - return GNUTLS_E_KEY_USAGE_VIOLATION; - } - - return _gnutls_sign( pkey->pk_algorithm, pkey->params, pkey->params_size, - hash_concat, signature); - -} - - /* This will create a PKCS1 or DSA signature, using the given parameters, and the * given data. The output will be allocated and be put in signature. */ @@ -206,6 +182,30 @@ int ret; return 0; } +/* This will create a PKCS1 or DSA signature, as defined in the TLS protocol. + * Cert is the certificate of the corresponding private key. It is only checked if + * it supports signing. + */ +static +int _gnutls_tls_sign( gnutls_cert* cert, gnutls_privkey* pkey, + const gnutls_datum* hash_concat, gnutls_datum *signature) +{ + + /* If our certificate supports signing + */ + + if ( cert != NULL) + if ( cert->keyUsage != 0) + if ( !(cert->keyUsage & KEY_DIGITAL_SIGNATURE)) { + gnutls_assert(); + return GNUTLS_E_KEY_USAGE_VIOLATION; + } + + return _gnutls_sign( pkey->pk_algorithm, pkey->params, pkey->params_size, + hash_concat, signature); + +} + static int _gnutls_pkcs1_rsa_verify_sig( gnutls_cert *cert, const gnutls_datum *hash_concat, diff --git a/lib/gnutls_ui.h b/lib/gnutls_ui.h index 9700d1ff58..8dcfd32d20 100644 --- a/lib/gnutls_ui.h +++ b/lib/gnutls_ui.h @@ -21,7 +21,7 @@ typedef int gnutls_certificate_client_retrieve_function( gnutls_session, const gnutls_datum* req_ca_cert, int nreqs, gnutls_datum** certs, unsigned int* ncerts, gnutls_datum* key); typedef int gnutls_certificate_server_retrieve_function( - gnutls_session, gnutls_datum **server_certs, unsigned int* ncerts + gnutls_session, gnutls_datum **server_certs, unsigned int* ncerts, gnutls_datum* key); diff --git a/lib/rsa_compat.c b/lib/rsa_compat.c index 67e4d10141..092d49a5fa 100644 --- a/lib/rsa_compat.c +++ b/lib/rsa_compat.c @@ -160,6 +160,7 @@ int gnutls_rsa_params_generate(gnutls_datum * m, gnutls_datum *e, { GNUTLS_MPI rsa_params[RSA_PRIVATE_PARAMS]; + int rsa_params_len; size_t siz; uint i; int ret; @@ -169,7 +170,7 @@ int gnutls_rsa_params_generate(gnutls_datum * m, gnutls_datum *e, return GNUTLS_E_INVALID_REQUEST; } - ret = _gnutls_rsa_generate_params( rsa_params, bits); + ret = _gnutls_rsa_generate_params( rsa_params, &rsa_params_len, bits); if (ret < 0) { gnutls_assert(); return ret; diff --git a/lib/x509/Makefile.am b/lib/x509/Makefile.am index 206617b223..b90f0bd869 100644 --- a/lib/x509/Makefile.am +++ b/lib/x509/Makefile.am @@ -1,12 +1,12 @@ 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 -COBJECTS = crl.c dn.c common.c x509.c extensions.c \ +COBJECTS = crl.c dn.c common.c x509.c extensions.c dsa.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 diff --git a/lib/x509/common.c b/lib/x509/common.c index 47ebd6314d..5868ff6dd5 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -948,7 +948,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) @@ -958,18 +957,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); 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"); @@ -979,34 +973,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; } diff --git a/lib/x509/crq.c b/lib/x509/crq.c index 07938ccab1..224ff3a70a 100644 --- a/lib/x509/crq.c +++ b/lib/x509/crq.c @@ -606,11 +606,6 @@ const char* pk; 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, @@ -648,12 +643,31 @@ const char* pk; 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) { - gnutls_assert(); - return _gnutls_asn2err(result); + if (key->pk_algorithm == GNUTLS_PK_DSA) { + gnutls_datum der; + + result = _gnutls_x509_write_dsa_params( key->params, key->params_size, &der); + if (result < 0) { + gnutls_assert(); + return result; + } + + result = asn1_write_value( crq->crq, "signatureAlgorithm.parameters", der.data, der.size); + _gnutls_free_datum( &der); + + if (result != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + } else { + /* RSA so disable the parameters. + */ + result = asn1_write_value( crq->crq, "signatureAlgorithm.parameters", NULL, 0); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } } return 0; diff --git a/lib/x509/dsa.c b/lib/x509/dsa.c new file mode 100644 index 0000000000..b5e35b94da --- /dev/null +++ b/lib/x509/dsa.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2003 Nikos Mavroyanopoulos + * + * 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 code for DSA keys. + */ + +#include <gnutls_int.h> +#include <gnutls_errors.h> +#include <gnutls_datum.h> +#include <debug.h> + +/* resarr will contain: p(0), q(1), g(2), y(3), x(4). + */ +int _gnutls_dsa_generate_params(GNUTLS_MPI* resarr, int* resarr_len, int bits) +{ + + int ret; + gcry_sexp_t parms, key, list; + + if (bits > 1024) bits = 1024; + + ret = gcry_sexp_build( &parms, NULL, "(genkey(dsa(nbits %d)))", bits); + if (ret != 0) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + /* generate the DSA key + */ + ret = gcry_pk_genkey( &key, parms); + gcry_sexp_release( parms); + + if (ret != 0) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + list = gcry_sexp_find_token( key, "p", 0); + if (list == NULL) { + gnutls_assert(); + gcry_sexp_release( key); + return GNUTLS_E_INTERNAL_ERROR; + } + + resarr[0] = gcry_sexp_nth_mpi(list, 1, 0); + gcry_sexp_release(list); + + list = gcry_sexp_find_token( key, "q", 0); + if (list == NULL) { + gnutls_assert(); + gcry_sexp_release( key); + return GNUTLS_E_INTERNAL_ERROR; + } + + resarr[1] = gcry_sexp_nth_mpi(list, 1, 0); + gcry_sexp_release(list); + + list = gcry_sexp_find_token( key, "g", 0); + if (list == NULL) { + gnutls_assert(); + gcry_sexp_release( key); + return GNUTLS_E_INTERNAL_ERROR; + } + + resarr[2] = gcry_sexp_nth_mpi(list, 1, 0); + gcry_sexp_release(list); + + list = gcry_sexp_find_token( key, "y", 0); + if (list == NULL) { + gnutls_assert(); + gcry_sexp_release( key); + return GNUTLS_E_INTERNAL_ERROR; + } + + resarr[3] = gcry_sexp_nth_mpi(list, 1, 0); + gcry_sexp_release(list); + + + list = gcry_sexp_find_token( key, "x", 0); + if (list == NULL) { + gnutls_assert(); + gcry_sexp_release( key); + return GNUTLS_E_INTERNAL_ERROR; + } + + resarr[4] = gcry_sexp_nth_mpi(list, 1, 0); + gcry_sexp_release(list); + + + gcry_sexp_release(key); + + _gnutls_dump_mpi( "p: ", resarr[0]); + _gnutls_dump_mpi( "q: ", resarr[1]); + _gnutls_dump_mpi( "g: ", resarr[2]); + _gnutls_dump_mpi( "y: ", resarr[3]); + _gnutls_dump_mpi( "x: ", resarr[4]); + + *resarr_len = 5; + + return 0; + +} + diff --git a/lib/x509/dsa.h b/lib/x509/dsa.h new file mode 100644 index 0000000000..4f9d7562b9 --- /dev/null +++ b/lib/x509/dsa.h @@ -0,0 +1 @@ +int _gnutls_dsa_generate_params(GNUTLS_MPI* resarr, int* resarr_len, int bits); diff --git a/lib/x509/mpi.c b/lib/x509/mpi.c index 2eb76bb064..c575732846 100644 --- a/lib/x509/mpi.c +++ b/lib/x509/mpi.c @@ -331,7 +331,7 @@ cleanup: } /* - * This function writes the BIT STRING subjectPublicKey for DSS keys. + * 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 +390,54 @@ cleanup: return result; } +/* + * This function writes the public parameters for DSS keys. + * Needs 1 parameter (y). + * + * Allocates the space used to store the DER data. + */ +int _gnutls_x509_write_dsa_public_key( GNUTLS_MPI * params, int params_size, + gnutls_datum* der) +{ + int result; + ASN1_TYPE spk = ASN1_TYPE_EMPTY; + + der->data = NULL; + der->size = 0; + + if (params_size < 3) { + gnutls_assert(); + result = GNUTLS_E_INVALID_REQUEST; + goto cleanup; + } + + if ((result=asn1_create_element + (_gnutls_get_gnutls_asn(), "GNUTLS.DSAPublicKey", &spk)) + != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + result = _gnutls_x509_write_int( spk, "", params[3], 0); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + result = _gnutls_x509_der_encode( spk, "", der, 0); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + asn1_delete_structure(&spk); + return 0; + +cleanup: + asn1_delete_structure(&spk); + return result; +} + /* this function reads a (small) unsigned integer * from asn1 structs. Combines the read and the convertion diff --git a/lib/x509/mpi.h b/lib/x509/mpi.h index 471a01c8de..6eff6f88b8 100644 --- a/lib/x509/mpi.h +++ b/lib/x509/mpi.h @@ -10,6 +10,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); diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index 7cc0097e85..8550026798 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -32,9 +32,11 @@ #include <mpi.h> #include <extensions.h> #include <sign.h> +#include <dsa.h> #include <verify.h> static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params); +static int _encode_dsa( ASN1_TYPE* c2, GNUTLS_MPI* params); /** * gnutls_x509_privkey_init - This function initializes a gnutls_crl structure @@ -356,7 +358,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 +393,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 +446,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,15 +702,115 @@ 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) { int result, i; - size_t size[8], total, tmp_size; + size_t size[8], total; opaque * m_data, *pube_data, *prie_data; opaque* p1_data, *p2_data, *u_data, *exp1_data, *exp2_data; - opaque * all_data = NULL; + opaque * all_data = NULL, *p; GNUTLS_MPI exp1 = NULL, exp2 = NULL, q1 = NULL, p1 = NULL; opaque null = '\0'; @@ -696,23 +875,24 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params) goto cleanup; } - m_data = &all_data[0]; - pube_data = &all_data[size[0]]; - prie_data = &all_data[size[1]]; - p1_data = &all_data[size[2]]; - p2_data = &all_data[size[3]]; - u_data = &all_data[size[4]]; - exp1_data = &all_data[size[5]]; - exp2_data = &all_data[size[6]]; - - _gnutls_mpi_print_lz( m_data, &tmp_size, params[0]); - _gnutls_mpi_print_lz( pube_data, &tmp_size, params[1]); - _gnutls_mpi_print_lz( prie_data, &tmp_size, params[2]); - _gnutls_mpi_print_lz( p1_data, &tmp_size, params[3]); - _gnutls_mpi_print_lz( p2_data, &tmp_size, params[4]); - _gnutls_mpi_print_lz( u_data, &tmp_size, params[5]); - _gnutls_mpi_print_lz( exp1_data, &tmp_size, exp1); - _gnutls_mpi_print_lz( exp2_data, &tmp_size, exp2); + p = all_data; + m_data = p; p+= size[0]; + pube_data = p; p+= size[1]; + prie_data = p; p+= size[2]; + p1_data = p; p+= size[3]; + p2_data = p; p+= size[4]; + u_data = p; p+= size[5]; + exp1_data = p; p+= size[6]; + exp2_data = p; + + _gnutls_mpi_print_lz( m_data, &size[0], params[0]); + _gnutls_mpi_print_lz( pube_data, &size[1], params[1]); + _gnutls_mpi_print_lz( prie_data, &size[2], params[2]); + _gnutls_mpi_print_lz( p1_data, &size[3], params[3]); + _gnutls_mpi_print_lz( p2_data, &size[4], params[4]); + _gnutls_mpi_print_lz( u_data, &size[5], params[5]); + _gnutls_mpi_print_lz( exp1_data, &size[6], exp1); + _gnutls_mpi_print_lz( exp2_data, &size[7], exp2); /* Ok. Now we have the data. Create the asn1 structures */ @@ -820,6 +1000,117 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params) 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_alloca( 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_afree(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_afree( all_data); + + return result; +} + /** * gnutls_x509_privkey_generate - This function will generate a private key @@ -829,8 +1120,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. * @@ -838,7 +1128,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(); @@ -847,10 +1138,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, ¶ms_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, ¶ms_len, bits); if (ret < 0) { gnutls_assert(); return ret; @@ -861,7 +1165,7 @@ int ret; gnutls_assert(); goto cleanup; } - key->params_size = 6; + key->params_size = params_len; key->pk_algorithm = GNUTLS_PK_RSA; break; @@ -875,12 +1179,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; } @@ -929,7 +1229,7 @@ gnutls_datum der = { NULL, 0 }; goto cleanup; } } else if (key->pk_algorithm == GNUTLS_PK_DSA) { - result = _gnutls_x509_write_dsa_params( key->params, key->params_size, &der); + result = _gnutls_x509_write_dsa_public_key( key->params, key->params_size, &der); if (result < 0) { gnutls_assert(); goto cleanup; diff --git a/lib/x509/sign.c b/lib/x509/sign.c index 3a45b0ecb1..bc0e0d9b9f 100644 --- a/lib/x509/sign.c +++ b/lib/x509/sign.c @@ -116,7 +116,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 +154,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 +200,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 +209,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; diff --git a/lib/x509/x509.c b/lib/x509/x509.c index d6d78592af..fccbd302f6 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -1136,7 +1136,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; diff --git a/lib/x509/x509_write.c b/lib/x509/x509_write.c index 77e59d2b10..dac2f48ed7 100644 --- a/lib/x509/x509_write.c +++ b/lib/x509/x509_write.c @@ -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) { @@ -344,11 +339,6 @@ const char* pk; 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); diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c index 707ee10ed0..cad74aa731 100644 --- a/src/certtool-gaa.c +++ b/src/certtool-gaa.c @@ -1,4 +1,4 @@ -/* File generated by GAA 1.6.2 +/* File generated by GAA 1.6.3 */ #define GAA_NO_WIN32 #line 1 "certtool.gaa" @@ -149,6 +149,7 @@ void gaa_help(void) __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,20 +174,22 @@ typedef struct _gaainfo gaainfo; struct _gaainfo { -#line 81 "certtool.gaa" +#line 84 "certtool.gaa" int debug; -#line 78 "certtool.gaa" +#line 81 "certtool.gaa" char *infile; -#line 75 "certtool.gaa" +#line 78 "certtool.gaa" char *outfile; -#line 72 "certtool.gaa" +#line 75 "certtool.gaa" int bits; -#line 69 "certtool.gaa" +#line 72 "certtool.gaa" int outcert_format; -#line 66 "certtool.gaa" +#line 69 "certtool.gaa" int incert_format; -#line 63 "certtool.gaa" +#line 66 "certtool.gaa" int export; +#line 63 "certtool.gaa" + int dsa; #line 60 "certtool.gaa" int pkcs8; #line 47 "certtool.gaa" @@ -257,7 +260,7 @@ int gaa_error = 0; #define GAA_MULTIPLE_OPTION 3 #define GAA_REST 0 -#define GAA_NB_OPTION 29 +#define GAA_NB_OPTION 30 #define GAAOPTID_copyright 1 #define GAAOPTID_version 2 #define GAAOPTID_help 3 @@ -268,25 +271,26 @@ 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_p12_info 15 +#define GAAOPTID_crl_info 16 +#define GAAOPTID_certificate_info 17 +#define GAAOPTID_password 18 +#define GAAOPTID_load_ca_certificate 19 +#define GAAOPTID_load_ca_privkey 20 +#define GAAOPTID_load_certificate 21 +#define GAAOPTID_load_request 22 +#define GAAOPTID_load_privkey 23 +#define GAAOPTID_generate_dh_params 24 +#define GAAOPTID_verify_chain 25 +#define GAAOPTID_generate_request 26 +#define GAAOPTID_generate_privkey 27 +#define GAAOPTID_update_certificate 28 +#define GAAOPTID_generate_certificate 29 +#define GAAOPTID_generate_self_signed 30 #line 168 "gaa.skel" @@ -580,6 +584,7 @@ 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); @@ -607,6 +612,7 @@ 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); @@ -670,21 +676,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 90 "certtool.gaa" { print_license(); exit(0); ;}; return GAA_OK; break; case GAAOPTID_version: OK = 0; -#line 86 "certtool.gaa" +#line 89 "certtool.gaa" { certtool_version(); exit(0); ;}; return GAA_OK; break; case GAAOPTID_help: OK = 0; -#line 84 "certtool.gaa" +#line 87 "certtool.gaa" { gaa_help(); exit(0); ;}; return GAA_OK; @@ -694,7 +700,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 85 "certtool.gaa" { gaaval->debug = GAATMP_debug.arg1 ;}; return GAA_OK; @@ -704,7 +710,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 82 "certtool.gaa" { gaaval->infile = GAATMP_infile.arg1 ;}; return GAA_OK; @@ -714,7 +720,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 79 "certtool.gaa" { gaaval->outfile = GAATMP_outfile.arg1 ;}; return GAA_OK; @@ -724,32 +730,39 @@ 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 76 "certtool.gaa" { gaaval->bits = GAATMP_bits.arg1 ;}; return GAA_OK; break; case GAAOPTID_outder: OK = 0; -#line 70 "certtool.gaa" +#line 73 "certtool.gaa" { gaaval->outcert_format=1 ;}; return GAA_OK; break; case GAAOPTID_inder: OK = 0; -#line 67 "certtool.gaa" +#line 70 "certtool.gaa" { gaaval->incert_format=1 ;}; return GAA_OK; break; case GAAOPTID_export_ciphers: OK = 0; -#line 64 "certtool.gaa" +#line 67 "certtool.gaa" { gaaval->export=1 ;}; return GAA_OK; break; + case GAAOPTID_dsa: + OK = 0; +#line 64 "certtool.gaa" +{ gaaval->dsa=1 ;}; + + return GAA_OK; + break; case GAAOPTID_pkcs8: OK = 0; #line 61 "certtool.gaa" @@ -925,7 +938,7 @@ int gaa(int argc, char **argv, gaainfo *gaaval) if(inited == 0) { -#line 89 "certtool.gaa" +#line 92 "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 +1061,7 @@ 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; int i = 0, len = 0, newline = 0; if(argc == 1) { @@ -1056,7 +1069,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 +1079,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 +1089,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; @@ -1125,7 +1141,7 @@ int gaa_file(char *name, gaainfo *gaaval) if((file = fopen(name, "r")) == NULL) { printf("Couldn't open '%s' configuration file for reading\n", name); - return 0; + return 1; } tmp_str = &first_str; diff --git a/src/certtool-gaa.h b/src/certtool-gaa.h index 15210d0aac..8d353e49dc 100644 --- a/src/certtool-gaa.h +++ b/src/certtool-gaa.h @@ -8,20 +8,22 @@ typedef struct _gaainfo gaainfo; struct _gaainfo { -#line 81 "certtool.gaa" +#line 84 "certtool.gaa" int debug; -#line 78 "certtool.gaa" +#line 81 "certtool.gaa" char *infile; -#line 75 "certtool.gaa" +#line 78 "certtool.gaa" char *outfile; -#line 72 "certtool.gaa" +#line 75 "certtool.gaa" int bits; -#line 69 "certtool.gaa" +#line 72 "certtool.gaa" int outcert_format; -#line 66 "certtool.gaa" +#line 69 "certtool.gaa" int incert_format; -#line 63 "certtool.gaa" +#line 66 "certtool.gaa" int export; +#line 63 "certtool.gaa" + int dsa; #line 60 "certtool.gaa" int pkcs8; #line 47 "certtool.gaa" diff --git a/src/certtool.c b/src/certtool.c index 173c044622..616601ca9d 100644 --- a/src/certtool.c +++ b/src/certtool.c @@ -176,7 +176,16 @@ 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; + } else { + msg = "RSA"; + key_type = GNUTLS_PK_RSA; + } if (info.privkey) return load_private_key(1); @@ -187,8 +196,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); @@ -1082,11 +1092,11 @@ void privkey_info( void) pem.data = buffer; pem.size = size; - pass = read_pass("Enter password: "); if (!info.pkcs8) { ret = gnutls_x509_privkey_import(key, &pem, in_cert_format); } else { + pass = read_pass("Enter password: "); ret = gnutls_x509_privkey_import_pkcs8(key, &pem, in_cert_format, pass, 0); } diff --git a/src/certtool.gaa b/src/certtool.gaa index 007200952a..79a192b0ab 100644 --- a/src/certtool.gaa +++ b/src/certtool.gaa @@ -60,6 +60,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." |