summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2003-12-18 14:19:13 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2003-12-18 14:19:13 +0000
commit1851a5c8ff0a863d244a8ef535f73b918605825a (patch)
tree1b852443d345acae6374220ab0da4277b5df00d9
parent4d4fa5bb8a4e2c2fb1fc9ab68a4d6b887e497aa7 (diff)
downloadgnutls-1851a5c8ff0a863d244a8ef535f73b918605825a.tar.gz
Added support for generating and exporting DSA private keys. Exporting to PKCS #8 is still not supported due to lack of standards.
-rw-r--r--NEWS1
-rw-r--r--doc/TODO4
-rw-r--r--includes/gnutls/x509.h9
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/gnutls_pk.c13
-rw-r--r--lib/gnutls_rsa_export.c4
-rw-r--r--lib/gnutls_rsa_export.h2
-rw-r--r--lib/gnutls_sig.c48
-rw-r--r--lib/gnutls_ui.h2
-rw-r--r--lib/rsa_compat.c3
-rw-r--r--lib/x509/Makefile.am4
-rw-r--r--lib/x509/common.c96
-rw-r--r--lib/x509/crq.c36
-rw-r--r--lib/x509/dsa.c121
-rw-r--r--lib/x509/dsa.h1
-rw-r--r--lib/x509/mpi.c50
-rw-r--r--lib/x509/mpi.h2
-rw-r--r--lib/x509/privkey.c382
-rw-r--r--lib/x509/sign.c35
-rw-r--r--lib/x509/x509.c2
-rw-r--r--lib/x509/x509_write.c10
-rw-r--r--src/certtool-gaa.c104
-rw-r--r--src/certtool-gaa.h16
-rw-r--r--src/certtool.c18
-rw-r--r--src/certtool.gaa3
25 files changed, 774 insertions, 194 deletions
diff --git a/NEWS b/NEWS
index 512b3a4e7f..89908c4e08 100644
--- a/NEWS
+++ b/NEWS
@@ -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
diff --git a/doc/TODO b/doc/TODO
index d2573725c4..eff10d9c50 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -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, &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;
@@ -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."