aboutsummaryrefslogtreecommitdiff
path: root/pkcs11.c
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2015-09-09 15:13:20 -0400
committerRob Austein <sra@hactrn.net>2015-09-09 15:13:20 -0400
commit0e0a9ea70f629387f869b7fad18a819d2669ff00 (patch)
tree626cc15980b6f96e87d68e5bb60830d00c579b8e /pkcs11.c
parent22a1a599999109e797fa340c462b7a0f874cbb37 (diff)
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.
Diffstat (limited to 'pkcs11.c')
-rw-r--r--pkcs11.c279
1 files 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);
}