[Cryptech-Commits] [sw/pkcs11] 04/14: Refactor C_Sign() and C_Verify() to move algorithm-dependent code to helper functions. As a happy side effect, this also simplifies locking slightly and gives us a straightforward path towards the *Update() and *Final() incremental-hashing functions. Compiles, not yet tested.

git at cryptech.is git at cryptech.is
Mon Sep 14 21:43:55 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 0e0a9ea70f629387f869b7fad18a819d2669ff00
Author: Rob Austein <sra at hactrn.net>
Date:   Wed Sep 9 15:13:20 2015 -0400

    Refactor C_Sign() and C_Verify() to move algorithm-dependent code to
    helper functions.  As a happy side effect, this also simplifies
    locking slightly and gives us a straightforward path towards the
    *Update() and *Final() incremental-hashing functions.
    Compiles, not yet tested.
---
 pkcs11.c | 279 ++++++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 152 insertions(+), 127 deletions(-)

diff --git a/pkcs11.c b/pkcs11.c
index 36ecefc..646d15f 100644
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -2103,17 +2103,42 @@ static CK_RV generate_keypair(p11_session_t *session,
 

 
 /*
+ * Add data to a digest.
+ */
+
+static CK_RV digest_update(const hal_hash_descriptor_t * const descriptor,
+                           hal_hash_state_t **state,
+                           const uint8_t * const data, const size_t data_len)
+{
+  assert(descriptor != NULL && state != NULL && data != NULL);
+
+  if (*state == NULL) {
+    switch (hal_hash_initialize(descriptor, state, NULL, 0)) {
+    case HAL_OK:
+      break;
+    case HAL_ERROR_ALLOCATION_FAILURE:
+      return CKR_HOST_MEMORY;
+    default:
+      return CKR_FUNCTION_FAILED;
+    }
+  }
+
+  if (!hal_check(hal_hash_update(*state, data, data_len)))
+    return CKR_FUNCTION_FAILED;
+
+  return CKR_OK;
+}
+
+/*
  * Construct a PKCS #1 DigestInfo object.  This requires some (very
  * basic) ASN.1 encoding, which we perform inline.
  */
 
 static int pkcs1_construct_digestinfo(const hal_hash_descriptor_t * const desc,
-                                      const uint8_t * const data, const size_t data_len,
+                                      hal_hash_state_t *state,
                                       uint8_t *digest_info, const size_t digest_info_len)
 {
-  uint8_t statebuf[desc->hash_state_length];
-  hal_hash_state_t *state = NULL;
-  uint8_t *d = digest_info;
+  assert(desc != NULL && state != NULL && digest_info != NULL);
 
   /*
    * Make sure size of output buffer is right.  Caller is responsible
@@ -2127,6 +2152,8 @@ static int pkcs1_construct_digestinfo(const hal_hash_descriptor_t * const desc,
   assert(digest_info_len == desc->digest_length + desc->digest_algorithm_id_length + 4);
   assert(digest_info_len < 130);
 
+  uint8_t *d = digest_info;
+
   *d++ = 0x30;                /* SEQUENCE */
   *d++ = (uint8_t) (digest_info_len - 2);
 
@@ -2138,14 +2165,7 @@ static int pkcs1_construct_digestinfo(const hal_hash_descriptor_t * const desc,
 
   assert(digest_info + digest_info_len == d + desc->digest_length);
 
-  const int ok = (hal_check(hal_hash_initialize(desc, &state, statebuf, sizeof(statebuf))) &&
-                  hal_check(hal_hash_update(state, data, data_len))                        &&
-                  hal_check(hal_hash_finalize(state, d, desc->digest_length)));
-
-  memset(statebuf, 0, sizeof(statebuf));
-  if (!ok)
-    memset(digest_info, 0, digest_info_len);
-  return ok;
+  return hal_check(hal_hash_finalize(state, d, desc->digest_length));
 }
 
 /*
@@ -2195,31 +2215,70 @@ static int pkcs1_5_pad(const uint8_t * const data, const size_t data_len,
 }
 
 /*
- * Sign a PKCS #1 DigestInfo using an RSA key and PKCS #1.5 padding.
+ * Generate an RSA PKCS #1.5 signature.
  *
  * As explained in RFC 3447, the RSASP1 (signature generation)
  * operation is the same mathematical operation as the RSADP
  * (decryption) operation (both use the private key as exponent).
  */
 
-static CK_RV sign_rsa_pkcs(const hal_rsa_key_t * const key,
-                           const uint8_t * const digest_info, const size_t digest_info_len,
-                           uint8_t *signature, const size_t signature_len)
+static CK_RV sign_rsa_pkcs(p11_session_t *session,
+                           CK_BYTE_PTR pData,
+                           CK_ULONG ulDataLen,
+                           CK_BYTE_PTR pSignature,
+                           CK_ULONG_PTR pulSignatureLen)
 {
+  uint8_t keybuf[hal_rsa_key_t_size];
+  hal_rsa_key_t *key = NULL;
+  size_t signature_len;
   CK_RV rv;
 
-  assert(digest_info != NULL && signature != NULL);
+  assert(session != NULL && pulSignatureLen != NULL);
 
-  if (!pkcs1_5_pad(digest_info, digest_info_len, signature, signature_len))
-    lose(CKR_DATA_LEN_RANGE);
+  const hal_hash_descriptor_t * const desc = session->sign_digest_descriptor;
+  const size_t digest_info_len = desc == NULL ? 1 : desc->digest_length + 4 + desc->digest_algorithm_id_length;
+  uint8_t digest_info[digest_info_len];
 
-  if (!hal_check(hal_rsa_decrypt(key, signature, signature_len, signature, signature_len)))
+  if (!p11_object_get_rsa_private_key(session->sign_key_handle,
+                                      &key, keybuf, sizeof(keybuf)))
     lose(CKR_FUNCTION_FAILED);
 
-  return CKR_OK;
+  /*
+   * Retrieve signature length, which is just the the modulus length.
+   */
+
+  if (!hal_check(hal_rsa_key_get_modulus(key, NULL, &signature_len, 0)))
+    lose(CKR_FUNCTION_FAILED);
+
+  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 (!pkcs1_construct_digestinfo(desc, session->sign_digest_state, digest_info, sizeof(digest_info)))
+      lose(CKR_FUNCTION_FAILED);
+
+    pData = digest_info;
+    ulDataLen = sizeof(digest_info);
+  }
+
+  if (pSignature != NULL) {
+
+    if (!pkcs1_5_pad(pData, ulDataLen, pSignature, signature_len))
+      lose(CKR_DATA_LEN_RANGE);
+
+    if (!hal_check(hal_rsa_decrypt(key, pSignature, signature_len, pSignature, signature_len)))
+      lose(CKR_FUNCTION_FAILED);
+  }
+
+  rv = CKR_OK;                  /* Fall through */
 
  fail:
-  memset(signature, 0, signature_len);
+  hal_rsa_key_clear(key);
   return rv;
 }
 
@@ -2233,37 +2292,59 @@ static CK_RV sign_rsa_pkcs(const hal_rsa_key_t * const key,
  * unnecessary, but it's also harmless.
  */
 
-static CK_RV verify_rsa_pkcs(const hal_rsa_key_t * const key,
-                             const uint8_t * const digest_info, const size_t digest_info_len,
-                             const uint8_t * const signature, const size_t signature_len)
+CK_RV verify_rsa_pkcs(p11_session_t *session,
+                      CK_BYTE_PTR pData,
+                      CK_ULONG ulDataLen,
+                      CK_BYTE_PTR pSignature,
+                      CK_ULONG ulSignatureLen)
 {
-  assert(digest_info != NULL && signature != NULL);
+  uint8_t keybuf[hal_rsa_key_t_size];
+  hal_rsa_key_t *key = NULL;
+  CK_RV rv;
+
+  assert(session != NULL);
 
-  uint8_t expected[signature_len], received[signature_len];
+  const hal_hash_descriptor_t * const desc = session->verify_digest_descriptor;
+  const size_t digest_info_len = desc == NULL ? 1 : desc->digest_length + 4 + desc->digest_algorithm_id_length;
+  uint8_t digest_info[digest_info_len];
+  uint8_t expected[ulSignatureLen], received[ulSignatureLen];
   unsigned diff = 0;
-  CK_RV rv;
 
-  if (!pkcs1_5_pad(digest_info, digest_info_len, expected, sizeof(expected)))
+  if (!p11_object_get_rsa_public_key(session->verify_key_handle,
+                                     &key, keybuf, sizeof(keybuf)))
+    lose(CKR_FUNCTION_FAILED);
+
+  if (session->verify_digest_descriptor != NULL) {
+
+    if (!pkcs1_construct_digestinfo(session->verify_digest_descriptor,
+                                    session->verify_digest_state,
+                                    digest_info, sizeof(digest_info)))
+      lose(CKR_FUNCTION_FAILED);
+
+    pData = digest_info;
+    ulSignatureLen = sizeof(digest_info);
+
+  }
+
+  if (!pkcs1_5_pad(pData, ulDataLen, expected, sizeof(expected)))
     lose(CKR_DATA_LEN_RANGE);
 
-  if (!hal_check(hal_rsa_encrypt(key, signature, signature_len, received, sizeof(received))))
+  if (!hal_check(hal_rsa_encrypt(key, pSignature, ulSignatureLen, received, sizeof(received))))
     lose(CKR_FUNCTION_FAILED);
 
-  for (int i = 0; i < signature_len; i++)
+  for (int i = 0; i < ulSignatureLen; i++)
     diff |= expected[i] ^ received[i];
 
   if (diff != 0)
     lose(CKR_SIGNATURE_INVALID);
 
-  rv = CKR_OK;
+  rv = CKR_OK;                  /* Fall through */
 
  fail:
-  memset(expected, 0, sizeof(expected));
-  memset(received, 0, sizeof(received));
+  hal_rsa_key_clear(key);
   return rv;
 }
 
-
 

 
 /*
@@ -3347,17 +3428,10 @@ CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession,
   if (!session->digest_descriptor->can_restore_state)
     lose(CKR_FUNCTION_FAILED);
 
-  if (session->digest_state == NULL) {
-    hal_error_t err = hal_hash_initialize(session->digest_descriptor,
-                                          &session->digest_state, NULL, 0);
-    if (err == HAL_ERROR_ALLOCATION_FAILURE)
-      lose(CKR_HOST_MEMORY);
-    else if (err != HAL_OK)
-      lose(CKR_FUNCTION_FAILED);    
-  }
-
-  if (!hal_check(hal_hash_update(session->digest_state, pPart, ulPartLen)))
-    lose(CKR_FUNCTION_FAILED);
+  if ((rv = digest_update(session->digest_descriptor,
+                          &session->digest_state,
+                          pPart, ulPartLen)) != CKR_OK)
+    goto fail;
 
   return mutex_unlock(p11_global_mutex);
 
@@ -3511,10 +3585,8 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
 {
   ENTER_PUBLIC_FUNCTION(C_Sign);
 
-  uint8_t keybuf[hal_rsa_key_t_size];
-  hal_rsa_key_t *key = NULL;
   p11_session_t *session;
-  size_t signature_len;
+  CK_KEY_TYPE key_type;
   CK_RV rv;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -3528,67 +3600,35 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
   if (session->sign_key_handle == CK_INVALID_HANDLE)
     lose(CKR_OPERATION_NOT_INITIALIZED);
 
-  /*
-   * 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)))
-    lose(CKR_FUNCTION_FAILED);
+  if (session->sign_digest_state != NULL)
+    lose(CKR_OPERATION_ACTIVE);
 
-  /*
-   * Retrieve signature length.  For RSA this is just the modulus
-   * length, other algorithms will need a more generic solution.
-   */
-#warning RSA-specific
+  if (session->sign_digest_descriptor != NULL &&
+      (rv = digest_update(session->sign_digest_descriptor,
+                          &session->sign_digest_state, pData, ulDataLen)) != CKR_OK)
+    goto fail;
 
-  if (!hal_check(hal_rsa_key_get_modulus(key, NULL, &signature_len, 0)))
+  if (!p11_attribute_get_ulong(session->sign_key_handle, CKA_KEY_TYPE, &key_type))
     lose(CKR_FUNCTION_FAILED);
 
-  rv = signature_len > *pulSignatureLen ? CKR_BUFFER_TOO_SMALL : CKR_OK;
-
-  *pulSignatureLen = signature_len;
-
-  if (pSignature == NULL) {
-    hal_rsa_key_clear(key);
-    return mutex_unlock(p11_global_mutex);
-  }
-
-  if (rv == CKR_BUFFER_TOO_SMALL)
-    lose(CKR_BUFFER_TOO_SMALL);
+  switch (key_type) {
 
-  if (session->sign_digest_descriptor != NULL) {
-    uint8_t digest_info[session->sign_digest_descriptor->digest_length + 4 +
-                        session->sign_digest_descriptor->digest_algorithm_id_length];
-
-    if (!pkcs1_construct_digestinfo(session->sign_digest_descriptor,
-                                    pData, ulDataLen, digest_info, sizeof(digest_info)))
-      lose(CKR_FUNCTION_FAILED);
-
-    rv = sign_rsa_pkcs(key, digest_info, sizeof(digest_info), pSignature, signature_len);
-    memset(digest_info, 0, sizeof(digest_info));
-    if (rv != CKR_OK)
-      goto fail;
-  }
+  case CKK_RSA:
+    rv = sign_rsa_pkcs(session, pData, ulDataLen, pSignature, pulSignatureLen);
+    break;
 
-  else {
-    if ((rv = sign_rsa_pkcs(key, pData, ulDataLen, pSignature, signature_len)) != CKR_OK)
-      goto fail;
+  default:
+    lose(CKR_FUNCTION_FAILED);
   }
 
-  rv = CKR_OK;                  /* Fall through */
+ fail:                          /* Fall through */
 
- fail:
-
-  if (session != NULL) {
+  if (session != NULL && pSignature != NULL) {
     session->sign_key_handle = CK_INVALID_HANDLE;
     session->sign_digest_descriptor = NULL;
+    hal_hash_cleanup(&session->sign_digest_state);
   }
 
-  hal_rsa_key_clear(key);
-
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
 
@@ -3691,9 +3731,8 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession,
 {
   ENTER_PUBLIC_FUNCTION(C_Verify);
 
-  uint8_t keybuf[hal_rsa_key_t_size];
-  hal_rsa_key_t *key = NULL;
   p11_session_t *session;
+  CK_KEY_TYPE key_type;
   CK_RV rv;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -3707,46 +3746,32 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession,
   if (session->verify_key_handle == CK_INVALID_HANDLE)
     lose(CKR_OPERATION_NOT_INITIALIZED);
 
-  /*
-   * From here down this function is RSA-specific, and will need
-   * rewriting when we add support for other algorithms.
-   */
-#warning RSA-specific
+  if (session->verify_digest_descriptor != NULL &&
+      (rv = digest_update(session->verify_digest_descriptor,
+                          &session->verify_digest_state, pData, ulDataLen)) != CKR_OK)
+    goto fail;
 
-  if (!p11_object_get_rsa_public_key(session->verify_key_handle,
-                                     &key, keybuf, sizeof(keybuf)))
+  if (!p11_attribute_get_ulong(session->verify_key_handle, CKA_KEY_TYPE, &key_type))
     lose(CKR_FUNCTION_FAILED);
 
-  if (session->verify_digest_descriptor != NULL) {
-    uint8_t digest_info[session->verify_digest_descriptor->digest_length + 4 +
-                        session->verify_digest_descriptor->digest_algorithm_id_length];
+  switch (key_type) {
 
-    if (!pkcs1_construct_digestinfo(session->verify_digest_descriptor,
-                                    pData, ulDataLen, digest_info, sizeof(digest_info)))
-      lose(CKR_FUNCTION_FAILED);
-
-    rv = verify_rsa_pkcs(key, digest_info, sizeof(digest_info), pSignature, ulSignatureLen);
-    memset(digest_info, 0, sizeof(digest_info));
-    if (rv != CKR_OK)
-      goto fail;
-  }
+  case CKK_RSA:
+    rv = verify_rsa_pkcs(session, pData, ulDataLen, pSignature, ulSignatureLen);
+    break;
 
-  else {
-    if ((rv = verify_rsa_pkcs(key, pData, ulDataLen, pSignature, ulSignatureLen)) != CKR_OK)
-      goto fail;
+  default:
+    lose(CKR_FUNCTION_FAILED);
   }
-
-  rv = CKR_OK;                  /* Fall through */
-
- fail:
+  
+ fail:                          /* Fall through */
 
   if (session != NULL) {
     session->verify_key_handle = CK_INVALID_HANDLE;
     session->verify_digest_descriptor = NULL;
+    hal_hash_cleanup(&session->verify_digest_state);
   }
 
-  hal_rsa_key_clear(key);
-
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
 



More information about the Commits mailing list