aboutsummaryrefslogtreecommitdiff
path: root/pkcs11.c
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2015-09-09 17:21:47 -0400
committerRob Austein <sra@hactrn.net>2015-09-09 17:21:47 -0400
commit6a80ee51ba03fd8958c566882922ddb4df39c7cd (patch)
tree73d90ca697e2642aaa632f0dcb5c584143b048e0 /pkcs11.c
parent0e0a9ea70f629387f869b7fad18a819d2669ff00 (diff)
Add ECDSA signature and verification. Compiles, not tested.
Diffstat (limited to 'pkcs11.c')
-rw-r--r--pkcs11.c124
1 files changed, 123 insertions, 1 deletions
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);
}