diff --git a/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp b/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp index d5e4d0345427..9af09b8bc3af 100644 --- a/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp +++ b/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp @@ -7,19 +7,11 @@ #include #include "pkixtestutil.h" +#include "pkixtestnss.h" #include "TLSServer.h" #include "secder.h" #include "secerr.h" -namespace mozilla { namespace pkix { namespace test { - -// Ownership of privateKey is transfered. -TestKeyPair* CreateTestKeyPair(const TestPublicKeyAlgorithm publicKeyAlg, - const SECKEYPublicKey& publicKey, - SECKEYPrivateKey* privateKey); - -} } } // namespace mozilla::pkix::test - using namespace mozilla; using namespace mozilla::pkix; using namespace mozilla::pkix::test; @@ -28,15 +20,15 @@ using namespace mozilla::test; static TestKeyPair* CreateTestKeyPairFromCert(const UniqueCERTCertificate& cert) { - UniqueSECKEYPrivateKey privateKey(PK11_FindKeyByAnyCert(cert.get(), nullptr)); + ScopedSECKEYPrivateKey privateKey(PK11_FindKeyByAnyCert(cert.get(), nullptr)); if (!privateKey) { return nullptr; } - UniqueSECKEYPublicKey publicKey(CERT_ExtractPublicKey(cert.get())); + ScopedSECKEYPublicKey publicKey(CERT_ExtractPublicKey(cert.get())); if (!publicKey) { return nullptr; } - return CreateTestKeyPair(RSA_PKCS1(), *publicKey.get(), privateKey.release()); + return CreateTestKeyPair(RSA_PKCS1(), publicKey, privateKey); } SECItemArray* diff --git a/security/nss.symbols b/security/nss.symbols index 4842b57c60f7..a3b14d517d7e 100644 --- a/security/nss.symbols +++ b/security/nss.symbols @@ -390,6 +390,7 @@ PK11_ImportCert PK11_ImportCertForKey PK11_ImportCRL PK11_ImportDERPrivateKeyInfoAndReturnKey +PK11_ImportEncryptedPrivateKeyInfoAndReturnKey PK11_ImportPublicKey PK11_ImportSymKey PK11_InitPin diff --git a/security/pkix/test/lib/pkixtestnss.cpp b/security/pkix/test/lib/pkixtestnss.cpp index 4d49b9e31ab8..504e0b279154 100644 --- a/security/pkix/test/lib/pkixtestnss.cpp +++ b/security/pkix/test/lib/pkixtestnss.cpp @@ -23,6 +23,7 @@ */ #include "pkixtestutil.h" +#include "pkixtestnss.h" #include @@ -42,17 +43,18 @@ namespace mozilla { namespace pkix { namespace test { namespace { -typedef ScopedPtr - ScopedSECKEYPublicKey; -typedef ScopedPtr - ScopedSECKEYPrivateKey; - inline void SECITEM_FreeItem_true(SECItem* item) { SECITEM_FreeItem(item, true); } +inline void +SECKEY_DestroyEncryptedPrivateKeyInfo_true(SECKEYEncryptedPrivateKeyInfo* e) +{ + SECKEY_DestroyEncryptedPrivateKeyInfo(e, true); +} + typedef mozilla::pkix::ScopedPtr ScopedSECItem; TestKeyPair* GenerateKeyPairInner(); @@ -78,12 +80,15 @@ InitReusedKeyPair() class NSSTestKeyPair final : public TestKeyPair { public: - // NSSTestKeyPair takes ownership of privateKey. NSSTestKeyPair(const TestPublicKeyAlgorithm& publicKeyAlg, const ByteString& spk, - SECKEYPrivateKey* privateKey) + const ByteString& encryptedPrivateKey, + const ByteString& encryptionAlgorithm, + const ByteString& encryptionParams) : TestKeyPair(publicKeyAlg, spk) - , privateKey(privateKey) + , encryptedPrivateKey(encryptedPrivateKey) + , encryptionAlgorithm(encryptionAlgorithm) + , encryptionParams(encryptionParams) { } @@ -121,10 +126,50 @@ public: abort(); } + ScopedPtr slot(PK11_GetInternalSlot()); + if (!slot) { + return MapPRErrorCodeToResult(PR_GetError()); + } + SECItem encryptedPrivateKeyInfoItem = { + siBuffer, + const_cast(encryptedPrivateKey.data()), + static_cast(encryptedPrivateKey.length()) + }; + SECItem encryptionAlgorithmItem = { + siBuffer, + const_cast(encryptionAlgorithm.data()), + static_cast(encryptionAlgorithm.length()) + }; + SECItem encryptionParamsItem = { + siBuffer, + const_cast(encryptionParams.data()), + static_cast(encryptionParams.length()) + }; + SECKEYEncryptedPrivateKeyInfo encryptedPrivateKeyInfo = { + nullptr, + { encryptionAlgorithmItem, encryptionParamsItem }, + encryptedPrivateKeyInfoItem + }; + SECItem passwordItem = { siBuffer, nullptr, 0 }; + SECItem publicValueItem = { + siBuffer, + const_cast(subjectPublicKey.data()), + static_cast(subjectPublicKey.length()) + }; + SECKEYPrivateKey* privateKey; + // This should always be an RSA key (we'll have aborted above if we're not + // doing an RSA signature). + if (PK11_ImportEncryptedPrivateKeyInfoAndReturnKey( + slot.get(), &encryptedPrivateKeyInfo, &passwordItem, nullptr, + &publicValueItem, false, false, rsaKey, KU_ALL, &privateKey, + nullptr) != SECSuccess) { + return MapPRErrorCodeToResult(PR_GetError()); + } + ScopedSECKEYPrivateKey scopedPrivateKey(privateKey); SECItem signatureItem; if (SEC_SignData(&signatureItem, tbs.data(), static_cast(tbs.length()), - privateKey.get(), oidTag) != SECSuccess) { + scopedPrivateKey.get(), oidTag) != SECSuccess) { return MapPRErrorCodeToResult(PR_GetError()); } signature.assign(signatureItem.data, signatureItem.len); @@ -134,40 +179,64 @@ public: TestKeyPair* Clone() const override { - ScopedSECKEYPrivateKey - privateKeyCopy(SECKEY_CopyPrivateKey(privateKey.get())); - if (!privateKeyCopy) { - return nullptr; - } return new (std::nothrow) NSSTestKeyPair(publicKeyAlg, subjectPublicKey, - privateKeyCopy.release()); + encryptedPrivateKey, + encryptionAlgorithm, + encryptionParams); } private: - ScopedSECKEYPrivateKey privateKey; + const ByteString encryptedPrivateKey; + const ByteString encryptionAlgorithm; + const ByteString encryptionParams; }; } // namespace // This private function is also used by Gecko's PSM test framework // (OCSPCommon.cpp). -// -// Ownership of privateKey is transfered. TestKeyPair* CreateTestKeyPair(const TestPublicKeyAlgorithm publicKeyAlg, - const SECKEYPublicKey& publicKey, - SECKEYPrivateKey* privateKey) + const ScopedSECKEYPublicKey& publicKey, + const ScopedSECKEYPrivateKey& privateKey) { ScopedPtr - spki(SECKEY_CreateSubjectPublicKeyInfo(&publicKey)); + spki(SECKEY_CreateSubjectPublicKeyInfo(publicKey.get())); if (!spki) { return nullptr; } SECItem spkDER = spki->subjectPublicKey; DER_ConvertBitString(&spkDER); // bits to bytes - return new (std::nothrow) NSSTestKeyPair(publicKeyAlg, - ByteString(spkDER.data, spkDER.len), - privateKey); + ScopedPtr slot(PK11_GetInternalSlot()); + if (!slot) { + return nullptr; + } + // Because NSSTestKeyPair isn't tracked by XPCOM and won't otherwise be aware + // of shutdown, we don't have a way to release NSS resources at the + // appropriate time. To work around this, NSSTestKeyPair doesn't hold on to + // NSS resources. Instead, we export the generated private key part as an + // encrypted blob (with an empty password and fairly lame encryption). When we + // need to use it (e.g. to sign something), we decrypt it and create a + // temporary key object. + SECItem passwordItem = { siBuffer, nullptr, 0 }; + ScopedPtr encryptedPrivateKey( + PK11_ExportEncryptedPrivKeyInfo( + slot.get(), SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC, + &passwordItem, privateKey.get(), 1, nullptr)); + if (!encryptedPrivateKey) { + return nullptr; + } + + return new (std::nothrow) NSSTestKeyPair( + publicKeyAlg, + ByteString(spkDER.data, spkDER.len), + ByteString(encryptedPrivateKey->encryptedData.data, + encryptedPrivateKey->encryptedData.len), + ByteString(encryptedPrivateKey->algorithm.algorithm.data, + encryptedPrivateKey->algorithm.algorithm.len), + ByteString(encryptedPrivateKey->algorithm.parameters.data, + encryptedPrivateKey->algorithm.parameters.len)); } namespace { @@ -194,7 +263,7 @@ GenerateKeyPairInner() nullptr)); ScopedSECKEYPublicKey publicKey(publicKeyTemp); if (privateKey) { - return CreateTestKeyPair(RSA_PKCS1(), *publicKey, privateKey.release()); + return CreateTestKeyPair(RSA_PKCS1(), publicKey, privateKey); } assert(!publicKeyTemp); @@ -275,7 +344,7 @@ GenerateDSSKeyPair() return nullptr; } ScopedSECKEYPublicKey publicKey(publicKeyTemp); - return CreateTestKeyPair(DSS(), *publicKey, privateKey.release()); + return CreateTestKeyPair(DSS(), publicKey, privateKey); } Result diff --git a/security/pkix/test/lib/pkixtestnss.h b/security/pkix/test/lib/pkixtestnss.h new file mode 100644 index 000000000000..18a7e1086552 --- /dev/null +++ b/security/pkix/test/lib/pkixtestnss.h @@ -0,0 +1,49 @@ +/* -*- 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 2018 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. + */ + +// This file provides some implementation-specific test utilities. This is only +// necessary because some PSM xpcshell test utilities overlap in functionality +// with these test utilities, so the underlying implementation is shared. + +#ifndef mozilla_pkix_test_pkixtestnss_h +#define mozilla_pkix_test_pkixtestnss_h + +#include "keyhi.h" +#include "keythi.h" +#include "pkixtestutil.h" + +namespace mozilla { namespace pkix { namespace test { + +typedef ScopedPtr + ScopedSECKEYPublicKey; +typedef ScopedPtr + ScopedSECKEYPrivateKey; + +TestKeyPair* CreateTestKeyPair(const TestPublicKeyAlgorithm publicKeyAlg, + const ScopedSECKEYPublicKey& publicKey, + const ScopedSECKEYPrivateKey& privateKey); + +} } } // namespace mozilla::pkix::test + +#endif // mozilla_pkix_test_pkixtestnss_h diff --git a/security/pkix/test/lib/pkixtestutil.h b/security/pkix/test/lib/pkixtestutil.h index 76f964a43db9..f46cdbea5de5 100644 --- a/security/pkix/test/lib/pkixtestutil.h +++ b/security/pkix/test/lib/pkixtestutil.h @@ -22,8 +22,8 @@ * limitations under the License. */ -#ifndef mozilla_pkix_test_pkixtestutils_h -#define mozilla_pkix_test_pkixtestutils_h +#ifndef mozilla_pkix_test_pkixtestutil_h +#define mozilla_pkix_test_pkixtestutil_h #include #include // Some Mozilla-supported compilers lack @@ -445,4 +445,4 @@ ByteString CreateEncodedOCSPResponse(OCSPResponseContext& context); } } } // namespace mozilla::pkix::test -#endif // mozilla_pkix_test_pkixtestutils_h +#endif // mozilla_pkix_test_pkixtestutil_h