зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1063006: Centralize direct use of NSS for crypto in the mozilla::pkix test suite, r=keeler
--HG-- rename : security/pkix/test/lib/pkixtestutil.cpp => security/pkix/test/lib/pkixtestnss.cpp extra : rebase_source : 93515d39abf91168fa86268f9b26f8c62d0d411e
This commit is contained in:
Родитель
ba3ad3aa0e
Коммит
8dbcf66d66
|
@ -12,11 +12,37 @@
|
|||
#include "secder.h"
|
||||
#include "secerr.h"
|
||||
|
||||
namespace mozilla { namespace pkix { namespace test {
|
||||
|
||||
// Ownership of privateKey is transfered.
|
||||
TestKeyPair* CreateTestKeyPair(const ByteString& spki,
|
||||
const ByteString& spk,
|
||||
SECKEYPrivateKey* privateKey);
|
||||
|
||||
} } } // namespace mozilla::pkix::test
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::pkix;
|
||||
using namespace mozilla::pkix::test;
|
||||
using namespace mozilla::test;
|
||||
|
||||
static TestKeyPair*
|
||||
CreateTestKeyPairFromCert(CERTCertificate& cert)
|
||||
{
|
||||
ScopedSECKEYPrivateKey privateKey(PK11_FindKeyByAnyCert(&cert, nullptr));
|
||||
if (!privateKey) {
|
||||
return nullptr;
|
||||
}
|
||||
ByteString subjectPublicKeyInfo(cert.derPublicKey.data,
|
||||
cert.derPublicKey.len);
|
||||
SECItem subjectPublicKeyItem = cert.subjectPublicKeyInfo.subjectPublicKey;
|
||||
DER_ConvertBitString(&subjectPublicKeyItem); // bits to bytes
|
||||
ByteString subjectPublicKey(subjectPublicKeyItem.data,
|
||||
subjectPublicKeyItem.len);
|
||||
return CreateTestKeyPair(subjectPublicKeyInfo, subjectPublicKey,
|
||||
privateKey.forget());
|
||||
}
|
||||
|
||||
SECItemArray *
|
||||
GetOCSPResponseForType(OCSPResponseType aORT, CERTCertificate *aCert,
|
||||
PLArenaPool *aArena, const char *aAdditionalCertName)
|
||||
|
@ -166,8 +192,8 @@ GetOCSPResponseForType(OCSPResponseType aORT, CERTCertificate *aCert,
|
|||
if (!signerCert) {
|
||||
signerCert = CERT_DupCertificate(issuerCert.get());
|
||||
}
|
||||
context.signerPrivateKey = PK11_FindKeyByAnyCert(signerCert.get(), nullptr);
|
||||
if (!context.signerPrivateKey) {
|
||||
context.signerKeyPair = CreateTestKeyPairFromCert(*signerCert);
|
||||
if (!context.signerKeyPair) {
|
||||
PrintPRError("PK11_FindKeyByAnyCert failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -25,11 +25,8 @@
|
|||
#include "cert.h"
|
||||
#include "nssgtest.h"
|
||||
#include "pkix/pkix.h"
|
||||
#include "pkix/pkixnss.h"
|
||||
#include "pkixgtest.h"
|
||||
#include "pkixtestutil.h"
|
||||
#include "prinit.h"
|
||||
#include "secerr.h"
|
||||
|
||||
using namespace mozilla::pkix;
|
||||
using namespace mozilla::pkix::test;
|
||||
|
@ -42,8 +39,8 @@ static ByteString
|
|||
CreateCert(const char* issuerCN,
|
||||
const char* subjectCN,
|
||||
EndEntityOrCA endEntityOrCA,
|
||||
/*optional*/ SECKEYPrivateKey* issuerKey,
|
||||
/*out*/ ScopedSECKEYPrivateKey& subjectKey,
|
||||
/*optional*/ TestKeyPair* issuerKey,
|
||||
/*out*/ ScopedTestKeyPair& subjectKey,
|
||||
/*out*/ ScopedCERTCertificate* subjectCert = nullptr)
|
||||
{
|
||||
static long serialNumberValue = 0;
|
||||
|
@ -196,7 +193,7 @@ private:
|
|||
ScopedCERTCertificate certChainTail[7];
|
||||
|
||||
public:
|
||||
ScopedSECKEYPrivateKey leafCAKey;
|
||||
ScopedTestKeyPair leafCAKey;
|
||||
CERTCertificate* GetLeafCACert() const
|
||||
{
|
||||
return certChainTail[MOZILLA_PKIX_ARRAY_LENGTH(certChainTail) - 1].get();
|
||||
|
@ -238,11 +235,11 @@ TEST_F(pkixbuild, MaxAcceptableCertChainLength)
|
|||
}
|
||||
|
||||
{
|
||||
ScopedSECKEYPrivateKey privateKey;
|
||||
ScopedTestKeyPair unusedKeyPair;
|
||||
ScopedCERTCertificate cert;
|
||||
ByteString certDER(CreateCert("CA7", "Direct End-Entity",
|
||||
EndEntityOrCA::MustBeEndEntity,
|
||||
trustDomain.leafCAKey.get(), privateKey));
|
||||
trustDomain.leafCAKey.get(), unusedKeyPair));
|
||||
ASSERT_NE(ENCODING_FAILED, certDER);
|
||||
Input certDERInput;
|
||||
ASSERT_EQ(Success, certDERInput.Init(certDER.data(), certDER.length()));
|
||||
|
@ -259,7 +256,7 @@ TEST_F(pkixbuild, MaxAcceptableCertChainLength)
|
|||
TEST_F(pkixbuild, BeyondMaxAcceptableCertChainLength)
|
||||
{
|
||||
static char const* const caCertName = "CA Too Far";
|
||||
ScopedSECKEYPrivateKey caPrivateKey;
|
||||
ScopedTestKeyPair caKeyPair;
|
||||
|
||||
// We need a CERTCertificate for caCert so that the trustdomain's FindIssuer
|
||||
// method can find it through the NSS cert DB.
|
||||
|
@ -267,7 +264,7 @@ TEST_F(pkixbuild, BeyondMaxAcceptableCertChainLength)
|
|||
|
||||
{
|
||||
ByteString certDER(CreateCert("CA7", caCertName, EndEntityOrCA::MustBeCA,
|
||||
trustDomain.leafCAKey.get(), caPrivateKey,
|
||||
trustDomain.leafCAKey.get(), caKeyPair,
|
||||
&caCert));
|
||||
ASSERT_NE(ENCODING_FAILED, certDER);
|
||||
Input certDERInput;
|
||||
|
@ -282,10 +279,10 @@ TEST_F(pkixbuild, BeyondMaxAcceptableCertChainLength)
|
|||
}
|
||||
|
||||
{
|
||||
ScopedSECKEYPrivateKey privateKey;
|
||||
ScopedTestKeyPair unusedKeyPair;
|
||||
ByteString certDER(CreateCert(caCertName, "End-Entity Too Far",
|
||||
EndEntityOrCA::MustBeEndEntity,
|
||||
caPrivateKey.get(), privateKey));
|
||||
caKeyPair.get(), unusedKeyPair));
|
||||
ASSERT_NE(ENCODING_FAILED, certDER);
|
||||
Input certDERInput;
|
||||
ASSERT_EQ(Success, certDERInput.Init(certDER.data(), certDER.length()));
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "pkix/pkix.h"
|
||||
#include "pkix/pkixnss.h"
|
||||
#include "pkixtestutil.h"
|
||||
#include "secerr.h"
|
||||
|
||||
using namespace mozilla::pkix;
|
||||
using namespace mozilla::pkix::test;
|
||||
|
@ -35,7 +34,7 @@ using namespace mozilla::pkix::test;
|
|||
static ByteString
|
||||
CreateCert(const char* subjectCN,
|
||||
const ByteString* extensions, // empty-string-terminated array
|
||||
/*out*/ ScopedSECKEYPrivateKey& subjectKey)
|
||||
/*out*/ ScopedTestKeyPair& subjectKey)
|
||||
{
|
||||
static long serialNumberValue = 0;
|
||||
++serialNumberValue;
|
||||
|
@ -58,7 +57,7 @@ CreateCert(const char* subjectCN,
|
|||
static ByteString
|
||||
CreateCert(const char* subjectStr,
|
||||
const ByteString& extension,
|
||||
/*out*/ ScopedSECKEYPrivateKey& subjectKey)
|
||||
/*out*/ ScopedTestKeyPair& subjectKey)
|
||||
{
|
||||
const ByteString extensions[] = { extension, ByteString() };
|
||||
return CreateCert(subjectStr, extensions, subjectKey);
|
||||
|
@ -145,7 +144,7 @@ TEST_F(pkixcert_extension, UnknownCriticalExtension)
|
|||
unknownCriticalExtension(unknownCriticalExtensionBytes,
|
||||
sizeof(unknownCriticalExtensionBytes));
|
||||
const char* certCN = "Cert With Unknown Critical Extension";
|
||||
ScopedSECKEYPrivateKey key;
|
||||
ScopedTestKeyPair key;
|
||||
ByteString cert(CreateCert(certCN, unknownCriticalExtension, key));
|
||||
ASSERT_NE(ENCODING_FAILED, cert);
|
||||
Input certInput;
|
||||
|
@ -175,7 +174,7 @@ TEST_F(pkixcert_extension, UnknownNonCriticalExtension)
|
|||
unknownNonCriticalExtension(unknownNonCriticalExtensionBytes,
|
||||
sizeof(unknownNonCriticalExtensionBytes));
|
||||
const char* certCN = "Cert With Unknown NonCritical Extension";
|
||||
ScopedSECKEYPrivateKey key;
|
||||
ScopedTestKeyPair key;
|
||||
ByteString cert(CreateCert(certCN, unknownNonCriticalExtension, key));
|
||||
ASSERT_NE(ENCODING_FAILED, cert);
|
||||
Input certInput;
|
||||
|
@ -206,7 +205,7 @@ TEST_F(pkixcert_extension, WrongOIDCriticalExtension)
|
|||
wrongOIDCriticalExtension(wrongOIDCriticalExtensionBytes,
|
||||
sizeof(wrongOIDCriticalExtensionBytes));
|
||||
const char* certCN = "Cert With Critical Wrong OID Extension";
|
||||
ScopedSECKEYPrivateKey key;
|
||||
ScopedTestKeyPair key;
|
||||
ByteString cert(CreateCert(certCN, wrongOIDCriticalExtension, key));
|
||||
ASSERT_NE(ENCODING_FAILED, cert);
|
||||
Input certInput;
|
||||
|
@ -239,7 +238,7 @@ TEST_F(pkixcert_extension, CriticalAIAExtension)
|
|||
criticalAIAExtension(criticalAIAExtensionBytes,
|
||||
sizeof(criticalAIAExtensionBytes));
|
||||
const char* certCN = "Cert With Critical AIA Extension";
|
||||
ScopedSECKEYPrivateKey key;
|
||||
ScopedTestKeyPair key;
|
||||
ByteString cert(CreateCert(certCN, criticalAIAExtension, key));
|
||||
ASSERT_NE(ENCODING_FAILED, cert);
|
||||
Input certInput;
|
||||
|
@ -269,7 +268,7 @@ TEST_F(pkixcert_extension, UnknownCriticalCEExtension)
|
|||
unknownCriticalCEExtension(unknownCriticalCEExtensionBytes,
|
||||
sizeof(unknownCriticalCEExtensionBytes));
|
||||
const char* certCN = "Cert With Unknown Critical id-ce Extension";
|
||||
ScopedSECKEYPrivateKey key;
|
||||
ScopedTestKeyPair key;
|
||||
ByteString cert(CreateCert(certCN, unknownCriticalCEExtension, key));
|
||||
ASSERT_NE(ENCODING_FAILED, cert);
|
||||
Input certInput;
|
||||
|
@ -299,7 +298,7 @@ TEST_F(pkixcert_extension, KnownCriticalCEExtension)
|
|||
criticalCEExtension(criticalCEExtensionBytes,
|
||||
sizeof(criticalCEExtensionBytes));
|
||||
const char* certCN = "Cert With Known Critical id-ce Extension";
|
||||
ScopedSECKEYPrivateKey key;
|
||||
ScopedTestKeyPair key;
|
||||
ByteString cert(CreateCert(certCN, criticalCEExtension, key));
|
||||
ASSERT_NE(ENCODING_FAILED, cert);
|
||||
Input certInput;
|
||||
|
@ -328,7 +327,7 @@ TEST_F(pkixcert_extension, DuplicateSubjectAltName)
|
|||
static const ByteString DER(DER_BYTES, sizeof(DER_BYTES));
|
||||
static const ByteString extensions[] = { DER, DER, ByteString() };
|
||||
static const char* certCN = "Cert With Duplicate subjectAltName";
|
||||
ScopedSECKEYPrivateKey key;
|
||||
ScopedTestKeyPair key;
|
||||
ByteString cert(CreateCert(certCN, extensions, key));
|
||||
ASSERT_NE(ENCODING_FAILED, cert);
|
||||
Input certInput;
|
||||
|
|
|
@ -23,11 +23,10 @@
|
|||
*/
|
||||
|
||||
#include "nssgtest.h"
|
||||
#include "pkix/pkix.h"
|
||||
#include "pkix/pkixnss.h"
|
||||
#include "pkix/pkix.h"
|
||||
#include "pkixder.h"
|
||||
#include "pkixtestutil.h"
|
||||
#include "secerr.h"
|
||||
|
||||
using namespace mozilla::pkix;
|
||||
using namespace mozilla::pkix::test;
|
||||
|
@ -90,15 +89,9 @@ protected:
|
|||
issuerDER = CNToDERName(issuerASCII);
|
||||
ASSERT_NE(ENCODING_FAILED, issuerDER);
|
||||
|
||||
ScopedSECKEYPublicKey issuerPublicKey;
|
||||
ScopedSECKEYPrivateKey issuerPrivateKey;
|
||||
ASSERT_EQ(Success, GenerateKeyPair(issuerPublicKey, issuerPrivateKey));
|
||||
|
||||
ScopedSECItem issuerSPKIOriginal(
|
||||
SECKEY_EncodeDERSubjectPublicKeyInfo(issuerPublicKey.get()));
|
||||
ASSERT_TRUE(issuerSPKIOriginal);
|
||||
|
||||
issuerSPKI.assign(issuerSPKIOriginal->data, issuerSPKIOriginal->len);
|
||||
ScopedTestKeyPair keyPair(GenerateKeyPair());
|
||||
ASSERT_TRUE(keyPair);
|
||||
issuerSPKI = keyPair->subjectPublicKeyInfo;
|
||||
}
|
||||
|
||||
CreateEncodedOCSPRequestTrustDomain trustDomain;
|
||||
|
|
|
@ -22,14 +22,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nss.h"
|
||||
#include "nssgtest.h"
|
||||
#include "pkix/pkix.h"
|
||||
#include "pkix/pkixnss.h"
|
||||
#include "pkixgtest.h"
|
||||
#include "pkixtestutil.h"
|
||||
#include "prinit.h"
|
||||
#include "secerr.h"
|
||||
|
||||
using namespace mozilla::pkix;
|
||||
using namespace mozilla::pkix::test;
|
||||
|
@ -107,17 +103,8 @@ class pkixocsp_VerifyEncodedResponse : public NSSTest
|
|||
public:
|
||||
static bool SetUpTestCaseInner()
|
||||
{
|
||||
ScopedSECKEYPublicKey rootPublicKey;
|
||||
if (GenerateKeyPair(rootPublicKey, rootPrivateKey) != Success) {
|
||||
return false;
|
||||
}
|
||||
ScopedSECItem rootSPKIItem(
|
||||
SECKEY_EncodeDERSubjectPublicKeyInfo(rootPublicKey.get()));
|
||||
if (!rootSPKIItem) {
|
||||
return false;
|
||||
}
|
||||
rootSPKI.assign(rootSPKIItem->data, rootSPKIItem->len);
|
||||
return true;
|
||||
rootKeyPair = GenerateKeyPair();
|
||||
return rootKeyPair.get() != nullptr;
|
||||
}
|
||||
|
||||
static void SetUpTestCase()
|
||||
|
@ -153,7 +140,9 @@ public:
|
|||
}
|
||||
|
||||
Input rootSPKIDER;
|
||||
if (rootSPKIDER.Init(rootSPKI.data(), rootSPKI.length()) != Success) {
|
||||
if (rootSPKIDER.Init(rootKeyPair->subjectPublicKeyInfo.data(),
|
||||
rootKeyPair->subjectPublicKeyInfo.length())
|
||||
!= Success) {
|
||||
abort();
|
||||
}
|
||||
endEntityCertID = new (std::nothrow) CertID(rootNameDERInput, rootSPKIDER,
|
||||
|
@ -163,20 +152,18 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
static ScopedSECKEYPrivateKey rootPrivateKey;
|
||||
static ByteString rootSPKI;
|
||||
static ScopedTestKeyPair rootKeyPair;
|
||||
static long rootIssuedCount;
|
||||
OCSPTestTrustDomain trustDomain;
|
||||
|
||||
// endEntityCertID references rootKeyPair, rootNameDER, and serialNumberDER.
|
||||
ByteString rootNameDER;
|
||||
ByteString serialNumberDER;
|
||||
// endEntityCertID references rootSPKI, rootNameDER, and serialNumberDER.
|
||||
// endEntityCertID references rootKeyPair, rootNameDER, and serialNumberDER.
|
||||
ScopedPtr<CertID, deleteCertID> endEntityCertID;
|
||||
};
|
||||
|
||||
/*static*/ ScopedSECKEYPrivateKey
|
||||
pkixocsp_VerifyEncodedResponse::rootPrivateKey;
|
||||
/*static*/ ByteString pkixocsp_VerifyEncodedResponse::rootSPKI;
|
||||
/*static*/ ScopedTestKeyPair pkixocsp_VerifyEncodedResponse::rootKeyPair;
|
||||
/*static*/ long pkixocsp_VerifyEncodedResponse::rootIssuedCount = 0;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -263,7 +250,7 @@ public:
|
|||
OCSPResponseContext::CertStatus certStatus,
|
||||
const CertID& certID,
|
||||
/*optional*/ const char* signerName,
|
||||
const ScopedSECKEYPrivateKey& signerPrivateKey,
|
||||
const TestKeyPair& signerKeyPair,
|
||||
time_t producedAt, time_t thisUpdate,
|
||||
/*optional*/ const time_t* nextUpdate,
|
||||
/*optional*/ const ByteString* certs = nullptr)
|
||||
|
@ -273,8 +260,8 @@ public:
|
|||
context.signerNameDER = CNToDERName(signerName);
|
||||
EXPECT_NE(ENCODING_FAILED, context.signerNameDER);
|
||||
}
|
||||
context.signerPrivateKey = SECKEY_CopyPrivateKey(signerPrivateKey.get());
|
||||
EXPECT_TRUE(context.signerPrivateKey);
|
||||
context.signerKeyPair = signerKeyPair.Clone();
|
||||
EXPECT_TRUE(context.signerKeyPair);
|
||||
context.responseStatus = OCSPResponseContext::successful;
|
||||
context.producedAt = producedAt;
|
||||
context.certs = certs;
|
||||
|
@ -293,7 +280,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, good_byKey)
|
|||
ByteString responseString(
|
||||
CreateEncodedOCSPSuccessfulResponse(
|
||||
OCSPResponseContext::good, *endEntityCertID, byKey,
|
||||
rootPrivateKey, oneDayBeforeNow,
|
||||
*rootKeyPair, oneDayBeforeNow,
|
||||
oneDayBeforeNow, &oneDayAfterNow));
|
||||
Input response;
|
||||
ASSERT_EQ(Success,
|
||||
|
@ -311,7 +298,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, good_byName)
|
|||
ByteString responseString(
|
||||
CreateEncodedOCSPSuccessfulResponse(
|
||||
OCSPResponseContext::good, *endEntityCertID, rootName,
|
||||
rootPrivateKey, oneDayBeforeNow,
|
||||
*rootKeyPair, oneDayBeforeNow,
|
||||
oneDayBeforeNow, &oneDayAfterNow));
|
||||
Input response;
|
||||
ASSERT_EQ(Success,
|
||||
|
@ -329,7 +316,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, good_byKey_without_nextUpdate)
|
|||
ByteString responseString(
|
||||
CreateEncodedOCSPSuccessfulResponse(
|
||||
OCSPResponseContext::good, *endEntityCertID, byKey,
|
||||
rootPrivateKey, oneDayBeforeNow,
|
||||
*rootKeyPair, oneDayBeforeNow,
|
||||
oneDayBeforeNow, nullptr));
|
||||
Input response;
|
||||
ASSERT_EQ(Success,
|
||||
|
@ -347,7 +334,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, revoked)
|
|||
ByteString responseString(
|
||||
CreateEncodedOCSPSuccessfulResponse(
|
||||
OCSPResponseContext::revoked, *endEntityCertID, byKey,
|
||||
rootPrivateKey, oneDayBeforeNow,
|
||||
*rootKeyPair, oneDayBeforeNow,
|
||||
oneDayBeforeNow, &oneDayAfterNow));
|
||||
Input response;
|
||||
ASSERT_EQ(Success,
|
||||
|
@ -365,7 +352,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, unknown)
|
|||
ByteString responseString(
|
||||
CreateEncodedOCSPSuccessfulResponse(
|
||||
OCSPResponseContext::unknown, *endEntityCertID, byKey,
|
||||
rootPrivateKey, oneDayBeforeNow,
|
||||
*rootKeyPair, oneDayBeforeNow,
|
||||
oneDayBeforeNow, &oneDayAfterNow));
|
||||
Input response;
|
||||
ASSERT_EQ(Success,
|
||||
|
@ -415,12 +402,12 @@ protected:
|
|||
: ByteString(),
|
||||
ByteString()
|
||||
};
|
||||
ScopedSECKEYPrivateKey signerPrivateKey;
|
||||
ScopedTestKeyPair signerKeyPair;
|
||||
ByteString signerDER(CreateEncodedCertificate(
|
||||
++rootIssuedCount, rootName,
|
||||
oneDayBeforeNow, oneDayAfterNow, certSubjectName,
|
||||
signerEKUDER ? extensions : nullptr,
|
||||
rootPrivateKey.get(), signerPrivateKey));
|
||||
rootKeyPair.get(), signerKeyPair));
|
||||
EXPECT_NE(ENCODING_FAILED, signerDER);
|
||||
if (signerDEROut) {
|
||||
*signerDEROut = signerDER;
|
||||
|
@ -433,7 +420,7 @@ protected:
|
|||
}
|
||||
ByteString certs[] = { signerDER, ByteString() };
|
||||
return CreateEncodedOCSPSuccessfulResponse(certStatus, *endEntityCertID,
|
||||
signerName, signerPrivateKey,
|
||||
signerName, *signerKeyPair,
|
||||
oneDayBeforeNow,
|
||||
oneDayBeforeNow,
|
||||
&oneDayAfterNow, certs);
|
||||
|
@ -445,8 +432,8 @@ protected:
|
|||
time_t notAfter,
|
||||
const char* subject,
|
||||
/*optional*/ const ByteString* extensions,
|
||||
/*optional*/ SECKEYPrivateKey* signerKey,
|
||||
/*out*/ ScopedSECKEYPrivateKey& privateKey)
|
||||
/*optional*/ TestKeyPair* signerKeyPair,
|
||||
/*out*/ ScopedTestKeyPair& keyPair)
|
||||
{
|
||||
ByteString serialNumberDER(CreateEncodedSerialNumber(serialNumber));
|
||||
if (serialNumberDER == ENCODING_FAILED) {
|
||||
|
@ -465,9 +452,9 @@ protected:
|
|||
sha256WithRSAEncryption,
|
||||
serialNumberDER, issuerDER, notBefore,
|
||||
notAfter, subjectDER, extensions,
|
||||
signerKey,
|
||||
signerKeyPair,
|
||||
SignatureAlgorithm::rsa_pkcs1_with_sha256,
|
||||
privateKey);
|
||||
keyPair);
|
||||
}
|
||||
|
||||
static const Input OCSPSigningEKUDER;
|
||||
|
@ -513,14 +500,13 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_byName)
|
|||
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
|
||||
good_byKey_missing_signer)
|
||||
{
|
||||
ScopedSECKEYPublicKey missingSignerPublicKey;
|
||||
ScopedSECKEYPrivateKey missingSignerPrivateKey;
|
||||
ASSERT_EQ(Success, GenerateKeyPair(missingSignerPublicKey,
|
||||
missingSignerPrivateKey));
|
||||
ScopedTestKeyPair missingSignerKeyPair(GenerateKeyPair());
|
||||
ASSERT_TRUE(missingSignerKeyPair);
|
||||
|
||||
ByteString responseString(
|
||||
CreateEncodedOCSPSuccessfulResponse(
|
||||
OCSPResponseContext::good, *endEntityCertID, byKey,
|
||||
missingSignerPrivateKey, oneDayBeforeNow,
|
||||
*missingSignerKeyPair, oneDayBeforeNow,
|
||||
oneDayBeforeNow, nullptr));
|
||||
Input response;
|
||||
ASSERT_EQ(Success,
|
||||
|
@ -536,14 +522,12 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
|
|||
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
|
||||
good_byName_missing_signer)
|
||||
{
|
||||
ScopedSECKEYPublicKey missingSignerPublicKey;
|
||||
ScopedSECKEYPrivateKey missingSignerPrivateKey;
|
||||
ASSERT_EQ(Success, GenerateKeyPair(missingSignerPublicKey,
|
||||
missingSignerPrivateKey));
|
||||
ScopedTestKeyPair missingSignerKeyPair(GenerateKeyPair());
|
||||
ASSERT_TRUE(missingSignerKeyPair);
|
||||
ByteString responseString(
|
||||
CreateEncodedOCSPSuccessfulResponse(
|
||||
OCSPResponseContext::good, *endEntityCertID,
|
||||
"missing", missingSignerPrivateKey,
|
||||
"missing", *missingSignerKeyPair,
|
||||
oneDayBeforeNow, oneDayBeforeNow, nullptr));
|
||||
Input response;
|
||||
ASSERT_EQ(Success,
|
||||
|
@ -566,20 +550,20 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_expired)
|
|||
ByteString()
|
||||
};
|
||||
|
||||
ScopedSECKEYPrivateKey signerPrivateKey;
|
||||
ScopedTestKeyPair signerKeyPair;
|
||||
ByteString signerDER(CreateEncodedCertificate(
|
||||
++rootIssuedCount, rootName,
|
||||
now - (10 * Time::ONE_DAY_IN_SECONDS),
|
||||
now - (2 * Time::ONE_DAY_IN_SECONDS),
|
||||
signerName, extensions, rootPrivateKey.get(),
|
||||
signerPrivateKey));
|
||||
signerName, extensions, rootKeyPair.get(),
|
||||
signerKeyPair));
|
||||
ASSERT_NE(ENCODING_FAILED, signerDER);
|
||||
|
||||
ByteString certs[] = { signerDER, ByteString() };
|
||||
ByteString responseString(
|
||||
CreateEncodedOCSPSuccessfulResponse(
|
||||
OCSPResponseContext::good, *endEntityCertID,
|
||||
signerName, signerPrivateKey, oneDayBeforeNow,
|
||||
signerName, *signerKeyPair, oneDayBeforeNow,
|
||||
oneDayBeforeNow, &oneDayAfterNow, certs));
|
||||
Input response;
|
||||
ASSERT_EQ(Success,
|
||||
|
@ -601,20 +585,20 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_future)
|
|||
ByteString()
|
||||
};
|
||||
|
||||
ScopedSECKEYPrivateKey signerPrivateKey;
|
||||
ScopedTestKeyPair signerKeyPair;
|
||||
ByteString signerDER(CreateEncodedCertificate(
|
||||
++rootIssuedCount, rootName,
|
||||
now + (2 * Time::ONE_DAY_IN_SECONDS),
|
||||
now + (10 * Time::ONE_DAY_IN_SECONDS),
|
||||
signerName, extensions, rootPrivateKey.get(),
|
||||
signerPrivateKey));
|
||||
signerName, extensions, rootKeyPair.get(),
|
||||
signerKeyPair));
|
||||
ASSERT_NE(ENCODING_FAILED, signerDER);
|
||||
|
||||
ByteString certs[] = { signerDER, ByteString() };
|
||||
ByteString responseString(
|
||||
CreateEncodedOCSPSuccessfulResponse(
|
||||
OCSPResponseContext::good, *endEntityCertID,
|
||||
signerName, signerPrivateKey, oneDayBeforeNow,
|
||||
signerName, *signerKeyPair, oneDayBeforeNow,
|
||||
oneDayBeforeNow, &oneDayAfterNow, certs));
|
||||
Input response;
|
||||
ASSERT_EQ(Success,
|
||||
|
@ -694,9 +678,8 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_unknown_issuer)
|
|||
static const char* signerName = "good_indirect_unknown_issuer OCSP signer";
|
||||
|
||||
// unknown issuer
|
||||
ScopedSECKEYPublicKey unknownPublicKey;
|
||||
ScopedSECKEYPrivateKey unknownPrivateKey;
|
||||
ASSERT_EQ(Success, GenerateKeyPair(unknownPublicKey, unknownPrivateKey));
|
||||
ScopedTestKeyPair unknownKeyPair(GenerateKeyPair());
|
||||
ASSERT_TRUE(unknownKeyPair);
|
||||
|
||||
// Delegated responder cert signed by unknown issuer
|
||||
const ByteString extensions[] = {
|
||||
|
@ -704,11 +687,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_unknown_issuer)
|
|||
ExtensionCriticality::NotCritical),
|
||||
ByteString()
|
||||
};
|
||||
ScopedSECKEYPrivateKey signerPrivateKey;
|
||||
ScopedTestKeyPair signerKeyPair;
|
||||
ByteString signerDER(CreateEncodedCertificate(
|
||||
1, subCAName, oneDayBeforeNow, oneDayAfterNow,
|
||||
signerName, extensions, unknownPrivateKey.get(),
|
||||
signerPrivateKey));
|
||||
signerName, extensions, unknownKeyPair.get(),
|
||||
signerKeyPair));
|
||||
ASSERT_NE(ENCODING_FAILED, signerDER);
|
||||
|
||||
// OCSP response signed by that delegated responder
|
||||
|
@ -716,7 +699,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_unknown_issuer)
|
|||
ByteString responseString(
|
||||
CreateEncodedOCSPSuccessfulResponse(
|
||||
OCSPResponseContext::good, *endEntityCertID,
|
||||
signerName, signerPrivateKey, oneDayBeforeNow,
|
||||
signerName, *signerKeyPair, oneDayBeforeNow,
|
||||
oneDayBeforeNow, &oneDayAfterNow, certs));
|
||||
Input response;
|
||||
ASSERT_EQ(Success,
|
||||
|
@ -743,12 +726,12 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
|
|||
CreateEncodedBasicConstraints(true, 0, ExtensionCriticality::NotCritical),
|
||||
ByteString()
|
||||
};
|
||||
ScopedSECKEYPrivateKey subCAPrivateKey;
|
||||
ScopedTestKeyPair subCAKeyPair;
|
||||
ByteString subCADER(CreateEncodedCertificate(
|
||||
++rootIssuedCount, rootName,
|
||||
oneDayBeforeNow, oneDayAfterNow,
|
||||
subCAName, subCAExtensions, rootPrivateKey.get(),
|
||||
subCAPrivateKey));
|
||||
subCAName, subCAExtensions, rootKeyPair.get(),
|
||||
subCAKeyPair));
|
||||
ASSERT_NE(ENCODING_FAILED, subCADER);
|
||||
|
||||
// Delegated responder cert signed by that sub-CA
|
||||
|
@ -757,11 +740,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
|
|||
ExtensionCriticality::NotCritical),
|
||||
ByteString(),
|
||||
};
|
||||
ScopedSECKEYPrivateKey signerPrivateKey;
|
||||
ScopedTestKeyPair signerKeyPair;
|
||||
ByteString signerDER(CreateEncodedCertificate(
|
||||
1, subCAName, oneDayBeforeNow, oneDayAfterNow,
|
||||
signerName, extensions, subCAPrivateKey.get(),
|
||||
signerPrivateKey));
|
||||
signerName, extensions, subCAKeyPair.get(),
|
||||
signerKeyPair));
|
||||
ASSERT_NE(ENCODING_FAILED, signerDER);
|
||||
|
||||
// OCSP response signed by the delegated responder issued by the sub-CA
|
||||
|
@ -770,7 +753,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
|
|||
ByteString responseString(
|
||||
CreateEncodedOCSPSuccessfulResponse(
|
||||
OCSPResponseContext::good, *endEntityCertID,
|
||||
signerName, signerPrivateKey, oneDayBeforeNow,
|
||||
signerName, *signerKeyPair, oneDayBeforeNow,
|
||||
oneDayBeforeNow, &oneDayAfterNow, certs));
|
||||
Input response;
|
||||
ASSERT_EQ(Success,
|
||||
|
@ -797,12 +780,12 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
|
|||
CreateEncodedBasicConstraints(true, 0, ExtensionCriticality::NotCritical),
|
||||
ByteString()
|
||||
};
|
||||
ScopedSECKEYPrivateKey subCAPrivateKey;
|
||||
ScopedTestKeyPair subCAKeyPair;
|
||||
ByteString subCADER(CreateEncodedCertificate(++rootIssuedCount, rootName,
|
||||
oneDayBeforeNow, oneDayAfterNow,
|
||||
subCAName, subCAExtensions,
|
||||
rootPrivateKey.get(),
|
||||
subCAPrivateKey));
|
||||
rootKeyPair.get(),
|
||||
subCAKeyPair));
|
||||
ASSERT_NE(ENCODING_FAILED, subCADER);
|
||||
|
||||
// Delegated responder cert signed by that sub-CA
|
||||
|
@ -811,11 +794,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
|
|||
ExtensionCriticality::NotCritical),
|
||||
ByteString()
|
||||
};
|
||||
ScopedSECKEYPrivateKey signerPrivateKey;
|
||||
ScopedTestKeyPair signerKeyPair;
|
||||
ByteString signerDER(CreateEncodedCertificate(
|
||||
1, subCAName, oneDayBeforeNow, oneDayAfterNow,
|
||||
signerName, extensions, subCAPrivateKey.get(),
|
||||
signerPrivateKey));
|
||||
signerName, extensions, subCAKeyPair.get(),
|
||||
signerKeyPair));
|
||||
ASSERT_NE(ENCODING_FAILED, signerDER);
|
||||
|
||||
// OCSP response signed by the delegated responder issued by the sub-CA
|
||||
|
@ -824,7 +807,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
|
|||
ByteString responseString(
|
||||
CreateEncodedOCSPSuccessfulResponse(
|
||||
OCSPResponseContext::good, *endEntityCertID,
|
||||
signerName, signerPrivateKey, oneDayBeforeNow,
|
||||
signerName, *signerKeyPair, oneDayBeforeNow,
|
||||
oneDayBeforeNow, &oneDayAfterNow, certs));
|
||||
Input response;
|
||||
ASSERT_EQ(Success,
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
# limitations under the License.
|
||||
|
||||
SOURCES += [
|
||||
'pkixtestnss.cpp',
|
||||
'pkixtestutil.cpp',
|
||||
]
|
||||
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This code is made available to you under your choice of the following sets
|
||||
* of licensing terms:
|
||||
*/
|
||||
/* 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/.
|
||||
*/
|
||||
/* Copyright 2013 Mozilla Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "pkixtestutil.h"
|
||||
|
||||
#include "cryptohi.h"
|
||||
#include "keyhi.h"
|
||||
#include "pk11pub.h"
|
||||
#include "pkix/pkixnss.h"
|
||||
#include "secerr.h"
|
||||
|
||||
namespace mozilla { namespace pkix { namespace test {
|
||||
|
||||
namespace {
|
||||
|
||||
typedef ScopedPtr<SECKEYPublicKey, SECKEY_DestroyPublicKey>
|
||||
ScopedSECKEYPublicKey;
|
||||
typedef ScopedPtr<SECKEYPrivateKey, SECKEY_DestroyPrivateKey>
|
||||
ScopedSECKEYPrivateKey;
|
||||
|
||||
class NSSTestKeyPair : public TestKeyPair
|
||||
{
|
||||
public:
|
||||
// NSSTestKeyPair takes ownership of privateKey.
|
||||
NSSTestKeyPair(const ByteString& spki,
|
||||
const ByteString& spk,
|
||||
SECKEYPrivateKey* privateKey)
|
||||
: TestKeyPair(spki, spk)
|
||||
, privateKey(privateKey)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Result SignData(const ByteString& tbs,
|
||||
SignatureAlgorithm signatureAlgorithm,
|
||||
/*out*/ ByteString& signature) const
|
||||
{
|
||||
SECOidTag signatureAlgorithmOidTag;
|
||||
switch (signatureAlgorithm) {
|
||||
case SignatureAlgorithm::rsa_pkcs1_with_sha256:
|
||||
signatureAlgorithmOidTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
|
||||
break;
|
||||
default:
|
||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
SECItem signatureItem;
|
||||
if (SEC_SignData(&signatureItem, tbs.data(), tbs.length(),
|
||||
privateKey.get(), signatureAlgorithmOidTag)
|
||||
!= SECSuccess) {
|
||||
return MapPRErrorCodeToResult(PR_GetError());
|
||||
}
|
||||
signature.assign(signatureItem.data, signatureItem.len);
|
||||
SECITEM_FreeItem(&signatureItem, false);
|
||||
return Success;
|
||||
}
|
||||
|
||||
virtual TestKeyPair* Clone() const
|
||||
{
|
||||
ScopedSECKEYPrivateKey
|
||||
privateKeyCopy(SECKEY_CopyPrivateKey(privateKey.get()));
|
||||
if (!privateKeyCopy) {
|
||||
return nullptr;
|
||||
}
|
||||
return new (std::nothrow) NSSTestKeyPair(subjectPublicKeyInfo,
|
||||
subjectPublicKey,
|
||||
privateKeyCopy.release());
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedSECKEYPrivateKey privateKey;
|
||||
};
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
// This private function is also used by Gecko's PSM test framework
|
||||
// (OCSPCommon.cpp).
|
||||
//
|
||||
// Ownership of privateKey is transfered.
|
||||
TestKeyPair* CreateTestKeyPair(const ByteString& spki,
|
||||
const ByteString& spk,
|
||||
SECKEYPrivateKey* privateKey)
|
||||
{
|
||||
return new (std::nothrow) NSSTestKeyPair(spki, spk, privateKey);
|
||||
}
|
||||
|
||||
TestKeyPair*
|
||||
GenerateKeyPair()
|
||||
{
|
||||
ScopedPtr<PK11SlotInfo, PK11_FreeSlot> slot(PK11_GetInternalSlot());
|
||||
if (!slot) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Bug 1012786: PK11_GenerateKeyPair can fail if there is insufficient
|
||||
// entropy to generate a random key. Attempting to add some entropy and
|
||||
// retrying appears to solve this issue.
|
||||
for (uint32_t retries = 0; retries < 10; retries++) {
|
||||
PK11RSAGenParams params;
|
||||
params.keySizeInBits = 2048;
|
||||
params.pe = 3;
|
||||
SECKEYPublicKey* publicKeyTemp = nullptr;
|
||||
ScopedSECKEYPrivateKey
|
||||
privateKey(PK11_GenerateKeyPair(slot.get(), CKM_RSA_PKCS_KEY_PAIR_GEN,
|
||||
¶ms, &publicKeyTemp, false, true,
|
||||
nullptr));
|
||||
ScopedSECKEYPublicKey publicKey(publicKeyTemp);
|
||||
if (privateKey) {
|
||||
ScopedSECItem
|
||||
spkiDER(SECKEY_EncodeDERSubjectPublicKeyInfo(publicKey.get()));
|
||||
if (!spkiDER) {
|
||||
return nullptr;
|
||||
}
|
||||
ScopedPtr<CERTSubjectPublicKeyInfo, SECKEY_DestroySubjectPublicKeyInfo>
|
||||
spki(SECKEY_CreateSubjectPublicKeyInfo(publicKey.get()));
|
||||
if (!spki) {
|
||||
return nullptr;
|
||||
}
|
||||
SECItem spkDER = spki->subjectPublicKey;
|
||||
DER_ConvertBitString(&spkDER); // bits to bytes
|
||||
return CreateTestKeyPair(ByteString(spkiDER->data, spkiDER->len),
|
||||
ByteString(spkDER.data, spkDER.len),
|
||||
privateKey.release());
|
||||
}
|
||||
|
||||
assert(!publicKeyTemp);
|
||||
|
||||
if (PR_GetError() != SEC_ERROR_PKCS11_FUNCTION_FAILED) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Since these keys are only for testing, we don't need them to be good,
|
||||
// random keys.
|
||||
// https://xkcd.com/221/
|
||||
static const uint8_t RANDOM_NUMBER[] = { 4, 4, 4, 4, 4, 4, 4, 4 };
|
||||
if (PK11_RandomUpdate((void*) &RANDOM_NUMBER,
|
||||
sizeof(RANDOM_NUMBER)) != SECSuccess) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} } } // namespace mozilla::pkix::test
|
|
@ -30,15 +30,10 @@
|
|||
#include <new>
|
||||
#include <sstream>
|
||||
|
||||
#include "cert.h"
|
||||
#include "cryptohi.h"
|
||||
#include "hasht.h"
|
||||
#include "pk11pub.h"
|
||||
#include "pkix/pkixnss.h"
|
||||
#include "pkixder.h"
|
||||
#include "pkixutil.h"
|
||||
#include "prinit.h"
|
||||
#include "secerr.h"
|
||||
#include "prprf.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -153,17 +148,17 @@ static ByteString ResponseBytes(OCSPResponseContext& context);
|
|||
static ByteString BasicOCSPResponse(OCSPResponseContext& context);
|
||||
static ByteString ResponseData(OCSPResponseContext& context);
|
||||
static ByteString ResponderID(OCSPResponseContext& context);
|
||||
static ByteString KeyHash(OCSPResponseContext& context);
|
||||
static ByteString KeyHash(const ByteString& subjectPublicKeyInfo);
|
||||
static ByteString SingleResponse(OCSPResponseContext& context);
|
||||
static ByteString CertID(OCSPResponseContext& context);
|
||||
static ByteString CertStatus(OCSPResponseContext& context);
|
||||
|
||||
static ByteString
|
||||
HashedOctetString(const SECItem& bytes)
|
||||
HashedOctetString(const ByteString& bytes)
|
||||
{
|
||||
uint8_t hashBuf[TrustDomain::DIGEST_LENGTH];
|
||||
Input input;
|
||||
if (input.Init(bytes.data, bytes.len) != Success) {
|
||||
if (input.Init(bytes.data(), bytes.length()) != Success) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
if (DigestBuf(input, hashBuf, sizeof(hashBuf)) != Success) {
|
||||
|
@ -172,15 +167,6 @@ HashedOctetString(const SECItem& bytes)
|
|||
return TLV(der::OCTET_STRING, ByteString(hashBuf, sizeof(hashBuf)));
|
||||
}
|
||||
|
||||
static ByteString
|
||||
KeyHashHelper(const CERTSubjectPublicKeyInfo* spki)
|
||||
{
|
||||
// We only need a shallow copy here.
|
||||
SECItem spk = spki->subjectPublicKey;
|
||||
DER_ConvertBitString(&spk); // bits to bytes
|
||||
return HashedOctetString(spk);
|
||||
}
|
||||
|
||||
static ByteString
|
||||
BitString(const ByteString& rawBytes, bool corrupt)
|
||||
{
|
||||
|
@ -361,20 +347,18 @@ YMDHMS(int16_t year, int16_t month, int16_t day,
|
|||
|
||||
static ByteString
|
||||
SignedData(const ByteString& tbsData,
|
||||
SECKEYPrivateKey* privKey,
|
||||
TestKeyPair& keyPair,
|
||||
SignatureAlgorithm signatureAlgorithm,
|
||||
bool corrupt, /*optional*/ const ByteString* certs)
|
||||
{
|
||||
assert(privKey);
|
||||
if (!privKey) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
ByteString signature;
|
||||
if (keyPair.SignData(tbsData, signatureAlgorithm, signature) != Success) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
|
||||
SECOidTag signatureAlgorithmOidTag;
|
||||
ByteString signatureAlgorithmDER;
|
||||
switch (signatureAlgorithm) {
|
||||
case SignatureAlgorithm::rsa_pkcs1_with_sha256:
|
||||
signatureAlgorithmOidTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
|
||||
signatureAlgorithmDER.assign(alg_sha256WithRSAEncryption,
|
||||
sizeof(alg_sha256WithRSAEncryption));
|
||||
break;
|
||||
|
@ -382,17 +366,9 @@ SignedData(const ByteString& tbsData,
|
|||
return ENCODING_FAILED;
|
||||
}
|
||||
|
||||
SECItem signature;
|
||||
if (SEC_SignData(&signature, tbsData.data(), tbsData.length(), privKey,
|
||||
signatureAlgorithmOidTag) != SECSuccess)
|
||||
{
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
// TODO: add ability to have signatures of bit length not divisible by 8,
|
||||
// resulting in unused bits in the bitstring encoding
|
||||
ByteString signatureNested(BitString(ByteString(signature.data, signature.len),
|
||||
corrupt));
|
||||
SECITEM_FreeItem(&signature, false);
|
||||
ByteString signatureNested(BitString(signature, corrupt));
|
||||
if (signatureNested == ENCODING_FAILED) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
|
@ -487,55 +463,6 @@ MaybeLogOutput(const ByteString& result, const char* suffix)
|
|||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Key Pairs
|
||||
|
||||
Result
|
||||
GenerateKeyPair(/*out*/ ScopedSECKEYPublicKey& publicKey,
|
||||
/*out*/ ScopedSECKEYPrivateKey& privateKey)
|
||||
{
|
||||
ScopedPtr<PK11SlotInfo, PK11_FreeSlot> slot(PK11_GetInternalSlot());
|
||||
if (!slot) {
|
||||
return MapPRErrorCodeToResult(PR_GetError());
|
||||
}
|
||||
|
||||
// Bug 1012786: PK11_GenerateKeyPair can fail if there is insufficient
|
||||
// entropy to generate a random key. Attempting to add some entropy and
|
||||
// retrying appears to solve this issue.
|
||||
for (uint32_t retries = 0; retries < 10; retries++) {
|
||||
PK11RSAGenParams params;
|
||||
params.keySizeInBits = 2048;
|
||||
params.pe = 3;
|
||||
SECKEYPublicKey* publicKeyTemp = nullptr;
|
||||
privateKey = PK11_GenerateKeyPair(slot.get(), CKM_RSA_PKCS_KEY_PAIR_GEN,
|
||||
¶ms, &publicKeyTemp, false, true,
|
||||
nullptr);
|
||||
if (privateKey) {
|
||||
publicKey = publicKeyTemp;
|
||||
assert(publicKey);
|
||||
return Success;
|
||||
}
|
||||
|
||||
assert(!publicKeyTemp);
|
||||
|
||||
if (PR_GetError() != SEC_ERROR_PKCS11_FUNCTION_FAILED) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Since these keys are only for testing, we don't need them to be good,
|
||||
// random keys.
|
||||
// https://xkcd.com/221/
|
||||
static const uint8_t RANDOM_NUMBER[] = { 4, 4, 4, 4, 4, 4, 4, 4 };
|
||||
if (PK11_RandomUpdate((void*) &RANDOM_NUMBER,
|
||||
sizeof(RANDOM_NUMBER)) != SECSuccess) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return MapPRErrorCodeToResult(PR_GetError());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Certificates
|
||||
|
||||
|
@ -543,7 +470,7 @@ static ByteString TBSCertificate(long version, const ByteString& serialNumber,
|
|||
Input signature, const ByteString& issuer,
|
||||
time_t notBefore, time_t notAfter,
|
||||
const ByteString& subject,
|
||||
const SECKEYPublicKey* subjectPublicKey,
|
||||
const ByteString& subjectPublicKeyInfo,
|
||||
/*optional*/ const ByteString* extensions);
|
||||
|
||||
// Certificate ::= SEQUENCE {
|
||||
|
@ -557,30 +484,30 @@ CreateEncodedCertificate(long version, Input signature,
|
|||
time_t notBefore, time_t notAfter,
|
||||
const ByteString& subjectNameDER,
|
||||
/*optional*/ const ByteString* extensions,
|
||||
/*optional*/ SECKEYPrivateKey* issuerPrivateKey,
|
||||
/*optional*/ TestKeyPair* issuerKeyPair,
|
||||
SignatureAlgorithm signatureAlgorithm,
|
||||
/*out*/ ScopedSECKEYPrivateKey& privateKeyResult)
|
||||
/*out*/ ScopedTestKeyPair& keyPairResult)
|
||||
{
|
||||
// It may be the case that privateKeyResult refers to the
|
||||
// ScopedSECKEYPrivateKey that owns issuerPrivateKey; thus, we can't set
|
||||
// privateKeyResult until after we're done with issuerPrivateKey.
|
||||
ScopedSECKEYPublicKey publicKey;
|
||||
ScopedSECKEYPrivateKey privateKeyTemp;
|
||||
if (GenerateKeyPair(publicKey, privateKeyTemp) != Success) {
|
||||
// It may be the case that privateKeyResult references the same TestKeyPair
|
||||
// as issuerKeyPair. Thus, we can't set keyPairResult until after we're done
|
||||
// with issuerKeyPair.
|
||||
ScopedTestKeyPair subjectKeyPair(GenerateKeyPair());
|
||||
if (!subjectKeyPair) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
|
||||
ByteString tbsCertificate(TBSCertificate(version, serialNumber,
|
||||
signature, issuerNameDER, notBefore,
|
||||
notAfter, subjectNameDER,
|
||||
publicKey.get(), extensions));
|
||||
subjectKeyPair->subjectPublicKeyInfo,
|
||||
extensions));
|
||||
if (tbsCertificate == ENCODING_FAILED) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
|
||||
ByteString result(SignedData(tbsCertificate,
|
||||
issuerPrivateKey ? issuerPrivateKey
|
||||
: privateKeyTemp.get(),
|
||||
issuerKeyPair ? *issuerKeyPair
|
||||
: *subjectKeyPair,
|
||||
signatureAlgorithm, false, nullptr));
|
||||
if (result == ENCODING_FAILED) {
|
||||
return ENCODING_FAILED;
|
||||
|
@ -588,7 +515,7 @@ CreateEncodedCertificate(long version, Input signature,
|
|||
|
||||
MaybeLogOutput(result, "cert");
|
||||
|
||||
privateKeyResult = privateKeyTemp.release();
|
||||
keyPairResult = subjectKeyPair.release();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -612,14 +539,9 @@ TBSCertificate(long versionValue,
|
|||
const ByteString& serialNumber, Input signature,
|
||||
const ByteString& issuer, time_t notBeforeTime,
|
||||
time_t notAfterTime, const ByteString& subject,
|
||||
const SECKEYPublicKey* subjectPublicKey,
|
||||
const ByteString& subjectPublicKeyInfo,
|
||||
/*optional*/ const ByteString* extensions)
|
||||
{
|
||||
assert(subjectPublicKey);
|
||||
if (!subjectPublicKey) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
|
||||
ByteString value;
|
||||
|
||||
if (versionValue != static_cast<long>(der::Version::v1)) {
|
||||
|
@ -664,15 +586,7 @@ TBSCertificate(long versionValue,
|
|||
|
||||
value.append(subject);
|
||||
|
||||
// SubjectPublicKeyInfo ::= SEQUENCE {
|
||||
// algorithm AlgorithmIdentifier,
|
||||
// subjectPublicKey BIT STRING }
|
||||
ScopedSECItem subjectPublicKeyInfo(
|
||||
SECKEY_EncodeDERSubjectPublicKeyInfo(subjectPublicKey));
|
||||
if (!subjectPublicKeyInfo) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
value.append(subjectPublicKeyInfo->data, subjectPublicKeyInfo->len);
|
||||
value.append(subjectPublicKeyInfo);
|
||||
|
||||
if (extensions) {
|
||||
ByteString extensionsValue;
|
||||
|
@ -809,7 +723,7 @@ ByteString
|
|||
CreateEncodedOCSPResponse(OCSPResponseContext& context)
|
||||
{
|
||||
if (!context.skipResponseBytes) {
|
||||
if (!context.signerPrivateKey) {
|
||||
if (!context.signerKeyPair) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
}
|
||||
|
@ -901,8 +815,7 @@ BasicOCSPResponse(OCSPResponseContext& context)
|
|||
}
|
||||
|
||||
// TODO(bug 980538): certs
|
||||
return SignedData(tbsResponseData,
|
||||
context.signerPrivateKey.get(),
|
||||
return SignedData(tbsResponseData, *context.signerKeyPair,
|
||||
SignatureAlgorithm::rsa_pkcs1_with_sha256,
|
||||
context.badSignature, context.certs);
|
||||
}
|
||||
|
@ -1005,7 +918,7 @@ ResponderID(OCSPResponseContext& context)
|
|||
contents = context.signerNameDER;
|
||||
responderIDType = 1; // byName
|
||||
} else {
|
||||
contents = KeyHash(context);
|
||||
contents = KeyHash(context.signerKeyPair->subjectPublicKey);
|
||||
if (contents == ENCODING_FAILED) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
|
@ -1022,19 +935,9 @@ ResponderID(OCSPResponseContext& context)
|
|||
// -- the tag, length, and number of unused
|
||||
// -- bits] in the responder's certificate)
|
||||
ByteString
|
||||
KeyHash(OCSPResponseContext& context)
|
||||
KeyHash(const ByteString& subjectPublicKey)
|
||||
{
|
||||
ScopedSECKEYPublicKey
|
||||
signerPublicKey(SECKEY_ConvertToPublicKey(context.signerPrivateKey.get()));
|
||||
if (!signerPublicKey) {
|
||||
return nullptr;
|
||||
}
|
||||
ScopedPtr<CERTSubjectPublicKeyInfo, SECKEY_DestroySubjectPublicKeyInfo>
|
||||
signerSPKI(SECKEY_CreateSubjectPublicKeyInfo(signerPublicKey.get()));
|
||||
if (!signerSPKI) {
|
||||
return nullptr;
|
||||
}
|
||||
return KeyHashHelper(signerSPKI.get());
|
||||
return HashedOctetString(subjectPublicKey);
|
||||
}
|
||||
|
||||
// SingleResponse ::= SEQUENCE {
|
||||
|
@ -1087,23 +990,37 @@ SingleResponse(OCSPResponseContext& context)
|
|||
ByteString
|
||||
CertID(OCSPResponseContext& context)
|
||||
{
|
||||
SECItem issuerSECItem = UnsafeMapInputToSECItem(context.certID.issuer);
|
||||
ByteString issuerNameHash(HashedOctetString(issuerSECItem));
|
||||
ByteString issuerName(context.certID.issuer.UnsafeGetData(),
|
||||
context.certID.issuer.GetLength());
|
||||
ByteString issuerNameHash(HashedOctetString(issuerName));
|
||||
if (issuerNameHash == ENCODING_FAILED) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
|
||||
SECItem issuerSubjectPublicKeyInfoSECItem =
|
||||
UnsafeMapInputToSECItem(context.certID.issuerSubjectPublicKeyInfo);
|
||||
ScopedPtr<CERTSubjectPublicKeyInfo, SECKEY_DestroySubjectPublicKeyInfo>
|
||||
spki(SECKEY_DecodeDERSubjectPublicKeyInfo(
|
||||
&issuerSubjectPublicKeyInfoSECItem));
|
||||
if (!spki) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
ByteString issuerKeyHash(KeyHashHelper(spki.get()));
|
||||
if (issuerKeyHash == ENCODING_FAILED) {
|
||||
return ENCODING_FAILED;
|
||||
ByteString issuerKeyHash;
|
||||
{
|
||||
// context.certID.issuerSubjectPublicKeyInfo is the entire
|
||||
// SubjectPublicKeyInfo structure, but we need just the subjectPublicKey
|
||||
// part.
|
||||
Reader input(context.certID.issuerSubjectPublicKeyInfo);
|
||||
Reader contents;
|
||||
if (der::ExpectTagAndGetValue(input, der::SEQUENCE, contents) != Success) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
// Skip AlgorithmIdentifier
|
||||
if (der::ExpectTagAndSkipValue(contents, der::SEQUENCE) != Success) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
Input subjectPublicKey;
|
||||
if (der::BitStringWithNoUnusedBits(contents, subjectPublicKey)
|
||||
!= Success) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
issuerKeyHash = KeyHash(ByteString(subjectPublicKey.UnsafeGetData(),
|
||||
subjectPublicKey.GetLength()));
|
||||
if (issuerKeyHash == ENCODING_FAILED) {
|
||||
return ENCODING_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ByteString serialNumberValue(context.certID.serialNumber.UnsafeGetData(),
|
||||
|
|
|
@ -29,11 +29,10 @@
|
|||
#include <stdint.h> // Some Mozilla-supported compilers lack <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "keyhi.h"
|
||||
#include "pkix/enumclass.h"
|
||||
#include "pkix/pkixtypes.h"
|
||||
#include "pkix/ScopedPtr.h"
|
||||
#include "seccomon.h"
|
||||
#include "secitem.h"
|
||||
|
||||
namespace mozilla { namespace pkix { namespace test {
|
||||
|
||||
|
@ -76,10 +75,6 @@ SECITEM_FreeItem_true(SECItem* item)
|
|||
} // unnamed namespace
|
||||
|
||||
typedef mozilla::pkix::ScopedPtr<SECItem, SECITEM_FreeItem_true> ScopedSECItem;
|
||||
typedef mozilla::pkix::ScopedPtr<SECKEYPublicKey, SECKEY_DestroyPublicKey>
|
||||
ScopedSECKEYPublicKey;
|
||||
typedef mozilla::pkix::ScopedPtr<SECKEYPrivateKey, SECKEY_DestroyPrivateKey>
|
||||
ScopedSECKEYPrivateKey;
|
||||
|
||||
// python DottedOIDToCode.py --tlv id-kp-OCSPSigning 1.3.6.1.5.5.7.3.9
|
||||
static const uint8_t tlv_id_kp_OCSPSigning[] = {
|
||||
|
@ -97,11 +92,42 @@ extern const Input sha256WithRSAEncryption;
|
|||
mozilla::pkix::Time YMDHMS(int16_t year, int16_t month, int16_t day,
|
||||
int16_t hour, int16_t minutes, int16_t seconds);
|
||||
|
||||
Result GenerateKeyPair(/*out*/ ScopedSECKEYPublicKey& publicKey,
|
||||
/*out*/ ScopedSECKEYPrivateKey& privateKey);
|
||||
|
||||
ByteString CNToDERName(const char* cn);
|
||||
|
||||
class TestKeyPair
|
||||
{
|
||||
public:
|
||||
virtual ~TestKeyPair() { }
|
||||
|
||||
// The DER encoding of the entire SubjectPublicKeyInfo structure. This is
|
||||
// what is encoded in certificates.
|
||||
const ByteString subjectPublicKeyInfo;
|
||||
|
||||
// The DER encoding of subjectPublicKeyInfo.subjectPublicKey. This is what is
|
||||
// hashed to create CertIDs for OCSP.
|
||||
const ByteString subjectPublicKey;
|
||||
|
||||
virtual Result SignData(const ByteString& tbs,
|
||||
SignatureAlgorithm signatureAlgorithm,
|
||||
/*out*/ ByteString& signature) const = 0;
|
||||
|
||||
virtual TestKeyPair* Clone() const = 0;
|
||||
protected:
|
||||
TestKeyPair(const ByteString& spki, const ByteString& spk)
|
||||
: subjectPublicKeyInfo(spki)
|
||||
, subjectPublicKey(spk)
|
||||
{
|
||||
}
|
||||
|
||||
TestKeyPair(const TestKeyPair&) /*= delete*/;
|
||||
void operator=(const TestKeyPair&) /*= delete*/;
|
||||
};
|
||||
|
||||
TestKeyPair* GenerateKeyPair();
|
||||
inline void DeleteTestKeyPair(TestKeyPair* keyPair) { delete keyPair; }
|
||||
typedef ScopedPtr<TestKeyPair, DeleteTestKeyPair> ScopedTestKeyPair;
|
||||
|
||||
// Replace one substring in item with another of the same length, but only if
|
||||
// the substring was found exactly once. The "same length" restriction is
|
||||
// useful for avoiding invalidating lengths encoded within the item. The
|
||||
|
@ -128,16 +154,15 @@ enum Version { v1 = 0, v2 = 1, v3 = 2 };
|
|||
// If issuerPrivateKey is null, then the certificate will be self-signed.
|
||||
// Parameter order is based on the order of the attributes of the certificate
|
||||
// in RFC 5280.
|
||||
ByteString CreateEncodedCertificate(long version,
|
||||
Input signature,
|
||||
ByteString CreateEncodedCertificate(long version, Input signature,
|
||||
const ByteString& serialNumber,
|
||||
const ByteString& issuerNameDER,
|
||||
std::time_t notBefore, std::time_t notAfter,
|
||||
time_t notBefore, time_t notAfter,
|
||||
const ByteString& subjectNameDER,
|
||||
/*optional*/ const ByteString* extensions,
|
||||
/*optional*/ SECKEYPrivateKey* issuerPrivateKey,
|
||||
/*optional*/ const ByteString* extensions,
|
||||
/*optional*/ TestKeyPair* issuerKeyPair,
|
||||
SignatureAlgorithm signatureAlgorithm,
|
||||
/*out*/ ScopedSECKEYPrivateKey& privateKey);
|
||||
/*out*/ ScopedTestKeyPair& keyPairResult);
|
||||
|
||||
ByteString CreateEncodedSerialNumber(long value);
|
||||
|
||||
|
@ -196,7 +221,7 @@ public:
|
|||
bool includeEmptyExtensions; // If true, include the extension wrapper
|
||||
// regardless of if there are any actual
|
||||
// extensions.
|
||||
ScopedSECKEYPrivateKey signerPrivateKey;
|
||||
ScopedTestKeyPair signerKeyPair;
|
||||
bool badSignature; // If true, alter the signature to fail verification
|
||||
const ByteString* certs; // optional; array terminated by an empty string
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче