mozilla-nss/nss-fips-combined-hash-sign-dsa-ecdsa.patch

354 lines
13 KiB
Diff

From 7f3606a84f6c62b002246ee73121279e59f83437 Mon Sep 17 00:00:00 2001
From: Hans Petter Jansson <hpj@cl.no>
Date: Thu, 28 May 2020 22:44:22 +0200
Subject: [PATCH] CKM_(EC)DSA_SHAxxx mechs: Add some missing pieces.
This includes pairwise consistency checks and entry points for
power-on self tests.
---
cmd/lib/pk11table.c | 8 ++
lib/pk11wrap/pk11mech.c | 8 ++
lib/softoken/pkcs11c.c | 213 +++++++++++++++++++++++++++-------------
lib/softoken/softoken.h | 10 ++
4 files changed, 169 insertions(+), 70 deletions(-)
Index: nss/cmd/lib/pk11table.c
===================================================================
--- nss.orig/cmd/lib/pk11table.c
+++ nss/cmd/lib/pk11table.c
@@ -274,6 +274,10 @@ const Constant _consts[] = {
mkEntry(CKM_DSA_KEY_PAIR_GEN, Mechanism),
mkEntry(CKM_DSA, Mechanism),
mkEntry(CKM_DSA_SHA1, Mechanism),
+ mkEntry(CKM_DSA_SHA224, Mechanism),
+ mkEntry(CKM_DSA_SHA256, Mechanism),
+ mkEntry(CKM_DSA_SHA384, Mechanism),
+ mkEntry(CKM_DSA_SHA512, Mechanism),
mkEntry(CKM_DH_PKCS_KEY_PAIR_GEN, Mechanism),
mkEntry(CKM_DH_PKCS_DERIVE, Mechanism),
mkEntry(CKM_X9_42_DH_DERIVE, Mechanism),
@@ -439,6 +443,10 @@ const Constant _consts[] = {
mkEntry(CKM_EC_KEY_PAIR_GEN, Mechanism),
mkEntry(CKM_ECDSA, Mechanism),
mkEntry(CKM_ECDSA_SHA1, Mechanism),
+ mkEntry(CKM_ECDSA_SHA224, Mechanism),
+ mkEntry(CKM_ECDSA_SHA256, Mechanism),
+ mkEntry(CKM_ECDSA_SHA384, Mechanism),
+ mkEntry(CKM_ECDSA_SHA512, Mechanism),
mkEntry(CKM_ECDH1_DERIVE, Mechanism),
mkEntry(CKM_ECDH1_COFACTOR_DERIVE, Mechanism),
mkEntry(CKM_EC_EDWARDS_KEY_PAIR_GEN, Mechanism),
Index: nss/lib/pk11wrap/pk11mech.c
===================================================================
--- nss.orig/lib/pk11wrap/pk11mech.c
+++ nss/lib/pk11wrap/pk11mech.c
@@ -377,6 +377,10 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type,
return CKK_RSA;
case CKM_DSA:
case CKM_DSA_SHA1:
+ case CKM_DSA_SHA224:
+ case CKM_DSA_SHA256:
+ case CKM_DSA_SHA384:
+ case CKM_DSA_SHA512:
case CKM_DSA_KEY_PAIR_GEN:
return CKK_DSA;
case CKM_DH_PKCS_DERIVE:
@@ -387,6 +391,10 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type,
return CKK_KEA;
case CKM_ECDSA:
case CKM_ECDSA_SHA1:
+ case CKM_ECDSA_SHA224:
+ case CKM_ECDSA_SHA256:
+ case CKM_ECDSA_SHA384:
+ case CKM_ECDSA_SHA512:
case CKM_EC_KEY_PAIR_GEN: /* aka CKM_ECDSA_KEY_PAIR_GEN */
case CKM_ECDH1_DERIVE:
return CKK_EC; /* CKK_ECDSA is deprecated */
Index: nss/lib/softoken/pkcs11c.c
===================================================================
--- nss.orig/lib/softoken/pkcs11c.c
+++ nss/lib/softoken/pkcs11c.c
@@ -2677,7 +2677,7 @@ nsc_DSA_Verify_Stub(void *ctx, void *sig
static SECStatus
nsc_DSA_Sign_Stub(void *ctx, void *sigBuf,
unsigned int *sigLen, unsigned int maxSigLen,
- void *dataBuf, unsigned int dataLen)
+ const void *dataBuf, unsigned int dataLen)
{
NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx;
SECItem signature = { siBuffer, (unsigned char *)sigBuf, maxSigLen };
@@ -2690,6 +2690,22 @@ nsc_DSA_Sign_Stub(void *ctx, void *sigBu
return rv;
}
+SECStatus
+DSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key,
+ unsigned char *sig, unsigned int *sigLen, unsigned int maxLen,
+ const unsigned char *hash, unsigned int hashLen)
+{
+ SECStatus rv;
+
+ rv = nsc_DSA_Sign_Stub(key, sig, sigLen, maxLen, hash, hashLen);
+
+ if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
+ sftk_fatalError = PR_TRUE;
+ }
+
+ return rv;
+}
+
static SECStatus
nsc_ECDSAVerifyStub(void *ctx, void *sigBuf, unsigned int sigLen,
void *dataBuf, unsigned int dataLen)
@@ -2703,7 +2719,7 @@ nsc_ECDSAVerifyStub(void *ctx, void *sig
static SECStatus
nsc_ECDSASignStub(void *ctx, void *sigBuf,
unsigned int *sigLen, unsigned int maxSigLen,
- void *dataBuf, unsigned int dataLen)
+ const void *dataBuf, unsigned int dataLen)
{
NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx;
SECItem signature = { siBuffer, (unsigned char *)sigBuf, maxSigLen };
@@ -2744,6 +2760,22 @@ nsc_EDDSASignStub(void *ctx, void *sigBu
return rv;
}
+SECStatus
+ECDSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key,
+ unsigned char *sig, unsigned int *sigLen, unsigned int maxLen,
+ const unsigned char *hash, unsigned int hashLen)
+{
+ SECStatus rv;
+
+ rv = nsc_ECDSASignStub(key, sig, sigLen, maxLen, hash, hashLen);
+
+ if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
+ sftk_fatalError = PR_TRUE;
+ }
+
+ return rv;
+}
+
/* NSC_SignInit setups up the signing operations. There are three basic
* types of signing:
* (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied
@@ -3647,6 +3679,22 @@ NSC_VerifyInit(CK_SESSION_HANDLE hSessio
info->hashOid = SEC_OID_##mmm; \
goto finish_rsa;
+#define INIT_DSA_VFY_MECH(mmm) \
+ case CKM_DSA_##mmm: \
+ context->multi = PR_TRUE; \
+ crv = sftk_doSub##mmm(context); \
+ if (crv != CKR_OK) \
+ break; \
+ goto finish_dsa;
+
+#define INIT_ECDSA_VFY_MECH(mmm) \
+ case CKM_ECDSA_##mmm: \
+ context->multi = PR_TRUE; \
+ crv = sftk_doSub##mmm(context); \
+ if (crv != CKR_OK) \
+ break; \
+ goto finish_ecdsa;
+
switch (pMechanism->mechanism) {
INIT_RSA_VFY_MECH(MD5)
INIT_RSA_VFY_MECH(MD2)
@@ -4904,6 +4952,73 @@ loser:
#define PAIRWISE_DIGEST_LENGTH SHA224_LENGTH /* 224-bits */
#define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */
+static CK_RV
+pairwise_signverify_mech (CK_SESSION_HANDLE hSession,
+ SFTKObject *publicKey, SFTKObject *privateKey,
+ CK_MECHANISM mech,
+ CK_ULONG signature_length,
+ CK_ULONG pairwise_digest_length)
+{
+ /* Variables used for Signature/Verification functions. */
+ /* Must be at least 256 bits for DSA2 digest */
+ unsigned char *known_digest = (unsigned char *)"Mozilla Rules the World through NSS!";
+ unsigned char *signature;
+ CK_RV crv;
+
+ /* Allocate space for signature data. */
+ signature = (unsigned char *)PORT_ZAlloc(signature_length);
+ if (signature == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+
+ /* Sign the known hash using the private key. */
+ crv = NSC_SignInit(hSession, &mech, privateKey->handle);
+ if (crv != CKR_OK) {
+ PORT_Free(signature);
+ return crv;
+ }
+
+ crv = NSC_Sign(hSession,
+ known_digest,
+ pairwise_digest_length,
+ signature,
+ &signature_length);
+ if (crv != CKR_OK) {
+ PORT_Free(signature);
+ return crv;
+ }
+
+ /* detect trivial signing transforms */
+ if ((signature_length >= pairwise_digest_length) &&
+ (PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0)) {
+ PORT_Free(signature);
+ return CKR_DEVICE_ERROR;
+ }
+
+ /* Verify the known hash using the public key. */
+ crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
+ if (crv != CKR_OK) {
+ PORT_Free(signature);
+ return crv;
+ }
+
+ crv = NSC_Verify(hSession,
+ known_digest,
+ pairwise_digest_length,
+ signature,
+ signature_length);
+
+ /* Free signature data. */
+ PORT_Free(signature);
+
+ if ((crv == CKR_SIGNATURE_LEN_RANGE) ||
+ (crv == CKR_SIGNATURE_INVALID)) {
+ return CKR_GENERAL_ERROR;
+ }
+
+ return crv;
+}
+
/*
* FIPS 140-2 pairwise consistency check utilized to validate key pair.
*
@@ -4957,8 +5072,6 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
/* Variables used for Signature/Verification functions. */
/* Must be at least 256 bits for DSA2 digest */
- unsigned char *known_digest = (unsigned char *)"Mozilla Rules the World through NSS!";
- unsigned char *signature;
CK_ULONG signature_length;
if (keyType == CKK_RSA) {
@@ -5112,80 +5225,36 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
}
}
+#define SIGNVERIFY_CHECK_MECH(vfymech) \
+ mech.mechanism = vfymech; \
+ crv = pairwise_signverify_mech (hSession, publicKey, privateKey, \
+ mech, signature_length, pairwise_digest_length); \
+ if (crv != CKR_OK) \
+ return crv;
+
if (canSignVerify) {
- /* Determine length of signature. */
switch (keyType) {
case CKK_RSA:
signature_length = modulusLen;
- mech.mechanism = CKM_RSA_PKCS;
+ SIGNVERIFY_CHECK_MECH(CKM_SHA224_RSA_PKCS)
break;
case CKK_DSA:
signature_length = DSA_MAX_SIGNATURE_LEN;
pairwise_digest_length = subPrimeLen;
- mech.mechanism = CKM_DSA;
+ SIGNVERIFY_CHECK_MECH(CKM_DSA_SHA224)
break;
case CKK_EC:
signature_length = MAX_ECKEY_LEN * 2;
- mech.mechanism = CKM_ECDSA;
+ SIGNVERIFY_CHECK_MECH(CKM_ECDSA_SHA224)
break;
case CKK_EC_EDWARDS:
signature_length = ED25519_SIGN_LEN;
- mech.mechanism = CKM_EDDSA;
+ SIGNVERIFY_CHECK_MECH(CKM_EDDSA)
break;
default:
return CKR_DEVICE_ERROR;
}
- /* Allocate space for signature data. */
- signature = (unsigned char *)PORT_ZAlloc(signature_length);
- if (signature == NULL) {
- return CKR_HOST_MEMORY;
- }
-
- /* Sign the known hash using the private key. */
- crv = NSC_SignInit(hSession, &mech, privateKey->handle);
- if (crv != CKR_OK) {
- PORT_Free(signature);
- return crv;
- }
-
- crv = NSC_Sign(hSession,
- known_digest,
- pairwise_digest_length,
- signature,
- &signature_length);
- if (crv != CKR_OK) {
- PORT_Free(signature);
- return crv;
- }
-
- /* detect trivial signing transforms */
- if ((signature_length >= pairwise_digest_length) &&
- (PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0)) {
- PORT_Free(signature);
- return CKR_DEVICE_ERROR;
- }
-
- /* Verify the known hash using the public key. */
- crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
- if (crv != CKR_OK) {
- PORT_Free(signature);
- return crv;
- }
-
- crv = NSC_Verify(hSession,
- known_digest,
- pairwise_digest_length,
- signature,
- signature_length);
-
- /* Free signature data. */
- PORT_Free(signature);
-
- if ((crv == CKR_SIGNATURE_LEN_RANGE) ||
- (crv == CKR_SIGNATURE_INVALID)) {
- return CKR_GENERAL_ERROR;
- }
if (crv != CKR_OK) {
return crv;
}
Index: nss/lib/softoken/softoken.h
===================================================================
--- nss.orig/lib/softoken/softoken.h
+++ nss/lib/softoken/softoken.h
@@ -35,6 +35,16 @@ RSA_HashCheckSign(SECOidTag hashOid, NSS
const unsigned char *sig, unsigned int sigLen,
const unsigned char *hash, unsigned int hashLen);
+extern SECStatus
+DSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key,
+ unsigned char *sig, unsigned int *sigLen, unsigned int maxLen,
+ const unsigned char *hash, unsigned int hashLen);
+
+extern SECStatus
+ECDSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key,
+ unsigned char *sig, unsigned int *sigLen, unsigned int maxLen,
+ const unsigned char *hash, unsigned int hashLen);
+
/*
** Prepare a buffer for padded CBC encryption, growing to the appropriate
** boundary, filling with the appropriate padding.