[Cryptech-Commits] [sw/pkcs11] 05/14: Add ECDSA signature and verification. Compiles, not tested.

git at cryptech.is git at cryptech.is
Mon Sep 14 21:43:56 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 6a80ee51ba03fd8958c566882922ddb4df39c7cd
Author: Rob Austein <sra at hactrn.net>
Date:   Wed Sep 9 17:21:47 2015 -0400

    Add ECDSA signature and verification.  Compiles, not tested.
---
 pkcs11.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 123 insertions(+), 1 deletion(-)

diff --git a/pkcs11.c b/pkcs11.c
index 646d15f..6a83127 100644
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -2322,7 +2322,7 @@ CK_RV verify_rsa_pkcs(p11_session_t *session,
       lose(CKR_FUNCTION_FAILED);
 
     pData = digest_info;
-    ulSignatureLen = sizeof(digest_info);
+    ulDataLen = sizeof(digest_info);
 
   }
 
@@ -2345,6 +2345,120 @@ CK_RV verify_rsa_pkcs(p11_session_t *session,
   return rv;
 }
 
+#warning May need to do something about truncating oversized hashes for ECDSA, see PKCS11 spec
+
+/*
+ * Generate an ECDSA signature.
+ */
+
+static CK_RV sign_ecdsa(p11_session_t *session,
+                        CK_BYTE_PTR pData,
+                        CK_ULONG ulDataLen,
+                        CK_BYTE_PTR pSignature,
+                        CK_ULONG_PTR pulSignatureLen)
+{
+  uint8_t keybuf[hal_ecdsa_key_t_size];
+  hal_ecdsa_key_t *key = NULL;
+  hal_ecdsa_curve_t curve;
+  size_t signature_len;
+  CK_RV rv;
+
+  assert(session != NULL && pulSignatureLen != NULL);
+
+  const hal_hash_descriptor_t * const desc = session->sign_digest_descriptor;
+  const size_t digest_len = desc == NULL ? 1 : desc->digest_length;
+  uint8_t digest[digest_len];
+
+  if (!p11_object_get_ec_private_key(session->sign_key_handle, &key, keybuf, sizeof(keybuf)))
+    lose(CKR_FUNCTION_FAILED);
+
+  /*
+   * Signature length is determined by curve parameters.
+   */
+
+  if (!hal_check(hal_ecdsa_key_get_curve(key, &curve)))
+    lose(CKR_FUNCTION_FAILED);
+
+  switch (curve) {
+  case HAL_ECDSA_CURVE_P256: signature_len = 256; break;
+  case HAL_ECDSA_CURVE_P384: signature_len = 384; break;
+  case HAL_ECDSA_CURVE_P521: signature_len = 521; break;
+  default: lose(CKR_FUNCTION_FAILED);
+  }
+
+  signature_len = ((signature_len + 7) / 8) * 2;
+
+  rv = signature_len > *pulSignatureLen ? CKR_BUFFER_TOO_SMALL : CKR_OK;
+
+  *pulSignatureLen = signature_len;
+
+  if (pSignature != NULL && rv == CKR_BUFFER_TOO_SMALL)
+    lose(CKR_BUFFER_TOO_SMALL);
+
+  if (pSignature != NULL && desc != NULL) {
+
+    if (!hal_check(hal_hash_finalize(session->sign_digest_state, digest, sizeof(digest))))
+      lose(CKR_FUNCTION_FAILED);
+
+    pData = digest;
+    ulDataLen = sizeof(digest);
+  }
+
+  if (pSignature != NULL && !hal_check(hal_ecdsa_sign(key, pData, ulDataLen,
+                                                      pSignature, pulSignatureLen, *pulSignatureLen,
+                                                      HAL_ECDSA_SIGNATURE_FORMAT_PKCS11)))
+    lose(CKR_FUNCTION_FAILED);
+
+  rv = CKR_OK;                  /* Fall through */
+
+ fail:
+  hal_ecdsa_key_clear(key);
+  return rv;
+}
+
+/*
+ * Verify an ECDSA signature.
+ */
+
+static CK_RV verify_ecdsa(p11_session_t *session,
+                          CK_BYTE_PTR pData,
+                          CK_ULONG ulDataLen,
+                          CK_BYTE_PTR pSignature,
+                          CK_ULONG ulSignatureLen)
+{
+  uint8_t keybuf[hal_ecdsa_key_t_size];
+  hal_ecdsa_key_t *key = NULL;
+  CK_RV rv;
+
+  assert(session != NULL && pSignature != NULL);
+
+  const hal_hash_descriptor_t * const desc = session->verify_digest_descriptor;
+  const size_t digest_len = desc == NULL ? 1 : desc->digest_length;
+  uint8_t digest[digest_len];
+
+  if (!p11_object_get_ec_public_key(session->verify_key_handle, &key, keybuf, sizeof(keybuf)))
+    lose(CKR_FUNCTION_FAILED);
+
+  if (session->verify_digest_descriptor != NULL) {
+
+    if (!hal_check(hal_hash_finalize(session->verify_digest_state, digest, sizeof(digest))))
+      lose(CKR_FUNCTION_FAILED);
+
+    pData = digest;
+    ulDataLen = sizeof(digest);
+
+  }
+
+  if (!hal_check(hal_ecdsa_verify(key, pData, ulDataLen, pSignature, ulSignatureLen, HAL_ECDSA_SIGNATURE_FORMAT_PKCS11)))
+    lose(CKR_SIGNATURE_INVALID);
+
+  rv = CKR_OK;                  /* Fall through */
+
+ fail:
+  hal_ecdsa_key_clear(key);
+  return rv;
+}
+
 

 
 /*
@@ -3617,6 +3731,10 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
     rv = sign_rsa_pkcs(session, pData, ulDataLen, pSignature, pulSignatureLen);
     break;
 
+  case CKK_EC:
+    rv = sign_ecdsa(session, pData, ulDataLen, pSignature, pulSignatureLen);
+    break;
+
   default:
     lose(CKR_FUNCTION_FAILED);
   }
@@ -3760,6 +3878,10 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession,
     rv = verify_rsa_pkcs(session, pData, ulDataLen, pSignature, ulSignatureLen);
     break;
 
+  case CKK_EC:
+    rv = verify_ecdsa(session, pData, ulDataLen, pSignature, ulSignatureLen);
+    break;
+
   default:
     lose(CKR_FUNCTION_FAILED);
   }



More information about the Commits mailing list