Commit 1bfef46c authored by Daiki Ueno's avatar Daiki Ueno

Bug 1400844, Implement handling of RSA-PSS signatures on certificates, r=mt

This series adds high level API to sign and verify RSA-PSS signatures on certificates and utilizes them in tools.

--HG--
extra : amend_source : 86724b58ef34574b980d8daaf494183b154c761c
parent d6ffd9c9
This diff is collapsed.
......@@ -1312,15 +1312,12 @@ SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m, int level)
return;
}
if (algtag == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
secu_PrintRSAPSSParams(out, &a->parameters, "Parameters", level + 1);
return;
}
if (a->parameters.len == 0 ||
(a->parameters.len == 2 &&
PORT_Memcmp(a->parameters.data, "\005\000", 2) == 0)) {
/* No arguments or NULL argument */
} else if (algtag == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
secu_PrintRSAPSSParams(out, &a->parameters, "Parameters", level + 1);
} else {
/* Print args to algorithm */
SECU_PrintAsHex(out, &a->parameters, "Args", level + 1);
......
#! gmake
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
include ../common/gtest.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
{
'includes': [
'../../coreconf/config.gypi',
'../common/gtest.gypi',
],
'targets': [
{
'target_name': 'cryptohi_gtest',
'type': 'executable',
'sources': [
'cryptohi_unittest.cc',
'<(DEPTH)/gtests/common/gtests.cc'
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
'<(DEPTH)/lib/util/util.gyp:nssutil3',
'<(DEPTH)/lib/ssl/ssl.gyp:ssl3',
'<(DEPTH)/lib/nss/nss.gyp:nss3',
]
}
],
'variables': {
'module': 'nss'
}
}
This diff is collapsed.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
CORE_DEPTH = ../..
DEPTH = ../..
MODULE = nss
CPPSRCS = \
cryptohi_unittest.cc \
$(NULL)
INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \
-I$(CORE_DEPTH)/gtests/common \
-I$(CORE_DEPTH)/cpputil
REQUIRES = nspr gtest
PROGRAM = cryptohi_gtest
EXTRA_LIBS = $(DIST)/lib/$(LIB_PREFIX)gtest.$(LIB_SUFFIX) $(EXTRA_OBJS) \
$(DIST)/lib/$(LIB_PREFIX)gtestutil.$(LIB_SUFFIX)
......@@ -21,6 +21,7 @@ ifneq ($(NSS_BUILD_UTIL_ONLY),1)
NSS_SRCDIRS = \
certdb_gtest \
certhigh_gtest \
cryptohi_gtest \
der_gtest \
pk11_gtest \
softoken_gtest \
......
......@@ -29,7 +29,25 @@ TEST_P(TlsConnectGeneric, ServerAuthBigRsa) {
}
TEST_P(TlsConnectGeneric, ServerAuthRsaChain) {
Reset(TlsAgent::kServerRsaChain);
Reset("rsa_chain");
Connect();
CheckKeys();
size_t chain_length;
EXPECT_TRUE(client_->GetPeerChainLength(&chain_length));
EXPECT_EQ(2UL, chain_length);
}
TEST_P(TlsConnectGeneric, ServerAuthRsaPssChain) {
Reset("rsa_pss_chain");
Connect();
CheckKeys();
size_t chain_length;
EXPECT_TRUE(client_->GetPeerChainLength(&chain_length));
EXPECT_EQ(2UL, chain_length);
}
TEST_P(TlsConnectGeneric, ServerAuthRsaCARsaPssChain) {
Reset("rsa_ca_rsa_pss_chain");
Connect();
CheckKeys();
size_t chain_length;
......
......@@ -36,7 +36,6 @@ const std::string TlsAgent::kServerRsa = "rsa"; // both sign and encrypt
const std::string TlsAgent::kServerRsaSign = "rsa_sign";
const std::string TlsAgent::kServerRsaPss = "rsa_pss";
const std::string TlsAgent::kServerRsaDecrypt = "rsa_decrypt";
const std::string TlsAgent::kServerRsaChain = "rsa_chain";
const std::string TlsAgent::kServerEcdsa256 = "ecdsa256";
const std::string TlsAgent::kServerEcdsa384 = "ecdsa384";
const std::string TlsAgent::kServerEcdsa521 = "ecdsa521";
......
......@@ -66,7 +66,6 @@ class TlsAgent : public PollTarget {
static const std::string kServerRsaSign;
static const std::string kServerRsaPss;
static const std::string kServerRsaDecrypt;
static const std::string kServerRsaChain; // A cert that requires a chain.
static const std::string kServerEcdsa256;
static const std::string kServerEcdsa384;
static const std::string kServerEcdsa521;
......
......@@ -1192,6 +1192,7 @@ CERT_CheckKeyUsage(CERTCertificate *cert, unsigned int requiredUsage)
case rsaKey:
requiredUsage |= KU_KEY_ENCIPHERMENT;
break;
case rsaPssKey:
case dsaKey:
requiredUsage |= KU_DIGITAL_SIGNATURE;
break;
......
......@@ -59,6 +59,14 @@ extern SECItem *DSAU_DecodeDerSigToLen(const SECItem *item, unsigned int len);
*/
extern SGNContext *SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *privKey);
/*
** Create a new signature context from an algorithmID.
** "alg" the signature algorithm to use
** "privKey" the private key to use
*/
extern SGNContext *SGN_NewContextWithAlgorithmID(SECAlgorithmID *alg,
SECKEYPrivateKey *privKey);
/*
** Destroy a signature-context object
** "cx" the object
......@@ -105,6 +113,21 @@ extern SECStatus SEC_SignData(SECItem *result,
const unsigned char *buf, int len,
SECKEYPrivateKey *pk, SECOidTag algid);
/*
** Sign a single block of data using private key encryption and given
** signature/hash algorithm with parameters from an algorithmID.
** "result" the final signature data (memory is allocated)
** "buf" the input data to sign
** "len" the amount of data to sign
** "pk" the private key to encrypt with
** "algid" the signature/hash algorithm to sign with
** (must be compatible with the key type).
*/
extern SECStatus SEC_SignDataWithAlgorithmID(SECItem *result,
const unsigned char *buf, int len,
SECKEYPrivateKey *pk,
SECAlgorithmID *algid);
/*
** Sign a pre-digested block of data using private key encryption, encoding
** The given signature/hash algorithm.
......@@ -131,6 +154,27 @@ extern SECStatus SEC_DerSignData(PLArenaPool *arena, SECItem *result,
const unsigned char *buf, int len,
SECKEYPrivateKey *pk, SECOidTag algid);
/*
** DER sign a single block of data using private key encryption and
** the given signature/hash algorithm with parameters from an
** algorithmID. This routine first computes a digital signature using
** SEC_SignData, then wraps it with an CERTSignedData and then der
** encodes the result.
** "arena" is the memory arena to use to allocate data from
** "result" the final der encoded data (memory is allocated)
** "buf" the input data to sign
** "len" the amount of data to sign
** "pk" the private key to encrypt with
** "algid" the signature/hash algorithm to sign with
** (must be compatible with the key type).
*/
extern SECStatus SEC_DerSignDataWithAlgorithmID(PLArenaPool *arena,
SECItem *result,
const unsigned char *buf,
int len,
SECKEYPrivateKey *pk,
SECAlgorithmID *algid);
/*
** Destroy a signed-data object.
** "sd" the object
......@@ -146,6 +190,23 @@ extern void SEC_DestroySignedData(CERTSignedData *sd, PRBool freeit);
extern SECOidTag SEC_GetSignatureAlgorithmOidTag(KeyType keyType,
SECOidTag hashAlgTag);
/*
** Create algorithm parameters for signing. Return a new item
** allocated from arena, or NULL on failure.
** "arena" is the memory arena to use to allocate data from
** "result" the encoded parameters (memory is allocated)
** "signAlgTag" is the signing algorithm
** "hashAlgTag" is the preferred hash algorithm
** "params" is the default parameters
** "key" is the private key
*/
extern SECItem *SEC_CreateSignatureAlgorithmParameters(PLArenaPool *arena,
SECItem *result,
SECOidTag signAlgTag,
SECOidTag hashAlgTag,
const SECItem *params,
const SECKEYPrivateKey *key);
/****************************************/
/*
** Signature verification operations
......
......@@ -17,6 +17,9 @@ KeyType seckey_GetKeyType(SECOidTag pubKeyOid);
SECStatus sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg);
SECStatus sec_RSAPSSParamsToMechanism(CK_RSA_PKCS_PSS_PARAMS *mech,
const SECKEYRSAPSSParams *params);
SEC_END_PROTOS
#endif /* _KEYHI_H_ */
......@@ -1048,6 +1048,7 @@ SECKEY_SignatureLen(const SECKEYPublicKey *pubk)
switch (pubk->keyType) {
case rsaKey:
case rsaPssKey:
b0 = pubk->u.rsa.modulus.data[0];
return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
case dsaKey:
......@@ -1974,3 +1975,92 @@ SECKEY_GetECCOid(const SECKEYECParams *params)
return oidData->offset;
}
static CK_MECHANISM_TYPE
sec_GetHashMechanismByOidTag(SECOidTag tag)
{
switch (tag) {
case SEC_OID_SHA512:
return CKM_SHA512;
case SEC_OID_SHA384:
return CKM_SHA384;
case SEC_OID_SHA256:
return CKM_SHA256;
default:
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
/* fallthrough */
case SEC_OID_SHA1:
break;
}
return CKM_SHA_1;
}
static CK_RSA_PKCS_MGF_TYPE
sec_GetMgfTypeByOidTag(SECOidTag tag)
{
switch (tag) {
case SEC_OID_SHA512:
return CKG_MGF1_SHA512;
case SEC_OID_SHA384:
return CKG_MGF1_SHA384;
case SEC_OID_SHA256:
return CKG_MGF1_SHA256;
default:
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
/* fallthrough */
case SEC_OID_SHA1:
break;
}
return CKG_MGF1_SHA1;
}
SECStatus
sec_RSAPSSParamsToMechanism(CK_RSA_PKCS_PSS_PARAMS *mech,
const SECKEYRSAPSSParams *params)
{
SECStatus rv = SECSuccess;
SECOidTag hashAlgTag;
unsigned long saltLength;
PORT_Memset(mech, 0, sizeof(CK_RSA_PKCS_PSS_PARAMS));
if (params->hashAlg) {
hashAlgTag = SECOID_GetAlgorithmTag(params->hashAlg);
} else {
hashAlgTag = SEC_OID_SHA1; /* default, SHA-1 */
}
mech->hashAlg = sec_GetHashMechanismByOidTag(hashAlgTag);
if (params->maskAlg) {
SECAlgorithmID maskHashAlg;
SECOidTag maskHashAlgTag;
PORTCheapArenaPool tmpArena;
if (SECOID_GetAlgorithmTag(params->maskAlg) != SEC_OID_PKCS1_MGF1) {
/* only MGF1 is known to PKCS#11 */
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return SECFailure;
}
PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
rv = SEC_QuickDERDecodeItem(&tmpArena.arena, &maskHashAlg,
SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
&params->maskAlg->parameters);
PORT_DestroyCheapArena(&tmpArena);
if (rv != SECSuccess) {
return rv;
}
maskHashAlgTag = SECOID_GetAlgorithmTag(&maskHashAlg);
mech->mgf = sec_GetMgfTypeByOidTag(maskHashAlgTag);
} else {
mech->mgf = CKG_MGF1_SHA1; /* default, MGF1 with SHA-1 */
}
rv = SEC_ASN1DecodeInteger((SECItem *)&params->saltLength, &saltLength);
if (rv != SECSuccess) {
return rv;
}
mech->sLen = saltLength;
return rv;
}
This diff is collapsed.
This diff is collapsed.
......@@ -1123,3 +1123,12 @@ CERT_FindCertByNicknameOrEmailAddrForUsageCX;
;+ local:
;+ *;
;+};
;+NSS_3.34 { # NSS 3.34 release
;+ global:
SGN_NewContextWithAlgorithmID;
SEC_SignDataWithAlgorithmID;
SEC_DerSignDataWithAlgorithmID;
SEC_CreateSignatureAlgorithmParameters;
;+ local:
;+ *;
;+};
......@@ -163,6 +163,7 @@
'cmd/vfychain/vfychain.gyp:vfychain',
'cmd/vfyserv/vfyserv.gyp:vfyserv',
'gtests/certhigh_gtest/certhigh_gtest.gyp:certhigh_gtest',
'gtests/cryptohi_gtest/cryptohi_gtest.gyp:cryptohi_gtest',
'gtests/der_gtest/der_gtest.gyp:der_gtest',
'gtests/certdb_gtest/certdb_gtest.gyp:certdb_gtest',
'gtests/freebl_gtest/freebl_gtest.gyp:prng_gtest',
......
This diff is collapsed.
......@@ -63,6 +63,7 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then
DBPASSDIR=${HOSTDIR}/dbpass
ECCURVES_DIR=${HOSTDIR}/eccurves
DISTRUSTDIR=${HOSTDIR}/distrust
RSAPSSDIR=${HOSTDIR}/rsapss
SERVER_CADIR=${HOSTDIR}/serverCA
CLIENT_CADIR=${HOSTDIR}/clientCA
......@@ -540,6 +541,7 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then
D_IMPLICIT_INIT="ImplicitInit.$version"
D_CERT_EXTENSTIONS="CertExtensions.$version"
D_DISTRUST="Distrust.$version"
D_RSAPSS="RSAPSS.$version"
# we need relative pathnames of these files abd directories, since our
# tools can't handle the unix style absolut pathnames on cygnus
......
......@@ -41,6 +41,7 @@ certscript() {
make_cert() {
name=$1
type=$2
unset type_args trust sign
case $type in
dsa) type_args='-g 1024' ;;
rsa) type_args='-g 1024' ;;
......@@ -51,6 +52,9 @@ make_cert() {
p521) type_args='-q secp521r1';type=ec ;;
rsa_ca) type_args='-g 1024';trust='CT,CT,CT';ca=y;type=rsa ;;
rsa_chain) type_args='-g 1024';sign='-c rsa_ca';type=rsa;;
rsapss_ca) type_args='-g 1024 --pss';trust='CT,CT,CT';ca=y;type=rsa ;;
rsapss_chain) type_args='-g 1024';sign='-c rsa_pss_ca';type=rsa;;
rsa_ca_rsapss_chain) type_args='-g 1024 --pss-sign';sign='-c rsa_ca';type=rsa;;
ecdh_rsa) type_args='-q nistp256';sign='-c rsa_ca';type=ec ;;
esac
shift 2
......@@ -87,6 +91,9 @@ ssl_gtest_certs() {
make_cert ecdh_ecdsa p256 kex
make_cert rsa_ca rsa_ca ca
make_cert rsa_chain rsa_chain sign
make_cert rsa_pss_ca rsapss_ca ca
make_cert rsa_pss_chain rsapss_chain sign
make_cert rsa_ca_rsa_pss_chain rsa_ca_rsapss_chain sign
make_cert ecdh_rsa ecdh_rsa kex
make_cert dsa dsa sign
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment