diff options
Diffstat (limited to 'security/pkix/test')
-rw-r--r-- | security/pkix/test/lib/pkixtestalg.cpp | 38 | ||||
-rw-r--r-- | security/pkix/test/lib/pkixtestnss.cpp | 167 | ||||
-rw-r--r-- | security/pkix/test/lib/pkixtestutil.cpp | 51 | ||||
-rw-r--r-- | security/pkix/test/lib/pkixtestutil.h | 447 |
4 files changed, 132 insertions, 571 deletions
diff --git a/security/pkix/test/lib/pkixtestalg.cpp b/security/pkix/test/lib/pkixtestalg.cpp index 9a2fcd69ae..d698154d04 100644 --- a/security/pkix/test/lib/pkixtestalg.cpp +++ b/security/pkix/test/lib/pkixtestalg.cpp @@ -1,29 +1,13 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 2015 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 "pkix/test/pkixtestutil.h" -#include "pkixder.h" +#include "pkix/pkixder.h" +#include "nss_scoped_ptrs.h" // python DottedOIDToCode.py --prefixdefine PREFIX_1_2_840_10040 1.2.840.10040 #define PREFIX_1_2_840_10040 0x2a, 0x86, 0x48, 0xce, 0x38 @@ -136,14 +120,14 @@ static const uint8_t DSS_G_RAW[] = } // namespace TestSignatureAlgorithm::TestSignatureAlgorithm( - const TestPublicKeyAlgorithm& publicKeyAlg, - TestDigestAlgorithmID digestAlg, - const ByteString& algorithmIdentifier, - bool accepted) - : publicKeyAlg(publicKeyAlg) - , digestAlg(digestAlg) - , algorithmIdentifier(algorithmIdentifier) - , accepted(accepted) + const TestPublicKeyAlgorithm& aPublicKeyAlg, + TestDigestAlgorithmID aDigestAlg, + const ByteString& aAlgorithmIdentifier, + bool aAccepted) + : publicKeyAlg(aPublicKeyAlg) + , digestAlg(aDigestAlg) + , algorithmIdentifier(aAlgorithmIdentifier) + , accepted(aAccepted) { } diff --git a/security/pkix/test/lib/pkixtestnss.cpp b/security/pkix/test/lib/pkixtestnss.cpp index ce9dfbb12e..001fdfbc46 100644 --- a/security/pkix/test/lib/pkixtestnss.cpp +++ b/security/pkix/test/lib/pkixtestnss.cpp @@ -1,27 +1,11 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "pkix/test/pkixtestutil.h" +#include "pkix/test/pkixtestnss.h" #include <limits> @@ -30,9 +14,10 @@ #include "nss.h" #include "pk11pqg.h" #include "pk11pub.h" +#include "nss_scoped_ptrs.h" #include "pkix/pkixnss.h" -#include "pkixder.h" -#include "pkixutil.h" +#include "pkix/pkixder.h" +#include "pkix/pkixutil.h" #include "prinit.h" #include "secerr.h" #include "secitem.h" @@ -41,19 +26,6 @@ namespace mozilla { namespace pkix { namespace test { namespace { -typedef ScopedPtr<SECKEYPublicKey, SECKEY_DestroyPublicKey> - ScopedSECKEYPublicKey; -typedef ScopedPtr<SECKEYPrivateKey, SECKEY_DestroyPrivateKey> - ScopedSECKEYPrivateKey; - -inline void -SECITEM_FreeItem_true(SECItem* item) -{ - SECITEM_FreeItem(item, true); -} - -typedef mozilla::pkix::ScopedPtr<SECItem, SECITEM_FreeItem_true> ScopedSECItem; - TestKeyPair* GenerateKeyPairInner(); void @@ -77,12 +49,15 @@ InitReusedKeyPair() class NSSTestKeyPair final : public TestKeyPair { public: - // NSSTestKeyPair takes ownership of privateKey. - NSSTestKeyPair(const TestPublicKeyAlgorithm& publicKeyAlg, + NSSTestKeyPair(const TestPublicKeyAlgorithm& aPublicKeyAlg, const ByteString& spk, - SECKEYPrivateKey* privateKey) - : TestKeyPair(publicKeyAlg, spk) - , privateKey(privateKey) + const ByteString& aEncryptedPrivateKey, + const ByteString& aEncryptionAlgorithm, + const ByteString& aEncryptionParams) + : TestKeyPair(aPublicKeyAlg, spk) + , encryptedPrivateKey(aEncryptedPrivateKey) + , encryptionAlgorithm(aEncryptionAlgorithm) + , encryptionParams(aEncryptionParams) { } @@ -120,10 +95,50 @@ public: abort(); } + ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); + if (!slot) { + return MapPRErrorCodeToResult(PR_GetError()); + } + SECItem encryptedPrivateKeyInfoItem = { + siBuffer, + const_cast<uint8_t*>(encryptedPrivateKey.data()), + static_cast<unsigned int>(encryptedPrivateKey.length()) + }; + SECItem encryptionAlgorithmItem = { + siBuffer, + const_cast<uint8_t*>(encryptionAlgorithm.data()), + static_cast<unsigned int>(encryptionAlgorithm.length()) + }; + SECItem encryptionParamsItem = { + siBuffer, + const_cast<uint8_t*>(encryptionParams.data()), + static_cast<unsigned int>(encryptionParams.length()) + }; + SECKEYEncryptedPrivateKeyInfo encryptedPrivateKeyInfo = { + nullptr, + { encryptionAlgorithmItem, encryptionParamsItem }, + encryptedPrivateKeyInfoItem + }; + SECItem passwordItem = { siBuffer, nullptr, 0 }; + SECItem publicValueItem = { + siBuffer, + const_cast<uint8_t*>(subjectPublicKey.data()), + static_cast<unsigned int>(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<int>(tbs.length()), - privateKey.get(), oidTag) != SECSuccess) { + scopedPrivateKey.get(), oidTag) != SECSuccess) { return MapPRErrorCodeToResult(PR_GetError()); } signature.assign(signatureItem.data, signatureItem.len); @@ -133,40 +148,63 @@ 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<CERTSubjectPublicKeyInfo, SECKEY_DestroySubjectPublicKeyInfo> - spki(SECKEY_CreateSubjectPublicKeyInfo(&publicKey)); + ScopedCERTSubjectPublicKeyInfo + 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); + ScopedPK11SlotInfo 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 }; + ScopedSECKEYEncryptedPrivateKeyInfo 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 { @@ -174,18 +212,18 @@ namespace { TestKeyPair* GenerateKeyPairInner() { - ScopedPtr<PK11SlotInfo, PK11_FreeSlot> slot(PK11_GetInternalSlot()); + ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); if (!slot) { abort(); } + PK11RSAGenParams params; + params.keySizeInBits = 2048; + params.pe = 65537; // 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, @@ -193,7 +231,7 @@ GenerateKeyPairInner() nullptr)); ScopedSECKEYPublicKey publicKey(publicKeyTemp); if (privateKey) { - return CreateTestKeyPair(RSA_PKCS1(), *publicKey, privateKey.release()); + return CreateTestKeyPair(RSA_PKCS1(), publicKey, privateKey); } assert(!publicKeyTemp); @@ -206,8 +244,9 @@ GenerateKeyPairInner() // 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) { + if (PK11_RandomUpdate( + const_cast<void*>(reinterpret_cast<const void*>(RANDOM_NUMBER)), + sizeof(RANDOM_NUMBER)) != SECSuccess) { break; } } @@ -240,7 +279,7 @@ GenerateDSSKeyPair() { InitNSSIfNeeded(); - ScopedPtr<PK11SlotInfo, PK11_FreeSlot> slot(PK11_GetInternalSlot()); + ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); if (!slot) { return nullptr; } @@ -274,7 +313,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/pkixtestutil.cpp b/security/pkix/test/lib/pkixtestutil.cpp index fa4d7eeee0..32401af81b 100644 --- a/security/pkix/test/lib/pkixtestutil.cpp +++ b/security/pkix/test/lib/pkixtestutil.cpp @@ -1,27 +1,10 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "pkix/test/pkixtestutil.h" #include <cerrno> #include <cstdio> @@ -30,8 +13,8 @@ #include <sstream> #include <cstdlib> -#include "pkixder.h" -#include "pkixutil.h" +#include "pkix/pkixder.h" +#include "pkix/pkixutil.h" using namespace std; @@ -39,12 +22,14 @@ namespace mozilla { namespace pkix { namespace test { namespace { -inline void -fclose_void(FILE* file) { - (void) fclose(file); -} - -typedef mozilla::pkix::ScopedPtr<FILE, fclose_void> ScopedFILE; +struct ScopedMaybeDeleteFile { + void operator()(FILE* f) { + if (f) { + (void)fclose(f); + } + } +}; +typedef std::unique_ptr<FILE, ScopedMaybeDeleteFile> ScopedFILE; FILE* OpenFile(const string& dir, const string& filename, const string& mode) @@ -151,8 +136,8 @@ OCSPResponseExtension::OCSPResponseExtension() { } -OCSPResponseContext::OCSPResponseContext(const CertID& certID, time_t time) - : certID(certID) +OCSPResponseContext::OCSPResponseContext(const CertID& aCertID, time_t time) + : certID(aCertID) , responseStatus(successful) , skipResponseBytes(false) , producedAt(time) @@ -248,7 +233,7 @@ Integer(long value) enum TimeEncoding { UTCTime = 0, GeneralizedTime = 1 }; // Windows doesn't provide gmtime_r, but it provides something very similar. -#if defined(WIN32) && !defined(_POSIX_THREAD_SAFE_FUNCTIONS) +#if defined(_WINDOWS) && (!defined(_POSIX_C_SOURCE) || !defined(_POSIX_THREAD_SAFE_FUNCTIONS)) static tm* gmtime_r(const time_t* t, /*out*/ tm* exploded) { @@ -738,7 +723,7 @@ CreateEncodedSerialNumber(long serialNumberValue) // pathLenConstraint INTEGER (0..MAX) OPTIONAL } ByteString CreateEncodedBasicConstraints(bool isCA, - /*optional*/ long* pathLenConstraintValue, + /*optional in*/ const long* pathLenConstraintValue, Critical critical) { ByteString value; @@ -1139,11 +1124,11 @@ CertStatus(OCSPResponseContext& context) static const ByteString NO_UNUSED_BITS(1, 0x00); // The SubjectPublicKeyInfo syntax is specified in RFC 5280 Section 4.1. -TestKeyPair::TestKeyPair(const TestPublicKeyAlgorithm& publicKeyAlg, +TestKeyPair::TestKeyPair(const TestPublicKeyAlgorithm& aPublicKeyAlg, const ByteString& spk) - : publicKeyAlg(publicKeyAlg) + : publicKeyAlg(aPublicKeyAlg) , subjectPublicKeyInfo(TLV(der::SEQUENCE, - publicKeyAlg.algorithmIdentifier + + aPublicKeyAlg.algorithmIdentifier + TLV(der::BIT_STRING, NO_UNUSED_BITS + spk))) , subjectPublicKey(spk) { diff --git a/security/pkix/test/lib/pkixtestutil.h b/security/pkix/test/lib/pkixtestutil.h deleted file mode 100644 index 7e00ed4f3b..0000000000 --- a/security/pkix/test/lib/pkixtestutil.h +++ /dev/null @@ -1,447 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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. - */ - -#ifndef mozilla_pkix_test_pkixtestutils_h -#define mozilla_pkix_test_pkixtestutils_h - -#include <ctime> -#include <stdint.h> // Some Mozilla-supported compilers lack <cstdint> -#include <string> -#include <cstring> - -#include "pkix/pkixtypes.h" -#include "../../lib/ScopedPtr.h" - -namespace mozilla { namespace pkix { namespace test { - -typedef std::basic_string<uint8_t> ByteString; - -inline bool ENCODING_FAILED(const ByteString& bs) { return bs.empty(); } - -template <size_t L> -inline ByteString -BytesToByteString(const uint8_t (&bytes)[L]) -{ - return ByteString(bytes, L); -} - -// XXX: Ideally, we should define this instead: -// -// template <typename T, std::size_t N> -// constexpr inline std::size_t -// ArrayLength(T (&)[N]) -// { -// return N; -// } -// -// However, we don't because not all supported compilers support constexpr, -// and we need to calculate array lengths in static_assert sometimes. -// -// XXX: Evaluates its argument twice -#define MOZILLA_PKIX_ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) - -bool InputEqualsByteString(Input input, const ByteString& bs); -ByteString InputToByteString(Input input); - -// python DottedOIDToCode.py --tlv id-kp-OCSPSigning 1.3.6.1.5.5.7.3.9 -static const uint8_t tlv_id_kp_OCSPSigning[] = { - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x09 -}; - -// python DottedOIDToCode.py --tlv id-kp-serverAuth 1.3.6.1.5.5.7.3.1 -static const uint8_t tlv_id_kp_serverAuth[] = { - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01 -}; - -enum class TestDigestAlgorithmID -{ - MD2, - MD5, - SHA1, - SHA224, - SHA256, - SHA384, - SHA512, -}; - -struct TestPublicKeyAlgorithm -{ - explicit TestPublicKeyAlgorithm(const ByteString& algorithmIdentifier) - : algorithmIdentifier(algorithmIdentifier) { } - bool operator==(const TestPublicKeyAlgorithm& other) const - { - return algorithmIdentifier == other.algorithmIdentifier; - } - ByteString algorithmIdentifier; -}; - -ByteString DSS_P(); -ByteString DSS_Q(); -ByteString DSS_G(); - -TestPublicKeyAlgorithm DSS(); -TestPublicKeyAlgorithm RSA_PKCS1(); - -struct TestSignatureAlgorithm -{ - TestSignatureAlgorithm(const TestPublicKeyAlgorithm& publicKeyAlg, - TestDigestAlgorithmID digestAlg, - const ByteString& algorithmIdentifier, - bool accepted); - - TestPublicKeyAlgorithm publicKeyAlg; - TestDigestAlgorithmID digestAlg; - ByteString algorithmIdentifier; - bool accepted; -}; - -TestSignatureAlgorithm md2WithRSAEncryption(); -TestSignatureAlgorithm md5WithRSAEncryption(); -TestSignatureAlgorithm sha1WithRSAEncryption(); -TestSignatureAlgorithm sha256WithRSAEncryption(); - -// e.g. YMDHMS(2016, 12, 31, 1, 23, 45) => 2016-12-31:01:23:45 (GMT) -mozilla::pkix::Time YMDHMS(uint16_t year, uint16_t month, uint16_t day, - uint16_t hour, uint16_t minutes, uint16_t seconds); - -ByteString TLV(uint8_t tag, size_t length, const ByteString& value); - -inline ByteString -TLV(uint8_t tag, const ByteString& value) -{ - return TLV(tag, value.length(), value); -} - -// Although we can't enforce it without relying on Cuser-defined literals, -// which aren't supported by all of our compilers yet, you should only pass -// string literals as the last parameter to the following two functions. - -template <size_t N> -inline ByteString -TLV(uint8_t tag, const char(&value)[N]) -{ - static_assert(N > 0, "cannot have string literal of size 0"); - assert(value[N - 1] == 0); - return TLV(tag, ByteString(reinterpret_cast<const uint8_t*>(&value), N - 1)); -} - -template <size_t N> -inline ByteString -TLV(uint8_t tag, size_t length, const char(&value)[N]) -{ - static_assert(N > 0, "cannot have string literal of size 0"); - assert(value[N - 1] == 0); - return TLV(tag, length, - ByteString(reinterpret_cast<const uint8_t*>(&value), N - 1)); -} - -ByteString Boolean(bool value); -ByteString Integer(long value); - -ByteString CN(const ByteString&, uint8_t encodingTag = 0x0c /*UTF8String*/); - -inline ByteString -CN(const char* value, uint8_t encodingTag = 0x0c /*UTF8String*/) -{ - return CN(ByteString(reinterpret_cast<const uint8_t*>(value), - std::strlen(value)), encodingTag); -} - -ByteString OU(const ByteString&, uint8_t encodingTag = 0x0c /*UTF8String*/); - -inline ByteString -OU(const char* value, uint8_t encodingTag = 0x0c /*UTF8String*/) -{ - return OU(ByteString(reinterpret_cast<const uint8_t*>(value), - std::strlen(value)), encodingTag); -} - -ByteString emailAddress(const ByteString&); - -inline ByteString -emailAddress(const char* value) -{ - return emailAddress(ByteString(reinterpret_cast<const uint8_t*>(value), - std::strlen(value))); -} - -// RelativeDistinguishedName ::= -// SET SIZE (1..MAX) OF AttributeTypeAndValue -// -ByteString RDN(const ByteString& avas); - -// Name ::= CHOICE { -- only one possibility for now -- -// rdnSequence RDNSequence } -// -// RDNSequence ::= SEQUENCE OF RelativeDistinguishedName -// -ByteString Name(const ByteString& rdns); - -inline ByteString -CNToDERName(const ByteString& cn) -{ - return Name(RDN(CN(cn))); -} - -inline ByteString -CNToDERName(const char* cn) -{ - return Name(RDN(CN(cn))); -} - -// GeneralName ::= CHOICE { -// otherName [0] OtherName, -// rfc822Name [1] IA5String, -// dNSName [2] IA5String, -// x400Address [3] ORAddress, -// directoryName [4] Name, -// ediPartyName [5] EDIPartyName, -// uniformResourceIdentifier [6] IA5String, -// iPAddress [7] OCTET STRING, -// registeredID [8] OBJECT IDENTIFIER } - -inline ByteString -RFC822Name(const ByteString& name) -{ - // (2 << 6) means "context-specific", 1 is the GeneralName tag. - return TLV((2 << 6) | 1, name); -} - -template <size_t L> -inline ByteString -RFC822Name(const char (&bytes)[L]) -{ - return RFC822Name(ByteString(reinterpret_cast<const uint8_t*>(&bytes), - L - 1)); -} - -inline ByteString -DNSName(const ByteString& name) -{ - // (2 << 6) means "context-specific", 2 is the GeneralName tag. - return TLV((2 << 6) | 2, name); -} - -template <size_t L> -inline ByteString -DNSName(const char (&bytes)[L]) -{ - return DNSName(ByteString(reinterpret_cast<const uint8_t*>(&bytes), - L - 1)); -} - -inline ByteString -DirectoryName(const ByteString& name) -{ - // (2 << 6) means "context-specific", (1 << 5) means "constructed", and 4 is - // the DirectoryName tag. - return TLV((2 << 6) | (1 << 5) | 4, name); -} - -inline ByteString -IPAddress() -{ - // (2 << 6) means "context-specific", 7 is the GeneralName tag. - return TLV((2 << 6) | 7, ByteString()); -} - -template <size_t L> -inline ByteString -IPAddress(const uint8_t (&bytes)[L]) -{ - // (2 << 6) means "context-specific", 7 is the GeneralName tag. - return TLV((2 << 6) | 7, ByteString(bytes, L)); -} - -// Names should be zero or more GeneralNames, like DNSName and IPAddress return, -// concatenated together. -// -// CreatedEncodedSubjectAltName(ByteString()) results in a SAN with an empty -// sequence. CreateEmptyEncodedSubjectName() results in a SAN without any -// sequence. -ByteString CreateEncodedSubjectAltName(const ByteString& names); -ByteString CreateEncodedEmptySubjectAltName(); - -class TestKeyPair -{ -public: - virtual ~TestKeyPair() { } - - const TestPublicKeyAlgorithm publicKeyAlg; - - // 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, - const TestSignatureAlgorithm& signatureAlgorithm, - /*out*/ ByteString& signature) const = 0; - - virtual TestKeyPair* Clone() const = 0; -protected: - TestKeyPair(const TestPublicKeyAlgorithm& publicKeyAlg, const ByteString& spk); - TestKeyPair(const TestKeyPair&) = delete; - void operator=(const TestKeyPair&) = delete; -}; - -TestKeyPair* CloneReusedKeyPair(); -TestKeyPair* GenerateKeyPair(); -TestKeyPair* GenerateDSSKeyPair(); -inline void DeleteTestKeyPair(TestKeyPair* keyPair) { delete keyPair; } -typedef ScopedPtr<TestKeyPair, DeleteTestKeyPair> ScopedTestKeyPair; - -Result TestVerifyECDSASignedDigest(const SignedDigest& signedDigest, - Input subjectPublicKeyInfo); -Result TestVerifyRSAPKCS1SignedDigest(const SignedDigest& signedDigest, - Input subjectPublicKeyInfo); -Result TestDigestBuf(Input item, DigestAlgorithm digestAlg, - /*out*/ uint8_t* digestBuf, size_t digestBufLen); - -// 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 -// "only once" restriction is helpful for avoiding making accidental changes. -// -// The string to search for must be 8 or more bytes long so that it is -// extremely unlikely that there will ever be any false positive matches -// in digital signatures, keys, hashes, etc. -Result TamperOnce(/*in/out*/ ByteString& item, const ByteString& from, - const ByteString& to); - -/////////////////////////////////////////////////////////////////////////////// -// Encode Certificates - -enum Version { v1 = 0, v2 = 1, v3 = 2 }; - -// signature is assumed to be the DER encoding of an AlgorithmIdentifer. It is -// put into the signature field of the TBSCertificate. In most cases, it will -// be the same as signatureAlgorithm, which is the algorithm actually used -// to sign the certificate. -// serialNumber is assumed to be the DER encoding of an INTEGER. -// -// If extensions is null, then no extensions will be encoded. Otherwise, -// extensions must point to an array of ByteStrings, terminated with an empty -// ByteString. (If the first item of the array is empty then an empty -// Extensions sequence will be encoded.) -ByteString CreateEncodedCertificate(long version, - const TestSignatureAlgorithm& signature, - const ByteString& serialNumber, - const ByteString& issuerNameDER, - time_t notBefore, time_t notAfter, - const ByteString& subjectNameDER, - const TestKeyPair& subjectKeyPair, - /*optional*/ const ByteString* extensions, - const TestKeyPair& issuerKeyPair, - const TestSignatureAlgorithm& signatureAlgorithm); - -ByteString CreateEncodedSerialNumber(long value); - -enum class Critical { No = 0, Yes = 1 }; - -ByteString CreateEncodedBasicConstraints(bool isCA, - /*optional*/ long* pathLenConstraint, - Critical critical); - -// Creates a DER-encoded extKeyUsage extension with one EKU OID. -ByteString CreateEncodedEKUExtension(Input eku, Critical critical); - -/////////////////////////////////////////////////////////////////////////////// -// Encode OCSP responses - -class OCSPResponseExtension final -{ -public: - OCSPResponseExtension(); - - ByteString id; - bool critical; - ByteString value; - OCSPResponseExtension* next; -}; - -class OCSPResponseContext final -{ -public: - OCSPResponseContext(const CertID& certID, std::time_t time); - - const CertID& certID; - // TODO(bug 980538): add a way to specify what certificates are included. - - // The fields below are in the order that they appear in an OCSP response. - - enum OCSPResponseStatus - { - successful = 0, - malformedRequest = 1, - internalError = 2, - tryLater = 3, - // 4 is not used - sigRequired = 5, - unauthorized = 6, - }; - uint8_t responseStatus; // an OCSPResponseStatus or an invalid value - bool skipResponseBytes; // If true, don't include responseBytes - - // responderID - ByteString signerNameDER; // If set, responderID will use the byName - // form; otherwise responderID will use the - // byKeyHash form. - - std::time_t producedAt; - - // SingleResponse extensions (for the certID given in the constructor). - OCSPResponseExtension* singleExtensions; - // ResponseData extensions. - OCSPResponseExtension* responseExtensions; - bool includeEmptyExtensions; // If true, include the extension wrapper - // regardless of if there are any actual - // extensions. - ScopedTestKeyPair signerKeyPair; - TestSignatureAlgorithm signatureAlgorithm; - bool badSignature; // If true, alter the signature to fail verification - const ByteString* certs; // optional; array terminated by an empty string - - // The following fields are on a per-SingleResponse basis. In the future we - // may support including multiple SingleResponses per response. - enum CertStatus - { - good = 0, - revoked = 1, - unknown = 2, - }; - uint8_t certStatus; // CertStatus or an invalid value - std::time_t revocationTime; // For certStatus == revoked - std::time_t thisUpdate; - std::time_t nextUpdate; - bool includeNextUpdate; -}; - -ByteString CreateEncodedOCSPResponse(OCSPResponseContext& context); - -} } } // namespace mozilla::pkix::test - -#endif // mozilla_pkix_test_pkixtestutils_h |