diff --git a/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp b/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp index 0b235adcbfb1..999fe5d5b691 100644 --- a/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp +++ b/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp @@ -36,9 +36,8 @@ GetOCSPResponseForType(OCSPResponseType aORT, CERTCertificate *aCert, return arr; } - PRTime now = PR_Now(); - PRTime oneDay = 60*60*24 * (PRTime)PR_USEC_PER_SEC; - PRTime oldNow = now - (8 * oneDay); + time_t now = time(nullptr); + time_t oldNow = now - (8 * Time::ONE_DAY_IN_SECONDS); mozilla::ScopedCERTCertificate cert(CERT_DupCertificate(aCert)); @@ -51,7 +50,7 @@ GetOCSPResponseForType(OCSPResponseType aORT, CERTCertificate *aCert, } // XXX CERT_FindCertIssuer uses the old, deprecated path-building logic mozilla::ScopedCERTCertificate - issuerCert(CERT_FindCertIssuer(aCert, now, certUsageSSLCA)); + issuerCert(CERT_FindCertIssuer(aCert, PR_Now(), certUsageSSLCA)); if (!issuerCert) { PrintPRError("CERT_FindCertIssuer failed"); return nullptr; @@ -127,13 +126,13 @@ GetOCSPResponseForType(OCSPResponseType aORT, CERTCertificate *aCert, if (aORT == ORTExpired || aORT == ORTExpiredFreshCA || aORT == ORTRevokedOld || aORT == ORTUnknownOld) { context.thisUpdate = oldNow; - context.nextUpdate = oldNow + 10 * PR_USEC_PER_SEC; + context.nextUpdate = oldNow + 10; } if (aORT == ORTLongValidityAlmostExpired) { - context.thisUpdate = now - (320 * oneDay); + context.thisUpdate = now - (320 * Time::ONE_DAY_IN_SECONDS); } if (aORT == ORTAncientAlmostExpired) { - context.thisUpdate = now - (640 * oneDay); + context.thisUpdate = now - (640 * Time::ONE_DAY_IN_SECONDS); } if (aORT == ORTRevoked || aORT == ORTRevokedOld) { context.certStatus = 1; diff --git a/security/pkix/lib/pkixutil.h b/security/pkix/lib/pkixutil.h index 2028a1ff0b41..668cb543b367 100644 --- a/security/pkix/lib/pkixutil.h +++ b/security/pkix/lib/pkixutil.h @@ -186,7 +186,6 @@ private: inline unsigned int DaysBeforeYear(unsigned int year) { - assert(year >= 1); assert(year <= 9999); return ((year - 1u) * 365u) + ((year - 1u) / 4u) // leap years are every 4 years, diff --git a/security/pkix/test/gtest/nssgtest.cpp b/security/pkix/test/gtest/nssgtest.cpp index e44034ec12e4..1c708abe6b62 100644 --- a/security/pkix/test/gtest/nssgtest.cpp +++ b/security/pkix/test/gtest/nssgtest.cpp @@ -25,7 +25,6 @@ #include "nssgtest.h" #include "nss.h" #include "pkixtestutil.h" -#include "prinit.h" using namespace std; using namespace testing; @@ -38,11 +37,6 @@ NSSTest::SetUpTestCase() if (NSS_NoDB_Init(nullptr) != SECSuccess) { abort(); } - - now = Now(); - pr_now = PR_Now(); - pr_oneDayBeforeNow = pr_now - ONE_DAY; - pr_oneDayAfterNow = pr_now + ONE_DAY; } NSSTest::NSSTest() @@ -53,9 +47,10 @@ NSSTest::NSSTest() } } -/*static*/ mozilla::pkix::Time NSSTest::now(Now()); -/*static*/ PRTime NSSTest::pr_now; -/*static*/ PRTime NSSTest::pr_oneDayBeforeNow; -/*static*/ PRTime NSSTest::pr_oneDayAfterNow; +// This assumes that time/time_t are POSIX-compliant in that time() returns +// the number of seconds since the Unix epoch. +const std::time_t now(time(nullptr)); +const std::time_t oneDayBeforeNow(time(nullptr) - Time::ONE_DAY_IN_SECONDS); +const std::time_t oneDayAfterNow(time(nullptr) + Time::ONE_DAY_IN_SECONDS); } } } // namespace mozilla::pkix::test diff --git a/security/pkix/test/gtest/nssgtest.h b/security/pkix/test/gtest/nssgtest.h index b499add65700..82e27d824a8c 100644 --- a/security/pkix/test/gtest/nssgtest.h +++ b/security/pkix/test/gtest/nssgtest.h @@ -25,15 +25,16 @@ #ifndef mozilla_pkix__nssgtest_h #define mozilla_pkix__nssgtest_h -#include "stdint.h" #include "gtest/gtest.h" #include "pkix/pkixtypes.h" #include "pkixtestutil.h" -#include "prtime.h" -#include "seccomon.h" namespace mozilla { namespace pkix { namespace test { +extern const std::time_t now; +extern const std::time_t oneDayBeforeNow; +extern const std::time_t oneDayAfterNow; + inline void PORT_FreeArena_false(PLArenaPool* arena) { @@ -53,10 +54,6 @@ protected: NSSTest(); ScopedPLArenaPool arena; - static mozilla::pkix::Time now; - static PRTime pr_now; - static PRTime pr_oneDayBeforeNow; - static PRTime pr_oneDayAfterNow; }; } } } // namespace mozilla::pkix::test diff --git a/security/pkix/test/gtest/pkixbuild_tests.cpp b/security/pkix/test/gtest/pkixbuild_tests.cpp index a72aa0ead47a..b6a2df34a03a 100644 --- a/security/pkix/test/gtest/pkixbuild_tests.cpp +++ b/security/pkix/test/gtest/pkixbuild_tests.cpp @@ -61,8 +61,7 @@ CreateCert(PLArenaPool* arena, const char* issuerStr, SECItem* certDER(CreateEncodedCertificate( arena, v3, SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION, - serialNumber, issuerDER, - PR_Now() - ONE_DAY, PR_Now() + ONE_DAY, + serialNumber, issuerDER, oneDayBeforeNow, oneDayAfterNow, subjectDER, extensions, issuerKey, SEC_OID_SHA256, subjectKey)); EXPECT_TRUE(certDER); @@ -228,7 +227,7 @@ TEST_F(pkixbuild, MaxAcceptableCertChainLength) ASSERT_EQ(Success, certDER.Init(trustDomain.GetLeafCACert()->derCert.data, trustDomain.GetLeafCACert()->derCert.len)); ASSERT_EQ(Success, - BuildCertChain(trustDomain, certDER, now, + BuildCertChain(trustDomain, certDER, Now(), EndEntityOrCA::MustBeCA, KeyUsage::noParticularKeyUsageRequired, KeyPurposeId::id_kp_serverAuth, @@ -245,7 +244,7 @@ TEST_F(pkixbuild, MaxAcceptableCertChainLength) EndEntityOrCA::MustBeEndEntity, trustDomain.leafCAKey.get(), privateKey)); ASSERT_EQ(Success, - BuildCertChain(trustDomain, certDER, now, + BuildCertChain(trustDomain, certDER, Now(), EndEntityOrCA::MustBeEndEntity, KeyUsage::noParticularKeyUsageRequired, KeyPurposeId::id_kp_serverAuth, @@ -270,7 +269,7 @@ TEST_F(pkixbuild, BeyondMaxAcceptableCertChainLength) trustDomain.leafCAKey.get(), caPrivateKey, &caCert)); ASSERT_EQ(Result::ERROR_UNKNOWN_ISSUER, - BuildCertChain(trustDomain, cert, now, + BuildCertChain(trustDomain, cert, Now(), EndEntityOrCA::MustBeCA, KeyUsage::noParticularKeyUsageRequired, KeyPurposeId::id_kp_serverAuth, @@ -285,7 +284,7 @@ TEST_F(pkixbuild, BeyondMaxAcceptableCertChainLength) EndEntityOrCA::MustBeEndEntity, caPrivateKey.get(), privateKey)); ASSERT_EQ(Result::ERROR_UNKNOWN_ISSUER, - BuildCertChain(trustDomain, cert, now, + BuildCertChain(trustDomain, cert, Now(), EndEntityOrCA::MustBeEndEntity, KeyUsage::noParticularKeyUsageRequired, KeyPurposeId::id_kp_serverAuth, diff --git a/security/pkix/test/gtest/pkixcert_extension_tests.cpp b/security/pkix/test/gtest/pkixcert_extension_tests.cpp index 26347968ffd0..213ea038c254 100644 --- a/security/pkix/test/gtest/pkixcert_extension_tests.cpp +++ b/security/pkix/test/gtest/pkixcert_extension_tests.cpp @@ -50,8 +50,7 @@ CreateCert(PLArenaPool* arena, const char* subjectStr, arena, v3, SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION, serialNumber, issuerDER, - PR_Now() - ONE_DAY, - PR_Now() + ONE_DAY, + oneDayBeforeNow, oneDayAfterNow, subjectDER, extensions, nullptr, SEC_OID_SHA256, subjectKey); EXPECT_TRUE(cert); @@ -158,7 +157,7 @@ TEST_F(pkixcert_extension, UnknownCriticalExtension) Input cert(CreateCert(arena.get(), certCN, &unknownCriticalExtension, key)); ASSERT_EQ(Result::ERROR_UNKNOWN_CRITICAL_EXTENSION, - BuildCertChain(trustDomain, cert, now, + BuildCertChain(trustDomain, cert, Now(), EndEntityOrCA::MustBeEndEntity, KeyUsage::noParticularKeyUsageRequired, KeyPurposeId::anyExtendedKeyUsage, @@ -189,7 +188,7 @@ TEST_F(pkixcert_extension, UnknownNonCriticalExtension) Input cert(CreateCert(arena.get(), certCN, &unknownNonCriticalExtension, key)); ASSERT_EQ(Success, - BuildCertChain(trustDomain, cert, now, + BuildCertChain(trustDomain, cert, Now(), EndEntityOrCA::MustBeEndEntity, KeyUsage::noParticularKeyUsageRequired, KeyPurposeId::anyExtendedKeyUsage, @@ -221,7 +220,7 @@ TEST_F(pkixcert_extension, WrongOIDCriticalExtension) Input cert(CreateCert(arena.get(), certCN, &wrongOIDCriticalExtension, key)); ASSERT_EQ(Result::ERROR_UNKNOWN_CRITICAL_EXTENSION, - BuildCertChain(trustDomain, cert, now, + BuildCertChain(trustDomain, cert, Now(), EndEntityOrCA::MustBeEndEntity, KeyUsage::noParticularKeyUsageRequired, KeyPurposeId::anyExtendedKeyUsage, @@ -254,7 +253,7 @@ TEST_F(pkixcert_extension, CriticalAIAExtension) // cert is owned by the arena Input cert(CreateCert(arena.get(), certCN, &criticalAIAExtension, key)); ASSERT_EQ(Success, - BuildCertChain(trustDomain, cert, now, + BuildCertChain(trustDomain, cert, Now(), EndEntityOrCA::MustBeEndEntity, KeyUsage::noParticularKeyUsageRequired, KeyPurposeId::anyExtendedKeyUsage, @@ -285,7 +284,7 @@ TEST_F(pkixcert_extension, UnknownCriticalCEExtension) Input cert(CreateCert(arena.get(), certCN, &unknownCriticalCEExtension, key)); ASSERT_EQ(Result::ERROR_UNKNOWN_CRITICAL_EXTENSION, - BuildCertChain(trustDomain, cert, now, + BuildCertChain(trustDomain, cert, Now(), EndEntityOrCA::MustBeEndEntity, KeyUsage::noParticularKeyUsageRequired, KeyPurposeId::anyExtendedKeyUsage, @@ -315,7 +314,7 @@ TEST_F(pkixcert_extension, KnownCriticalCEExtension) // cert is owned by the arena Input cert(CreateCert(arena.get(), certCN, &criticalCEExtension, key)); ASSERT_EQ(Success, - BuildCertChain(trustDomain, cert, now, + BuildCertChain(trustDomain, cert, Now(), EndEntityOrCA::MustBeEndEntity, KeyUsage::noParticularKeyUsageRequired, KeyPurposeId::anyExtendedKeyUsage, @@ -346,7 +345,7 @@ TEST_F(pkixcert_extension, DuplicateSubjectAltName) // cert is owned by the arena Input cert(CreateCert(arena.get(), certCN, extensions, key)); ASSERT_EQ(Result::ERROR_EXTENSION_VALUE_INVALID, - BuildCertChain(trustDomain, cert, now, + BuildCertChain(trustDomain, cert, Now(), EndEntityOrCA::MustBeEndEntity, KeyUsage::noParticularKeyUsageRequired, KeyPurposeId::anyExtendedKeyUsage, diff --git a/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp b/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp index ec5254c7ba03..c56e2f342920 100644 --- a/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp +++ b/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp @@ -204,7 +204,7 @@ protected: static const Input EMPTY; OCSPResponseContext context(arena.get(), CertID(EMPTY, EMPTY, EMPTY), - pr_oneDayBeforeNow); + oneDayBeforeNow); context.responseStatus = status; context.skipResponseBytes = true; SECItem* response = CreateEncodedOCSPResponse(context); @@ -224,7 +224,7 @@ TEST_P(pkixocsp_VerifyEncodedResponse_WithoutResponseBytes, CorrectErrorCode) bool expired; ASSERT_EQ(GetParam().expectedError, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); } @@ -263,8 +263,8 @@ public: const CertID& certID, /*optional*/ const char* signerName, const ScopedSECKEYPrivateKey& signerPrivateKey, - PRTime producedAt, PRTime thisUpdate, - /*optional*/ const PRTime* nextUpdate, + time_t producedAt, time_t thisUpdate, + /*optional*/ const time_t* nextUpdate, /*optional*/ SECItem const* const* certs = nullptr) { OCSPResponseContext context(arena.get(), certID, producedAt); @@ -296,12 +296,12 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, good_byKey) { Input response(CreateEncodedOCSPSuccessfulResponse( OCSPResponseContext::good, *endEntityCertID, byKey, - rootPrivateKey, pr_oneDayBeforeNow, - pr_oneDayBeforeNow, &pr_oneDayAfterNow)); + rootPrivateKey, oneDayBeforeNow, + oneDayBeforeNow, &oneDayAfterNow)); bool expired; ASSERT_EQ(Success, VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, - now, END_ENTITY_MAX_LIFETIME_IN_DAYS, + Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); } @@ -310,11 +310,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, good_byName) { Input response(CreateEncodedOCSPSuccessfulResponse( OCSPResponseContext::good, *endEntityCertID, rootName, - rootPrivateKey, pr_oneDayBeforeNow, - pr_oneDayBeforeNow, &pr_oneDayAfterNow)); + rootPrivateKey, oneDayBeforeNow, + oneDayBeforeNow, &oneDayAfterNow)); bool expired; ASSERT_EQ(Success, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -324,11 +324,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, good_byKey_without_nextUpdate) { Input response(CreateEncodedOCSPSuccessfulResponse( OCSPResponseContext::good, *endEntityCertID, byKey, - rootPrivateKey, pr_oneDayBeforeNow, - pr_oneDayBeforeNow, nullptr)); + rootPrivateKey, oneDayBeforeNow, + oneDayBeforeNow, nullptr)); bool expired; ASSERT_EQ(Success, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -338,11 +338,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, revoked) { Input response(CreateEncodedOCSPSuccessfulResponse( OCSPResponseContext::revoked, *endEntityCertID, byKey, - rootPrivateKey, pr_oneDayBeforeNow, - pr_oneDayBeforeNow, &pr_oneDayAfterNow)); + rootPrivateKey, oneDayBeforeNow, + oneDayBeforeNow, &oneDayAfterNow)); bool expired; ASSERT_EQ(Result::ERROR_REVOKED_CERTIFICATE, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -352,11 +352,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, unknown) { Input response(CreateEncodedOCSPSuccessfulResponse( OCSPResponseContext::unknown, *endEntityCertID, byKey, - rootPrivateKey, pr_oneDayBeforeNow, - pr_oneDayBeforeNow, &pr_oneDayAfterNow)); + rootPrivateKey, oneDayBeforeNow, + oneDayBeforeNow, &oneDayAfterNow)); bool expired; ASSERT_EQ(Result::ERROR_OCSP_UNKNOWN_CERT, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -404,8 +404,7 @@ protected: ScopedSECKEYPrivateKey signerPrivateKey; SECItem* signerDER(CreateEncodedCertificate( arena.get(), ++rootIssuedCount, rootName, - pr_oneDayBeforeNow, pr_oneDayAfterNow, - certSubjectName, + oneDayBeforeNow, oneDayAfterNow, certSubjectName, signerEKU != SEC_OID_UNKNOWN ? extensions : nullptr, rootPrivateKey.get(), signerPrivateKey)); EXPECT_TRUE(signerDER); @@ -422,16 +421,16 @@ protected: SECItem const* const certs[] = { signerDER, nullptr }; return CreateEncodedOCSPSuccessfulResponse(certStatus, *endEntityCertID, signerName, signerPrivateKey, - pr_oneDayBeforeNow, - pr_oneDayBeforeNow, - &pr_oneDayAfterNow, certs); + oneDayBeforeNow, + oneDayBeforeNow, + &oneDayAfterNow, certs); } static SECItem* CreateEncodedCertificate(PLArenaPool* arena, uint32_t serialNumber, const char* issuer, - PRTime notBefore, - PRTime notAfter, + time_t notBefore, + time_t notAfter, const char* subject, /*optional*/ SECItem const* const* extensions, /*optional*/ SECKEYPrivateKey* signerKey, @@ -466,7 +465,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_byKey) byKey)); bool expired; ASSERT_EQ(Success, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -479,7 +478,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_byName) "CN=good_indirect_byName")); bool expired; ASSERT_EQ(Success, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -494,11 +493,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, missingSignerPrivateKey)); Input response(CreateEncodedOCSPSuccessfulResponse( OCSPResponseContext::good, *endEntityCertID, byKey, - missingSignerPrivateKey, pr_oneDayBeforeNow, - pr_oneDayBeforeNow, nullptr)); + missingSignerPrivateKey, oneDayBeforeNow, + oneDayBeforeNow, nullptr)); bool expired; ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -514,10 +513,10 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, Input response(CreateEncodedOCSPSuccessfulResponse( OCSPResponseContext::good, *endEntityCertID, "CN=missing", missingSignerPrivateKey, - pr_oneDayBeforeNow, pr_oneDayBeforeNow, nullptr)); + oneDayBeforeNow, oneDayBeforeNow, nullptr)); bool expired; ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -533,11 +532,12 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_expired) ExtensionCriticality::NotCritical), nullptr }; + ScopedSECKEYPrivateKey signerPrivateKey; SECItem* signerDER(CreateEncodedCertificate(arena.get(), ++rootIssuedCount, rootName, - pr_now - (10 * ONE_DAY), - pr_now - (2 * ONE_DAY), + now - (10 * Time::ONE_DAY_IN_SECONDS), + now - (2 * Time::ONE_DAY_IN_SECONDS), signerName, extensions, rootPrivateKey.get(), signerPrivateKey)); @@ -546,11 +546,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_expired) SECItem const* const certs[] = { signerDER, nullptr }; Input response(CreateEncodedOCSPSuccessfulResponse( OCSPResponseContext::good, *endEntityCertID, - signerName, signerPrivateKey, pr_oneDayBeforeNow, - pr_oneDayBeforeNow, &pr_oneDayAfterNow, certs)); + signerName, signerPrivateKey, oneDayBeforeNow, + oneDayBeforeNow, &oneDayAfterNow, certs)); bool expired; ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); } @@ -565,11 +565,12 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_future) ExtensionCriticality::NotCritical), nullptr }; + ScopedSECKEYPrivateKey signerPrivateKey; SECItem* signerDER(CreateEncodedCertificate(arena.get(), ++rootIssuedCount, rootName, - pr_now + (2 * ONE_DAY), - pr_now + (10 * ONE_DAY), + now + (2 * Time::ONE_DAY_IN_SECONDS), + now + (10 * Time::ONE_DAY_IN_SECONDS), signerName, extensions, rootPrivateKey.get(), signerPrivateKey)); @@ -578,11 +579,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_future) SECItem const* const certs[] = { signerDER, nullptr }; Input response(CreateEncodedOCSPSuccessfulResponse( OCSPResponseContext::good, *endEntityCertID, - signerName, signerPrivateKey, pr_oneDayBeforeNow, - pr_oneDayBeforeNow, &pr_oneDayAfterNow, certs)); + signerName, signerPrivateKey, oneDayBeforeNow, + oneDayBeforeNow, &oneDayAfterNow, certs)); bool expired; ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -595,7 +596,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_no_eku) OCSPResponseContext::good, byKey, SEC_OID_UNKNOWN)); bool expired; ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -610,7 +611,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH)); bool expired; ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -639,7 +640,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_tampered_eku) bool expired; ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -664,7 +665,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_unknown_issuer) }; ScopedSECKEYPrivateKey signerPrivateKey; SECItem* signerDER(CreateEncodedCertificate(arena.get(), 1, - subCAName, pr_oneDayBeforeNow, pr_oneDayAfterNow, + subCAName, oneDayBeforeNow, oneDayAfterNow, signerName, extensions, unknownPrivateKey.get(), signerPrivateKey)); ASSERT_TRUE(signerDER); @@ -673,11 +674,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_unknown_issuer) SECItem const* const certs[] = { signerDER, nullptr }; Input response(CreateEncodedOCSPSuccessfulResponse( OCSPResponseContext::good, *endEntityCertID, - signerName, signerPrivateKey, pr_oneDayBeforeNow, - pr_oneDayBeforeNow, &pr_oneDayAfterNow, certs)); + signerName, signerPrivateKey, oneDayBeforeNow, + oneDayBeforeNow, &oneDayAfterNow, certs)); bool expired; ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -701,7 +702,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, ScopedSECKEYPrivateKey subCAPrivateKey; SECItem* subCADER(CreateEncodedCertificate(arena.get(), ++rootIssuedCount, rootName, - pr_oneDayBeforeNow, pr_oneDayAfterNow, + oneDayBeforeNow, oneDayAfterNow, subCAName, subCAExtensions, rootPrivateKey.get(), subCAPrivateKey)); @@ -716,8 +717,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, }; ScopedSECKEYPrivateKey signerPrivateKey; SECItem* signerDER(CreateEncodedCertificate(arena.get(), 1, subCAName, - pr_oneDayBeforeNow, - pr_oneDayAfterNow, + oneDayBeforeNow, oneDayAfterNow, signerName, extensions, subCAPrivateKey.get(), signerPrivateKey)); @@ -728,11 +728,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, SECItem const* const certs[] = { subCADER, signerDER, nullptr }; Input response(CreateEncodedOCSPSuccessfulResponse( OCSPResponseContext::good, *endEntityCertID, - signerName, signerPrivateKey, pr_oneDayBeforeNow, - pr_oneDayBeforeNow, &pr_oneDayAfterNow, certs)); + signerName, signerPrivateKey, oneDayBeforeNow, + oneDayBeforeNow, &oneDayAfterNow, certs)); bool expired; ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -756,8 +756,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, ScopedSECKEYPrivateKey subCAPrivateKey; SECItem* subCADER(CreateEncodedCertificate(arena.get(), ++rootIssuedCount, rootName, - pr_oneDayBeforeNow, - pr_oneDayAfterNow, + oneDayBeforeNow, oneDayAfterNow, subCAName, subCAExtensions, rootPrivateKey.get(), subCAPrivateKey)); @@ -772,8 +771,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, }; ScopedSECKEYPrivateKey signerPrivateKey; SECItem* signerDER(CreateEncodedCertificate(arena.get(), 1, subCAName, - pr_oneDayBeforeNow, - pr_oneDayAfterNow, + oneDayBeforeNow, oneDayAfterNow, signerName, extensions, subCAPrivateKey.get(), signerPrivateKey)); @@ -784,11 +782,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, SECItem const* const certs[] = { signerDER, subCADER, nullptr }; Input response(CreateEncodedOCSPSuccessfulResponse( OCSPResponseContext::good, *endEntityCertID, - signerName, signerPrivateKey, pr_oneDayBeforeNow, - pr_oneDayBeforeNow, &pr_oneDayAfterNow, certs)); + signerName, signerPrivateKey, oneDayBeforeNow, + oneDayBeforeNow, &oneDayAfterNow, certs)); bool expired; ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -857,7 +855,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_GetCertTrust, InheritTrust) TrustLevel::InheritsTrust)); bool expired; ASSERT_EQ(Success, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -869,7 +867,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_GetCertTrust, TrustAnchor) TrustLevel::TrustAnchor)); bool expired; ASSERT_EQ(Success, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); @@ -881,7 +879,7 @@ TEST_F(pkixocsp_VerifyEncodedResponse_GetCertTrust, ActivelyDistrusted) TrustLevel::ActivelyDistrusted)); bool expired; ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT, - VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, now, + VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS, response, expired)); ASSERT_FALSE(expired); diff --git a/security/pkix/test/lib/pkixtestutil.cpp b/security/pkix/test/lib/pkixtestutil.cpp index 0157844ea6f5..a7565624a9c0 100644 --- a/security/pkix/test/lib/pkixtestutil.cpp +++ b/security/pkix/test/lib/pkixtestutil.cpp @@ -44,8 +44,6 @@ using namespace std; namespace mozilla { namespace pkix { namespace test { -const PRTime ONE_DAY = PRTime(24) * PRTime(60) * PRTime(60) * PR_USEC_PER_SEC; - namespace { inline void @@ -236,7 +234,7 @@ private: }; OCSPResponseContext::OCSPResponseContext(PLArenaPool* arena, - const CertID& certID, PRTime time) + const CertID& certID, time_t time) : arena(arena) , certID(certID) , responseStatus(successful) @@ -252,7 +250,7 @@ OCSPResponseContext::OCSPResponseContext(PLArenaPool* arena, , certStatus(good) , revocationTime(0) , thisUpdate(time) - , nextUpdate(time + 10 * PR_USEC_PER_SEC) + , nextUpdate(time + 10) , includeNextUpdate(true) { } @@ -409,23 +407,43 @@ OID(PLArenaPool* arena, SECOidTag tag) enum TimeEncoding { UTCTime = 0, GeneralizedTime = 1 }; +// Windows doesn't provide gmtime_r, but it provides something very similar. +#ifdef WIN32 +static tm* +gmtime_r(const time_t* t, /*out*/ tm* exploded) +{ + if (gmtime_s(exploded, t) != 0) { + return nullptr; + } + return exploded; +} +#endif + // http://tools.ietf.org/html/rfc5280#section-4.1.2.5 // UTCTime: YYMMDDHHMMSSZ (years 1950-2049 only) // GeneralizedTime: YYYYMMDDHHMMSSZ +// +// This assumes that time/time_t are POSIX-compliant in that time() returns +// the number of seconds since the Unix epoch. static SECItem* -PRTimeToEncodedTime(PLArenaPool* arena, PRTime time, TimeEncoding encoding) +TimeToEncodedTime(PLArenaPool* arena, time_t time, TimeEncoding encoding) { assert(encoding == UTCTime || encoding == GeneralizedTime); - PRExplodedTime exploded; - PR_ExplodeTime(time, PR_GMTParameters, &exploded); + tm exploded; + if (!gmtime_r(&time, &exploded)) { + return nullptr; + } + if (exploded.tm_sec >= 60) { // round down for leap seconds exploded.tm_sec = 59; } - if (encoding == UTCTime && - (exploded.tm_year < 1950 || exploded.tm_year >= 2050)) { + // exploded.tm_year is the year offset by 1900. + int year = exploded.tm_year + 1900; + + if (encoding == UTCTime && (year < 1950 || year >= 2050)) { return nullptr; } @@ -441,14 +459,14 @@ PRTimeToEncodedTime(PLArenaPool* arena, PRTime time, TimeEncoding encoding) derTime->data[i++] = static_cast(derTime->len - 2); // length if (encoding == GeneralizedTime) { - derTime->data[i++] = '0' + (exploded.tm_year / 1000); - derTime->data[i++] = '0' + ((exploded.tm_year % 1000) / 100); + derTime->data[i++] = '0' + (year / 1000); + derTime->data[i++] = '0' + ((year % 1000) / 100); } - derTime->data[i++] = '0' + ((exploded.tm_year % 100) / 10); - derTime->data[i++] = '0' + (exploded.tm_year % 10); - derTime->data[i++] = '0' + ((exploded.tm_month + 1) / 10); - derTime->data[i++] = '0' + ((exploded.tm_month + 1) % 10); + derTime->data[i++] = '0' + ((year % 100) / 10); + derTime->data[i++] = '0' + (year % 10); + derTime->data[i++] = '0' + ((exploded.tm_mon + 1) / 10); + derTime->data[i++] = '0' + ((exploded.tm_mon + 1) % 10); derTime->data[i++] = '0' + (exploded.tm_mday / 10); derTime->data[i++] = '0' + (exploded.tm_mday % 10); derTime->data[i++] = '0' + (exploded.tm_hour / 10); @@ -463,9 +481,9 @@ PRTimeToEncodedTime(PLArenaPool* arena, PRTime time, TimeEncoding encoding) } static SECItem* -PRTimeToGeneralizedTime(PLArenaPool* arena, PRTime time) +TimeToGeneralizedTime(PLArenaPool* arena, time_t time) { - return PRTimeToEncodedTime(arena, time, GeneralizedTime); + return TimeToEncodedTime(arena, time, GeneralizedTime); } // http://tools.ietf.org/html/rfc5280#section-4.1.2.5: "CAs conforming to this @@ -474,33 +492,66 @@ PRTimeToGeneralizedTime(PLArenaPool* arena, PRTime time) // GeneralizedTime." (This is a special case of the rule that we must always // use the shortest possible encoding.) static SECItem* -PRTimeToTimeChoice(PLArenaPool* arena, PRTime time) +TimeToTimeChoice(PLArenaPool* arena, time_t time) { - PRExplodedTime exploded; - PR_ExplodeTime(time, PR_GMTParameters, &exploded); - return PRTimeToEncodedTime(arena, time, - (exploded.tm_year >= 1950 && exploded.tm_year < 2050) ? UTCTime - : GeneralizedTime); + tm exploded; + if (!gmtime_r(&time, &exploded)) { + return nullptr; + } + TimeEncoding encoding = (exploded.tm_year + 1900 >= 1950 && + exploded.tm_year + 1900 < 2050) + ? UTCTime + : GeneralizedTime; + + return TimeToEncodedTime(arena, time, encoding); } Time YMDHMS(int16_t year, int16_t month, int16_t day, int16_t hour, int16_t minutes, int16_t seconds) { - PRExplodedTime tm; - tm.tm_usec = 0; - tm.tm_sec = seconds; - tm.tm_min = minutes; - tm.tm_hour = hour; - tm.tm_mday = day; - tm.tm_month = month - 1; // tm_month is zero-based - tm.tm_year = year; - tm.tm_params.tp_gmt_offset = 0; - tm.tm_params.tp_dst_offset = 0; - PRTime time = PR_ImplodeTime(&tm); - return TimeFromElapsedSecondsAD((time / PR_USEC_PER_SEC) + - (DaysBeforeYear(1970) * - Time::ONE_DAY_IN_SECONDS)); + assert(year <= 9999); + assert(month >= 1); + assert(month <= 12); + assert(day >= 1); + assert(hour >= 0); + assert(hour < 24); + assert(minutes >= 0); + assert(minutes < 60); + assert(seconds >= 0); + assert(seconds < 60); + + uint64_t days = DaysBeforeYear(year); + + { + static const int16_t DAYS_IN_MONTH[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + + int16_t i = 1; + for (;;) { + int16_t daysInMonth = DAYS_IN_MONTH[i - 1]; + if (i == 2 && + ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)))) { + // Add leap day + ++daysInMonth; + } + if (i == month) { + assert(day <= daysInMonth); + break; + } + days += daysInMonth; + ++i; + } + } + + days += (day - 1); + + uint64_t totalSeconds = days * Time::ONE_DAY_IN_SECONDS; + totalSeconds += hour * 60 * 60; + totalSeconds += minutes * 60; + totalSeconds += seconds; + return TimeFromElapsedSecondsAD(totalSeconds); } static SECItem* @@ -691,8 +742,12 @@ GenerateKeyPair(/*out*/ ScopedSECKEYPublicKey& publicKey, break; } - PRTime now = PR_Now(); - if (PK11_RandomUpdate(&now, sizeof(PRTime)) != SECSuccess) { + // 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; } } @@ -706,8 +761,8 @@ GenerateKeyPair(/*out*/ ScopedSECKEYPublicKey& publicKey, static SECItem* TBSCertificate(PLArenaPool* arena, long version, const SECItem* serialNumber, SECOidTag signature, - const SECItem* issuer, PRTime notBefore, - PRTime notAfter, const SECItem* subject, + const SECItem* issuer, time_t notBefore, + time_t notAfter, const SECItem* subject, const SECKEYPublicKey* subjectPublicKey, /*optional*/ SECItem const* const* extensions); @@ -718,8 +773,8 @@ static SECItem* TBSCertificate(PLArenaPool* arena, long version, SECItem* CreateEncodedCertificate(PLArenaPool* arena, long version, SECOidTag signature, const SECItem* serialNumber, - const SECItem* issuerNameDER, PRTime notBefore, - PRTime notAfter, const SECItem* subjectNameDER, + const SECItem* issuerNameDER, time_t notBefore, + time_t notAfter, const SECItem* subjectNameDER, /*optional*/ SECItem const* const* extensions, /*optional*/ SECKEYPrivateKey* issuerPrivateKey, SECOidTag signatureHashAlg, @@ -779,8 +834,8 @@ CreateEncodedCertificate(PLArenaPool* arena, long version, static SECItem* TBSCertificate(PLArenaPool* arena, long versionValue, const SECItem* serialNumber, SECOidTag signatureOidTag, - const SECItem* issuer, PRTime notBeforeTime, - PRTime notAfterTime, const SECItem* subject, + const SECItem* issuer, time_t notBeforeTime, + time_t notAfterTime, const SECItem* subject, const SECKEYPublicKey* subjectPublicKey, /*optional*/ SECItem const* const* extensions) { @@ -831,11 +886,11 @@ TBSCertificate(PLArenaPool* arena, long versionValue, // notAfter Time } SECItem* validity; { - SECItem* notBefore(PRTimeToTimeChoice(arena, notBeforeTime)); + SECItem* notBefore(TimeToTimeChoice(arena, notBeforeTime)); if (!notBefore) { return nullptr; } - SECItem* notAfter(PRTimeToTimeChoice(arena, notAfterTime)); + SECItem* notAfter(TimeToTimeChoice(arena, notAfterTime)); if (!notAfter) { return nullptr; } @@ -1168,8 +1223,8 @@ ResponseData(OCSPResponseContext& context) if (!responderID) { return nullptr; } - SECItem* producedAtEncoded = PRTimeToGeneralizedTime(context.arena, - context.producedAt); + SECItem* producedAtEncoded = TimeToGeneralizedTime(context.arena, + context.producedAt); if (!producedAtEncoded) { return nullptr; } @@ -1270,15 +1325,15 @@ SingleResponse(OCSPResponseContext& context) if (!certStatus) { return nullptr; } - SECItem* thisUpdateEncoded = PRTimeToGeneralizedTime(context.arena, - context.thisUpdate); + SECItem* thisUpdateEncoded = TimeToGeneralizedTime(context.arena, + context.thisUpdate); if (!thisUpdateEncoded) { return nullptr; } SECItem* nextUpdateEncodedNested = nullptr; if (context.includeNextUpdate) { - SECItem* nextUpdateEncoded = PRTimeToGeneralizedTime(context.arena, - context.nextUpdate); + SECItem* nextUpdateEncoded = TimeToGeneralizedTime(context.arena, + context.nextUpdate); if (!nextUpdateEncoded) { return nullptr; } @@ -1402,8 +1457,8 @@ CertStatus(OCSPResponseContext& context) } case 1: { - SECItem* revocationTime = PRTimeToGeneralizedTime(context.arena, - context.revocationTime); + SECItem* revocationTime = TimeToGeneralizedTime(context.arena, + context.revocationTime); if (!revocationTime) { return nullptr; } diff --git a/security/pkix/test/lib/pkixtestutil.h b/security/pkix/test/lib/pkixtestutil.h index f191a4ab0f6e..9c2fd82b5763 100644 --- a/security/pkix/test/lib/pkixtestutil.h +++ b/security/pkix/test/lib/pkixtestutil.h @@ -25,6 +25,7 @@ #ifndef mozilla_pkix_test__pkixtestutils_h #define mozilla_pkix_test__pkixtestutils_h +#include #include #include "cert.h" @@ -79,8 +80,6 @@ typedef mozilla::pkix::ScopedPtr typedef mozilla::pkix::ScopedPtr ScopedSECKEYPrivateKey; -extern const PRTime ONE_DAY; - // e.g. YMDHMS(2016, 12, 31, 1, 23, 45) => 2016-12-31:01:23:45 (GMT) mozilla::pkix::Time YMDHMS(int16_t year, int16_t month, int16_t day, int16_t hour, int16_t minutes, int16_t seconds); @@ -126,7 +125,7 @@ SECItem* CreateEncodedCertificate(PLArenaPool* arena, long version, SECOidTag signature, const SECItem* serialNumber, const SECItem* issuerNameDER, - PRTime notBefore, PRTime notAfter, + std::time_t notBefore, std::time_t notAfter, const SECItem* subjectNameDER, /*optional*/ SECItem const* const* extensions, /*optional*/ SECKEYPrivateKey* issuerPrivateKey, @@ -166,7 +165,7 @@ public: class OCSPResponseContext { public: - OCSPResponseContext(PLArenaPool* arena, const CertID& certID, PRTime time); + OCSPResponseContext(PLArenaPool* arena, const CertID& certID, std::time_t time); PLArenaPool* arena; const CertID& certID; @@ -202,7 +201,7 @@ public: // form; otherwise responderID will use the // byKeyHash form. - PRTime producedAt; + std::time_t producedAt; OCSPResponseExtension* extensions; bool includeEmptyExtensions; // If true, include the extension wrapper @@ -221,9 +220,9 @@ public: unknown = 2, }; uint8_t certStatus; // CertStatus or an invalid value - PRTime revocationTime; // For certStatus == revoked - PRTime thisUpdate; - PRTime nextUpdate; + std::time_t revocationTime; // For certStatus == revoked + std::time_t thisUpdate; + std::time_t nextUpdate; bool includeNextUpdate; };