gnutls-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU gnutls branch, master, updated. gnutls_3_0_2-15-gb40785d


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_3_0_2-15-gb40785d
Date: Tue, 06 Sep 2011 11:23:24 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=b40785d940c460680347a886aabe6adace6b0861

The branch, master has been updated
       via  b40785d940c460680347a886aabe6adace6b0861 (commit)
       via  2a693e1d3d7a7c6e4a14ecea664d0cc86f12216b (commit)
       via  08de2069506b3c1e69e1fbdfe772ae5329c64c53 (commit)
      from  ab782d356200f44736edb687304d5e90438e2185 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit b40785d940c460680347a886aabe6adace6b0861
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Tue Sep 6 12:52:29 2011 +0200

    Modified fix of "Allow CA importing of 0 certificates to succeed".
    gnutls_x509_crt_list_import() is still failing when no certificates
    are found and only gnutls_certificate_set_x509_trust_mem() returns
    zero when no certificates are found.

commit 2a693e1d3d7a7c6e4a14ecea664d0cc86f12216b
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Tue Sep 6 11:59:11 2011 +0200

    Added support to read elliptic curve public keys from PKCS #11 tokens 
(untested).

commit 08de2069506b3c1e69e1fbdfe772ae5329c64c53
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Mon Sep 5 00:46:41 2011 +0200

    Added gnutls_pkcs11_privkey_generate().
    p11tool can be used to generate keys in tokens.

-----------------------------------------------------------------------

Summary of changes:
 NEWS                           |   18 +++
 lib/gnutls_pubkey.c            |  154 ++++++++++++++++++++++++++
 lib/gnutls_x509.c              |    3 +
 lib/includes/gnutls/abstract.h |   13 +++
 lib/includes/gnutls/pkcs11.h   |    5 +
 lib/libgnutls.map              |    3 +
 lib/pkcs11.c                   |  133 +++++++++++++++++------
 lib/pkcs11_int.h               |   42 +++++++
 lib/pkcs11_privkey.c           |  213 ++++++++++++++++++++++++++++++++++--
 lib/pkcs11_write.c             |   55 +++++++++-
 lib/x509/key_decode.c          |    5 +-
 lib/x509/key_encode.c          |   24 +----
 lib/x509/privkey.c             |    2 +-
 lib/x509/x509.c                |    7 +-
 lib/x509/x509_int.h            |    9 ++
 src/certtool-common.c          |   58 ++++++++++
 src/certtool-common.h          |    9 +-
 src/certtool-gaa.c             |    5 +-
 src/certtool.c                 |   69 +-----------
 src/certtool.gaa               |    3 +-
 src/p11common.c                |    1 +
 src/p11tool-gaa.c              |  232 +++++++++++++++++++++++++++++----------
 src/p11tool-gaa.h              |   34 ++++---
 src/p11tool.c                  |    5 +
 src/p11tool.gaa                |   15 +++-
 src/p11tool.h                  |    6 +
 src/pkcs11.c                   |   40 +++++++
 src/prime.c                    |   24 +++--
 28 files changed, 949 insertions(+), 238 deletions(-)

diff --git a/NEWS b/NEWS
index 419bb85..406abaf 100644
--- a/NEWS
+++ b/NEWS
@@ -2,10 +2,28 @@ GnuTLS NEWS -- History of user-visible changes.               
 -*- outline -*-
 Copyright (C) 2000-2011 Free Software Foundation, Inc.
 See the end for copying conditions.
 
+* Version 3.0.3 (unreleased)
+
 ** libgnutls: Allow CA importing of 0 certificates to succeed.
 Reported by Jonathan Nieder <address@hidden> in
 <http://bugs.debian.org/640639>.
 
+** libgnutls: Added support for elliptic curves in
+PKCS #11.
+
+** libgnutls: Added gnutls_pkcs11_privkey_generate()
+to allow generating a key in a token.
+
+** p11tool: Added generate-rsa, generate-dsa and 
+generate-ecc options.
+
+** API and ABI modifications:
+gnutls_pkcs11_privkey_generate: Added
+gnutls_pubkey_import_ecc_raw: Added
+gnutls_pubkey_import_ecc_x962: Added
+gnutls_pubkey_get_pk_ecc_x962: Added
+
+
 * Version 3.0.2 (released 2011-09-01)
 
 ** libgnutls: OpenPGP certificate type is not enabled
diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c
index baea500..52a0720 100644
--- a/lib/gnutls_pubkey.c
+++ b/lib/gnutls_pubkey.c
@@ -34,6 +34,7 @@
 #include <x509/common.h>
 #include <x509_b64.h>
 #include <abstract_int.h>
+#include <gnutls_ecc.h>
 
 #define PK_PEM_HEADER "PUBLIC KEY"
 
@@ -299,6 +300,10 @@ gnutls_pubkey_import_pkcs11 (gnutls_pubkey_t key,
                                           &obj->pubkey[1],
                                           &obj->pubkey[2], &obj->pubkey[3]);
       break;
+    case GNUTLS_PK_ECC:
+      ret = gnutls_pubkey_import_ecc_x962 (key, &obj->pubkey[0],
+                                          &obj->pubkey[1]);
+      break;
     default:
       gnutls_assert ();
       return GNUTLS_E_UNIMPLEMENTED_FEATURE;
@@ -753,6 +758,42 @@ gnutls_pubkey_get_pk_ecc_raw (gnutls_pubkey_t key, 
gnutls_ecc_curve_t *curve,
 }
 
 /**
+ * gnutls_pubkey_get_pk_ecc_x962:
+ * @key: Holds the public key
+ * @parameters: DER encoding of an ANSI X9.62 parameters
+ * @ecpoint: DER encoding of ANSI X9.62 ECPoint
+ *
+ * This function will export the ECC public key's parameters found in
+ * the given certificate.  The new parameters will be allocated using
+ * gnutls_malloc() and will be stored in the appropriate datum.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
+ *
+ * Since: 3.0.0
+ **/
+int gnutls_pubkey_get_pk_ecc_x962 (gnutls_pubkey_t key, gnutls_datum_t* 
parameters,
+                                   gnutls_datum_t * ecpoint)
+{
+  int ret;
+
+  if (key == NULL || key->pk_algorithm != GNUTLS_PK_ECC)
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+  ret = _gnutls_x509_write_ecc_pubkey(&key->params, ecpoint);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+    
+  ret = _gnutls_x509_write_ecc_params(&key->params, parameters);
+  if (ret < 0)
+    {
+      _gnutls_free_datum(ecpoint);
+      return gnutls_assert_val(ret);
+    }
+  
+  return 0;
+}
+
+/**
  * gnutls_pubkey_import:
  * @key: The structure to store the parsed public key. 
  * @data: The DER or PEM encoded certificate. 
@@ -1060,6 +1101,119 @@ gnutls_pubkey_import_rsa_raw (gnutls_pubkey_t key,
 }
 
 /**
+ * gnutls_pubkey_import_ecc_raw:
+ * @key: The structure to store the parsed key
+ * @curve: holds the curve
+ * @x: holds the x
+ * @y: holds the y
+ *
+ * This function will convert the given elliptic curve parameters to a
+ * #gnutls_pubkey_t.  The output will be stored in @key.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ *
+ * Since: 3.0.0
+ **/
+int
+gnutls_pubkey_import_ecc_raw (gnutls_pubkey_t key,
+                              gnutls_ecc_curve_t curve,
+                              const gnutls_datum_t * x,
+                              const gnutls_datum_t * y)
+{
+  int ret;
+
+  if (key == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
+  key->params.flags = curve;
+
+  ret = _gnutls_ecc_curve_fill_params(curve, &key->params);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+
+  if (_gnutls_mpi_scan_nz (&key->params.params[5], x->data, x->size))
+    {
+      gnutls_assert ();
+      ret = GNUTLS_E_MPI_SCAN_FAILED;
+      goto cleanup;
+    }
+  key->params.params_nr++;
+
+  if (_gnutls_mpi_scan_nz (&key->params.params[6], y->data, y->size))
+    {
+      gnutls_assert ();
+      ret = GNUTLS_E_MPI_SCAN_FAILED;
+      goto cleanup;
+    }
+  key->params.params_nr++;
+  key->pk_algorithm = GNUTLS_PK_ECC;
+
+  return 0;
+
+cleanup:
+  gnutls_pk_params_release(&key->params);
+  return ret;
+}
+
+/**
+ * gnutls_pubkey_import_ecc_x962:
+ * @key: The structure to store the parsed key
+ * @parameters: DER encoding of an ANSI X9.62 parameters
+ * @ecpoint: DER encoding of ANSI X9.62 ECPoint
+ *
+ * This function will convert the given elliptic curve parameters to a
+ * #gnutls_pubkey_t.  The output will be stored in @key.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ *
+ * Since: 3.0.0
+ **/
+int
+gnutls_pubkey_import_ecc_x962 (gnutls_pubkey_t key,
+                               const gnutls_datum_t * parameters,
+                               const gnutls_datum_t * ecpoint)
+{
+  int ret;
+
+  if (key == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
+  key->params.params_nr = 0;
+
+  ret = _gnutls_x509_read_ecc_params(parameters->data, parameters->size,
+                                     &key->params);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  ret = _gnutls_ecc_ansi_x963_import(ecpoint->data, ecpoint->size,
+         &key->params.params[5], &key->params.params[6]);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+  key->params.params_nr+=2;
+  key->pk_algorithm = GNUTLS_PK_ECC;
+
+  return 0;
+
+cleanup:
+  gnutls_pk_params_release(&key->params);
+  return ret;
+}
+
+/**
  * gnutls_pubkey_import_dsa_raw:
  * @key: The structure to store the parsed key
  * @p: holds the p
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c
index a2b8838..16c0cf8 100644
--- a/lib/gnutls_x509.c
+++ b/lib/gnutls_x509.c
@@ -1378,6 +1378,9 @@ gnutls_certificate_set_x509_trust_mem 
(gnutls_certificate_credentials_t res,
     ret = parse_pem_ca_mem (res,
                             ca->data, ca->size);
 
+  if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND)
+    return 0;
+
   return ret;
 }
 
diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h
index 429b06f..2d57079 100644
--- a/lib/includes/gnutls/abstract.h
+++ b/lib/includes/gnutls/abstract.h
@@ -64,6 +64,8 @@ int gnutls_pubkey_get_pk_dsa_raw (gnutls_pubkey_t key,
                                   gnutls_datum_t * g, gnutls_datum_t * y);
 int gnutls_pubkey_get_pk_ecc_raw (gnutls_pubkey_t key, gnutls_ecc_curve_t 
*curve,
                               gnutls_datum_t * x, gnutls_datum_t * y);
+int gnutls_pubkey_get_pk_ecc_x962 (gnutls_pubkey_t key, gnutls_datum_t* 
parameters,
+                                   gnutls_datum_t * ecpoint);
 
 int gnutls_pubkey_export (gnutls_pubkey_t key,
                           gnutls_x509_crt_fmt_t format,
@@ -99,6 +101,17 @@ int gnutls_pubkey_import_rsa_raw (gnutls_pubkey_t key,
                                   const gnutls_datum_t * m,
                                   const gnutls_datum_t * e);
 
+int
+gnutls_pubkey_import_ecc_x962 (gnutls_pubkey_t key,
+                               const gnutls_datum_t * parameters,
+                               const gnutls_datum_t * ecpoint);
+
+int
+gnutls_pubkey_import_ecc_raw (gnutls_pubkey_t key,
+                              gnutls_ecc_curve_t curve,
+                              const gnutls_datum_t * x,
+                              const gnutls_datum_t * y);
+
 int gnutls_x509_crt_set_pubkey (gnutls_x509_crt_t crt, gnutls_pubkey_t key);
 
 int gnutls_x509_crq_set_pubkey (gnutls_x509_crq_t crq, gnutls_pubkey_t key);
diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h
index 6dca20f..7db5d9e 100644
--- a/lib/includes/gnutls/pkcs11.h
+++ b/lib/includes/gnutls/pkcs11.h
@@ -338,4 +338,9 @@ int gnutls_pkcs11_privkey_export_url 
(gnutls_pkcs11_privkey_t key,
                                       gnutls_pkcs11_url_type_t detailed,
                                       char **url);
 
+int
+gnutls_pkcs11_privkey_generate (const char* url, 
+  gnutls_pk_algorithm_t pk, unsigned int bits, 
+  const char* label, unsigned int flags);
+
 #endif
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 3330533..97ff01c 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -713,6 +713,9 @@ GNUTLS_3_0_0 {
        gnutls_x509_trust_list_add_named_crt;
        gnutls_alert_get_strname;
        gnutls_pcert_list_import_x509_raw;
+       gnutls_pkcs11_privkey_generate;
+       gnutls_pubkey_import_ecc_raw;
+       gnutls_pubkey_import_ecc_raw2;
 } GNUTLS_2_12;
 
 GNUTLS_PRIVATE {
diff --git a/lib/pkcs11.c b/lib/pkcs11.c
index 91db86c..89bda0c 100644
--- a/lib/pkcs11.c
+++ b/lib/pkcs11.c
@@ -1109,30 +1109,15 @@ pkcs11_obj_import (ck_object_class_t class, 
gnutls_pkcs11_obj_t obj,
   return 0;
 }
 
-static int
-pkcs11_obj_import_pubkey (struct ck_function_list *module,
-                          ck_session_handle_t pks,
-                          ck_object_handle_t obj,
-                          gnutls_pkcs11_obj_t crt,
-                          const gnutls_datum_t * id,
-                          const gnutls_datum_t * label,
-                          struct ck_token_info *tinfo,
-                          struct ck_info *lib_info)
+static int read_pkcs11_pubkey(struct ck_function_list *module,
+                              ck_session_handle_t pks, ck_object_handle_t obj,
+                              ck_key_type_t key_type, gnutls_datum_t * pubkey)
 {
-
   struct ck_attribute a[4];
-  ck_key_type_t key_type;
   opaque tmp1[2048];
   opaque tmp2[2048];
   int ret;
-  ck_bool_t tval;
-
-  a[0].type = CKA_KEY_TYPE;
-  a[0].value = &key_type;
-  a[0].value_len = sizeof (key_type);
 
-  if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
-    {
       switch (key_type)
         {
         case CKK_RSA:
@@ -1147,19 +1132,19 @@ pkcs11_obj_import_pubkey (struct ck_function_list 
*module,
             {
 
               ret =
-                _gnutls_set_datum (&crt->pubkey[0],
+                _gnutls_set_datum (&pubkey[0],
                                    a[0].value, a[0].value_len);
 
               if (ret >= 0)
                 ret =
-                  _gnutls_set_datum (&crt->pubkey
+                  _gnutls_set_datum (&pubkey
                                      [1], a[1].value, a[1].value_len);
 
               if (ret < 0)
                 {
                   gnutls_assert ();
-                  _gnutls_free_datum (&crt->pubkey[1]);
-                  _gnutls_free_datum (&crt->pubkey[0]);
+                  _gnutls_free_datum (&pubkey[1]);
+                  _gnutls_free_datum (&pubkey[0]);
                   return GNUTLS_E_MEMORY_ERROR;
                 }
             }
@@ -1168,7 +1153,6 @@ pkcs11_obj_import_pubkey (struct ck_function_list *module,
               gnutls_assert ();
               return GNUTLS_E_PKCS11_ERROR;
             }
-          crt->pk_algorithm = GNUTLS_PK_RSA;
           break;
         case CKK_DSA:
           a[0].type = CKA_PRIME;
@@ -1181,19 +1165,19 @@ pkcs11_obj_import_pubkey (struct ck_function_list 
*module,
           if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
             {
               ret =
-                _gnutls_set_datum (&crt->pubkey[0],
+                _gnutls_set_datum (&pubkey[0],
                                    a[0].value, a[0].value_len);
 
               if (ret >= 0)
                 ret =
-                  _gnutls_set_datum (&crt->pubkey
+                  _gnutls_set_datum (&pubkey
                                      [1], a[1].value, a[1].value_len);
 
               if (ret < 0)
                 {
                   gnutls_assert ();
-                  _gnutls_free_datum (&crt->pubkey[1]);
-                  _gnutls_free_datum (&crt->pubkey[0]);
+                  _gnutls_free_datum (&pubkey[1]);
+                  _gnutls_free_datum (&pubkey[0]);
                   return GNUTLS_E_MEMORY_ERROR;
                 }
             }
@@ -1213,21 +1197,21 @@ pkcs11_obj_import_pubkey (struct ck_function_list 
*module,
           if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
             {
               ret =
-                _gnutls_set_datum (&crt->pubkey[2],
+                _gnutls_set_datum (&pubkey[2],
                                    a[0].value, a[0].value_len);
 
               if (ret >= 0)
                 ret =
-                  _gnutls_set_datum (&crt->pubkey
+                  _gnutls_set_datum (&pubkey
                                      [3], a[1].value, a[1].value_len);
 
               if (ret < 0)
                 {
                   gnutls_assert ();
-                  _gnutls_free_datum (&crt->pubkey[0]);
-                  _gnutls_free_datum (&crt->pubkey[1]);
-                  _gnutls_free_datum (&crt->pubkey[2]);
-                  _gnutls_free_datum (&crt->pubkey[3]);
+                  _gnutls_free_datum (&pubkey[0]);
+                  _gnutls_free_datum (&pubkey[1]);
+                  _gnutls_free_datum (&pubkey[2]);
+                  _gnutls_free_datum (&pubkey[3]);
                   return GNUTLS_E_MEMORY_ERROR;
                 }
             }
@@ -1236,12 +1220,74 @@ pkcs11_obj_import_pubkey (struct ck_function_list 
*module,
               gnutls_assert ();
               return GNUTLS_E_PKCS11_ERROR;
             }
-          crt->pk_algorithm = GNUTLS_PK_RSA;
+          break;
+        case CKK_ECDSA:
+          a[0].type = CKA_EC_PARAMS;
+          a[0].value = tmp1;
+          a[0].value_len = sizeof (tmp1);
+          a[1].type = CKA_EC_POINT;
+          a[1].value = tmp2;
+          a[1].value_len = sizeof (tmp2);
+
+          if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK)
+            {
+              ret =
+                _gnutls_set_datum (&pubkey[0],
+                                   a[0].value, a[0].value_len);
+
+              if (ret >= 0)
+                ret =
+                  _gnutls_set_datum (&pubkey
+                                     [1], a[1].value, a[1].value_len);
+
+              if (ret < 0)
+                {
+                  gnutls_assert ();
+                  _gnutls_free_datum (&pubkey[1]);
+                  _gnutls_free_datum (&pubkey[0]);
+                  return GNUTLS_E_MEMORY_ERROR;
+                }
+            }
+          else
+            {
+              gnutls_assert ();
+              return GNUTLS_E_PKCS11_ERROR;
+            }
+
           break;
         default:
-          gnutls_assert ();
-          return GNUTLS_E_UNIMPLEMENTED_FEATURE;
+          return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
         }
+
+  return 0;
+}
+
+static int
+pkcs11_obj_import_pubkey (struct ck_function_list *module,
+                          ck_session_handle_t pks,
+                          ck_object_handle_t obj,
+                          gnutls_pkcs11_obj_t crt,
+                          const gnutls_datum_t * id,
+                          const gnutls_datum_t * label,
+                          struct ck_token_info *tinfo,
+                          struct ck_info *lib_info)
+{
+  struct ck_attribute a[4];
+  ck_key_type_t key_type;
+  int ret;
+  ck_bool_t tval;
+
+  a[0].type = CKA_KEY_TYPE;
+  a[0].value = &key_type;
+  a[0].value_len = sizeof (key_type);
+
+  if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
+    {
+      crt->pk_algorithm = mech_to_pk(key_type);
+
+      ret = read_pkcs11_pubkey(module, pks, obj, key_type, crt->pubkey);
+      if (ret < 0)
+        return gnutls_assert_val(ret);
     }
 
   /* read key usage flags */
@@ -2849,6 +2895,21 @@ pkcs11_sign (struct ck_function_list *module,
 }
 
 ck_rv_t
+pkcs11_generate_key_pair (struct ck_function_list *module,
+             ck_session_handle_t sess,
+             struct ck_mechanism *mechanism,
+             struct ck_attribute *pub_templ,
+             unsigned long pub_templ_count,
+             struct ck_attribute *priv_templ,
+             unsigned long priv_templ_count,
+             ck_object_handle_t *pub,
+             ck_object_handle_t *priv)
+{
+       return (module)->C_GenerateKeyPair (sess, mechanism, pub_templ, 
pub_templ_count,
+                                           priv_templ, priv_templ_count, pub, 
priv);
+}
+
+ck_rv_t
 pkcs11_decrypt_init (struct ck_function_list *module,
                      ck_session_handle_t sess,
                      struct ck_mechanism *mechanism,
diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h
index cd62904..2480da7 100644
--- a/lib/pkcs11_int.h
+++ b/lib/pkcs11_int.h
@@ -96,6 +96,48 @@ _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t 
key,
                                     const gnutls_datum_t * ciphertext,
                                     gnutls_datum_t * plaintext);
 
+static inline int pk_to_mech(gnutls_pk_algorithm_t pk)
+{
+  if (pk == GNUTLS_PK_DSA)
+    return CKM_DSA;
+  else if (pk == GNUTLS_PK_ECC)
+    return CKM_ECDSA;
+  else 
+    return CKM_RSA_PKCS;
+}
+
+static inline gnutls_pk_algorithm_t mech_to_pk(ck_key_type_t m)
+{
+  if (m == CKK_RSA)
+    return GNUTLS_PK_RSA;
+  else if (m == CKK_DSA)
+    return GNUTLS_PK_DSA;
+  else  if (m == CKK_ECDSA)
+    return GNUTLS_PK_ECC;
+  else return GNUTLS_PK_UNKNOWN;
+}
+
+static inline int pk_to_genmech(gnutls_pk_algorithm_t pk)
+{
+  if (pk == GNUTLS_PK_DSA)
+    return CKM_DSA_KEY_PAIR_GEN;
+  else if (pk == GNUTLS_PK_ECC)
+    return CKM_ECDSA_KEY_PAIR_GEN;
+  else 
+    return CKM_RSA_PKCS_KEY_PAIR_GEN;
+}
+
+ck_rv_t
+pkcs11_generate_key_pair (struct ck_function_list *module,
+             ck_session_handle_t sess,
+             struct ck_mechanism *mechanism,
+             struct ck_attribute *pub_templ,
+             unsigned long pub_templ_count,
+             struct ck_attribute *priv_templ,
+             unsigned long priv_templ_count,
+             ck_object_handle_t *pub,
+             ck_object_handle_t *priv);
+
 ck_rv_t
 pkcs11_get_slot_list (struct ck_function_list * module,
                       unsigned char token_present,
diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c
index c1ba8fb..ffc5ac6 100644
--- a/lib/pkcs11_privkey.c
+++ b/lib/pkcs11_privkey.c
@@ -169,8 +169,7 @@ _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t 
key,
 
   FIND_OBJECT (module, pks, obj, key);
 
-  mech.mechanism =
-    key->pk_algorithm == GNUTLS_PK_DSA ? CKM_DSA : CKM_RSA_PKCS;
+  mech.mechanism = pk_to_mech(key->pk_algorithm);
   mech.parameter = NULL;
   mech.parameter_len = 0;
 
@@ -272,15 +271,9 @@ gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t 
pkey,
 
   if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
     {
-      switch (key_type)
+      pkey->pk_algorithm = mech_to_pk(key_type);
+      if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN)
         {
-        case CKK_RSA:
-          pkey->pk_algorithm = GNUTLS_PK_RSA;
-          break;
-        case CKK_DSA:
-          pkey->pk_algorithm = GNUTLS_PK_DSA;
-          break;
-        default:
           _gnutls_debug_log("Cannot determine PKCS #11 key algorithm\n");
           ret = GNUTLS_E_UNKNOWN_ALGORITHM;
           goto cleanup;
@@ -324,8 +317,10 @@ _gnutls_pkcs11_privkey_decrypt_data 
(gnutls_pkcs11_privkey_t key,
 
   FIND_OBJECT (module, pks, obj, key);
 
-  mech.mechanism =
-    key->pk_algorithm == GNUTLS_PK_DSA ? CKM_DSA : CKM_RSA_PKCS;
+  if (key->pk_algorithm != GNUTLS_PK_RSA)
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+  mech.mechanism = CKM_RSA_PKCS;
   mech.parameter = NULL;
   mech.parameter_len = 0;
 
@@ -399,3 +394,197 @@ gnutls_pkcs11_privkey_export_url (gnutls_pkcs11_privkey_t 
key,
 
   return 0;
 }
+
+
+/**
+ * gnutls_pkcs11_privkey_generate:
+ * @url: a token URL
+ * @pk: the public key algorithm
+ * @bits: the security bits
+ * @label: a label
+ * @flags: should be zero
+ *
+ * This function will generate a private key in the specified
+ * by the @url token. The pivate key will be generate within
+ * the token and will not be exportable.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ **/
+int
+gnutls_pkcs11_privkey_generate (const char* url, 
+  gnutls_pk_algorithm_t pk, unsigned int bits, 
+  const char* label, unsigned int flags)
+{
+  int ret;
+  const ck_bool_t tval = 1;
+  const ck_bool_t fval = 0;
+  struct ck_function_list *module;
+  ck_session_handle_t pks = 0;
+  struct p11_kit_uri *info = NULL;
+  ck_rv_t rv;
+  size_t id_size;
+  opaque id[20];
+  struct ck_attribute a[10], p[10];
+  ck_object_handle_t pub, priv;
+  unsigned long _bits = bits;
+  int a_val, p_val;
+  struct ck_mechanism mech;
+
+  ret = pkcs11_url_to_info (url, &info);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      return ret;
+    }
+
+  ret =
+    pkcs11_open_session (&module, &pks, info,
+                         SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
+  p11_kit_uri_free (info);
+
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  /* a holds the public key template
+   * and p the private key */
+  a_val = p_val = 0;
+  mech.parameter = NULL;
+  mech.parameter_len = 0;
+  mech.mechanism = pk_to_genmech(pk);
+
+  switch(pk)
+    {
+      case GNUTLS_PK_RSA:
+        p[p_val].type = CKA_DECRYPT;
+        p[p_val].value = (void*)&tval;
+        p[p_val].value_len = sizeof (tval);
+        p_val++;
+
+        p[p_val].type = CKA_SIGN;
+        p[p_val].value = (void*)&tval;
+        p[p_val].value_len = sizeof (tval);
+        p_val++;
+
+        a[a_val].type = CKA_ENCRYPT;
+        a[a_val].value = (void*)&tval;
+        a[a_val].value_len = sizeof (tval);
+        a_val++;
+
+        a[a_val].type = CKA_VERIFY;
+        a[a_val].value = (void*)&tval;
+        a[a_val].value_len = sizeof (tval);
+        a_val++;
+
+        a[a_val].type = CKA_MODULUS_BITS;
+        a[a_val].value = &_bits;
+        a[a_val].value_len = sizeof (_bits);
+        a_val++;
+        break;
+      case GNUTLS_PK_DSA:
+        p[p_val].type = CKA_SIGN;
+        p[p_val].value = (void*)&tval;
+        p[p_val].value_len = sizeof (tval);
+        p_val++;
+
+        a[a_val].type = CKA_VERIFY;
+        a[a_val].value = (void*)&tval;
+        a[a_val].value_len = sizeof (tval);
+        a_val++;
+
+        a[a_val].type = CKA_MODULUS_BITS;
+        a[a_val].value = &_bits;
+        a[a_val].value_len = sizeof (_bits);
+        a_val++;
+        break;
+      case GNUTLS_PK_ECC:
+        p[p_val].type = CKA_SIGN;
+        p[p_val].value = (void*)&tval;
+        p[p_val].value_len = sizeof (tval);
+        p_val++;
+
+        a[a_val].type = CKA_VERIFY;
+        a[a_val].value = (void*)&tval;
+        a[a_val].value_len = sizeof (tval);
+        a_val++;
+
+        a[a_val].type = CKA_MODULUS_BITS;
+        a[a_val].value = &_bits;
+        a[a_val].value_len = sizeof (_bits);
+        a_val++;
+        break;
+      default:
+        ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+        goto cleanup;
+    }
+
+  /* a private key is set always as private unless
+   * requested otherwise
+   */
+  if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE)
+    {
+      p[p_val].type = CKA_PRIVATE;
+      p[p_val].value = (void*)&fval;
+      p[p_val].value_len = sizeof(fval);
+      p_val++;
+    }
+  else
+    {
+      p[p_val].type = CKA_PRIVATE;
+      p[p_val].value = (void*)&tval;
+      p[p_val].value_len = sizeof (tval);
+      p_val++;
+    }
+
+  p[p_val].type = CKA_TOKEN;
+  p[p_val].value = (void *)&tval;
+  p[p_val].value_len = sizeof (tval);
+  p_val++;
+
+  if (label)
+    {
+      p[p_val].type = CKA_LABEL;
+      p[p_val].value = (void*)label;
+      p[p_val].value_len = strlen (label);
+      p_val++;
+
+      a[a_val].type = CKA_LABEL;
+      a[a_val].value = (void*)label;
+      a[a_val].value_len = strlen (label);
+      a_val++;
+    }
+
+  if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE)
+    {
+      p[p_val].type = CKA_SENSITIVE;
+      p[p_val].value = (void*)&tval;
+      p[p_val].value_len = sizeof (tval);
+      p_val++;
+    }
+  else
+    {
+      p[p_val].type = CKA_SENSITIVE;
+      p[p_val].value = (void*)&fval;
+      p[p_val].value_len = sizeof (fval);
+      p_val++;
+    }
+
+  rv = pkcs11_generate_key_pair( module, pks, &mech, a, a_val, p, p_val, &pub, 
&priv);
+  if (rv != CKR_OK)
+    {
+      gnutls_assert ();
+      _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
+      ret = pkcs11_rv_to_err (rv);
+      goto cleanup;
+    }
+    
+
+cleanup:
+  if (pks != 0)
+    pkcs11_close_session (module, pks);
+
+  return ret;
+}
diff --git a/lib/pkcs11_write.c b/lib/pkcs11_write.c
index e5226a4..5b2fd7b 100644
--- a/lib/pkcs11_write.c
+++ b/lib/pkcs11_write.c
@@ -243,6 +243,17 @@ gnutls_pkcs11_copy_x509_privkey (const char *token_url,
   gnutls_datum_t p, q, g, y, x;
   gnutls_datum_t m, e, d, u, exp1, exp2;
 
+  memset(&p, 0, sizeof(p));
+  memset(&q, 0, sizeof(q));
+  memset(&g, 0, sizeof(g));
+  memset(&y, 0, sizeof(y));
+  memset(&x, 0, sizeof(x));
+  memset(&m, 0, sizeof(m));
+  memset(&e, 0, sizeof(e));
+  memset(&d, 0, sizeof(d));
+  memset(&u, 0, sizeof(u));
+  memset(&exp1, 0, sizeof(exp1));
+  memset(&exp2, 0, sizeof(exp2));
 
   ret = pkcs11_url_to_info (token_url, &info);
   if (ret < 0)
@@ -427,6 +438,36 @@ gnutls_pkcs11_copy_x509_privkey (const char *token_url,
 
         break;
       }
+    case GNUTLS_PK_ECC:
+      {
+        ret = _gnutls_x509_write_ecc_params(&key->params, &p);
+        if (ret < 0)
+          {
+            gnutls_assert ();
+            goto cleanup;
+          }
+
+        ret = _gnutls_mpi_dprint_lz(&key->params.params[7], &x);
+        if (ret < 0)
+          {
+            gnutls_assert ();
+            goto cleanup;
+          }
+
+        type = CKK_ECDSA;
+
+        a[a_val].type = CKA_EC_PARAMS;
+        a[a_val].value = p.data;
+        a[a_val].value_len = p.size;
+        a_val++;
+
+        a[a_val].type = CKA_VALUE;
+        a[a_val].value = x.data;
+        a[a_val].value_len = x.size;
+        a_val++;
+
+        break;
+      }
     default:
       gnutls_assert ();
       ret = GNUTLS_E_INVALID_REQUEST;
@@ -442,9 +483,9 @@ gnutls_pkcs11_copy_x509_privkey (const char *token_url,
       goto cleanup;
     }
 
-  /* generated! 
-   */
+  ret = 0;
 
+cleanup:
   switch (pk)
     {
     case GNUTLS_PK_RSA:
@@ -468,15 +509,18 @@ gnutls_pkcs11_copy_x509_privkey (const char *token_url,
         gnutls_free (x.data);
         break;
       }
+    case GNUTLS_PK_ECC:
+      {
+        gnutls_free (p.data);
+        gnutls_free (x.data);
+        break;
+      }
     default:
       gnutls_assert ();
       ret = GNUTLS_E_INVALID_REQUEST;
       goto cleanup;
     }
 
-  ret = 0;
-
-cleanup:
   if (pks != 0)
     pkcs11_close_session (module, pks);
 
@@ -786,3 +830,4 @@ finish:
   return ret;
 
 }
+
diff --git a/lib/x509/key_decode.c b/lib/x509/key_decode.c
index 0690a49..a13a725 100644
--- a/lib/x509/key_decode.c
+++ b/lib/x509/key_decode.c
@@ -40,9 +40,6 @@ static int _gnutls_x509_read_ecc_pubkey (opaque * der, int 
dersize,
 static int
 _gnutls_x509_read_dsa_params (opaque * der, int dersize, gnutls_pk_params_st * 
params);
 
-static int
-_gnutls_x509_read_ecc_params (opaque * der, int dersize, gnutls_pk_params_st * 
params);
-
 /*
  * some x509 certificate parsing functions that relate to MPI parameter
  * extraction. This reads the BIT STRING subjectPublicKey.
@@ -180,7 +177,7 @@ _gnutls_x509_read_dsa_params (opaque * der, int dersize, 
gnutls_pk_params_st * p
 /* reads the curve from the certificate.
  * params[0-4]. It does NOT set params_nr.
  */
-static int
+int
 _gnutls_x509_read_ecc_params (opaque * der, int dersize, gnutls_pk_params_st * 
params)
 {
   int ret;
diff --git a/lib/x509/key_encode.c b/lib/x509/key_encode.c
index 7c442f3..42df697 100644
--- a/lib/x509/key_encode.c
+++ b/lib/x509/key_encode.c
@@ -39,12 +39,6 @@ static int _gnutls_x509_write_dsa_params 
(gnutls_pk_params_st * params,
 static int _gnutls_x509_write_dsa_pubkey (gnutls_pk_params_st * params,
                                        gnutls_datum_t * der);
 
-static int _gnutls_x509_write_ecc_params (gnutls_pk_params_st * params,
-                                   gnutls_datum_t * der);
-static int _gnutls_x509_write_ecc_pubkey (gnutls_pk_params_st * params,
-                                       gnutls_datum_t * der);
-
-
 /*
  * some x509 certificate functions that relate to MPI parameter
  * setting. This writes the BIT STRING subjectPublicKey.
@@ -112,33 +106,23 @@ cleanup:
  *
  * Allocates the space used to store the DER data.
  */
-static int
+int
 _gnutls_x509_write_ecc_pubkey (gnutls_pk_params_st * params,
                                gnutls_datum_t * der)
 {
   int result;
-  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
 
   der->data = NULL;
   der->size = 0;
 
   if (params->params_nr < ECC_PUBLIC_PARAMS)
-    {
-      gnutls_assert ();
-      result = GNUTLS_E_INVALID_REQUEST;
-      goto cleanup;
-    }
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
 
   result = _gnutls_ecc_ansi_x963_export(params->flags, params->params[5], 
params->params[6], /*&out*/der);
   if (result < 0)
     return gnutls_assert_val(result);
 
-  result = 0;
-
-cleanup:
-  asn1_delete_structure (&spk);
-
-  return result;
+  return 0;
 }
 
 int
@@ -255,7 +239,7 @@ cleanup:
  *
  * Allocates the space used to store the DER data.
  */
-static int
+int
 _gnutls_x509_write_ecc_params (gnutls_pk_params_st* params,
                                gnutls_datum_t * der)
 {
diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c
index 31762da..9327bdf 100644
--- a/lib/x509/privkey.c
+++ b/lib/x509/privkey.c
@@ -830,7 +830,7 @@ cleanup:
  * @y: holds the y
  * @k: holds the k
  *
- * This function will convert the given DSA raw parameters to the
+ * This function will convert the given elliptic curve parameters to the
  * native #gnutls_x509_privkey_t format.  The output will be stored
  * in @key.
  *
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index 9d85384..3431072 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -3217,12 +3217,7 @@ gnutls_x509_crt_list_import (gnutls_x509_crt_t * certs,
                   PEM_CERT_SEP2, sizeof (PEM_CERT_SEP2) - 1);
 
   if (ptr == NULL)
-    {
-      gnutls_assert ();
-      *cert_max = 0;
-      /* no certificate found, likely empty file or garbage input */
-      return 0;
-    }
+    return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND);
 
   count = 0;
 
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index c5d466a..6976b07 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -189,6 +189,10 @@ ASN1_TYPE _gnutls_privkey_decode_pkcs1_rsa_key (const 
gnutls_datum_t *
 ASN1_TYPE _gnutls_privkey_decode_ecc_key (const gnutls_datum_t *
                                                 raw_key,
                                                 gnutls_x509_privkey_t pkey);
+
+int
+_gnutls_x509_read_ecc_params (opaque * der, int dersize, gnutls_pk_params_st * 
params);
+
 int _gnutls_asn1_encode_privkey (gnutls_pk_algorithm_t pk, ASN1_TYPE * c2, 
gnutls_pk_params_st * params);
 
 /* extensions.c */
@@ -275,6 +279,11 @@ int _gnutls_x509_read_pubkey_params 
(gnutls_pk_algorithm_t, opaque * der, int de
 int _gnutls_x509_read_pubkey (gnutls_pk_algorithm_t, opaque * der, int dersize,
                                   gnutls_pk_params_st * params);
 
+int _gnutls_x509_write_ecc_params (gnutls_pk_params_st * params,
+                                   gnutls_datum_t * der);
+int _gnutls_x509_write_ecc_pubkey (gnutls_pk_params_st * params,
+                                       gnutls_datum_t * der);
+
 int
 _gnutls_x509_write_pubkey_params (gnutls_pk_algorithm_t algo,
                                    gnutls_pk_params_st* params,
diff --git a/src/certtool-common.c b/src/certtool-common.c
index 1482d34..5ad9934 100644
--- a/src/certtool-common.c
+++ b/src/certtool-common.c
@@ -607,3 +607,61 @@ int ret;
   return pubkey;
 }
 
+int
+get_bits (gnutls_pk_algorithm_t key_type, int info_bits, const char* 
info_sec_param)
+{
+  int bits;
+
+  if (info_bits != 0)
+    {
+      static int warned = 0;
+
+      if (warned == 0)
+        {
+          warned = 1;
+          fprintf (stderr,
+                   "** Note: Please use the --sec-param instead of --bits\n");
+        }
+      bits = info_bits;
+    }
+  else
+    {
+      if (info_sec_param)
+        {
+          bits =
+            gnutls_sec_param_to_pk_bits (key_type,
+                                         str_to_sec_param (info_sec_param));
+        }
+      else
+        bits =
+          gnutls_sec_param_to_pk_bits (key_type, GNUTLS_SEC_PARAM_NORMAL);
+    }
+
+  return bits;
+}
+
+gnutls_sec_param_t str_to_sec_param (const char *str)
+{
+  if (strcasecmp (str, "low") == 0)
+    {
+      return GNUTLS_SEC_PARAM_LOW;
+    }
+  else if (strcasecmp (str, "normal") == 0)
+    {
+      return GNUTLS_SEC_PARAM_NORMAL;
+    }
+  else if (strcasecmp (str, "high") == 0)
+    {
+      return GNUTLS_SEC_PARAM_HIGH;
+    }
+  else if (strcasecmp (str, "ultra") == 0)
+    {
+      return GNUTLS_SEC_PARAM_ULTRA;
+    }
+  else
+    {
+      fprintf (stderr, "Unknown security parameter string: %s\n", str);
+      exit (1);
+    }
+
+}
diff --git a/src/certtool-common.h b/src/certtool-common.h
index e8ed9c7..a67ee69 100644
--- a/src/certtool-common.h
+++ b/src/certtool-common.h
@@ -54,6 +54,8 @@ typedef struct common_info
   const char *request;
   const char *ca;
   const char *ca_privkey;
+  int bits;
+  const char* sec_param;
 } common_info_st;
 
 gnutls_pubkey_t load_public_key_or_import(int mand, gnutls_privkey_t privkey, 
common_info_st * info);
@@ -67,12 +69,11 @@ gnutls_datum_t *load_secret_key (int mand, common_info_st * 
info);
 gnutls_pubkey_t load_pubkey (int mand, common_info_st * info);
 gnutls_x509_crt_t *load_cert_list (int mand, size_t * size,
                                    common_info_st * info);
-
-/* returns the bits specified in cmd */
-int get_bits (gnutls_pk_algorithm_t);
+int get_bits (gnutls_pk_algorithm_t key_type, int info_bits, const char* 
info_sec_param);
+gnutls_sec_param_t str_to_sec_param (const char *str);
 
 /* prime.c */
-int generate_prime (int how);
+int generate_prime (int how, common_info_st * info);
 
 FILE *safe_open_rw (const char *file, int privkey_op);
 
diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c
index 67ba16b..01aebc4 100644
--- a/src/certtool-gaa.c
+++ b/src/certtool-gaa.c
@@ -1289,7 +1289,8 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
        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; gaaval->v1_cert = 0;
        gaaval->export = 0; gaaval->template = NULL; gaaval->hash=NULL; 
gaaval->fix_key = 0; gaaval->quick_random=1; 
-       gaaval->privkey_op = 0; gaaval->pkcs_cipher = "aes-128"; 
gaaval->crq_extensions=1; gaaval->ecc=0; ;};
+       gaaval->privkey_op = 0; gaaval->pkcs_cipher = "aes-128"; 
gaaval->crq_extensions=1; gaaval->ecc=0; 
+       gaaval->sec_param = NULL; ;};
 
     }
     inited = 1;
@@ -1437,7 +1438,7 @@ static int gaa_internal_get_next_str(FILE *file, 
gaa_str_node *tmp_str, int argc
 
         len++;
         a = fgetc( file);
-        if(a==EOF) return 0; //a = ' ';
+        if(a==EOF) return 0;
     }
 
     len += 1;
diff --git a/src/certtool.c b/src/certtool.c
index acdc8d7..5362871 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -188,67 +188,6 @@ print_rsa_pkey (gnutls_datum_t * m, gnutls_datum_t * e, 
gnutls_datum_t * d,
     }
 }
 
-static gnutls_sec_param_t
-str_to_sec_param (const char *str)
-{
-  if (strcasecmp (str, "low") == 0)
-    {
-      return GNUTLS_SEC_PARAM_LOW;
-    }
-  else if (strcasecmp (str, "normal") == 0)
-    {
-      return GNUTLS_SEC_PARAM_NORMAL;
-    }
-  else if (strcasecmp (str, "high") == 0)
-    {
-      return GNUTLS_SEC_PARAM_HIGH;
-    }
-  else if (strcasecmp (str, "ultra") == 0)
-    {
-      return GNUTLS_SEC_PARAM_ULTRA;
-    }
-  else
-    {
-      fprintf (stderr, "Unknown security parameter string: %s\n", str);
-      exit (1);
-    }
-
-}
-
-int
-get_bits (gnutls_pk_algorithm_t key_type)
-{
-  int bits;
-
-  if (info.bits != 0)
-    {
-      static int warned = 0;
-
-      if (warned == 0)
-        {
-          warned = 1;
-          fprintf (stderr,
-                   "** Note: Please use the --sec-param instead of --bits\n");
-        }
-      bits = info.bits;
-    }
-  else
-    {
-      if (info.sec_param)
-        {
-          bits =
-            gnutls_sec_param_to_pk_bits (key_type,
-                                         str_to_sec_param (info.sec_param));
-        }
-      else
-        bits =
-          gnutls_sec_param_to_pk_bits (key_type, GNUTLS_SEC_PARAM_NORMAL);
-    }
-
-  return bits;
-}
-
-
 static gnutls_x509_privkey_t
 generate_private_key_int (void)
 {
@@ -266,7 +205,7 @@ generate_private_key_int (void)
   if (ret < 0)
     error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
 
-  bits = get_bits (key_type);
+  bits = get_bits (key_type, info.bits, info.sec_param);
 
   fprintf (stderr, "Generating a %d bit %s private key...\n",
            bits, gnutls_pk_algorithm_get_name (key_type));
@@ -1109,6 +1048,8 @@ gaa_parser (int argc, char **argv)
   cinfo.request = info.request;
   cinfo.ca = info.ca;
   cinfo.ca_privkey = info.ca_privkey;
+  cinfo.bits = info.bits;
+  cinfo.sec_param = info.sec_param;
 
   switch (info.action)
     {
@@ -1152,10 +1093,10 @@ gaa_parser (int argc, char **argv)
       pkcs12_info ();
       break;
     case ACTION_GENERATE_DH:
-      generate_prime (1);
+      generate_prime (1, &cinfo);
       break;
     case ACTION_GET_DH:
-      generate_prime (0);
+      generate_prime (0, &cinfo);
       break;
     case ACTION_CRL_INFO:
       crl_info ();
diff --git a/src/certtool.gaa b/src/certtool.gaa
index 078a5e8..4834d60 100644
--- a/src/certtool.gaa
+++ b/src/certtool.gaa
@@ -153,4 +153,5 @@ init { $bits = 0; $pkcs8 = 0; $privkey = NULL; $ca=NULL; 
$ca_privkey = NULL;
        $debug=1; $request = NULL; $infile = NULL; $outfile = NULL; $cert = 
NULL; 
        $incert_format = 0; $outcert_format = 0; $action=-1; $pass = NULL; 
$v1_cert = 0;
        $export = 0; $template = NULL; $hash=NULL; $fix_key = 0; 
$quick_random=1; 
-       $privkey_op = 0; $pkcs_cipher = "aes-128"; $crq_extensions=1; $ecc=0; }
+       $privkey_op = 0; $pkcs_cipher = "aes-128"; $crq_extensions=1; $ecc=0; 
+       $sec_param = NULL; }
diff --git a/src/p11common.c b/src/p11common.c
index 4c7df1e..0a8cf85 100644
--- a/src/p11common.c
+++ b/src/p11common.c
@@ -129,3 +129,4 @@ pkcs11_common (void)
   gnutls_pkcs11_set_token_function (token_callback, NULL);
 
 }
+
diff --git a/src/p11tool-gaa.c b/src/p11tool-gaa.c
index 1816240..8938e33 100644
--- a/src/p11tool-gaa.c
+++ b/src/p11tool-gaa.c
@@ -145,6 +145,9 @@ void gaa_help(void)
        __gaa_helpsingle(0, "initialize", "URL ", "Initializes a PKCS11 
token.");
        __gaa_helpsingle(0, "write", "URL ", "Writes loaded certificates, 
private or secret keys to a PKCS11 token.");
        __gaa_helpsingle(0, "delete", "URL ", "Deletes objects matching the 
URL.");
+       __gaa_helpsingle(0, "generate-rsa", "URL ", "Generates an RSA private 
key on the specified token.");
+       __gaa_helpsingle(0, "generate-dsa", "URL ", "Generates a DSA private 
key on the specified token.");
+       __gaa_helpsingle(0, "generate-ecc", "URL ", "Generates an ECDSA private 
key on the specified token.");
        __gaa_helpsingle(0, "label", "label ", "Sets a label for the write 
operation.");
        __gaa_helpsingle(0, "trusted", "", "Marks the certificate to be written 
as trusted.");
        __gaa_helpsingle(0, "private", "", "Marks the object to be written as 
private (requires PIN).");
@@ -157,6 +160,8 @@ void gaa_help(void)
        __gaa_helpsingle(0, "load-pubkey", "FILE ", "Private key file to use.");
        __gaa_helpsingle(0, "load-certificate", "FILE ", "Certificate file to 
use.");
        __gaa_helpsingle('8', "pkcs8", "", "Use PKCS #8 format for private 
keys.");
+       __gaa_helpsingle(0, "bits", "BITS ", "specify the number of bits for 
key generation.");
+       __gaa_helpsingle(0, "sec-param", "PARAM ", "specify the security level 
[low|normal|high|ultra].");
        __gaa_helpsingle(0, "inder", "", "Use DER format for input certificates 
and private keys.");
        __gaa_helpsingle(0, "inraw", "", "Use RAW/DER format for input 
certificates and private keys.");
        __gaa_helpsingle(0, "provider", "Library ", "Specify the pkcs11 
provider library");
@@ -177,34 +182,40 @@ typedef struct _gaainfo gaainfo;
 
 struct _gaainfo
 {
-#line 84 "p11tool.gaa"
+#line 94 "p11tool.gaa"
        int debug;
-#line 79 "p11tool.gaa"
+#line 89 "p11tool.gaa"
        char *outfile;
-#line 76 "p11tool.gaa"
+#line 86 "p11tool.gaa"
        int action;
-#line 75 "p11tool.gaa"
+#line 85 "p11tool.gaa"
        char* pkcs11_provider;
-#line 71 "p11tool.gaa"
+#line 81 "p11tool.gaa"
        int incert_format;
-#line 68 "p11tool.gaa"
+#line 78 "p11tool.gaa"
+       char* sec_param;
+#line 75 "p11tool.gaa"
+       int bits;
+#line 72 "p11tool.gaa"
        int pkcs8;
-#line 65 "p11tool.gaa"
+#line 69 "p11tool.gaa"
        char *cert;
-#line 62 "p11tool.gaa"
+#line 66 "p11tool.gaa"
        char *pubkey;
-#line 59 "p11tool.gaa"
+#line 63 "p11tool.gaa"
        char *privkey;
-#line 56 "p11tool.gaa"
+#line 60 "p11tool.gaa"
        char* secret_key;
-#line 52 "p11tool.gaa"
+#line 56 "p11tool.gaa"
        int pkcs11_detailed_url;
-#line 49 "p11tool.gaa"
+#line 53 "p11tool.gaa"
        int pkcs11_login;
-#line 45 "p11tool.gaa"
+#line 49 "p11tool.gaa"
        int pkcs11_private;
-#line 42 "p11tool.gaa"
+#line 46 "p11tool.gaa"
        int pkcs11_trusted;
+#line 40 "p11tool.gaa"
+       int key_type;
 #line 35 "p11tool.gaa"
        char* pkcs11_label;
 #line 24 "p11tool.gaa"
@@ -265,36 +276,41 @@ static int gaa_error = 0;
 #define GAA_MULTIPLE_OPTION     3
 
 #define GAA_REST                0
-#define GAA_NB_OPTION           29
+#define GAA_NB_OPTION           34
 #define GAAOPTID_help  1
 #define GAAOPTID_debug 2
 #define GAAOPTID_outfile       3
 #define GAAOPTID_provider      4
 #define GAAOPTID_inraw 5
 #define GAAOPTID_inder 6
-#define GAAOPTID_pkcs8 7
-#define GAAOPTID_load_certificate      8
-#define GAAOPTID_load_pubkey   9
-#define GAAOPTID_load_privkey  10
-#define GAAOPTID_secret_key    11
-#define GAAOPTID_no_detailed_url       12
-#define GAAOPTID_detailed_url  13
-#define GAAOPTID_login 14
-#define GAAOPTID_no_private    15
-#define GAAOPTID_private       16
-#define GAAOPTID_trusted       17
-#define GAAOPTID_label 18
-#define GAAOPTID_delete        19
-#define GAAOPTID_write 20
-#define GAAOPTID_initialize    21
-#define GAAOPTID_list_trusted  22
-#define GAAOPTID_list_privkeys 23
-#define GAAOPTID_list_certs    24
-#define GAAOPTID_list_all_certs        25
-#define GAAOPTID_list_all      26
-#define GAAOPTID_list_mechanisms       27
-#define GAAOPTID_list_tokens   28
-#define GAAOPTID_export        29
+#define GAAOPTID_sec_param     7
+#define GAAOPTID_bits  8
+#define GAAOPTID_pkcs8 9
+#define GAAOPTID_load_certificate      10
+#define GAAOPTID_load_pubkey   11
+#define GAAOPTID_load_privkey  12
+#define GAAOPTID_secret_key    13
+#define GAAOPTID_no_detailed_url       14
+#define GAAOPTID_detailed_url  15
+#define GAAOPTID_login 16
+#define GAAOPTID_no_private    17
+#define GAAOPTID_private       18
+#define GAAOPTID_trusted       19
+#define GAAOPTID_label 20
+#define GAAOPTID_generate_ecc  21
+#define GAAOPTID_generate_dsa  22
+#define GAAOPTID_generate_rsa  23
+#define GAAOPTID_delete        24
+#define GAAOPTID_write 25
+#define GAAOPTID_initialize    26
+#define GAAOPTID_list_trusted  27
+#define GAAOPTID_list_privkeys 28
+#define GAAOPTID_list_certs    29
+#define GAAOPTID_list_all_certs        30
+#define GAAOPTID_list_all      31
+#define GAAOPTID_list_mechanisms       32
+#define GAAOPTID_list_tokens   33
+#define GAAOPTID_export        34
 
 #line 168 "gaa.skel"
 
@@ -499,6 +515,18 @@ struct GAAOPTION_provider
        int size1;
 };
 
+struct GAAOPTION_sec_param 
+{
+       char* arg1;
+       int size1;
+};
+
+struct GAAOPTION_bits 
+{
+       int arg1;
+       int size1;
+};
+
 struct GAAOPTION_load_certificate 
 {
        char* arg1;
@@ -529,6 +557,24 @@ struct GAAOPTION_label
        int size1;
 };
 
+struct GAAOPTION_generate_ecc 
+{
+       char* arg1;
+       int size1;
+};
+
+struct GAAOPTION_generate_dsa 
+{
+       char* arg1;
+       int size1;
+};
+
+struct GAAOPTION_generate_rsa 
+{
+       char* arg1;
+       int size1;
+};
+
 struct GAAOPTION_delete 
 {
        char* arg1;
@@ -591,11 +637,16 @@ static int gaa_get_option_num(char *str, int status)
                        GAA_CHECK1STR("d", GAAOPTID_debug);
                        GAA_CHECK1STR("", GAAOPTID_outfile);
                        GAA_CHECK1STR("", GAAOPTID_provider);
+                       GAA_CHECK1STR("", GAAOPTID_sec_param);
+                       GAA_CHECK1STR("", GAAOPTID_bits);
                        GAA_CHECK1STR("", GAAOPTID_load_certificate);
                        GAA_CHECK1STR("", GAAOPTID_load_pubkey);
                        GAA_CHECK1STR("", GAAOPTID_load_privkey);
                        GAA_CHECK1STR("", GAAOPTID_secret_key);
                        GAA_CHECK1STR("", GAAOPTID_label);
+                       GAA_CHECK1STR("", GAAOPTID_generate_ecc);
+                       GAA_CHECK1STR("", GAAOPTID_generate_dsa);
+                       GAA_CHECK1STR("", GAAOPTID_generate_rsa);
                        GAA_CHECK1STR("", GAAOPTID_delete);
                        GAA_CHECK1STR("", GAAOPTID_write);
                        GAA_CHECK1STR("", GAAOPTID_initialize);
@@ -629,6 +680,8 @@ static int gaa_get_option_num(char *str, int status)
                        GAA_CHECKSTR("provider", GAAOPTID_provider);
                        GAA_CHECKSTR("inraw", GAAOPTID_inraw);
                        GAA_CHECKSTR("inder", GAAOPTID_inder);
+                       GAA_CHECKSTR("sec-param", GAAOPTID_sec_param);
+                       GAA_CHECKSTR("bits", GAAOPTID_bits);
                        GAA_CHECKSTR("pkcs8", GAAOPTID_pkcs8);
                        GAA_CHECKSTR("load-certificate", 
GAAOPTID_load_certificate);
                        GAA_CHECKSTR("load-pubkey", GAAOPTID_load_pubkey);
@@ -641,6 +694,9 @@ static int gaa_get_option_num(char *str, int status)
                        GAA_CHECKSTR("private", GAAOPTID_private);
                        GAA_CHECKSTR("trusted", GAAOPTID_trusted);
                        GAA_CHECKSTR("label", GAAOPTID_label);
+                       GAA_CHECKSTR("generate-ecc", GAAOPTID_generate_ecc);
+                       GAA_CHECKSTR("generate-dsa", GAAOPTID_generate_dsa);
+                       GAA_CHECKSTR("generate-rsa", GAAOPTID_generate_rsa);
                        GAA_CHECKSTR("delete", GAAOPTID_delete);
                        GAA_CHECKSTR("write", GAAOPTID_write);
                        GAA_CHECKSTR("initialize", GAAOPTID_initialize);
@@ -667,11 +723,16 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
        struct GAAOPTION_debug GAATMP_debug;
        struct GAAOPTION_outfile GAATMP_outfile;
        struct GAAOPTION_provider GAATMP_provider;
+       struct GAAOPTION_sec_param GAATMP_sec_param;
+       struct GAAOPTION_bits GAATMP_bits;
        struct GAAOPTION_load_certificate GAATMP_load_certificate;
        struct GAAOPTION_load_pubkey GAATMP_load_pubkey;
        struct GAAOPTION_load_privkey GAATMP_load_privkey;
        struct GAAOPTION_secret_key GAATMP_secret_key;
        struct GAAOPTION_label GAATMP_label;
+       struct GAAOPTION_generate_ecc GAATMP_generate_ecc;
+       struct GAAOPTION_generate_dsa GAATMP_generate_dsa;
+       struct GAAOPTION_generate_rsa GAATMP_generate_rsa;
        struct GAAOPTION_delete GAATMP_delete;
        struct GAAOPTION_write GAATMP_write;
        struct GAAOPTION_initialize GAATMP_initialize;
@@ -699,7 +760,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
     {
        case GAAOPTID_help:
        OK = 0;
-#line 87 "p11tool.gaa"
+#line 97 "p11tool.gaa"
 { gaa_help(); exit(0); ;};
 
                return GAA_OK;
@@ -709,7 +770,7 @@ static 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 85 "p11tool.gaa"
+#line 95 "p11tool.gaa"
 { gaaval->debug = GAATMP_debug.arg1 ;};
 
                return GAA_OK;
@@ -719,7 +780,7 @@ static 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 80 "p11tool.gaa"
+#line 90 "p11tool.gaa"
 { gaaval->outfile = GAATMP_outfile.arg1 ;};
 
                return GAA_OK;
@@ -729,28 +790,48 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_provider.arg1, gaa_getstr, 
GAATMP_provider.size1);
                gaa_index++;
-#line 77 "p11tool.gaa"
+#line 87 "p11tool.gaa"
 { gaaval->pkcs11_provider = GAATMP_provider.arg1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_inraw:
        OK = 0;
-#line 73 "p11tool.gaa"
+#line 83 "p11tool.gaa"
 { gaaval->incert_format=GNUTLS_X509_FMT_DER ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_inder:
        OK = 0;
-#line 72 "p11tool.gaa"
+#line 82 "p11tool.gaa"
 { gaaval->incert_format=GNUTLS_X509_FMT_DER ;};
 
                return GAA_OK;
                break;
+       case GAAOPTID_sec_param:
+       OK = 0;
+               GAA_TESTMOREARGS;
+               GAA_FILL(GAATMP_sec_param.arg1, gaa_getstr, 
GAATMP_sec_param.size1);
+               gaa_index++;
+#line 79 "p11tool.gaa"
+{ gaaval->sec_param = GAATMP_sec_param.arg1 ;};
+
+               return GAA_OK;
+               break;
+       case GAAOPTID_bits:
+       OK = 0;
+               GAA_TESTMOREARGS;
+               GAA_FILL(GAATMP_bits.arg1, gaa_getint, GAATMP_bits.size1);
+               gaa_index++;
+#line 76 "p11tool.gaa"
+{ gaaval->bits = GAATMP_bits.arg1 ;};
+
+               return GAA_OK;
+               break;
        case GAAOPTID_pkcs8:
        OK = 0;
-#line 69 "p11tool.gaa"
+#line 73 "p11tool.gaa"
 { gaaval->pkcs8=1 ;};
 
                return GAA_OK;
@@ -760,7 +841,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_load_certificate.arg1, gaa_getstr, 
GAATMP_load_certificate.size1);
                gaa_index++;
-#line 66 "p11tool.gaa"
+#line 70 "p11tool.gaa"
 { gaaval->cert = GAATMP_load_certificate.arg1 ;};
 
                return GAA_OK;
@@ -770,7 +851,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_load_pubkey.arg1, gaa_getstr, 
GAATMP_load_pubkey.size1);
                gaa_index++;
-#line 63 "p11tool.gaa"
+#line 67 "p11tool.gaa"
 { gaaval->pubkey = GAATMP_load_pubkey.arg1 ;};
 
                return GAA_OK;
@@ -780,7 +861,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_load_privkey.arg1, gaa_getstr, 
GAATMP_load_privkey.size1);
                gaa_index++;
-#line 60 "p11tool.gaa"
+#line 64 "p11tool.gaa"
 { gaaval->privkey = GAATMP_load_privkey.arg1 ;};
 
                return GAA_OK;
@@ -790,49 +871,49 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_secret_key.arg1, gaa_getstr, 
GAATMP_secret_key.size1);
                gaa_index++;
-#line 57 "p11tool.gaa"
+#line 61 "p11tool.gaa"
 { gaaval->secret_key = GAATMP_secret_key.arg1; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_no_detailed_url:
        OK = 0;
-#line 54 "p11tool.gaa"
+#line 58 "p11tool.gaa"
 { gaaval->pkcs11_detailed_url = 0; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_detailed_url:
        OK = 0;
-#line 53 "p11tool.gaa"
+#line 57 "p11tool.gaa"
 { gaaval->pkcs11_detailed_url = GNUTLS_PKCS11_URL_LIB; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_login:
        OK = 0;
-#line 50 "p11tool.gaa"
+#line 54 "p11tool.gaa"
 { gaaval->pkcs11_login = 1; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_no_private:
        OK = 0;
-#line 47 "p11tool.gaa"
+#line 51 "p11tool.gaa"
 { gaaval->pkcs11_private = 0; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_private:
        OK = 0;
-#line 46 "p11tool.gaa"
+#line 50 "p11tool.gaa"
 { gaaval->pkcs11_private = 1; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_trusted:
        OK = 0;
-#line 43 "p11tool.gaa"
+#line 47 "p11tool.gaa"
 { gaaval->pkcs11_trusted = 1; ;};
 
                return GAA_OK;
@@ -842,11 +923,41 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_label.arg1, gaa_getstr, GAATMP_label.size1);
                gaa_index++;
-#line 41 "p11tool.gaa"
+#line 45 "p11tool.gaa"
 { gaaval->pkcs11_label = GAATMP_label.arg1; ;};
 
                return GAA_OK;
                break;
+       case GAAOPTID_generate_ecc:
+       OK = 0;
+               GAA_TESTMOREARGS;
+               GAA_FILL(GAATMP_generate_ecc.arg1, gaa_getstr, 
GAATMP_generate_ecc.size1);
+               gaa_index++;
+#line 43 "p11tool.gaa"
+{ gaaval->action = ACTION_PKCS11_GENERATE; gaaval->key_type = GNUTLS_PK_ECC; 
gaaval->pkcs11_url = GAATMP_generate_ecc.arg1; ;};
+
+               return GAA_OK;
+               break;
+       case GAAOPTID_generate_dsa:
+       OK = 0;
+               GAA_TESTMOREARGS;
+               GAA_FILL(GAATMP_generate_dsa.arg1, gaa_getstr, 
GAATMP_generate_dsa.size1);
+               gaa_index++;
+#line 42 "p11tool.gaa"
+{ gaaval->action = ACTION_PKCS11_GENERATE; gaaval->key_type = GNUTLS_PK_DSA; 
gaaval->pkcs11_url = GAATMP_generate_dsa.arg1; ;};
+
+               return GAA_OK;
+               break;
+       case GAAOPTID_generate_rsa:
+       OK = 0;
+               GAA_TESTMOREARGS;
+               GAA_FILL(GAATMP_generate_rsa.arg1, gaa_getstr, 
GAATMP_generate_rsa.size1);
+               gaa_index++;
+#line 41 "p11tool.gaa"
+{ gaaval->action = ACTION_PKCS11_GENERATE; gaaval->key_type = GNUTLS_PK_RSA; 
gaaval->pkcs11_url = GAATMP_generate_rsa.arg1; ;};
+
+               return GAA_OK;
+               break;
        case GAAOPTID_delete:
        OK = 0;
                GAA_TESTMOREARGS;
@@ -963,12 +1074,13 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
     if(inited == 0)
     {
 
-#line 89 "p11tool.gaa"
+#line 99 "p11tool.gaa"
 {
        gaaval->action = -1; gaaval->pkcs11_provider= NULL; gaaval->outfile = 
NULL; gaaval->pubkey = NULL; gaaval->privkey = NULL;
        gaaval->pkcs11_url = NULL; gaaval->pkcs11_type = PKCS11_TYPE_PK; 
gaaval->pubkey=NULL; gaaval->pkcs11_label = NULL; 
-       gaaval->pkcs11_trusted=0; gaaval->pkcs11_login = 0; 
gaaval->pkcs11_detailed_url = GNUTLS_PKCS11_URL_LIB; 
-       gaaval->secret_key = NULL; gaaval->cert = NULL; gaaval->incert_format = 
GNUTLS_X509_FMT_PEM; gaaval->pkcs11_private = -1; ;};
+       gaaval->pkcs11_trusted=0; gaaval->pkcs11_login = 0; 
gaaval->pkcs11_detailed_url = 0; 
+       gaaval->secret_key = NULL; gaaval->cert = NULL; gaaval->incert_format = 
GNUTLS_X509_FMT_PEM; gaaval->pkcs11_private = -1; 
+       gaaval->key_type = 0; gaaval->bits = 0; gaaval->sec_param = NULL; ;};
 
     }
     inited = 1;
@@ -1116,7 +1228,7 @@ static int gaa_internal_get_next_str(FILE *file, 
gaa_str_node *tmp_str, int argc
 
         len++;
         a = fgetc( file);
-        if(a==EOF) return 0; //a = ' ';
+        if(a==EOF) return 0;
     }
 
     len += 1;
diff --git a/src/p11tool-gaa.h b/src/p11tool-gaa.h
index bc5871f..7fec01a 100644
--- a/src/p11tool-gaa.h
+++ b/src/p11tool-gaa.h
@@ -8,34 +8,40 @@ typedef struct _gaainfo gaainfo;
 
 struct _gaainfo
 {
-#line 84 "p11tool.gaa"
+#line 94 "p11tool.gaa"
        int debug;
-#line 79 "p11tool.gaa"
+#line 89 "p11tool.gaa"
        char *outfile;
-#line 76 "p11tool.gaa"
+#line 86 "p11tool.gaa"
        int action;
-#line 75 "p11tool.gaa"
+#line 85 "p11tool.gaa"
        char* pkcs11_provider;
-#line 71 "p11tool.gaa"
+#line 81 "p11tool.gaa"
        int incert_format;
-#line 68 "p11tool.gaa"
+#line 78 "p11tool.gaa"
+       char* sec_param;
+#line 75 "p11tool.gaa"
+       int bits;
+#line 72 "p11tool.gaa"
        int pkcs8;
-#line 65 "p11tool.gaa"
+#line 69 "p11tool.gaa"
        char *cert;
-#line 62 "p11tool.gaa"
+#line 66 "p11tool.gaa"
        char *pubkey;
-#line 59 "p11tool.gaa"
+#line 63 "p11tool.gaa"
        char *privkey;
-#line 56 "p11tool.gaa"
+#line 60 "p11tool.gaa"
        char* secret_key;
-#line 52 "p11tool.gaa"
+#line 56 "p11tool.gaa"
        int pkcs11_detailed_url;
-#line 49 "p11tool.gaa"
+#line 53 "p11tool.gaa"
        int pkcs11_login;
-#line 45 "p11tool.gaa"
+#line 49 "p11tool.gaa"
        int pkcs11_private;
-#line 42 "p11tool.gaa"
+#line 46 "p11tool.gaa"
        int pkcs11_trusted;
+#line 40 "p11tool.gaa"
+       int key_type;
 #line 35 "p11tool.gaa"
        char* pkcs11_label;
 #line 24 "p11tool.gaa"
diff --git a/src/p11tool.c b/src/p11tool.c
index ebaa6fd..2df036b 100644
--- a/src/p11tool.c
+++ b/src/p11tool.c
@@ -155,6 +155,11 @@ gaa_parser (int argc, char **argv)
     case ACTION_PKCS11_DELETE_URL:
       pkcs11_delete (outfile, info.pkcs11_url, 0, info.pkcs11_login, &cinfo);
       break;
+    case ACTION_PKCS11_GENERATE:
+      pkcs11_generate (outfile, info.pkcs11_url, info.key_type, 
get_bits(info.key_type, info.bits, info.sec_param), 
+                       info.pkcs11_label, info.pkcs11_private, 
info.pkcs11_detailed_url, info.pkcs11_login, 
+                       &cinfo);
+      break;
     default:
       gaa_help ();
       exit (0);
diff --git a/src/p11tool.gaa b/src/p11tool.gaa
index 9c2e4ae..3c3cdfc 100644
--- a/src/p11tool.gaa
+++ b/src/p11tool.gaa
@@ -37,6 +37,10 @@ option (initialize) STR "URL" { $action = 
ACTION_PKCS11_TOKEN_INIT; $pkcs11_url
 option (write) STR "URL" { $action = ACTION_PKCS11_WRITE_URL; $pkcs11_url = 
$1; } "Writes loaded certificates, private or secret keys to a PKCS11 token."
 option (delete) STR "URL" { $action = ACTION_PKCS11_DELETE_URL; $pkcs11_url = 
$1; } "Deletes objects matching the URL."
 
+#int key_type;
+option (generate-rsa) STR "URL" { $action = ACTION_PKCS11_GENERATE; $key_type 
= GNUTLS_PK_RSA; $pkcs11_url = $1; } "Generates an RSA private key on the 
specified token."
+option (generate-dsa) STR "URL" { $action = ACTION_PKCS11_GENERATE; $key_type 
= GNUTLS_PK_DSA; $pkcs11_url = $1; } "Generates a DSA private key on the 
specified token."
+option (generate-ecc) STR "URL" { $action = ACTION_PKCS11_GENERATE; $key_type 
= GNUTLS_PK_ECC; $pkcs11_url = $1; } "Generates an ECDSA private key on the 
specified token."
 
 option (label) STR "label" { $pkcs11_label = $1; } "Sets a label for the write 
operation."
 #int pkcs11_trusted;
@@ -68,6 +72,12 @@ option (load-certificate) STR "FILE" { $cert = $1 } 
"Certificate file to use."
 #int pkcs8;
 option (8, pkcs8) { $pkcs8=1 } "Use PKCS #8 format for private keys."
 
+#int bits;
+option (bits) INT "BITS" { $bits = $1 } "specify the number of bits for key 
generation."
+
+#char* sec_param;
+option (sec-param) STR "PARAM" { $sec_param = $1 } "specify the security level 
[low|normal|high|ultra]."
+
 #int incert_format;
 option (inder) { $incert_format=GNUTLS_X509_FMT_DER } "Use DER format for 
input certificates and private keys."
 option (inraw) { $incert_format=GNUTLS_X509_FMT_DER } "Use RAW/DER format for 
input certificates and private keys."
@@ -89,5 +99,6 @@ option (h, help) { gaa_help(); exit(0); } "shows this help 
text"
 init {
        $action = -1; $pkcs11_provider= NULL; $outfile = NULL; $pubkey = NULL; 
$privkey = NULL;
        $pkcs11_url = NULL; $pkcs11_type = PKCS11_TYPE_PK; $pubkey=NULL; 
$pkcs11_label = NULL; 
-       $pkcs11_trusted=0; $pkcs11_login = 0; $pkcs11_detailed_url = 
GNUTLS_PKCS11_URL_LIB; 
-       $secret_key = NULL; $cert = NULL; $incert_format = GNUTLS_X509_FMT_PEM; 
$pkcs11_private = -1; }
+       $pkcs11_trusted=0; $pkcs11_login = 0; $pkcs11_detailed_url = 0; 
+       $secret_key = NULL; $cert = NULL; $incert_format = GNUTLS_X509_FMT_PEM; 
$pkcs11_private = -1; 
+       $key_type = 0; $bits = 0; $sec_param = NULL; }
diff --git a/src/p11tool.h b/src/p11tool.h
index 3682fb1..7506751 100644
--- a/src/p11tool.h
+++ b/src/p11tool.h
@@ -18,6 +18,11 @@ void pkcs11_delete (FILE * outfile, const char *pkcs11_url, 
int batch,
                     unsigned int login, common_info_st *);
 void pkcs11_init (FILE * outfile, const char *pkcs11_url, const char *label,
                   common_info_st *);
+void
+pkcs11_generate (FILE * outfile, const char *url, gnutls_pk_algorithm_t type,
+              unsigned int bits,
+              const char *label, int private, int detailed,
+              unsigned int login, common_info_st * info);
 
 #define PKCS11_TYPE_CRT_ALL 1
 #define PKCS11_TYPE_TRUSTED 2
@@ -35,6 +40,7 @@ enum
   ACTION_PKCS11_DELETE_URL,
   ACTION_PKCS11_TOKEN_INIT,
   ACTION_PKCS11_MECHANISMS,
+  ACTION_PKCS11_GENERATE,
 };
 
 #endif
diff --git a/src/pkcs11.c b/src/pkcs11.c
index 8a74204..251f79f 100644
--- a/src/pkcs11.c
+++ b/src/pkcs11.c
@@ -546,6 +546,39 @@ pkcs11_write (FILE * outfile, const char *url, const char 
*label,
 }
 
 void
+pkcs11_generate (FILE * outfile, const char *url, gnutls_pk_algorithm_t pk,
+              unsigned int bits,
+              const char *label, int private, int detailed,
+              unsigned int login, common_info_st * info)
+{
+  int ret;
+  unsigned int flags = 0;
+
+  if (login)
+    flags = GNUTLS_PKCS11_OBJ_FLAG_LOGIN;
+
+  pkcs11_common ();
+
+  if (url == NULL)
+    url = "pkcs11:";
+
+  if (private == 1)
+    flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE;
+  else if (private == 0)
+    flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE;
+
+  ret = gnutls_pkcs11_privkey_generate(url, pk, bits, label, flags);
+  if (ret < 0)
+    {
+      fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
+               gnutls_strerror (ret));
+      exit(1);
+    }
+
+  return;
+}
+
+void
 pkcs11_init (FILE * outfile, const char *url, const char *label,
              common_info_st * info)
 {
@@ -783,6 +816,13 @@ const char *mech_list[] = {
   [0x2000] = "CKM_DSA_PARAMETER_GEN",
   [0x2001] = "CKM_DH_PKCS_PARAMETER_GEN",
   [0x2002] = "CKM_X9_42_DH_PARAMETER_GEN",
+  [0x1200] = "CKM_GOSTR3410_KEY_PAIR_GEN",
+  [0x1201] = "CKM_GOSTR3410",
+  [0x1202] = "CKM_GOSTR3410_WITH_GOSTR3411",
+  [0x1203] = "CKM_GOSTR3410_KEY_WRAP",
+  [0x1204] = "CKM_GOSTR3410_DERIVE",
+  [0x1210] = "CKM_GOSTR3411",
+  [0x1211] = "CKM_GOSTR3411_HMAC",
   [0x255] = "CKM_SHA224",
   [0x256] = "CKM_SHA224_HMAC",
   [0x257] = "CKM_SHA224_HMAC_GENERAL",
diff --git a/src/prime.c b/src/prime.c
index 4c4efd3..d3241e1 100644
--- a/src/prime.c
+++ b/src/prime.c
@@ -37,22 +37,28 @@
 extern FILE *outfile;
 extern FILE *infile;
 
-static int cparams = 0;
+const static int cparams = 0;
 
 /* If how is zero then the included parameters are used.
  */
 int
-generate_prime (int how)
+generate_prime (int how, common_info_st * info)
 {
   unsigned int i;
   int ret;
   gnutls_dh_params_t dh_params;
   gnutls_datum_t p, g;
-  int bits = get_bits (GNUTLS_PK_DH);
+  int bits = get_bits (GNUTLS_PK_DH, info->bits, info->sec_param);
 
   gnutls_dh_params_init (&dh_params);
 
-  fprintf (stderr, "Generating DH parameters...");
+  if (how != 0)
+    {
+      fprintf (stderr, "Generating DH parameters (%d bits)...\n", bits);
+      fprintf (stderr, "(might take long time)\n");
+    }
+  else
+    fprintf (stderr, "Retrieving DH parameters...\n", bits);
 
   if (how != 0)
     {
@@ -79,16 +85,19 @@ generate_prime (int how)
         {
           p = gnutls_srp_1024_group_prime;
           g = gnutls_srp_1024_group_generator;
+          bits = 1024;
         }
       else if (bits <= 1536)
         {
           p = gnutls_srp_1536_group_prime;
           g = gnutls_srp_1536_group_generator;
+          bits = 1536;
         }
       else
         {
           p = gnutls_srp_2048_group_prime;
           g = gnutls_srp_2048_group_generator;
+          bits = 2048;
         }
 
       ret = gnutls_dh_params_import_raw (dh_params, &p, &g);
@@ -99,7 +108,8 @@ generate_prime (int how)
           exit (1);
         }
 #else
-      fprintf (stderr, "Parameters unavailable as SRP disabled.\n");
+      fprintf (stderr, "Parameters unavailable as SRP is disabled.\n");
+      exit(1);
 #endif
     }
 
@@ -157,11 +167,11 @@ generate_prime (int how)
     }
   else
     {
-      fprintf (outfile, "Prime: ");
+      fprintf (outfile, "Prime (%d bits):", bits);
 
       for (i = 0; i < p.size; i++)
         {
-          if (i != 0 && i % 12 == 0)
+          if (i % 12 == 0)
             fprintf (outfile, "\n\t");
           else if (i != 0 && i != p.size)
             fprintf (outfile, ":");


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]