[Cryptech-Commits] [sw/pkcs11] 02/14: Checkpoint of partial support for ECDSA. Compiles, not yet tested, probably doesn't work. Probably should merge state_access branch before going much further with this.

git at cryptech.is git at cryptech.is
Mon Sep 14 21:43:53 UTC 2015


This is an automated email from the git hooks/post-receive script.

sra at hactrn.net pushed a commit to branch ecdsa
in repository sw/pkcs11.

commit 92325a4ca95c99e164257528514c24cbb982ea7a
Author: Rob Austein <sra at hactrn.net>
Date:   Mon Sep 7 18:40:55 2015 -0400

    Checkpoint of partial support for ECDSA.  Compiles, not yet tested,
    probably doesn't work.  Probably should merge state_access branch
    before going much further with this.
---
 pkcs11.c | 630 ++++++++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 502 insertions(+), 128 deletions(-)

diff --git a/pkcs11.c b/pkcs11.c
index 93e051a..ff5304a 100644
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -478,6 +478,37 @@ static CK_RV posix_mutex_unlock(CK_VOID_PTR pMutex)
 

 
 /*
+ * Translate between libhal EC curve names and OIDs.
+ */
+#warning Perhaps this should be  a utility routine in libhal instead of here
+
+static int ec_curve_oid_to_name(const uint8_t * const oid, const size_t oid_len, hal_ecdsa_curve_t *curve)
+{
+  static uint8_t ec_curve_oid_p256[] = { 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
+  static uint8_t ec_curve_oid_p384[] = { 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22 };
+  static uint8_t ec_curve_oid_p521[] = { 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23 };
+
+  if (oid == NULL || curve == NULL)
+    return 0;
+
+  else if (oid_len == sizeof(ec_curve_oid_p256) && memcmp(oid, ec_curve_oid_p256, oid_len) == 0)
+    *curve = HAL_ECDSA_CURVE_P256;
+
+  else if (oid_len == sizeof(ec_curve_oid_p384) && memcmp(oid, ec_curve_oid_p384, oid_len) == 0)
+    *curve = HAL_ECDSA_CURVE_P384;
+
+  else if (oid_len == sizeof(ec_curve_oid_p521) && memcmp(oid, ec_curve_oid_p521, oid_len) == 0)
+    *curve = HAL_ECDSA_CURVE_P521;
+
+  else
+    return 0;
+
+  return 1;
+}
+
+

+
+/*
  * Initialize KEK.  If we had proper hardware support the KEK would be
  * living in special RAM where we could wipe it if anything triggered
  * our tamper circuitry.  But we have no such at the moment, so we
@@ -1132,17 +1163,19 @@ static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session,
 }
 
 /*
- * Store an RSA private key.
+ * Store a private key.
  *
- * Write the key as PKCS #1.5 RSAPrivateKey DER, encrypt that using
- * AES key wrap, and store the result as an SQL blob.
+ * Write the key as DER, encrypt that using AES key wrap, and store
+ * the result as an SQL blob.
  *
  * We jump through a few minor hoops to let us do all the encoding and
  * wrapping in place in a single buffer.
  */
 
-static int p11_object_set_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
-                                          const hal_rsa_key_t * const key)
+static int p11_object_set_generic_private_key(const CK_OBJECT_HANDLE object_handle,
+                                              const void * const key,
+                                              const size_t key_der_len,
+                                              hal_error_t (*to_der)(const void * const, uint8_t *, size_t *, const size_t))
 {
   static const char select_kek[] =
     " SELECT kek FROM global";
@@ -1151,17 +1184,18 @@ static int p11_object_set_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
     " UPDATE %s_object SET private_key = ?1"
     " WHERE %s_object_id = (SELECT %s_object_id FROM object WHERE object_handle = ?2)";
 
-  uint8_t wrapbuf[hal_aes_keywrap_ciphertext_length(hal_rsa_key_to_der_len(key))];
+  uint8_t wrapbuf[hal_aes_keywrap_ciphertext_length(key_der_len)];
   const char *flavor = is_token_handle(object_handle) ? "token" : "session";
   size_t der_len, wrapbuf_len = sizeof(wrapbuf);
   sqlite3_stmt *q = NULL;
   int ok = 0;
 
+  assert(to_der);
+
   if (!sql_check_ok(sql_prepare(&q, select_kek))                                ||
       !sql_check_row(sqlite3_step(q))                                           ||
       sqlite3_column_type(q, 0) == SQLITE_NULL                                  ||
-      !hal_check(hal_rsa_key_to_der(key, wrapbuf+8, &der_len,
-                                    sizeof(wrapbuf)-8))                         ||
+      !hal_check(to_der(key, wrapbuf + 8, &der_len, sizeof(wrapbuf) - 8))       ||
       !hal_check(hal_aes_keywrap(sqlite3_column_blob(q, 0),
                                  sqlite3_column_bytes(q, 0),
                                  wrapbuf+8, der_len, wrapbuf, &wrapbuf_len))	||
@@ -1181,18 +1215,67 @@ static int p11_object_set_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
 }
 
 /*
- * Fetch an RSA private key.
+ * Store an RSA private key.
+ *
+ * Use p11_object_set_generic_private_key() to wrap the PKCS #1.5
+ * RSAPrivateKey encoding of the private key.
+ */
+
+static hal_error_t p11_object_encode_rsa_key(const void * const key,
+                                             uint8_t * der,
+                                             size_t *der_len,
+                                             const size_t der_max)
+{
+  return hal_rsa_key_to_der(key, der, der_len, der_max);
+}
+
+static int p11_object_set_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
+                                          const hal_rsa_key_t * const key)
+{
+  return p11_object_set_generic_private_key(object_handle,
+                                            key,
+                                            hal_rsa_key_to_der_len(key),
+                                            p11_object_encode_rsa_key);
+}
+
+/*
+ * Store an EC private key.
+ *
+ * Use p11_object_set_generic_private_key() to wrap the RFC 5915
+ * ECPrivateKey encoding of the private key.
+ */
+
+static hal_error_t p11_object_encode_ec_key(const void * const key,
+                                            uint8_t * der,
+                                            size_t *der_len,
+                                            const size_t der_max)
+{
+  return hal_ecdsa_key_to_der(key, der, der_len, der_max);
+}
+
+static int p11_object_set_ec_private_key(const CK_OBJECT_HANDLE object_handle,
+                                         const hal_ecdsa_key_t * const key)
+{
+  return p11_object_set_generic_private_key(object_handle,
+                                            key,
+                                            hal_ecdsa_key_to_der_len(key),
+                                            p11_object_encode_ec_key);
+}
+
+/*
+ * Fetch a private key.
  *
  * Retrieve SQL blob from the object, unwrap that to get the DER
- * encoding of a PKCS #1.5 RSAPrivateKey object, load the key from
- * that.
+ * encoding, load the key from that.
  *
  * If the key isn't set, we return success with null key.
  */
 
-static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
-                                          hal_rsa_key_t **key,
-                                          uint8_t *keybuf, const size_t keybuf_len)
+static int p11_object_get_generic_private_key(const CK_OBJECT_HANDLE object_handle,
+                                              void **key,
+                                              uint8_t *keybuf, const size_t keybuf_len,
+                                              hal_error_t (*from_der)(void **, void *,
+                                                                      const size_t, const uint8_t * const, const size_t))
 {
   static const char select_format[] =
     " SELECT kek, private_key FROM global, %s_object NATURAL JOIN object WHERE object_handle = ?1";
@@ -1228,7 +1311,7 @@ static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
     uint8_t wrapbuf[pkey_len];
 
     ok = (hal_check(hal_aes_keyunwrap(kek, kek_len, pkey, pkey_len, wrapbuf, &wrapbuf_len)) &&
-          hal_check(hal_rsa_key_from_der(key, keybuf, keybuf_len, wrapbuf, wrapbuf_len)));
+          hal_check(from_der(key, keybuf, keybuf_len, wrapbuf, wrapbuf_len)));
 
     memset(wrapbuf, 0, sizeof(wrapbuf));
   }
@@ -1240,14 +1323,72 @@ static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
   return ok;
 }
 
-#warning Revisit return semantics of p11_object_get_rsa_private_key() and p11_object_get_rsa_public_key()
+/*
+ * Fetch an RSA private key.
+ *
+ * Use p11_object_get_generic_private_key() to unwrap the DER encoding
+ * of a PKCS #1.5 RSAPrivateKey object.
+ */
+
+static hal_error_t p11_object_decode_rsa_key(void **key_,
+                                             void *keybuf, const size_t keybuf_len,
+                                             const uint8_t * const der, const size_t der_len)
+{
+  assert(key_ != NULL);
+  hal_rsa_key_t *key = NULL;
+  hal_error_t err = hal_rsa_key_from_der(&key, keybuf, keybuf_len, der, der_len);
+  *key_ = key;
+  return err;
+}
+
+static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
+                                          hal_rsa_key_t **key,
+                                          uint8_t *keybuf, const size_t keybuf_len)
+{
+  assert(key != NULL);
+  void *key_ = NULL;
+  int ok = p11_object_get_generic_private_key(object_handle, &key_, keybuf, keybuf_len, p11_object_decode_rsa_key);
+  *key = key_;
+  return ok;
+}
+
+/*
+ * Fetch an EC private key.
+ *
+ * Use p11_object_get_generic_private_key() to unwrap the DER encoding
+ * of an RFC 5915 ECPrivateKey object.
+ */
+
+static hal_error_t p11_object_decode_ec_key(void **key_,
+                                             void *keybuf, const size_t keybuf_len,
+                                             const uint8_t * const der, const size_t der_len)
+{
+  assert(key_ != NULL);
+  hal_ecdsa_key_t *key = NULL;
+  hal_error_t err = hal_ecdsa_key_from_der(&key, keybuf, keybuf_len, der, der_len);
+  *key_ = key;
+  return err;
+}
+
+static int p11_object_get_ec_private_key(const CK_OBJECT_HANDLE object_handle,
+                                          hal_ecdsa_key_t **key,
+                                          uint8_t *keybuf, const size_t keybuf_len)
+{
+  assert(key != NULL);
+  void *key_ = NULL;
+  int ok = p11_object_get_generic_private_key(object_handle, &key_, keybuf, keybuf_len, p11_object_decode_ec_key);
+  *key = key_;
+  return ok;
+}
+
+#warning Revisit return semantics of p11_object_get_*_private_key() and p11_object_*_rsa_public_key()
 
 /*
  * Fetch an RSA public key.
  *
  * Public keys aren't stored separately the way that private keys are,
  * so we're looking for the public components so we can load them into
- * a key objet.
+ * a key object.
  */
 
 static int p11_object_get_rsa_public_key(const CK_OBJECT_HANDLE object_handle,
@@ -1280,6 +1421,47 @@ static int p11_object_get_rsa_public_key(const CK_OBJECT_HANDLE object_handle,
   return ok;
 }
 
+/*
+ * Fetch an EC public key.
+ *
+ * Public keys aren't stored separately the way that private keys are,
+ * so we're looking for the public components so we can load them into
+ * a key object.
+ */
+
+static int p11_object_get_ec_public_key(const CK_OBJECT_HANDLE object_handle,
+                                        hal_ecdsa_key_t **key,
+                                        uint8_t *keybuf, const size_t keybuf_len)
+{
+  static const char select_format[] =
+    " WITH a (type, value) "
+    "   AS (SELECT type, value FROM %s_attribute NATURAL JOIN object WHERE object_handle = ?1)"
+    " SELECT a1.value, a2.value FROM a AS a1, a AS a2 WHERE a1.type = %u AND a2.type = %u";
+
+  const char *flavor = is_token_handle(object_handle) ? "token" : "session";
+  sqlite3_stmt *q = NULL;
+  hal_ecdsa_curve_t curve;
+
+  assert(key != NULL && keybuf != NULL);
+
+  const int ok = (sql_check_ok(sql_prepare(&q, select_format, flavor,
+                                           CKA_EC_PARAMS, CKA_EC_POINT))        &&
+                  sql_check_ok(sqlite3_bind_int64(q, 1, object_handle))         &&
+                  sql_check_row(sqlite3_step(q))                                &&
+                  sqlite3_column_type(q, 0) == SQLITE_BLOB                      &&
+                  sqlite3_column_type(q, 1) == SQLITE_BLOB                      &&
+                  ec_curve_oid_to_name(sqlite3_column_blob( q, 0),
+                                       sqlite3_column_bytes(q, 0),
+                                       &curve)                                  &&
+                  hal_check(hal_ecdsa_key_from_ecpoint(key, keybuf, keybuf_len,
+                                                       sqlite3_column_blob( q, 1),
+                                                       sqlite3_column_bytes(q, 1),
+                                                       curve)));
+
+  sqlite3_finalize(q);
+  return ok;
+}
+
 

 
 /*
@@ -1704,152 +1886,223 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session,
 }
 
 /*
- * CKM_RSA_PKCS_KEY_PAIR_GEN key pair generation implemetation.
- *
- * Much mechanism-independent code has already been factored out of
- * this function, no doubt much remains that will require further
- * refactoring once we implement other mechanisms.
+ * CKM_RSA_PKCS_KEY_PAIR_GEN key pair generation handler.
  */
 
 static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session,
-                                       const CK_MECHANISM_PTR pMechanism,
                                        const CK_ATTRIBUTE_PTR pPublicKeyTemplate,
                                        const CK_ULONG ulPublicKeyAttributeCount,
                                        const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
                                        const CK_ULONG ulPrivateKeyAttributeCount,
-                                       CK_OBJECT_HANDLE_PTR phPublicKey,
-                                       CK_OBJECT_HANDLE_PTR phPrivateKey)
+                                       const CK_OBJECT_HANDLE private_handle,
+                                       const CK_OBJECT_HANDLE public_handle)
 {
-  CK_OBJECT_HANDLE private_handle = CK_INVALID_HANDLE;
-  CK_OBJECT_HANDLE public_handle = CK_INVALID_HANDLE;
-  handle_flavor_t public_handle_flavor = handle_flavor_session_object;
-  handle_flavor_t private_handle_flavor = handle_flavor_session_object;
-  uint8_t
-    keybuf[hal_rsa_key_t_size],
-    modulus[hal_rsa_key_t_size/8],
-    public_exponent[hal_rsa_key_t_size/8];
-  size_t modulus_len;
-  CK_ULONG public_exponent_len;
+  const uint8_t *public_exponent = const_0x010001;
+  size_t public_exponent_len = sizeof(const_0x010001);
+  uint8_t keybuf[hal_rsa_key_t_size];
   hal_rsa_key_t *key = NULL;
   CK_ULONG keysize = 0;
+  size_t modulus_len;
   CK_RV rv;
   int i;
 
-  /*
-   * Do mechanism-independent checks before anything else.
-   */
-
-  rv = p11_check_keypair_attributes(session,
-                                    pPublicKeyTemplate,  ulPublicKeyAttributeCount,  &p11_descriptor_rsa_public_key,
-                                    pPrivateKeyTemplate, ulPrivateKeyAttributeCount, &p11_descriptor_rsa_private_key);
-  if (rv != CKR_OK)
-    return rv;
-
-  assert(session             != NULL && pMechanism   != NULL &&
-         pPublicKeyTemplate  != NULL && phPublicKey  != NULL &&
-         pPrivateKeyTemplate != NULL && phPrivateKey != NULL);
-
-  /*
-   * Grab values and perform mechanism-specific checks.
-   */
+  assert(pPublicKeyTemplate  != NULL && pPrivateKeyTemplate);
 
   for (i = 0; i < ulPublicKeyAttributeCount; i++) {
     const CK_ATTRIBUTE_TYPE type = pPublicKeyTemplate[i].type;
     const void * const       val = pPublicKeyTemplate[i].pValue;
-#if 0
     const size_t             len = pPublicKeyTemplate[i].ulValueLen;
-#endif
-
-    assert(val != NULL);
 
     switch (type) {
 
-    case CKA_TOKEN:             /* Object stored on token */
-      public_handle_flavor = p11_handle_flavor_from_cka_token(val);
-      continue;
-
     case CKA_MODULUS_BITS:      /* Keysize in bits -- only allow multiples of 8 */
       keysize = *(CK_ULONG *) val;
       if ((keysize & 7) != 0)
         return CKR_ATTRIBUTE_VALUE_INVALID;
       continue;
 
+    case CKA_PUBLIC_EXPONENT:
+      public_exponent = val;
+      public_exponent_len = len;
+      continue;
     }
   }
 
-  for (i = 0; i < ulPrivateKeyAttributeCount; i++) {
-    const CK_ATTRIBUTE_TYPE type = pPrivateKeyTemplate[i].type;
-    const void * const       val = pPrivateKeyTemplate[i].pValue;
-#if 0
-    const size_t             len = pPrivateKeyTemplate[i].ulValueLen;
-#endif
+  if (keysize == 0)
+    return CKR_TEMPLATE_INCOMPLETE;
 
-    assert (val != NULL);
+  memset(keybuf, 0, sizeof(keybuf));
+
+  if (!hal_check(hal_rsa_key_gen(&key, keybuf, sizeof(keybuf), keysize / 8,
+                                 public_exponent, public_exponent_len)))
+    lose(CKR_FUNCTION_FAILED);
+
+  if (!p11_object_set_rsa_private_key(private_handle, key))
+    lose(CKR_FUNCTION_FAILED);
+
+  if (!hal_check(hal_rsa_key_get_modulus(key, NULL, &modulus_len, 0)))
+    lose(CKR_FUNCTION_FAILED);
+
+  {
+    uint8_t modulus[modulus_len];
+
+    if (!hal_check(hal_rsa_key_get_modulus(key, modulus, &modulus_len, sizeof(modulus))) ||
+        !p11_attribute_set(public_handle,  CKA_MODULUS, modulus, modulus_len)            ||
+        !p11_attribute_set(private_handle, CKA_MODULUS, modulus, modulus_len))
+      lose(CKR_FUNCTION_FAILED);
+  }
+
+  rv = CKR_OK;
+
+ fail:
+  hal_rsa_key_clear(key);
+  return rv;
+}
+
+/*
+ * CKM_EC_KEY_PAIR_GEN key pair generation handler.
+ */
+
+static CK_RV generate_keypair_ec(p11_session_t *session,
+                                       const CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+                                       const CK_ULONG ulPublicKeyAttributeCount,
+                                       const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+                                       const CK_ULONG ulPrivateKeyAttributeCount,
+                                       const CK_OBJECT_HANDLE private_handle,
+                                       const CK_OBJECT_HANDLE public_handle)
+{
+  uint8_t keybuf[hal_ecdsa_key_t_size];
+  hal_ecdsa_key_t *key = NULL;
+  const CK_BYTE *params = NULL;
+  hal_ecdsa_curve_t curve;
+  size_t params_len;
+  CK_RV rv;
+  int i;
+
+  assert(session != NULL && pPublicKeyTemplate != NULL && pPrivateKeyTemplate != NULL);
+
+  for (i = 0; i < ulPublicKeyAttributeCount; i++) {
+    const CK_ATTRIBUTE_TYPE type = pPublicKeyTemplate[i].type;
+    const void * const       val = pPublicKeyTemplate[i].pValue;
+    const size_t             len = pPublicKeyTemplate[i].ulValueLen;
 
     switch (type) {
 
-    case CKA_TOKEN:             /* Object stored on token */
-      private_handle_flavor = p11_handle_flavor_from_cka_token(val);
+    case CKA_EC_PARAMS:
+      params = val;
+      params_len = len;
       continue;
-
     }
   }
 
-  /*
-   * We require a key size.
-   */
-  if (keysize == 0)
+  if (!ec_curve_oid_to_name(params, params_len, &curve))
     return CKR_TEMPLATE_INCOMPLETE;
 
-  /*
-   * Create the PKCS #11 objects and generate the keypair.
-   */
+  memset(keybuf, 0, sizeof(keybuf));
+
+  if (!hal_check(hal_ecdsa_key_gen(&key, keybuf, sizeof(keybuf), curve))        ||
+      !p11_object_set_ec_private_key(private_handle, key)                       ||
+      !p11_attribute_set(public_handle,  CKA_EC_PARAMS, params, params_len)     ||
+      !p11_attribute_set(private_handle, CKA_EC_PARAMS, params, params_len))
+    lose(CKR_FUNCTION_FAILED);
 
-  if (!sql_exec("BEGIN")                                                                        ||
-      (public_handle = p11_object_create(session, public_handle_flavor,
+  {
+    uint8_t point[hal_ecdsa_key_to_ecpoint_len(key)];
+
+    if (!hal_check(hal_ecdsa_key_to_ecpoint(key, point, NULL, sizeof(point)))   ||
+        !p11_attribute_set(public_handle,  CKA_EC_POINT, point, sizeof(point)))
+      lose(CKR_FUNCTION_FAILED);
+  }
+
+  rv = CKR_OK;
+
+ fail:
+  hal_ecdsa_key_clear(key);
+  return rv;
+}
+
+/*
+ * Key pair generation.  This needs a mechanism-specific function to
+ * do the inner bits, but there's a lot of boilerplate.
+ */
+
+static CK_RV generate_keypair(p11_session_t *session,
+                              const CK_MECHANISM_PTR pMechanism,
+                              const CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+                              const CK_ULONG ulPublicKeyAttributeCount,
+                              const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+                              const CK_ULONG ulPrivateKeyAttributeCount,
+                              CK_OBJECT_HANDLE_PTR phPublicKey,
+                              CK_OBJECT_HANDLE_PTR phPrivateKey,
+                              CK_RV (*mechanism_handler)(p11_session_t *session,
+                                                         const CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+                                                         const CK_ULONG ulPublicKeyAttributeCount,
+                                                         const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+                                                         const CK_ULONG ulPrivateKeyAttributeCount,
+                                                         const CK_OBJECT_HANDLE private_handle,
+                                                         const CK_OBJECT_HANDLE public_handle),
+                              const p11_descriptor_t * const public_descriptor,
+                              const p11_descriptor_t * const private_descriptor)
+{
+  CK_OBJECT_HANDLE private_handle = CK_INVALID_HANDLE;
+  CK_OBJECT_HANDLE public_handle = CK_INVALID_HANDLE;
+  handle_flavor_t public_handle_flavor = handle_flavor_session_object;
+  handle_flavor_t private_handle_flavor = handle_flavor_session_object;
+  CK_RV rv;
+  int i;
+
+  rv = p11_check_keypair_attributes(session,
+                                    pPublicKeyTemplate,  ulPublicKeyAttributeCount,  public_descriptor,
+                                    pPrivateKeyTemplate, ulPrivateKeyAttributeCount, private_descriptor);
+  if (rv != CKR_OK)
+    return rv;
+
+  assert(session             != NULL && pMechanism   != NULL &&
+         pPublicKeyTemplate  != NULL && phPublicKey  != NULL &&
+         pPrivateKeyTemplate != NULL && phPrivateKey != NULL);
+
+  for (i = 0; i < ulPublicKeyAttributeCount; i++)
+    if (pPublicKeyTemplate[i].type == CKA_TOKEN)
+      public_handle_flavor = p11_handle_flavor_from_cka_token(pPublicKeyTemplate[i].pValue);
+
+  for (i = 0; i < ulPrivateKeyAttributeCount; i++)
+    if (pPrivateKeyTemplate[i].type == CKA_TOKEN)
+      private_handle_flavor = p11_handle_flavor_from_cka_token(pPrivateKeyTemplate[i].pValue);
+
+  if (!sql_exec("BEGIN"))
+    lose(CKR_FUNCTION_FAILED);
+
+  if ((public_handle = p11_object_create(session, public_handle_flavor,
                                          pPublicKeyTemplate, ulPublicKeyAttributeCount,
-                                         &p11_descriptor_rsa_public_key,
-                                         pMechanism)) == CK_INVALID_HANDLE                      ||
-      (private_handle = p11_object_create(session, private_handle_flavor,
-                                          pPrivateKeyTemplate,  ulPrivateKeyAttributeCount,
-                                          &p11_descriptor_rsa_private_key,
-                                          pMechanism)) == CK_INVALID_HANDLE			||
-      !p11_attribute_get(public_handle, CKA_PUBLIC_EXPONENT,
-                         public_exponent, &public_exponent_len, sizeof(public_exponent))	||
-      !hal_check(hal_rsa_key_gen(&key, keybuf, sizeof(keybuf), keysize/8,
-                                 public_exponent, (size_t) public_exponent_len))                ||
-      !p11_object_set_rsa_private_key(private_handle, key)                                      ||
-      !hal_check(hal_rsa_key_get_modulus(key, modulus, &modulus_len, sizeof(modulus)))          ||
-      !p11_attribute_set(public_handle,  CKA_MODULUS, modulus, modulus_len)                     ||
-      !p11_attribute_set(private_handle, CKA_MODULUS, modulus, modulus_len))
+                                         public_descriptor, pMechanism)) == CK_INVALID_HANDLE)
     lose(CKR_FUNCTION_FAILED);
 
-  hal_rsa_key_clear(key);
+  if ((private_handle = p11_object_create(session, private_handle_flavor,
+                                          pPrivateKeyTemplate,  ulPrivateKeyAttributeCount,
+                                          private_descriptor, pMechanism)) == CK_INVALID_HANDLE)
+    lose(CKR_FUNCTION_FAILED);
 
-  /*
-   * Commit the SQL transaction.
-   */
+  if ((rv = mechanism_handler(session,
+                              pPublicKeyTemplate, ulPublicKeyAttributeCount,
+                              pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+                              private_handle, public_handle)) != CKR_OK)
+    goto fail;
 
   if (!sql_exec("COMMIT"))
     lose(CKR_FUNCTION_FAILED);
 
-  /*
-   * All went well, return handles and we're done.
-   */
   *phPublicKey  = public_handle;
   *phPrivateKey = private_handle;
   return CKR_OK;
 
  fail:
-
-  memset(keybuf, 0, sizeof(keybuf));
-
   if (!sql_exec("ROLLBACK"))
     rv = CKR_GENERAL_ERROR;
-
   return rv;
 }
 
+

+
 /*
  * Construct a PKCS #1 DigestInfo object.  This requires some (very
  * basic) ASN.1 encoding, which we perform inline.
@@ -3076,6 +3329,9 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession,
   ENTER_PUBLIC_FUNCTION(C_SignInit);
 
   p11_session_t *session;
+  CK_OBJECT_CLASS key_class;
+  CK_KEY_TYPE key_type;
+  CK_BBOOL key_sign;
   CK_RV rv = CKR_OK;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -3092,20 +3348,59 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession,
   if ((rv = p11_object_check_rights(session, hKey, p11_object_access_read)) != CKR_OK)
     goto fail;
 
-  /*
-   * Will need to check key algorithm type here once we add support
-   * for signature algorithms other than RSA.
-   */
+  if (!p11_attribute_get_ulong(hKey, CKA_CLASS,    &key_class)  ||
+      !p11_attribute_get_ulong(hKey, CKA_KEY_TYPE, &key_type)   ||
+      !p11_attribute_get_bbool(hKey, CKA_SIGN,     &key_sign)   ||
+      key_class != CKO_PRIVATE_KEY)
+    lose(CKR_KEY_HANDLE_INVALID);
+
+  if (!key_sign)
+    lose(CKR_KEY_FUNCTION_NOT_PERMITTED);
+
+  switch (pMechanism->mechanism) {
+  case CKM_RSA_PKCS:
+  case CKM_SHA1_RSA_PKCS:
+  case CKM_SHA256_RSA_PKCS:
+  case CKM_SHA384_RSA_PKCS:     
+  case CKM_SHA512_RSA_PKCS:
+    if (key_type != CKK_RSA)
+      lose(CKR_KEY_TYPE_INCONSISTENT);
+    break;
+  case CKM_ECDSA:
+  case CKM_ECDSA_SHA256:
+  case CKM_ECDSA_SHA384:
+  case CKM_ECDSA_SHA512:
+    if (key_type != CKK_EC)
+      lose(CKR_KEY_TYPE_INCONSISTENT);
+    break;
+  default:
+    return CKR_MECHANISM_INVALID;
+  }
 
   session->sign_key_handle = hKey;
 
   switch (pMechanism->mechanism) {
-  case CKM_RSA_PKCS:            session->sign_digest_descriptor = NULL;                 break;
-  case CKM_SHA1_RSA_PKCS:       session->sign_digest_descriptor = hal_hash_sha1;        break;
-  case CKM_SHA256_RSA_PKCS:     session->sign_digest_descriptor = hal_hash_sha256;      break;
-  case CKM_SHA384_RSA_PKCS:     session->sign_digest_descriptor = hal_hash_sha384;      break;
-  case CKM_SHA512_RSA_PKCS:     session->sign_digest_descriptor = hal_hash_sha512;      break;
-  default:                      return CKR_MECHANISM_INVALID;
+  case CKM_RSA_PKCS:
+  case CKM_ECDSA:
+    session->sign_digest_descriptor = NULL;
+    break;
+  case CKM_SHA1_RSA_PKCS:
+    session->sign_digest_descriptor = hal_hash_sha1;
+    break;
+  case CKM_SHA256_RSA_PKCS:
+  case CKM_ECDSA_SHA256:
+    session->sign_digest_descriptor = hal_hash_sha256;
+    break;
+  case CKM_SHA384_RSA_PKCS:     
+  case CKM_ECDSA_SHA384:
+    session->sign_digest_descriptor = hal_hash_sha384;
+    break;
+  case CKM_SHA512_RSA_PKCS:     
+  case CKM_ECDSA_SHA512:
+    session->sign_digest_descriptor = hal_hash_sha512;
+    break;
+  default:
+    return CKR_MECHANISM_INVALID;
   }
 
   return mutex_unlock(p11_global_mutex);
@@ -3147,6 +3442,7 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
    * From here down this function is RSA-specific, and will need
    * rewriting when we add support for other algorithms.
    */
+#warning RSA-specific
 
   if (!p11_object_get_rsa_private_key(session->sign_key_handle,
                                       &key, keybuf, sizeof(keybuf)))
@@ -3156,6 +3452,7 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
    * Retrieve signature length.  For RSA this is just the modulus
    * length, other algorithms will need a more generic solution.
    */
+#warning RSA-specific
 
   if (!hal_check(hal_rsa_key_get_modulus(key, NULL, &signature_len, 0)))
     lose(CKR_FUNCTION_FAILED);
@@ -3212,6 +3509,9 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession,
   ENTER_PUBLIC_FUNCTION(C_VerifyInit);
 
   p11_session_t *session;
+  CK_OBJECT_CLASS key_class;
+  CK_KEY_TYPE key_type;
+  CK_BBOOL key_verify;
   CK_RV rv = CKR_OK;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -3228,20 +3528,59 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession,
   if ((rv = p11_object_check_rights(session, hKey, p11_object_access_read)) != CKR_OK)
     goto fail;
 
-  /*
-   * Will need to check key algorithm type here once we add support
-   * for signature algorithms other than RSA.
-   */
+  if (!p11_attribute_get_ulong(hKey, CKA_CLASS,    &key_class)  ||
+      !p11_attribute_get_ulong(hKey, CKA_KEY_TYPE, &key_type)   ||
+      !p11_attribute_get_bbool(hKey, CKA_SIGN,     &key_verify) ||
+      key_class != CKO_PRIVATE_KEY)
+    lose(CKR_KEY_HANDLE_INVALID);
+
+  if (!key_verify)
+    lose(CKR_KEY_FUNCTION_NOT_PERMITTED);
+
+  switch (pMechanism->mechanism) {
+  case CKM_RSA_PKCS:
+  case CKM_SHA1_RSA_PKCS:
+  case CKM_SHA256_RSA_PKCS:
+  case CKM_SHA384_RSA_PKCS:     
+  case CKM_SHA512_RSA_PKCS:
+    if (key_type != CKK_RSA)
+      lose(CKR_KEY_TYPE_INCONSISTENT);
+    break;
+  case CKM_ECDSA:
+  case CKM_ECDSA_SHA256:
+  case CKM_ECDSA_SHA384:
+  case CKM_ECDSA_SHA512:
+    if (key_type != CKK_EC)
+      lose(CKR_KEY_TYPE_INCONSISTENT);
+    break;
+  default:
+    return CKR_MECHANISM_INVALID;
+  }
 
   session->verify_key_handle = hKey;
 
   switch (pMechanism->mechanism) {
-  case CKM_RSA_PKCS:            session->verify_digest_descriptor = NULL;               break;
-  case CKM_SHA1_RSA_PKCS:       session->verify_digest_descriptor = hal_hash_sha1;      break;
-  case CKM_SHA256_RSA_PKCS:     session->verify_digest_descriptor = hal_hash_sha256;    break;
-  case CKM_SHA384_RSA_PKCS:     session->verify_digest_descriptor = hal_hash_sha384;    break;
-  case CKM_SHA512_RSA_PKCS:     session->verify_digest_descriptor = hal_hash_sha512;	break;
-  default:                      return CKR_MECHANISM_INVALID;
+  case CKM_RSA_PKCS:
+  case CKM_ECDSA:
+    session->verify_digest_descriptor = NULL;
+    break;
+  case CKM_SHA1_RSA_PKCS:
+    session->verify_digest_descriptor = hal_hash_sha1;
+    break;
+  case CKM_SHA256_RSA_PKCS:
+  case CKM_ECDSA_SHA256:
+    session->verify_digest_descriptor = hal_hash_sha256;
+    break;
+  case CKM_SHA384_RSA_PKCS:
+  case CKM_ECDSA_SHA384:
+    session->verify_digest_descriptor = hal_hash_sha384;
+    break;
+  case CKM_SHA512_RSA_PKCS:
+  case CKM_ECDSA_SHA512:
+    session->verify_digest_descriptor = hal_hash_sha512;
+    break;
+  default:
+    return CKR_MECHANISM_INVALID;
   }
 
   return mutex_unlock(p11_global_mutex);
@@ -3282,6 +3621,7 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession,
    * From here down this function is RSA-specific, and will need
    * rewriting when we add support for other algorithms.
    */
+#warning RSA-specific
 
   if (!p11_object_get_rsa_public_key(session->verify_key_handle,
                                      &key, keybuf, sizeof(keybuf)))
@@ -3354,10 +3694,23 @@ CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession,
   switch (pMechanism->mechanism) {
 
   case CKM_RSA_PKCS_KEY_PAIR_GEN:
-    rv = generate_keypair_rsa_pkcs(session, pMechanism,
-                                   pPublicKeyTemplate, ulPublicKeyAttributeCount,
-                                   pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
-                                   phPublicKey, phPrivateKey);
+    rv = generate_keypair(session, pMechanism,
+                          pPublicKeyTemplate, ulPublicKeyAttributeCount,
+                          pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+                          phPublicKey, phPrivateKey,
+                          generate_keypair_rsa_pkcs,
+                          &p11_descriptor_rsa_public_key,
+                          &p11_descriptor_rsa_private_key);
+    break;
+
+  case CKM_EC_KEY_PAIR_GEN:
+    rv = generate_keypair(session, pMechanism,
+                          pPublicKeyTemplate, ulPublicKeyAttributeCount,
+                          pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+                          phPublicKey, phPrivateKey,
+                          generate_keypair_ec,
+                          &p11_descriptor_ec_public_key,
+                          &p11_descriptor_ec_private_key);
     break;
 
   default:
@@ -3412,6 +3765,8 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
 
   const CK_ULONG rsa_key_min = 1024;
   const CK_ULONG rsa_key_max = 8192;
+  const CK_ULONG ec_key_min  = 256;
+  const CK_ULONG ec_key_max  = 521;
 
   /*
    * No locking here, no obvious need for it.
@@ -3428,6 +3783,7 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
   case CKM_SHA_1:
   case CKM_SHA1_RSA_PKCS:
   case CKM_SHA_1_HMAC:
+  case CKM_ECDSA_SHA1:
     if (hal_hash_core_present(hal_hash_sha1) != HAL_OK)
       return CKR_MECHANISM_INVALID;
     break;
@@ -3435,6 +3791,7 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
   case CKM_SHA256:
   case CKM_SHA256_RSA_PKCS:
   case CKM_SHA256_HMAC:
+  case CKM_ECDSA_SHA256:
     if (hal_hash_core_present(hal_hash_sha256) != HAL_OK)
       return CKR_MECHANISM_INVALID;
     break;
@@ -3442,6 +3799,7 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
   case CKM_SHA384:
   case CKM_SHA384_RSA_PKCS:
   case CKM_SHA384_HMAC:
+  case CKM_ECDSA_SHA384:
     if (hal_hash_core_present(hal_hash_sha384) != HAL_OK)
       return CKR_MECHANISM_INVALID;
     break;
@@ -3449,6 +3807,7 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
   case CKM_SHA512:
   case CKM_SHA512_RSA_PKCS:
   case CKM_SHA512_HMAC:
+  case CKM_ECDSA_SHA512:
     if (hal_hash_core_present(hal_hash_sha512) != HAL_OK)
       return CKR_MECHANISM_INVALID;
     break;
@@ -3465,6 +3824,12 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
     pInfo->flags = CKF_HW | CKF_GENERATE_KEY_PAIR;
     break;
 
+  case CKM_EC_KEY_PAIR_GEN:
+    pInfo->ulMinKeySize = ec_key_min;
+    pInfo->ulMaxKeySize = ec_key_max;
+    pInfo->flags = CKF_HW | CKF_GENERATE_KEY_PAIR | CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS;
+    break;
+
   case CKM_RSA_PKCS:
   case CKM_SHA1_RSA_PKCS:
   case CKM_SHA256_RSA_PKCS:
@@ -3475,6 +3840,15 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
     pInfo->flags = CKF_HW | CKF_SIGN | CKF_VERIFY;
     break;
 
+  case CKM_ECDSA:
+  case CKM_ECDSA_SHA256:
+  case CKM_ECDSA_SHA384:
+  case CKM_ECDSA_SHA512:
+    pInfo->ulMinKeySize = ec_key_min;
+    pInfo->ulMaxKeySize = ec_key_max;
+    pInfo->flags = CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS;
+    break;
+
   case CKM_SHA_1:
   case CKM_SHA256:
   case CKM_SHA384:



More information about the Commits mailing list