--- a/security/apps/AppTrustDomain.cpp
+++ b/security/apps/AppTrustDomain.cpp
@@ -25,18 +25,16 @@
#include "manifest-signing-test-root.inc"
using namespace mozilla::pkix;
#ifdef PR_LOGGING
extern PRLogModuleInfo* gPIPNSSLog;
#endif
-static const unsigned int MINIMUM_NON_ECC_BITS = 2048;
-
namespace mozilla { namespace psm {
AppTrustDomain::AppTrustDomain(ScopedCERTCertList& certChain, void* pinArg)
: mCertChain(certChain)
, mPinArg(pinArg)
{
}
@@ -210,17 +208,17 @@ AppTrustDomain::GetCertTrust(EndEntityOr
return Success;
}
Result
AppTrustDomain::VerifySignedData(const SignedDataWithSignature& signedData,
Input subjectPublicKeyInfo)
{
return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
- MINIMUM_NON_ECC_BITS, mPinArg);
+ mPinArg);
}
Result
AppTrustDomain::DigestBuf(Input item, /*out*/ uint8_t* digestBuf,
size_t digestBufLen)
{
return ::mozilla::pkix::DigestBuf(item, digestBuf, digestBufLen);
}
@@ -244,13 +242,12 @@ AppTrustDomain::IsChainValid(const DERAr
return MapPRErrorCodeToResult(PR_GetError());
}
return Success;
}
Result
AppTrustDomain::CheckPublicKey(Input subjectPublicKeyInfo)
{
- return ::mozilla::pkix::CheckPublicKey(subjectPublicKeyInfo,
- MINIMUM_NON_ECC_BITS);
+ return ::mozilla::pkix::CheckPublicKey(subjectPublicKeyInfo);
}
} } // namespace mozilla::psm
--- a/security/certverifier/CertVerifier.cpp
+++ b/security/certverifier/CertVerifier.cpp
@@ -206,17 +206,17 @@ CertVerifier::VerifyCert(CERTCertificate
}
switch (usage) {
case certificateUsageSSLClient: {
// XXX: We don't really have a trust bit for SSL client authentication so
// just use trustEmail as it is the closest alternative.
NSSCertDBTrustDomain trustDomain(trustEmail, ocspFetching, mOCSPCache,
pinArg, ocspGETConfig, pinningDisabled,
- false, nullptr, builtChain);
+ nullptr, builtChain);
rv = BuildCertChain(trustDomain, certDER, time,
EndEntityOrCA::MustBeEndEntity,
KeyUsage::digitalSignature,
KeyPurposeId::id_kp_clientAuth,
CertPolicyId::anyPolicy, stapledOCSPResponse);
break;
}
@@ -231,17 +231,17 @@ CertVerifier::VerifyCert(CERTCertificate
SECOidTag evPolicyOidTag;
SECStatus srv = GetFirstEVPolicy(cert, evPolicy, evPolicyOidTag);
if (srv == SECSuccess) {
NSSCertDBTrustDomain
trustDomain(trustSSL,
ocspFetching == NSSCertDBTrustDomain::NeverFetchOCSP
? NSSCertDBTrustDomain::LocalOnlyOCSPForEV
: NSSCertDBTrustDomain::FetchOCSPForEV,
- mOCSPCache, pinArg, ocspGETConfig, mPinningMode, true,
+ mOCSPCache, pinArg, ocspGETConfig, mPinningMode,
hostname, builtChain);
rv = BuildCertChainForOneKeyUsage(trustDomain, certDER, time,
KeyUsage::digitalSignature,// (EC)DHE
KeyUsage::keyEncipherment, // RSA
KeyUsage::keyAgreement, // (EC)DH
KeyPurposeId::id_kp_serverAuth,
evPolicy, stapledOCSPResponse);
if (rv == Success) {
@@ -256,57 +256,57 @@ CertVerifier::VerifyCert(CERTCertificate
if (flags & FLAG_MUST_BE_EV) {
rv = Result::ERROR_POLICY_VALIDATION_FAILED;
break;
}
// Now try non-EV.
NSSCertDBTrustDomain trustDomain(trustSSL, ocspFetching, mOCSPCache,
pinArg, ocspGETConfig, mPinningMode,
- false, hostname, builtChain);
+ hostname, builtChain);
rv = BuildCertChainForOneKeyUsage(trustDomain, certDER, time,
KeyUsage::digitalSignature, // (EC)DHE
KeyUsage::keyEncipherment, // RSA
KeyUsage::keyAgreement, // (EC)DH
KeyPurposeId::id_kp_serverAuth,
CertPolicyId::anyPolicy,
stapledOCSPResponse);
break;
}
case certificateUsageSSLCA: {
NSSCertDBTrustDomain trustDomain(trustSSL, ocspFetching, mOCSPCache,
pinArg, ocspGETConfig, pinningDisabled,
- false, nullptr, builtChain);
+ nullptr, builtChain);
rv = BuildCertChain(trustDomain, certDER, time,
EndEntityOrCA::MustBeCA, KeyUsage::keyCertSign,
KeyPurposeId::id_kp_serverAuth,
CertPolicyId::anyPolicy, stapledOCSPResponse);
break;
}
case certificateUsageEmailSigner: {
NSSCertDBTrustDomain trustDomain(trustEmail, ocspFetching, mOCSPCache,
pinArg, ocspGETConfig, pinningDisabled,
- false, nullptr, builtChain);
+ nullptr, builtChain);
rv = BuildCertChain(trustDomain, certDER, time,
EndEntityOrCA::MustBeEndEntity,
KeyUsage::digitalSignature,
KeyPurposeId::id_kp_emailProtection,
CertPolicyId::anyPolicy, stapledOCSPResponse);
break;
}
case certificateUsageEmailRecipient: {
// TODO: The higher level S/MIME processing should pass in which key
// usage it is trying to verify for, and base its algorithm choices
// based on the result of the verification(s).
NSSCertDBTrustDomain trustDomain(trustEmail, ocspFetching, mOCSPCache,
pinArg, ocspGETConfig, pinningDisabled,
- false, nullptr, builtChain);
+ nullptr, builtChain);
rv = BuildCertChain(trustDomain, certDER, time,
EndEntityOrCA::MustBeEndEntity,
KeyUsage::keyEncipherment, // RSA
KeyPurposeId::id_kp_emailProtection,
CertPolicyId::anyPolicy, stapledOCSPResponse);
if (rv == Result::ERROR_INADEQUATE_KEY_USAGE) {
rv = BuildCertChain(trustDomain, certDER, time,
EndEntityOrCA::MustBeEndEntity,
@@ -315,18 +315,17 @@ CertVerifier::VerifyCert(CERTCertificate
CertPolicyId::anyPolicy, stapledOCSPResponse);
}
break;
}
case certificateUsageObjectSigner: {
NSSCertDBTrustDomain trustDomain(trustObjectSigning, ocspFetching,
mOCSPCache, pinArg, ocspGETConfig,
- pinningDisabled, false, nullptr,
- builtChain);
+ pinningDisabled, nullptr, builtChain);
rv = BuildCertChain(trustDomain, certDER, time,
EndEntityOrCA::MustBeEndEntity,
KeyUsage::digitalSignature,
KeyPurposeId::id_kp_codeSigning,
CertPolicyId::anyPolicy, stapledOCSPResponse);
break;
}
@@ -344,34 +343,34 @@ CertVerifier::VerifyCert(CERTCertificate
eku = KeyPurposeId::anyExtendedKeyUsage;
} else {
endEntityOrCA = EndEntityOrCA::MustBeEndEntity;
keyUsage = KeyUsage::digitalSignature;
eku = KeyPurposeId::id_kp_OCSPSigning;
}
NSSCertDBTrustDomain sslTrust(trustSSL, ocspFetching, mOCSPCache, pinArg,
- ocspGETConfig, pinningDisabled, false,
- nullptr, builtChain);
+ ocspGETConfig, pinningDisabled, nullptr,
+ builtChain);
rv = BuildCertChain(sslTrust, certDER, time, endEntityOrCA,
keyUsage, eku, CertPolicyId::anyPolicy,
stapledOCSPResponse);
if (rv == Result::ERROR_UNKNOWN_ISSUER) {
NSSCertDBTrustDomain emailTrust(trustEmail, ocspFetching, mOCSPCache,
pinArg, ocspGETConfig, pinningDisabled,
- false, nullptr, builtChain);
+ nullptr, builtChain);
rv = BuildCertChain(emailTrust, certDER, time, endEntityOrCA,
keyUsage, eku, CertPolicyId::anyPolicy,
stapledOCSPResponse);
if (rv == Result::ERROR_UNKNOWN_ISSUER) {
NSSCertDBTrustDomain objectSigningTrust(trustObjectSigning,
ocspFetching, mOCSPCache,
pinArg, ocspGETConfig,
- pinningDisabled, false,
- nullptr, builtChain);
+ pinningDisabled, nullptr,
+ builtChain);
rv = BuildCertChain(objectSigningTrust, certDER, time,
endEntityOrCA, keyUsage, eku,
CertPolicyId::anyPolicy, stapledOCSPResponse);
}
}
break;
}
--- a/security/certverifier/NSSCertDBTrustDomain.cpp
+++ b/security/certverifier/NSSCertDBTrustDomain.cpp
@@ -30,19 +30,16 @@ using namespace mozilla;
using namespace mozilla::pkix;
#ifdef PR_LOGGING
extern PRLogModuleInfo* gCertVerifierLog;
#endif
static const uint64_t ServerFailureDelaySeconds = 5 * 60;
-static const unsigned int MINIMUM_NON_ECC_BITS_DV = 1024;
-static const unsigned int MINIMUM_NON_ECC_BITS_EV = 2048;
-
namespace mozilla { namespace psm {
const char BUILTIN_ROOTS_MODULE_DEFAULT_NAME[] = "Builtin Roots Module";
void PORT_Free_string(char* str) { PORT_Free(str); }
namespace {
@@ -51,26 +48,24 @@ typedef ScopedPtr<SECMODModule, SECMOD_D
} // unnamed namespace
NSSCertDBTrustDomain::NSSCertDBTrustDomain(SECTrustType certDBTrustType,
OCSPFetching ocspFetching,
OCSPCache& ocspCache,
/*optional but shouldn't be*/ void* pinArg,
CertVerifier::ocsp_get_config ocspGETConfig,
CertVerifier::PinningMode pinningMode,
- bool forEV,
/*optional*/ const char* hostname,
/*optional*/ ScopedCERTCertList* builtChain)
: mCertDBTrustType(certDBTrustType)
, mOCSPFetching(ocspFetching)
, mOCSPCache(ocspCache)
, mPinArg(pinArg)
, mOCSPGetConfig(ocspGETConfig)
, mPinningMode(pinningMode)
- , mMinimumNonECCBits(forEV ? MINIMUM_NON_ECC_BITS_EV : MINIMUM_NON_ECC_BITS_DV)
, mHostname(hostname)
, mBuiltChain(builtChain)
{
}
// E=igca@sgdn.pm.gouv.fr,CN=IGC/A,OU=DCSSI,O=PM/SGDN,L=Paris,ST=France,C=FR
static const uint8_t ANSSI_SUBJECT_DATA[] =
"\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04"
@@ -226,17 +221,17 @@ NSSCertDBTrustDomain::GetCertTrust(EndEn
return Success;
}
Result
NSSCertDBTrustDomain::VerifySignedData(const SignedDataWithSignature& signedData,
Input subjectPublicKeyInfo)
{
return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
- mMinimumNonECCBits, mPinArg);
+ mPinArg);
}
Result
NSSCertDBTrustDomain::DigestBuf(Input item,
/*out*/ uint8_t* digestBuf, size_t digestBufLen)
{
return ::mozilla::pkix::DigestBuf(item, digestBuf, digestBufLen);
}
@@ -663,18 +658,17 @@ NSSCertDBTrustDomain::IsChainValid(const
}
return Success;
}
Result
NSSCertDBTrustDomain::CheckPublicKey(Input subjectPublicKeyInfo)
{
- return ::mozilla::pkix::CheckPublicKey(subjectPublicKeyInfo,
- mMinimumNonECCBits);
+ return ::mozilla::pkix::CheckPublicKey(subjectPublicKeyInfo);
}
namespace {
static char*
nss_addEscape(const char* string, char quote)
{
char* newString = 0;
--- a/security/certverifier/NSSCertDBTrustDomain.h
+++ b/security/certverifier/NSSCertDBTrustDomain.h
@@ -49,17 +49,16 @@ public:
FetchOCSPForDVHardFail = 2,
FetchOCSPForEV = 3,
LocalOnlyOCSPForEV = 4,
};
NSSCertDBTrustDomain(SECTrustType certDBTrustType, OCSPFetching ocspFetching,
OCSPCache& ocspCache, void* pinArg,
CertVerifier::ocsp_get_config ocspGETConfig,
CertVerifier::PinningMode pinningMode,
- bool forEV,
/*optional*/ const char* hostname = nullptr,
/*optional out*/ ScopedCERTCertList* builtChain = nullptr);
virtual Result FindIssuer(mozilla::pkix::Input encodedIssuerName,
IssuerChecker& checker,
mozilla::pkix::Time time) MOZ_OVERRIDE;
virtual Result GetCertTrust(mozilla::pkix::EndEntityOrCA endEntityOrCA,
@@ -102,16 +101,15 @@ private:
EncodedResponseSource responseSource, /*out*/ bool& expired);
const SECTrustType mCertDBTrustType;
const OCSPFetching mOCSPFetching;
OCSPCache& mOCSPCache; // non-owning!
void* mPinArg; // non-owning!
const CertVerifier::ocsp_get_config mOCSPGetConfig;
CertVerifier::PinningMode mPinningMode;
- const unsigned int mMinimumNonECCBits;
const char* mHostname; // non-owning - only used for pinning checks
ScopedCERTCertList* mBuiltChain; // non-owning
};
} } // namespace mozilla::psm
#endif // mozilla_psm__NSSCertDBTrustDomain_h
--- a/security/pkix/include/pkix/pkixnss.h
+++ b/security/pkix/include/pkix/pkixnss.h
@@ -29,37 +29,34 @@
#include "prerror.h"
#include "seccomon.h"
namespace mozilla { namespace pkix {
// Verify the given signed data using the given public key.
Result VerifySignedData(const SignedDataWithSignature& sd,
Input subjectPublicKeyInfo,
- unsigned int minimumNonECCBits,
void* pkcs11PinArg);
// Computes the SHA-1 hash of the data in the current item.
//
// item contains the data to hash.
// digestBuf must point to a buffer to where the SHA-1 hash will be written.
// digestBufLen must be 20 (the length of a SHA-1 hash,
// TrustDomain::DIGEST_LENGTH).
//
// TODO(bug 966856): Add SHA-2 support
// TODO: Taking the output buffer as (uint8_t*, size_t) is counter to our
// other, extensive, memory safety efforts in mozilla::pkix, and we should find
// a way to provide a more-obviously-safe interface.
Result DigestBuf(Input item, /*out*/ uint8_t* digestBuf,
size_t digestBufLen);
-// Checks, for RSA keys and DSA keys, that the modulus is at least the given
-// number of bits.
-Result CheckPublicKey(Input subjectPublicKeyInfo,
- unsigned int minimumNonECCBits);
+// Checks, for RSA keys and DSA keys, that the modulus is at least 1024 bits.
+Result CheckPublicKey(Input subjectPublicKeyInfo);
Result MapPRErrorCodeToResult(PRErrorCode errorCode);
PRErrorCode MapResultToPRErrorCode(Result result);
// The error codes within each module must fit in 16 bits. We want these
// errors to fit in the same module as the NSS errors but not overlap with
// any of them. Converting an NSS SEC, NSS SSL, or PSM error to an NS error
// involves negating the value of the error and then synthesizing an error
--- a/security/pkix/lib/pkixnss.cpp
+++ b/security/pkix/lib/pkixnss.cpp
@@ -34,38 +34,41 @@
#include "pkix/ScopedPtr.h"
#include "secerr.h"
namespace mozilla { namespace pkix {
typedef ScopedPtr<SECKEYPublicKey, SECKEY_DestroyPublicKey> ScopedSECKeyPublicKey;
Result
-CheckPublicKeySize(Input subjectPublicKeyInfo, unsigned int minimumNonECCBits,
+CheckPublicKeySize(Input subjectPublicKeyInfo,
/*out*/ ScopedSECKeyPublicKey& publicKey)
{
SECItem subjectPublicKeyInfoSECItem =
UnsafeMapInputToSECItem(subjectPublicKeyInfo);
ScopedPtr<CERTSubjectPublicKeyInfo, SECKEY_DestroySubjectPublicKeyInfo>
spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&subjectPublicKeyInfoSECItem));
if (!spki) {
return MapPRErrorCodeToResult(PR_GetError());
}
publicKey = SECKEY_ExtractPublicKey(spki.get());
if (!publicKey) {
return MapPRErrorCodeToResult(PR_GetError());
}
+ static const unsigned int MINIMUM_NON_ECC_BITS = 1024;
+
switch (publicKey.get()->keyType) {
case ecKey:
- // TODO(bug 1077790): We should check which curve.
+ // TODO(bug 622859): We should check which curve.
return Success;
case dsaKey: // fall through
case rsaKey:
- if (SECKEY_PublicKeyStrengthInBits(publicKey.get()) < minimumNonECCBits) {
+ // TODO(bug 622859): Enforce a minimum of 2048 bits for EV certs.
+ if (SECKEY_PublicKeyStrengthInBits(publicKey.get()) < MINIMUM_NON_ECC_BITS) {
return Result::ERROR_INADEQUATE_KEY_SIZE;
}
break;
case nullKey:
case fortezzaKey:
case dhKey:
case keaKey:
case rsaPssKey:
@@ -73,26 +76,25 @@ CheckPublicKeySize(Input subjectPublicKe
default:
return Result::ERROR_UNSUPPORTED_KEYALG;
}
return Success;
}
Result
-CheckPublicKey(Input subjectPublicKeyInfo, unsigned int minimumNonECCBits)
+CheckPublicKey(Input subjectPublicKeyInfo)
{
ScopedSECKeyPublicKey unused;
- return CheckPublicKeySize(subjectPublicKeyInfo, minimumNonECCBits, unused);
+ return CheckPublicKeySize(subjectPublicKeyInfo, unused);
}
Result
VerifySignedData(const SignedDataWithSignature& sd,
- Input subjectPublicKeyInfo, unsigned int minimumNonECCBits,
- void* pkcs11PinArg)
+ Input subjectPublicKeyInfo, void* pkcs11PinArg)
{
SECOidTag pubKeyAlg;
SECOidTag digestAlg;
switch (sd.algorithm) {
case SignatureAlgorithm::ecdsa_with_sha512:
pubKeyAlg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
digestAlg = SEC_OID_SHA512;
break;
@@ -135,17 +137,17 @@ VerifySignedData(const SignedDataWithSig
case SignatureAlgorithm::unsupported_algorithm:
default:
PR_NOT_REACHED("unknown signature algorithm");
return Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED;
}
Result rv;
ScopedSECKeyPublicKey pubKey;
- rv = CheckPublicKeySize(subjectPublicKeyInfo, minimumNonECCBits, pubKey);
+ rv = CheckPublicKeySize(subjectPublicKeyInfo, pubKey);
if (rv != Success) {
return rv;
}
// The static_cast is safe as long as the length of the data in sd.data can
// fit in an int. Right now that length is stored as a uint16_t, so this
// works. In the future this may change, hence the assertion.
// See also bug 921585.
--- a/security/pkix/test/gtest/pkixbuild_tests.cpp
+++ b/security/pkix/test/gtest/pkixbuild_tests.cpp
@@ -164,17 +164,17 @@ private:
{
return Success;
}
virtual Result VerifySignedData(const SignedDataWithSignature& signedData,
Input subjectPublicKeyInfo)
{
return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
- MINIMUM_TEST_KEY_BITS, nullptr);
+ nullptr);
}
virtual Result DigestBuf(Input item, /*out*/ uint8_t *digestBuf,
size_t digestBufLen)
{
ADD_FAILURE();
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}
@@ -347,17 +347,17 @@ public:
{
return Success;
}
virtual Result VerifySignedData(const SignedDataWithSignature& signedData,
Input subjectPublicKeyInfo)
{
return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
- MINIMUM_TEST_KEY_BITS, nullptr);
+ nullptr);
}
virtual Result DigestBuf(Input, /*out*/uint8_t*, size_t)
{
ADD_FAILURE();
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}
--- a/security/pkix/test/gtest/pkixcert_signature_algorithm_tests.cpp
+++ b/security/pkix/test/gtest/pkixcert_signature_algorithm_tests.cpp
@@ -106,17 +106,17 @@ private:
return Success;
}
virtual Result VerifySignedData(const SignedDataWithSignature& signedData,
Input subjectPublicKeyInfo)
{
EXPECT_NE(SignatureAlgorithm::unsupported_algorithm, signedData.algorithm);
return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
- MINIMUM_TEST_KEY_BITS, nullptr);
+ nullptr);
}
virtual Result DigestBuf(Input, uint8_t*, size_t)
{
ADD_FAILURE();
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}
--- a/security/pkix/test/lib/pkixtestnss.cpp
+++ b/security/pkix/test/lib/pkixtestnss.cpp
@@ -254,26 +254,25 @@ SHA1(const ByteString& toHash)
}
return ByteString(digestBuf, sizeof(digestBuf));
}
Result
TestCheckPublicKey(Input subjectPublicKeyInfo)
{
InitNSSIfNeeded();
- return CheckPublicKey(subjectPublicKeyInfo, MINIMUM_TEST_KEY_BITS);
+ return CheckPublicKey(subjectPublicKeyInfo);
}
Result
TestVerifySignedData(const SignedDataWithSignature& signedData,
Input subjectPublicKeyInfo)
{
InitNSSIfNeeded();
- return VerifySignedData(signedData, subjectPublicKeyInfo,
- MINIMUM_TEST_KEY_BITS, nullptr);
+ return VerifySignedData(signedData, subjectPublicKeyInfo, nullptr);
}
Result
TestDigestBuf(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
{
InitNSSIfNeeded();
return DigestBuf(item, digestBuf, digestBufLen);
}
--- a/security/pkix/test/lib/pkixtestutil.h
+++ b/security/pkix/test/lib/pkixtestutil.h
@@ -28,18 +28,16 @@
#include <ctime>
#include <stdint.h> // Some Mozilla-supported compilers lack <cstdint>
#include <string>
#include "pkix/enumclass.h"
#include "pkix/pkixtypes.h"
#include "pkix/ScopedPtr.h"
-static const unsigned int MINIMUM_TEST_KEY_BITS = 1024;
-
namespace mozilla { namespace pkix { namespace test {
typedef std::basic_string<uint8_t> ByteString;
inline bool ENCODING_FAILED(const ByteString& bs) { return bs.empty(); }
// XXX: Ideally, we should define this instead:
//