mirror of
https://github.com/roytam1/UXP.git
synced 2026-05-26 13:58:49 +00:00
Issue #1746 - Update pkix code with later NSS code.
This commit is contained in:
@@ -292,6 +292,7 @@ AppTrustDomain::DigestBuf(Input item,
|
||||
|
||||
Result
|
||||
AppTrustDomain::CheckRevocation(EndEntityOrCA, const CertID&, Time, Duration,
|
||||
/*optional*/ const Input*,
|
||||
/*optional*/ const Input*,
|
||||
/*optional*/ const Input*)
|
||||
{
|
||||
@@ -301,7 +302,8 @@ AppTrustDomain::CheckRevocation(EndEntityOrCA, const CertID&, Time, Duration,
|
||||
}
|
||||
|
||||
Result
|
||||
AppTrustDomain::IsChainValid(const DERArray& certChain, Time time)
|
||||
AppTrustDomain::IsChainValid(const DERArray& certChain, Time time,
|
||||
const CertPolicyId& requiredPolicy)
|
||||
{
|
||||
SECStatus srv = ConstructCERTCertListFromReversedDERArray(certChain,
|
||||
mCertChain);
|
||||
|
||||
@@ -37,9 +37,11 @@ public:
|
||||
mozilla::pkix::Time time,
|
||||
mozilla::pkix::Duration validityDuration,
|
||||
/*optional*/ const mozilla::pkix::Input* stapledOCSPresponse,
|
||||
/*optional*/ const mozilla::pkix::Input* aiaExtension) override;
|
||||
/*optional*/ const mozilla::pkix::Input* aiaExtension,
|
||||
/*optional*/ const mozilla::pkix::Input* sctExtension) override;
|
||||
virtual Result IsChainValid(const mozilla::pkix::DERArray& certChain,
|
||||
mozilla::pkix::Time time) override;
|
||||
mozilla::pkix::Time time,
|
||||
const mozilla::pkix::CertPolicyId& requiredPolicy) override;
|
||||
virtual Result CheckSignatureDigestAlgorithm(
|
||||
mozilla::pkix::DigestAlgorithm digestAlg,
|
||||
mozilla::pkix::EndEntityOrCA endEntityOrCA,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "pkix/pkixnss.h"
|
||||
#include "pkixutil.h"
|
||||
#include "pkix/pkixutil.h"
|
||||
|
||||
namespace mozilla { namespace ct {
|
||||
|
||||
@@ -42,12 +42,12 @@ public:
|
||||
}
|
||||
|
||||
Result CheckRevocation(EndEntityOrCA, const CertID&, Time, Duration,
|
||||
const Input*, const Input*) override
|
||||
const Input*, const Input*, const Input*) override
|
||||
{
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
Result IsChainValid(const DERArray&, Time) override
|
||||
Result IsChainValid(const DERArray&, Time, const CertPolicyId&) override
|
||||
{
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "mozilla/RangedPtr.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "pkix/pkixnss.h"
|
||||
#include "pkixutil.h"
|
||||
#include "pkix/pkixutil.h"
|
||||
|
||||
namespace mozilla { namespace ct {
|
||||
|
||||
|
||||
@@ -348,7 +348,8 @@ NSSCertDBTrustDomain::CheckRevocation(EndEntityOrCA endEntityOrCA,
|
||||
const CertID& certID, Time time,
|
||||
Duration validityDuration,
|
||||
/*optional*/ const Input* stapledOCSPResponse,
|
||||
/*optional*/ const Input* aiaExtension)
|
||||
/*optional*/ const Input* aiaExtension,
|
||||
/*optional*/ const Input* sctExtension)
|
||||
{
|
||||
// Actively distrusted certificates will have already been blocked by
|
||||
// GetCertTrust.
|
||||
@@ -788,7 +789,9 @@ CheckForStartComOrWoSign(const UniqueCERTCertList& certChain)
|
||||
}
|
||||
|
||||
Result
|
||||
NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray, Time time)
|
||||
NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray,
|
||||
Time time,
|
||||
const CertPolicyId& requiredPolicy)
|
||||
{
|
||||
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
|
||||
("NSSCertDBTrustDomain: IsChainValid"));
|
||||
|
||||
@@ -134,11 +134,13 @@ public:
|
||||
mozilla::pkix::Time time,
|
||||
mozilla::pkix::Duration validityDuration,
|
||||
/*optional*/ const mozilla::pkix::Input* stapledOCSPResponse,
|
||||
/*optional*/ const mozilla::pkix::Input* aiaExtension)
|
||||
/*optional*/ const mozilla::pkix::Input* aiaExtension,
|
||||
/*optional*/ const mozilla::pkix::Input* sctExtension)
|
||||
override;
|
||||
|
||||
virtual Result IsChainValid(const mozilla::pkix::DERArray& certChain,
|
||||
mozilla::pkix::Time time) override;
|
||||
mozilla::pkix::Time time,
|
||||
const mozilla::pkix::CertPolicyId& requiredPolicy) override;
|
||||
|
||||
virtual void NoteAuxiliaryExtension(
|
||||
mozilla::pkix::AuxiliaryExtension extension,
|
||||
|
||||
@@ -35,7 +35,7 @@ OCSPVerificationTrustDomain::FindIssuer(Input, IssuerChecker&, Time)
|
||||
}
|
||||
|
||||
Result
|
||||
OCSPVerificationTrustDomain::IsChainValid(const DERArray&, Time)
|
||||
OCSPVerificationTrustDomain::IsChainValid(const DERArray&, Time, const CertPolicyId&)
|
||||
{
|
||||
// We do not expect this to be called for OCSP signers
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
@@ -44,7 +44,7 @@ OCSPVerificationTrustDomain::IsChainValid(const DERArray&, Time)
|
||||
Result
|
||||
OCSPVerificationTrustDomain::CheckRevocation(EndEntityOrCA, const CertID&,
|
||||
Time, Duration, const Input*,
|
||||
const Input*)
|
||||
const Input*, const Input*)
|
||||
{
|
||||
// We do not expect this to be called for OCSP signers
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
|
||||
@@ -68,11 +68,13 @@ public:
|
||||
mozilla::pkix::Time time,
|
||||
mozilla::pkix::Duration validityDuration,
|
||||
/*optional*/ const mozilla::pkix::Input* stapledOCSPResponse,
|
||||
/*optional*/ const mozilla::pkix::Input* aiaExtension)
|
||||
/*optional*/ const mozilla::pkix::Input* aiaExtension,
|
||||
/*optional*/ const mozilla::pkix::Input* sctExtension)
|
||||
override;
|
||||
|
||||
virtual Result IsChainValid(const mozilla::pkix::DERArray& certChain,
|
||||
mozilla::pkix::Time time) override;
|
||||
mozilla::pkix::Time time,
|
||||
const mozilla::pkix::CertPolicyId& requiredPolicy) override;
|
||||
|
||||
virtual void NoteAuxiliaryExtension(
|
||||
mozilla::pkix::AuxiliaryExtension extension,
|
||||
|
||||
@@ -35,7 +35,6 @@ if not CONFIG['NSS_NO_EV_CERTS']:
|
||||
LOCAL_INCLUDES += [
|
||||
'/security/manager/ssl',
|
||||
'/security/pkix/include',
|
||||
'/security/pkix/lib',
|
||||
]
|
||||
|
||||
DIRS += [
|
||||
|
||||
@@ -129,7 +129,8 @@ CSTrustDomain::CheckRevocation(EndEntityOrCA endEntityOrCA,
|
||||
const CertID& certID, Time time,
|
||||
Duration validityDuration,
|
||||
/*optional*/ const Input* stapledOCSPresponse,
|
||||
/*optional*/ const Input* aiaExtension)
|
||||
/*optional*/ const Input* aiaExtension,
|
||||
/*optional*/ const Input* sctExtension)
|
||||
{
|
||||
// We're relying solely on the CertBlocklist for revocation - and we're
|
||||
// performing checks on this in GetCertTrust (as per nsNSSCertDBTrustDomain)
|
||||
@@ -137,7 +138,8 @@ CSTrustDomain::CheckRevocation(EndEntityOrCA endEntityOrCA,
|
||||
}
|
||||
|
||||
Result
|
||||
CSTrustDomain::IsChainValid(const DERArray& certChain, Time time)
|
||||
CSTrustDomain::IsChainValid(const DERArray& certChain, Time time,
|
||||
const CertPolicyId& requiredPolicy)
|
||||
{
|
||||
// Check that our chain is not empty
|
||||
if (certChain.GetLength() == 0) {
|
||||
|
||||
@@ -36,9 +36,11 @@ public:
|
||||
const mozilla::pkix::CertID& certID, mozilla::pkix::Time time,
|
||||
mozilla::pkix::Duration validityDuration,
|
||||
/*optional*/ const mozilla::pkix::Input* stapledOCSPresponse,
|
||||
/*optional*/ const mozilla::pkix::Input* aiaExtension) override;
|
||||
/*optional*/ const mozilla::pkix::Input* aiaExtension,
|
||||
/*optional*/ const mozilla::pkix::Input* sctExtension) override;
|
||||
virtual Result IsChainValid(const mozilla::pkix::DERArray& certChain,
|
||||
mozilla::pkix::Time time) override;
|
||||
mozilla::pkix::Time time,
|
||||
const mozilla::pkix::CertPolicyId& requiredPolicy) override;
|
||||
virtual Result CheckSignatureDigestAlgorithm(
|
||||
mozilla::pkix::DigestAlgorithm digestAlg,
|
||||
mozilla::pkix::EndEntityOrCA endEntityOrCA,
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/.
|
||||
*/
|
||||
|
||||
// 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 "nss_scoped_ptrs.h"
|
||||
#include "pkix/test/pkixtestutil.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace pkix {
|
||||
namespace test {
|
||||
|
||||
TestKeyPair* CreateTestKeyPair(const TestPublicKeyAlgorithm publicKeyAlg,
|
||||
const ScopedSECKEYPublicKey& publicKey,
|
||||
const ScopedSECKEYPrivateKey& privateKey);
|
||||
}
|
||||
}
|
||||
} // namespace mozilla::pkix::test
|
||||
|
||||
#endif // mozilla_pkix_test_pkixtestnss_h
|
||||
+88
-147
@@ -1,47 +1,29 @@
|
||||
/* -*- 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
|
||||
#ifndef mozilla_pkix_test_pkixtestutil_h
|
||||
#define mozilla_pkix_test_pkixtestutil_h
|
||||
|
||||
#include <ctime>
|
||||
#include <stdint.h> // Some Mozilla-supported compilers lack <cstdint>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
|
||||
#include "pkix/pkixtypes.h"
|
||||
#include "../../lib/ScopedPtr.h"
|
||||
|
||||
namespace mozilla { namespace pkix { namespace test {
|
||||
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])
|
||||
{
|
||||
inline ByteString BytesToByteString(const uint8_t (&bytes)[L]) {
|
||||
return ByteString(bytes, L);
|
||||
}
|
||||
|
||||
@@ -64,17 +46,14 @@ 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
|
||||
};
|
||||
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
|
||||
};
|
||||
static const uint8_t tlv_id_kp_serverAuth[] = {0x06, 0x08, 0x2b, 0x06, 0x01,
|
||||
0x05, 0x05, 0x07, 0x03, 0x01};
|
||||
|
||||
enum class TestDigestAlgorithmID
|
||||
{
|
||||
enum class TestDigestAlgorithmID {
|
||||
MD2,
|
||||
MD5,
|
||||
SHA1,
|
||||
@@ -84,12 +63,10 @@ enum class TestDigestAlgorithmID
|
||||
SHA512,
|
||||
};
|
||||
|
||||
struct TestPublicKeyAlgorithm
|
||||
{
|
||||
explicit TestPublicKeyAlgorithm(const ByteString& algorithmIdentifier)
|
||||
: algorithmIdentifier(algorithmIdentifier) { }
|
||||
bool operator==(const TestPublicKeyAlgorithm& other) const
|
||||
{
|
||||
struct TestPublicKeyAlgorithm {
|
||||
explicit TestPublicKeyAlgorithm(const ByteString& aAlgorithmIdentifier)
|
||||
: algorithmIdentifier(aAlgorithmIdentifier) {}
|
||||
bool operator==(const TestPublicKeyAlgorithm& other) const {
|
||||
return algorithmIdentifier == other.algorithmIdentifier;
|
||||
}
|
||||
ByteString algorithmIdentifier;
|
||||
@@ -102,12 +79,10 @@ ByteString DSS_G();
|
||||
TestPublicKeyAlgorithm DSS();
|
||||
TestPublicKeyAlgorithm RSA_PKCS1();
|
||||
|
||||
struct TestSignatureAlgorithm
|
||||
{
|
||||
struct TestSignatureAlgorithm {
|
||||
TestSignatureAlgorithm(const TestPublicKeyAlgorithm& publicKeyAlg,
|
||||
TestDigestAlgorithmID digestAlg,
|
||||
const ByteString& algorithmIdentifier,
|
||||
bool accepted);
|
||||
const ByteString& algorithmIdentifier, bool accepted);
|
||||
|
||||
TestPublicKeyAlgorithm publicKeyAlg;
|
||||
TestDigestAlgorithmID digestAlg;
|
||||
@@ -126,9 +101,7 @@ mozilla::pkix::Time YMDHMS(uint16_t year, uint16_t month, uint16_t day,
|
||||
|
||||
ByteString TLV(uint8_t tag, size_t length, const ByteString& value);
|
||||
|
||||
inline ByteString
|
||||
TLV(uint8_t tag, const ByteString& value)
|
||||
{
|
||||
inline ByteString TLV(uint8_t tag, const ByteString& value) {
|
||||
return TLV(tag, value.length(), value);
|
||||
}
|
||||
|
||||
@@ -137,18 +110,14 @@ TLV(uint8_t tag, const ByteString& value)
|
||||
// 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])
|
||||
{
|
||||
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])
|
||||
{
|
||||
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,
|
||||
@@ -160,29 +129,27 @@ 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);
|
||||
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);
|
||||
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)));
|
||||
inline ByteString emailAddress(const char* value) {
|
||||
return emailAddress(
|
||||
ByteString(reinterpret_cast<const uint8_t*>(value), std::strlen(value)));
|
||||
}
|
||||
|
||||
// RelativeDistinguishedName ::=
|
||||
@@ -197,17 +164,11 @@ ByteString RDN(const ByteString& avas);
|
||||
//
|
||||
ByteString Name(const ByteString& rdns);
|
||||
|
||||
inline ByteString
|
||||
CNToDERName(const ByteString& cn)
|
||||
{
|
||||
inline ByteString CNToDERName(const ByteString& cn) {
|
||||
return Name(RDN(CN(cn)));
|
||||
}
|
||||
|
||||
inline ByteString
|
||||
CNToDERName(const char* cn)
|
||||
{
|
||||
return Name(RDN(CN(cn)));
|
||||
}
|
||||
inline ByteString CNToDERName(const char* cn) { return Name(RDN(CN(cn))); }
|
||||
|
||||
// GeneralName ::= CHOICE {
|
||||
// otherName [0] OtherName,
|
||||
@@ -220,55 +181,40 @@ CNToDERName(const char* cn)
|
||||
// iPAddress [7] OCTET STRING,
|
||||
// registeredID [8] OBJECT IDENTIFIER }
|
||||
|
||||
inline ByteString
|
||||
RFC822Name(const ByteString& name)
|
||||
{
|
||||
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 RFC822Name(const char (&bytes)[L]) {
|
||||
return RFC822Name(
|
||||
ByteString(reinterpret_cast<const uint8_t*>(&bytes), L - 1));
|
||||
}
|
||||
|
||||
inline ByteString
|
||||
DNSName(const ByteString& name)
|
||||
{
|
||||
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 DNSName(const char (&bytes)[L]) {
|
||||
return DNSName(ByteString(reinterpret_cast<const uint8_t*>(&bytes), L - 1));
|
||||
}
|
||||
|
||||
inline ByteString
|
||||
DirectoryName(const ByteString& name)
|
||||
{
|
||||
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()
|
||||
{
|
||||
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])
|
||||
{
|
||||
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));
|
||||
}
|
||||
@@ -282,10 +228,9 @@ IPAddress(const uint8_t (&bytes)[L])
|
||||
ByteString CreateEncodedSubjectAltName(const ByteString& names);
|
||||
ByteString CreateEncodedEmptySubjectAltName();
|
||||
|
||||
class TestKeyPair
|
||||
{
|
||||
public:
|
||||
virtual ~TestKeyPair() { }
|
||||
class TestKeyPair {
|
||||
public:
|
||||
virtual ~TestKeyPair() {}
|
||||
|
||||
const TestPublicKeyAlgorithm publicKeyAlg;
|
||||
|
||||
@@ -302,8 +247,10 @@ public:
|
||||
/*out*/ ByteString& signature) const = 0;
|
||||
|
||||
virtual TestKeyPair* Clone() const = 0;
|
||||
protected:
|
||||
TestKeyPair(const TestPublicKeyAlgorithm& publicKeyAlg, const ByteString& spk);
|
||||
|
||||
protected:
|
||||
TestKeyPair(const TestPublicKeyAlgorithm& publicKeyAlg,
|
||||
const ByteString& spk);
|
||||
TestKeyPair(const TestKeyPair&) = delete;
|
||||
void operator=(const TestKeyPair&) = delete;
|
||||
};
|
||||
@@ -312,7 +259,7 @@ TestKeyPair* CloneReusedKeyPair();
|
||||
TestKeyPair* GenerateKeyPair();
|
||||
TestKeyPair* GenerateDSSKeyPair();
|
||||
inline void DeleteTestKeyPair(TestKeyPair* keyPair) { delete keyPair; }
|
||||
typedef ScopedPtr<TestKeyPair, DeleteTestKeyPair> ScopedTestKeyPair;
|
||||
typedef std::unique_ptr<TestKeyPair> ScopedTestKeyPair;
|
||||
|
||||
Result TestVerifyECDSASignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo);
|
||||
@@ -347,24 +294,21 @@ enum Version { v1 = 0, v2 = 1, v3 = 2 };
|
||||
// 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 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);
|
||||
ByteString CreateEncodedBasicConstraints(
|
||||
bool isCA,
|
||||
/*optional in*/ const long* pathLenConstraint, Critical critical);
|
||||
|
||||
// Creates a DER-encoded extKeyUsage extension with one EKU OID.
|
||||
ByteString CreateEncodedEKUExtension(Input eku, Critical critical);
|
||||
@@ -372,9 +316,8 @@ ByteString CreateEncodedEKUExtension(Input eku, Critical critical);
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Encode OCSP responses
|
||||
|
||||
class OCSPResponseExtension final
|
||||
{
|
||||
public:
|
||||
class OCSPResponseExtension final {
|
||||
public:
|
||||
OCSPResponseExtension();
|
||||
|
||||
ByteString id;
|
||||
@@ -383,9 +326,8 @@ public:
|
||||
OCSPResponseExtension* next;
|
||||
};
|
||||
|
||||
class OCSPResponseContext final
|
||||
{
|
||||
public:
|
||||
class OCSPResponseContext final {
|
||||
public:
|
||||
OCSPResponseContext(const CertID& certID, std::time_t time);
|
||||
|
||||
const CertID& certID;
|
||||
@@ -393,8 +335,7 @@ public:
|
||||
|
||||
// The fields below are in the order that they appear in an OCSP response.
|
||||
|
||||
enum OCSPResponseStatus
|
||||
{
|
||||
enum OCSPResponseStatus {
|
||||
successful = 0,
|
||||
malformedRequest = 1,
|
||||
internalError = 2,
|
||||
@@ -403,13 +344,13 @@ public:
|
||||
sigRequired = 5,
|
||||
unauthorized = 6,
|
||||
};
|
||||
uint8_t responseStatus; // an OCSPResponseStatus or an invalid value
|
||||
bool skipResponseBytes; // If true, don't include responseBytes
|
||||
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.
|
||||
ByteString signerNameDER; // If set, responderID will use the byName
|
||||
// form; otherwise responderID will use the
|
||||
// byKeyHash form.
|
||||
|
||||
std::time_t producedAt;
|
||||
|
||||
@@ -417,31 +358,31 @@ public:
|
||||
OCSPResponseExtension* singleExtensions;
|
||||
// ResponseData extensions.
|
||||
OCSPResponseExtension* responseExtensions;
|
||||
bool includeEmptyExtensions; // If true, include the extension wrapper
|
||||
// regardless of if there are any actual
|
||||
// extensions.
|
||||
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
|
||||
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
|
||||
{
|
||||
enum CertStatus {
|
||||
good = 0,
|
||||
revoked = 1,
|
||||
unknown = 2,
|
||||
};
|
||||
uint8_t certStatus; // CertStatus or an invalid value
|
||||
std::time_t revocationTime; // For certStatus == revoked
|
||||
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
|
||||
|
||||
} } } // namespace mozilla::pkix::test
|
||||
|
||||
#endif // mozilla_pkix_test_pkixtestutils_h
|
||||
#endif // mozilla_pkix_test_pkixtestutil_h
|
||||
@@ -1,25 +1,8 @@
|
||||
/* -*- 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_Input_h
|
||||
#define mozilla_pkix_Input_h
|
||||
@@ -29,7 +12,8 @@
|
||||
#include "pkix/Result.h"
|
||||
#include "stdint.h"
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
namespace mozilla {
|
||||
namespace pkix {
|
||||
|
||||
class Reader;
|
||||
|
||||
@@ -48,9 +32,8 @@ class Reader;
|
||||
//
|
||||
// Note that in the example, GoodExample has the same performance
|
||||
// characteristics as WorseExample, but with much better safety guarantees.
|
||||
class Input final
|
||||
{
|
||||
public:
|
||||
class Input final {
|
||||
public:
|
||||
typedef uint16_t size_type;
|
||||
|
||||
// This constructor is useful for inputs that are statically known to be of a
|
||||
@@ -65,37 +48,28 @@ public:
|
||||
// Input expected;
|
||||
// Result rv = expected.Init(EXPECTED_BYTES, sizeof EXPECTED_BYTES);
|
||||
template <size_type N>
|
||||
explicit Input(const uint8_t (&data)[N])
|
||||
: data(data)
|
||||
, len(N)
|
||||
{
|
||||
}
|
||||
explicit Input(const uint8_t (&aData)[N]) : data(aData), len(N) {}
|
||||
|
||||
// Construct a valid, empty, Init-able Input.
|
||||
Input()
|
||||
: data(nullptr)
|
||||
, len(0u)
|
||||
{
|
||||
}
|
||||
Input() : data(nullptr), len(0u) {}
|
||||
|
||||
// This is intentionally not explicit in order to allow value semantics.
|
||||
Input(const Input&) = default;
|
||||
|
||||
// Initialize the input. data must be non-null and len must be less than
|
||||
// 65536. Init may not be called more than once.
|
||||
Result Init(const uint8_t* data, size_t len)
|
||||
{
|
||||
Result Init(const uint8_t* aData, size_t aLen) {
|
||||
if (this->data) {
|
||||
// already initialized
|
||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||
}
|
||||
if (!data || len > 0xffffu) {
|
||||
if (!aData || aLen > 0xffffu) {
|
||||
// input too large
|
||||
return Result::ERROR_BAD_DER;
|
||||
}
|
||||
|
||||
this->data = data;
|
||||
this->len = len;
|
||||
this->data = aData;
|
||||
this->len = aLen;
|
||||
|
||||
return Success;
|
||||
}
|
||||
@@ -106,10 +80,7 @@ public:
|
||||
// This is basically operator=, but it wasn't given that name because
|
||||
// normally callers do not check the result of operator=, and normally
|
||||
// operator= can be used multiple times.
|
||||
Result Init(Input other)
|
||||
{
|
||||
return Init(other.data, other.len);
|
||||
}
|
||||
Result Init(Input other) { return Init(other.data, other.len); }
|
||||
|
||||
// Returns the length of the input.
|
||||
//
|
||||
@@ -121,18 +92,17 @@ public:
|
||||
// don't want to declare in this header file.
|
||||
const uint8_t* UnsafeGetData() const { return data; }
|
||||
|
||||
private:
|
||||
private:
|
||||
const uint8_t* data;
|
||||
size_t len;
|
||||
|
||||
void operator=(const Input&) = delete; // Use Init instead.
|
||||
void operator=(const Input&) = delete; // Use Init instead.
|
||||
};
|
||||
|
||||
inline bool
|
||||
InputsAreEqual(const Input& a, const Input& b)
|
||||
{
|
||||
inline bool InputsAreEqual(const Input& a, const Input& b) {
|
||||
return a.GetLength() == b.GetLength() &&
|
||||
std::equal(a.UnsafeGetData(), a.UnsafeGetData() + a.GetLength(), b.UnsafeGetData());
|
||||
std::equal(a.UnsafeGetData(), a.UnsafeGetData() + a.GetLength(),
|
||||
b.UnsafeGetData());
|
||||
}
|
||||
|
||||
// An Reader is a cursor/iterator through the contents of an Input, designed to
|
||||
@@ -143,38 +113,28 @@ InputsAreEqual(const Input& a, const Input& b)
|
||||
//
|
||||
// In general, Reader allows for one byte of lookahead and no backtracking.
|
||||
// However, the Match* functions internally may have more lookahead.
|
||||
class Reader final
|
||||
{
|
||||
public:
|
||||
Reader()
|
||||
: input(nullptr)
|
||||
, end(nullptr)
|
||||
{
|
||||
}
|
||||
class Reader final {
|
||||
public:
|
||||
Reader() : input(nullptr), end(nullptr) {}
|
||||
|
||||
explicit Reader(Input input)
|
||||
: input(input.UnsafeGetData())
|
||||
, end(input.UnsafeGetData() + input.GetLength())
|
||||
{
|
||||
}
|
||||
explicit Reader(Input aInput)
|
||||
: input(aInput.UnsafeGetData()),
|
||||
end(aInput.UnsafeGetData() + aInput.GetLength()) {}
|
||||
|
||||
Result Init(Input input)
|
||||
{
|
||||
Result Init(Input aInput) {
|
||||
if (this->input) {
|
||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||
}
|
||||
this->input = input.UnsafeGetData();
|
||||
this->end = input.UnsafeGetData() + input.GetLength();
|
||||
this->input = aInput.UnsafeGetData();
|
||||
this->end = aInput.UnsafeGetData() + aInput.GetLength();
|
||||
return Success;
|
||||
}
|
||||
|
||||
bool Peek(uint8_t expectedByte) const
|
||||
{
|
||||
bool Peek(uint8_t expectedByte) const {
|
||||
return input < end && *input == expectedByte;
|
||||
}
|
||||
|
||||
Result Read(uint8_t& out)
|
||||
{
|
||||
Result Read(uint8_t& out) {
|
||||
Result rv = EnsureLength(1);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
@@ -183,8 +143,7 @@ public:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result Read(uint16_t& out)
|
||||
{
|
||||
Result Read(uint16_t& out) {
|
||||
Result rv = EnsureLength(2);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
@@ -196,8 +155,7 @@ public:
|
||||
}
|
||||
|
||||
template <Input::size_type N>
|
||||
bool MatchRest(const uint8_t (&toMatch)[N])
|
||||
{
|
||||
bool MatchRest(const uint8_t (&toMatch)[N]) {
|
||||
// Normally we use EnsureLength which compares (input + len < end), but
|
||||
// here we want to be sure that there is nothing following the matched
|
||||
// bytes
|
||||
@@ -211,8 +169,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MatchRest(Input toMatch)
|
||||
{
|
||||
bool MatchRest(Input toMatch) {
|
||||
// Normally we use EnsureLength which compares (input + len < end), but
|
||||
// here we want to be sure that there is nothing following the matched
|
||||
// bytes
|
||||
@@ -227,8 +184,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
Result Skip(Input::size_type len)
|
||||
{
|
||||
Result Skip(Input::size_type len) {
|
||||
Result rv = EnsureLength(len);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
@@ -237,8 +193,7 @@ public:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result Skip(Input::size_type len, Reader& skipped)
|
||||
{
|
||||
Result Skip(Input::size_type len, Reader& skipped) {
|
||||
Result rv = EnsureLength(len);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
@@ -251,8 +206,7 @@ public:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result Skip(Input::size_type len, /*out*/ Input& skipped)
|
||||
{
|
||||
Result Skip(Input::size_type len, /*out*/ Input& skipped) {
|
||||
Result rv = EnsureLength(len);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
@@ -265,18 +219,13 @@ public:
|
||||
return Success;
|
||||
}
|
||||
|
||||
void SkipToEnd()
|
||||
{
|
||||
input = end;
|
||||
}
|
||||
void SkipToEnd() { input = end; }
|
||||
|
||||
Result SkipToEnd(/*out*/ Input& skipped)
|
||||
{
|
||||
Result SkipToEnd(/*out*/ Input& skipped) {
|
||||
return Skip(static_cast<Input::size_type>(end - input), skipped);
|
||||
}
|
||||
|
||||
Result EnsureLength(Input::size_type len)
|
||||
{
|
||||
Result EnsureLength(Input::size_type len) {
|
||||
if (static_cast<size_t>(end - input) < len) {
|
||||
return Result::ERROR_BAD_DER;
|
||||
}
|
||||
@@ -285,13 +234,13 @@ public:
|
||||
|
||||
bool AtEnd() const { return input == end; }
|
||||
|
||||
class Mark final
|
||||
{
|
||||
public:
|
||||
Mark(const Mark&) = default; // Intentionally not explicit.
|
||||
private:
|
||||
class Mark final {
|
||||
public:
|
||||
Mark(const Mark&) = default; // Intentionally not explicit.
|
||||
private:
|
||||
friend class Reader;
|
||||
Mark(const Reader& input, const uint8_t* mark) : input(input), mark(mark) { }
|
||||
Mark(const Reader& aInput, const uint8_t* aMark)
|
||||
: input(aInput), mark(aMark) {}
|
||||
const Reader& input;
|
||||
const uint8_t* const mark;
|
||||
void operator=(const Mark&) = delete;
|
||||
@@ -299,8 +248,7 @@ public:
|
||||
|
||||
Mark GetMark() const { return Mark(*this, input); }
|
||||
|
||||
Result GetInput(const Mark& mark, /*out*/ Input& item)
|
||||
{
|
||||
Result GetInput(const Mark& mark, /*out*/ Input& item) {
|
||||
if (&mark.input != this || mark.mark > input) {
|
||||
return NotReached("invalid mark", Result::FATAL_ERROR_INVALID_ARGS);
|
||||
}
|
||||
@@ -308,9 +256,8 @@ public:
|
||||
static_cast<Input::size_type>(input - mark.mark));
|
||||
}
|
||||
|
||||
private:
|
||||
Result Init(const uint8_t* data, Input::size_type len)
|
||||
{
|
||||
private:
|
||||
Result Init(const uint8_t* data, Input::size_type len) {
|
||||
if (input) {
|
||||
// already initialized
|
||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||
@@ -327,9 +274,7 @@ private:
|
||||
void operator=(const Reader&) = delete;
|
||||
};
|
||||
|
||||
inline bool
|
||||
InputContains(const Input& input, uint8_t toFind)
|
||||
{
|
||||
inline bool InputContains(const Input& input, uint8_t toFind) {
|
||||
Reader reader(input);
|
||||
for (;;) {
|
||||
uint8_t b;
|
||||
@@ -341,7 +286,7 @@ InputContains(const Input& input, uint8_t toFind)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace mozilla::pkix
|
||||
|
||||
} } // namespace mozilla::pkix
|
||||
|
||||
#endif // mozilla_pkix_Input_h
|
||||
#endif // mozilla_pkix_Input_h
|
||||
|
||||
+113
-146
@@ -1,32 +1,16 @@
|
||||
/* -*- 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_Result_h
|
||||
#define mozilla_pkix_Result_h
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
namespace mozilla {
|
||||
namespace pkix {
|
||||
|
||||
static const unsigned int FATAL_ERROR_FLAG = 0x800;
|
||||
|
||||
@@ -82,126 +66,113 @@ static const unsigned int FATAL_ERROR_FLAG = 0x800;
|
||||
// The third argument to MOZILLA_PKIX_MAP() is used, along with the first
|
||||
// argument, for maintaining the mapping of mozilla::pkix error codes to
|
||||
// NSS/NSPR error codes in pkixnss.cpp.
|
||||
#define MOZILLA_PKIX_MAP_LIST \
|
||||
MOZILLA_PKIX_MAP(Success, 0, 0) \
|
||||
MOZILLA_PKIX_MAP(ERROR_BAD_DER, 1, \
|
||||
SEC_ERROR_BAD_DER) \
|
||||
MOZILLA_PKIX_MAP(ERROR_CA_CERT_INVALID, 2, \
|
||||
SEC_ERROR_CA_CERT_INVALID) \
|
||||
MOZILLA_PKIX_MAP(ERROR_BAD_SIGNATURE, 3, \
|
||||
SEC_ERROR_BAD_SIGNATURE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_CERT_BAD_ACCESS_LOCATION, 4, \
|
||||
SEC_ERROR_CERT_BAD_ACCESS_LOCATION) \
|
||||
MOZILLA_PKIX_MAP(ERROR_CERT_NOT_IN_NAME_SPACE, 5, \
|
||||
SEC_ERROR_CERT_NOT_IN_NAME_SPACE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED, 6, \
|
||||
SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) \
|
||||
MOZILLA_PKIX_MAP(ERROR_CONNECT_REFUSED, 7, \
|
||||
PR_CONNECT_REFUSED_ERROR) \
|
||||
MOZILLA_PKIX_MAP(ERROR_EXPIRED_CERTIFICATE, 8, \
|
||||
SEC_ERROR_EXPIRED_CERTIFICATE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_EXTENSION_VALUE_INVALID, 9, \
|
||||
SEC_ERROR_EXTENSION_VALUE_INVALID) \
|
||||
MOZILLA_PKIX_MAP(ERROR_INADEQUATE_CERT_TYPE, 10, \
|
||||
SEC_ERROR_INADEQUATE_CERT_TYPE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_INADEQUATE_KEY_USAGE, 11, \
|
||||
SEC_ERROR_INADEQUATE_KEY_USAGE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_INVALID_ALGORITHM, 12, \
|
||||
SEC_ERROR_INVALID_ALGORITHM) \
|
||||
MOZILLA_PKIX_MAP(ERROR_INVALID_DER_TIME, 13, \
|
||||
SEC_ERROR_INVALID_TIME) \
|
||||
MOZILLA_PKIX_MAP(ERROR_KEY_PINNING_FAILURE, 14, \
|
||||
MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_PATH_LEN_CONSTRAINT_INVALID, 15, \
|
||||
SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID) \
|
||||
MOZILLA_PKIX_MAP(ERROR_POLICY_VALIDATION_FAILED, 16, \
|
||||
SEC_ERROR_POLICY_VALIDATION_FAILED) \
|
||||
MOZILLA_PKIX_MAP(ERROR_REVOKED_CERTIFICATE, 17, \
|
||||
SEC_ERROR_REVOKED_CERTIFICATE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNKNOWN_CRITICAL_EXTENSION, 18, \
|
||||
SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNKNOWN_ERROR, 19, \
|
||||
PR_UNKNOWN_ERROR) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNKNOWN_ISSUER, 20, \
|
||||
SEC_ERROR_UNKNOWN_ISSUER) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNTRUSTED_CERT, 21, \
|
||||
SEC_ERROR_UNTRUSTED_CERT) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNTRUSTED_ISSUER, 22, \
|
||||
SEC_ERROR_UNTRUSTED_ISSUER) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_BAD_SIGNATURE, 23, \
|
||||
SEC_ERROR_OCSP_BAD_SIGNATURE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_INVALID_SIGNING_CERT, 24, \
|
||||
SEC_ERROR_OCSP_INVALID_SIGNING_CERT) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_MALFORMED_REQUEST, 25, \
|
||||
SEC_ERROR_OCSP_MALFORMED_REQUEST) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_MALFORMED_RESPONSE, 26, \
|
||||
SEC_ERROR_OCSP_MALFORMED_RESPONSE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_OLD_RESPONSE, 27, \
|
||||
SEC_ERROR_OCSP_OLD_RESPONSE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_REQUEST_NEEDS_SIG, 28, \
|
||||
SEC_ERROR_OCSP_REQUEST_NEEDS_SIG) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_RESPONDER_CERT_INVALID, 29, \
|
||||
SEC_ERROR_OCSP_RESPONDER_CERT_INVALID) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_SERVER_ERROR, 30, \
|
||||
SEC_ERROR_OCSP_SERVER_ERROR) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_TRY_SERVER_LATER, 31, \
|
||||
SEC_ERROR_OCSP_TRY_SERVER_LATER) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_UNAUTHORIZED_REQUEST, 32, \
|
||||
SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, 33, \
|
||||
SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_UNKNOWN_CERT, 34, \
|
||||
SEC_ERROR_OCSP_UNKNOWN_CERT) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_FUTURE_RESPONSE, 35, \
|
||||
SEC_ERROR_OCSP_FUTURE_RESPONSE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_INVALID_KEY, 36, \
|
||||
SEC_ERROR_INVALID_KEY) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNSUPPORTED_KEYALG, 37, \
|
||||
SEC_ERROR_UNSUPPORTED_KEYALG) \
|
||||
MOZILLA_PKIX_MAP(ERROR_EXPIRED_ISSUER_CERTIFICATE, 38, \
|
||||
SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_CA_CERT_USED_AS_END_ENTITY, 39, \
|
||||
MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY) \
|
||||
MOZILLA_PKIX_MAP(ERROR_INADEQUATE_KEY_SIZE, 40, \
|
||||
MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_V1_CERT_USED_AS_CA, 41, \
|
||||
MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA) \
|
||||
MOZILLA_PKIX_MAP(ERROR_BAD_CERT_DOMAIN, 42, \
|
||||
SSL_ERROR_BAD_CERT_DOMAIN) \
|
||||
MOZILLA_PKIX_MAP(ERROR_NO_RFC822NAME_MATCH, 43, \
|
||||
MOZILLA_PKIX_ERROR_NO_RFC822NAME_MATCH) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNSUPPORTED_ELLIPTIC_CURVE, 44, \
|
||||
SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_NOT_YET_VALID_CERTIFICATE, 45, \
|
||||
MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE, 46, \
|
||||
MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNSUPPORTED_EC_POINT_FORM, 47, \
|
||||
SEC_ERROR_UNSUPPORTED_EC_POINT_FORM) \
|
||||
MOZILLA_PKIX_MAP(ERROR_SIGNATURE_ALGORITHM_MISMATCH, 48, \
|
||||
MOZILLA_PKIX_ERROR_SIGNATURE_ALGORITHM_MISMATCH) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_RESPONSE_FOR_CERT_MISSING, 49, \
|
||||
MOZILLA_PKIX_ERROR_OCSP_RESPONSE_FOR_CERT_MISSING) \
|
||||
MOZILLA_PKIX_MAP(ERROR_VALIDITY_TOO_LONG, 50, \
|
||||
MOZILLA_PKIX_ERROR_VALIDITY_TOO_LONG) \
|
||||
MOZILLA_PKIX_MAP(ERROR_REQUIRED_TLS_FEATURE_MISSING, 51, \
|
||||
MOZILLA_PKIX_ERROR_REQUIRED_TLS_FEATURE_MISSING) \
|
||||
MOZILLA_PKIX_MAP(ERROR_INVALID_INTEGER_ENCODING, 52, \
|
||||
MOZILLA_PKIX_ERROR_INVALID_INTEGER_ENCODING) \
|
||||
MOZILLA_PKIX_MAP(ERROR_EMPTY_ISSUER_NAME, 53, \
|
||||
MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME) \
|
||||
MOZILLA_PKIX_MAP(FATAL_ERROR_INVALID_ARGS, FATAL_ERROR_FLAG | 1, \
|
||||
SEC_ERROR_INVALID_ARGS) \
|
||||
MOZILLA_PKIX_MAP(FATAL_ERROR_INVALID_STATE, FATAL_ERROR_FLAG | 2, \
|
||||
PR_INVALID_STATE_ERROR) \
|
||||
MOZILLA_PKIX_MAP(FATAL_ERROR_LIBRARY_FAILURE, FATAL_ERROR_FLAG | 3, \
|
||||
SEC_ERROR_LIBRARY_FAILURE) \
|
||||
MOZILLA_PKIX_MAP(FATAL_ERROR_NO_MEMORY, FATAL_ERROR_FLAG | 4, \
|
||||
SEC_ERROR_NO_MEMORY) \
|
||||
/* nothing here */
|
||||
#define MOZILLA_PKIX_MAP_LIST \
|
||||
MOZILLA_PKIX_MAP(Success, 0, 0) \
|
||||
MOZILLA_PKIX_MAP(ERROR_BAD_DER, 1, SEC_ERROR_BAD_DER) \
|
||||
MOZILLA_PKIX_MAP(ERROR_CA_CERT_INVALID, 2, SEC_ERROR_CA_CERT_INVALID) \
|
||||
MOZILLA_PKIX_MAP(ERROR_BAD_SIGNATURE, 3, SEC_ERROR_BAD_SIGNATURE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_CERT_BAD_ACCESS_LOCATION, 4, \
|
||||
SEC_ERROR_CERT_BAD_ACCESS_LOCATION) \
|
||||
MOZILLA_PKIX_MAP(ERROR_CERT_NOT_IN_NAME_SPACE, 5, \
|
||||
SEC_ERROR_CERT_NOT_IN_NAME_SPACE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED, 6, \
|
||||
SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) \
|
||||
MOZILLA_PKIX_MAP(ERROR_CONNECT_REFUSED, 7, PR_CONNECT_REFUSED_ERROR) \
|
||||
MOZILLA_PKIX_MAP(ERROR_EXPIRED_CERTIFICATE, 8, \
|
||||
SEC_ERROR_EXPIRED_CERTIFICATE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_EXTENSION_VALUE_INVALID, 9, \
|
||||
SEC_ERROR_EXTENSION_VALUE_INVALID) \
|
||||
MOZILLA_PKIX_MAP(ERROR_INADEQUATE_CERT_TYPE, 10, \
|
||||
SEC_ERROR_INADEQUATE_CERT_TYPE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_INADEQUATE_KEY_USAGE, 11, \
|
||||
SEC_ERROR_INADEQUATE_KEY_USAGE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_INVALID_ALGORITHM, 12, SEC_ERROR_INVALID_ALGORITHM) \
|
||||
MOZILLA_PKIX_MAP(ERROR_INVALID_DER_TIME, 13, SEC_ERROR_INVALID_TIME) \
|
||||
MOZILLA_PKIX_MAP(ERROR_KEY_PINNING_FAILURE, 14, \
|
||||
MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_PATH_LEN_CONSTRAINT_INVALID, 15, \
|
||||
SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID) \
|
||||
MOZILLA_PKIX_MAP(ERROR_POLICY_VALIDATION_FAILED, 16, \
|
||||
SEC_ERROR_POLICY_VALIDATION_FAILED) \
|
||||
MOZILLA_PKIX_MAP(ERROR_REVOKED_CERTIFICATE, 17, \
|
||||
SEC_ERROR_REVOKED_CERTIFICATE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNKNOWN_CRITICAL_EXTENSION, 18, \
|
||||
SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNKNOWN_ERROR, 19, PR_UNKNOWN_ERROR) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNKNOWN_ISSUER, 20, SEC_ERROR_UNKNOWN_ISSUER) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNTRUSTED_CERT, 21, SEC_ERROR_UNTRUSTED_CERT) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNTRUSTED_ISSUER, 22, SEC_ERROR_UNTRUSTED_ISSUER) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_BAD_SIGNATURE, 23, SEC_ERROR_OCSP_BAD_SIGNATURE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_INVALID_SIGNING_CERT, 24, \
|
||||
SEC_ERROR_OCSP_INVALID_SIGNING_CERT) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_MALFORMED_REQUEST, 25, \
|
||||
SEC_ERROR_OCSP_MALFORMED_REQUEST) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_MALFORMED_RESPONSE, 26, \
|
||||
SEC_ERROR_OCSP_MALFORMED_RESPONSE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_OLD_RESPONSE, 27, SEC_ERROR_OCSP_OLD_RESPONSE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_REQUEST_NEEDS_SIG, 28, \
|
||||
SEC_ERROR_OCSP_REQUEST_NEEDS_SIG) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_RESPONDER_CERT_INVALID, 29, \
|
||||
SEC_ERROR_OCSP_RESPONDER_CERT_INVALID) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_SERVER_ERROR, 30, SEC_ERROR_OCSP_SERVER_ERROR) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_TRY_SERVER_LATER, 31, \
|
||||
SEC_ERROR_OCSP_TRY_SERVER_LATER) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_UNAUTHORIZED_REQUEST, 32, \
|
||||
SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, 33, \
|
||||
SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_UNKNOWN_CERT, 34, SEC_ERROR_OCSP_UNKNOWN_CERT) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_FUTURE_RESPONSE, 35, \
|
||||
SEC_ERROR_OCSP_FUTURE_RESPONSE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_INVALID_KEY, 36, SEC_ERROR_INVALID_KEY) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNSUPPORTED_KEYALG, 37, SEC_ERROR_UNSUPPORTED_KEYALG) \
|
||||
MOZILLA_PKIX_MAP(ERROR_EXPIRED_ISSUER_CERTIFICATE, 38, \
|
||||
SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_CA_CERT_USED_AS_END_ENTITY, 39, \
|
||||
MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY) \
|
||||
MOZILLA_PKIX_MAP(ERROR_INADEQUATE_KEY_SIZE, 40, \
|
||||
MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_V1_CERT_USED_AS_CA, 41, \
|
||||
MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA) \
|
||||
MOZILLA_PKIX_MAP(ERROR_BAD_CERT_DOMAIN, 42, SSL_ERROR_BAD_CERT_DOMAIN) \
|
||||
MOZILLA_PKIX_MAP(ERROR_NO_RFC822NAME_MATCH, 43, \
|
||||
MOZILLA_PKIX_ERROR_NO_RFC822NAME_MATCH) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNSUPPORTED_ELLIPTIC_CURVE, 44, \
|
||||
SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_NOT_YET_VALID_CERTIFICATE, 45, \
|
||||
MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE, 46, \
|
||||
MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE) \
|
||||
MOZILLA_PKIX_MAP(ERROR_UNSUPPORTED_EC_POINT_FORM, 47, \
|
||||
SEC_ERROR_UNSUPPORTED_EC_POINT_FORM) \
|
||||
MOZILLA_PKIX_MAP(ERROR_SIGNATURE_ALGORITHM_MISMATCH, 48, \
|
||||
MOZILLA_PKIX_ERROR_SIGNATURE_ALGORITHM_MISMATCH) \
|
||||
MOZILLA_PKIX_MAP(ERROR_OCSP_RESPONSE_FOR_CERT_MISSING, 49, \
|
||||
MOZILLA_PKIX_ERROR_OCSP_RESPONSE_FOR_CERT_MISSING) \
|
||||
MOZILLA_PKIX_MAP(ERROR_VALIDITY_TOO_LONG, 50, \
|
||||
MOZILLA_PKIX_ERROR_VALIDITY_TOO_LONG) \
|
||||
MOZILLA_PKIX_MAP(ERROR_REQUIRED_TLS_FEATURE_MISSING, 51, \
|
||||
MOZILLA_PKIX_ERROR_REQUIRED_TLS_FEATURE_MISSING) \
|
||||
MOZILLA_PKIX_MAP(ERROR_INVALID_INTEGER_ENCODING, 52, \
|
||||
MOZILLA_PKIX_ERROR_INVALID_INTEGER_ENCODING) \
|
||||
MOZILLA_PKIX_MAP(ERROR_EMPTY_ISSUER_NAME, 53, \
|
||||
MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME) \
|
||||
MOZILLA_PKIX_MAP(ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED, 54, \
|
||||
MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED) \
|
||||
MOZILLA_PKIX_MAP(ERROR_SELF_SIGNED_CERT, 55, \
|
||||
MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT) \
|
||||
MOZILLA_PKIX_MAP(ERROR_MITM_DETECTED, 56, MOZILLA_PKIX_ERROR_MITM_DETECTED) \
|
||||
MOZILLA_PKIX_MAP(FATAL_ERROR_INVALID_ARGS, FATAL_ERROR_FLAG | 1, \
|
||||
SEC_ERROR_INVALID_ARGS) \
|
||||
MOZILLA_PKIX_MAP(FATAL_ERROR_INVALID_STATE, FATAL_ERROR_FLAG | 2, \
|
||||
PR_INVALID_STATE_ERROR) \
|
||||
MOZILLA_PKIX_MAP(FATAL_ERROR_LIBRARY_FAILURE, FATAL_ERROR_FLAG | 3, \
|
||||
SEC_ERROR_LIBRARY_FAILURE) \
|
||||
MOZILLA_PKIX_MAP(FATAL_ERROR_NO_MEMORY, FATAL_ERROR_FLAG | 4, \
|
||||
SEC_ERROR_NO_MEMORY) \
|
||||
/* nothing here */
|
||||
|
||||
enum class Result
|
||||
{
|
||||
enum class Result {
|
||||
#define MOZILLA_PKIX_MAP(name, value, nss_name) name = value,
|
||||
MOZILLA_PKIX_MAP_LIST
|
||||
#undef MOZILLA_PKIX_MAP
|
||||
@@ -216,19 +187,15 @@ const char* MapResultToName(Result result);
|
||||
// results in less line wrapping.
|
||||
static const Result Success = Result::Success;
|
||||
|
||||
inline bool
|
||||
IsFatalError(Result rv)
|
||||
{
|
||||
inline bool IsFatalError(Result rv) {
|
||||
return (static_cast<unsigned int>(rv) & FATAL_ERROR_FLAG) != 0;
|
||||
}
|
||||
|
||||
inline Result
|
||||
NotReached(const char* /*explanation*/, Result result)
|
||||
{
|
||||
inline Result NotReached(const char* /*explanation*/, Result result) {
|
||||
assert(false);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} // namespace mozilla::pkix
|
||||
|
||||
} } // namespace mozilla::pkix
|
||||
|
||||
#endif // mozilla_pkix_Result_h
|
||||
#endif // mozilla_pkix_Result_h
|
||||
|
||||
@@ -1,45 +1,28 @@
|
||||
/* -*- 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 2014 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_Time_h
|
||||
#define mozilla_pkix_Time_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <ctime>
|
||||
#include <limits>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "pkix/Result.h"
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
namespace mozilla {
|
||||
namespace pkix {
|
||||
|
||||
// Time with a range from the first second of year 0 (AD) through at least the
|
||||
// last second of year 9999, which is the range of legal times in X.509 and
|
||||
// OCSP. This type has second-level precision. The time zone is always UTC.
|
||||
//
|
||||
// Pass by value, not by reference.
|
||||
class Time final
|
||||
{
|
||||
public:
|
||||
class Time final {
|
||||
public:
|
||||
// Construct an uninitialized instance.
|
||||
//
|
||||
// This will fail to compile because there is no default constructor:
|
||||
@@ -48,52 +31,44 @@ public:
|
||||
// This will succeed, leaving the time uninitialized:
|
||||
// Time x(Time::uninitialized);
|
||||
enum Uninitialized { uninitialized };
|
||||
explicit Time(Uninitialized) { }
|
||||
explicit Time(Uninitialized) {}
|
||||
|
||||
bool operator==(const Time& other) const
|
||||
{
|
||||
bool operator==(const Time& other) const {
|
||||
return elapsedSecondsAD == other.elapsedSecondsAD;
|
||||
}
|
||||
bool operator>(const Time& other) const
|
||||
{
|
||||
bool operator>(const Time& other) const {
|
||||
return elapsedSecondsAD > other.elapsedSecondsAD;
|
||||
}
|
||||
bool operator>=(const Time& other) const
|
||||
{
|
||||
bool operator>=(const Time& other) const {
|
||||
return elapsedSecondsAD >= other.elapsedSecondsAD;
|
||||
}
|
||||
bool operator<(const Time& other) const
|
||||
{
|
||||
bool operator<(const Time& other) const {
|
||||
return elapsedSecondsAD < other.elapsedSecondsAD;
|
||||
}
|
||||
bool operator<=(const Time& other) const
|
||||
{
|
||||
bool operator<=(const Time& other) const {
|
||||
return elapsedSecondsAD <= other.elapsedSecondsAD;
|
||||
}
|
||||
|
||||
Result AddSeconds(uint64_t seconds)
|
||||
{
|
||||
if (std::numeric_limits<uint64_t>::max() - elapsedSecondsAD
|
||||
< seconds) {
|
||||
return Result::FATAL_ERROR_INVALID_ARGS; // integer overflow
|
||||
Result AddSeconds(uint64_t seconds) {
|
||||
if (std::numeric_limits<uint64_t>::max() - elapsedSecondsAD < seconds) {
|
||||
return Result::FATAL_ERROR_INVALID_ARGS; // integer overflow
|
||||
}
|
||||
elapsedSecondsAD += seconds;
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result SubtractSeconds(uint64_t seconds)
|
||||
{
|
||||
Result SubtractSeconds(uint64_t seconds) {
|
||||
if (seconds > elapsedSecondsAD) {
|
||||
return Result::FATAL_ERROR_INVALID_ARGS; // integer overflow
|
||||
return Result::FATAL_ERROR_INVALID_ARGS; // integer overflow
|
||||
}
|
||||
elapsedSecondsAD -= seconds;
|
||||
return Success;
|
||||
}
|
||||
|
||||
static const uint64_t ONE_DAY_IN_SECONDS
|
||||
= UINT64_C(24) * UINT64_C(60) * UINT64_C(60);
|
||||
static const uint64_t ONE_DAY_IN_SECONDS =
|
||||
UINT64_C(24) * UINT64_C(60) * UINT64_C(60);
|
||||
|
||||
private:
|
||||
private:
|
||||
// This constructor is hidden to prevent accidents like this:
|
||||
//
|
||||
// Time foo(time_t t)
|
||||
@@ -101,19 +76,16 @@ private:
|
||||
// // WRONG! 1970-01-01-00:00:00 == time_t(0), but not Time(0)!
|
||||
// return Time(t);
|
||||
// }
|
||||
explicit Time(uint64_t elapsedSecondsAD)
|
||||
: elapsedSecondsAD(elapsedSecondsAD)
|
||||
{
|
||||
}
|
||||
explicit Time(uint64_t aElapsedSecondsAD)
|
||||
: elapsedSecondsAD(aElapsedSecondsAD) {}
|
||||
friend Time TimeFromElapsedSecondsAD(uint64_t);
|
||||
friend class Duration;
|
||||
|
||||
uint64_t elapsedSecondsAD;
|
||||
};
|
||||
|
||||
inline Time TimeFromElapsedSecondsAD(uint64_t elapsedSecondsAD)
|
||||
{
|
||||
return Time(elapsedSecondsAD);
|
||||
inline Time TimeFromElapsedSecondsAD(uint64_t aElapsedSecondsAD) {
|
||||
return Time(aElapsedSecondsAD);
|
||||
}
|
||||
|
||||
Time Now();
|
||||
@@ -121,34 +93,27 @@ Time Now();
|
||||
// Note the epoch is the unix epoch (ie 00:00:00 UTC, 1 January 1970)
|
||||
Time TimeFromEpochInSeconds(uint64_t secondsSinceEpoch);
|
||||
|
||||
class Duration final
|
||||
{
|
||||
public:
|
||||
class Duration final {
|
||||
public:
|
||||
Duration(Time timeA, Time timeB)
|
||||
: durationInSeconds(timeA < timeB
|
||||
? timeB.elapsedSecondsAD - timeA.elapsedSecondsAD
|
||||
: timeA.elapsedSecondsAD - timeB.elapsedSecondsAD)
|
||||
{
|
||||
}
|
||||
: durationInSeconds(
|
||||
timeA < timeB ? timeB.elapsedSecondsAD - timeA.elapsedSecondsAD
|
||||
: timeA.elapsedSecondsAD - timeB.elapsedSecondsAD) {}
|
||||
|
||||
explicit Duration(uint64_t durationInSeconds)
|
||||
: durationInSeconds(durationInSeconds)
|
||||
{
|
||||
}
|
||||
explicit Duration(uint64_t aDurationInSeconds)
|
||||
: durationInSeconds(aDurationInSeconds) {}
|
||||
|
||||
bool operator>(const Duration& other) const
|
||||
{
|
||||
bool operator>(const Duration& other) const {
|
||||
return durationInSeconds > other.durationInSeconds;
|
||||
}
|
||||
bool operator<(const Duration& other) const
|
||||
{
|
||||
bool operator<(const Duration& other) const {
|
||||
return durationInSeconds < other.durationInSeconds;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
uint64_t durationInSeconds;
|
||||
};
|
||||
}
|
||||
} // namespace mozilla::pkix
|
||||
|
||||
} } // namespace mozilla::pkix
|
||||
|
||||
#endif // mozilla_pkix_Time_h
|
||||
#endif // mozilla_pkix_Time_h
|
||||
|
||||
@@ -1,32 +1,16 @@
|
||||
/* -*- 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_pkix_h
|
||||
#define mozilla_pkix_pkix_h
|
||||
|
||||
#include "pkixtypes.h"
|
||||
#include "pkix/pkixtypes.h"
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
namespace mozilla {
|
||||
namespace pkix {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// LIMITED SUPPORT FOR CERTIFICATE POLICIES
|
||||
@@ -102,8 +86,8 @@ namespace mozilla { namespace pkix {
|
||||
// requiredPolicy:
|
||||
// This is the policy to apply; typically included in EV certificates.
|
||||
// If there is no policy, pass in CertPolicyId::anyPolicy.
|
||||
Result BuildCertChain(TrustDomain& trustDomain, Input cert,
|
||||
Time time, EndEntityOrCA endEntityOrCA,
|
||||
Result BuildCertChain(TrustDomain& trustDomain, Input cert, Time time,
|
||||
EndEntityOrCA endEntityOrCA,
|
||||
KeyUsage requiredKeyUsageIfPresent,
|
||||
KeyPurposeId requiredEKUIfPresent,
|
||||
const CertPolicyId& requiredPolicy,
|
||||
@@ -121,8 +105,7 @@ Result CheckCertHostname(Input cert, Input hostname,
|
||||
// Construct an RFC-6960-encoded OCSP request, ready for submission to a
|
||||
// responder, for the provided CertID. The request has no extensions.
|
||||
static const size_t OCSP_REQUEST_MAX_LENGTH = 127;
|
||||
Result CreateEncodedOCSPRequest(TrustDomain& trustDomain,
|
||||
const CertID& certID,
|
||||
Result CreateEncodedOCSPRequest(TrustDomain& trustDomain, const CertID& certID,
|
||||
/*out*/ uint8_t (&out)[OCSP_REQUEST_MAX_LENGTH],
|
||||
/*out*/ size_t& outLen);
|
||||
|
||||
@@ -139,13 +122,12 @@ Result CreateEncodedOCSPRequest(TrustDomain& trustDomain,
|
||||
// which the encoded response is considered trustworthy (that is, as long as
|
||||
// the given time at which to validate is less than or equal to validThrough,
|
||||
// the response will be considered trustworthy).
|
||||
Result VerifyEncodedOCSPResponse(TrustDomain& trustDomain,
|
||||
const CertID& certID, Time time,
|
||||
uint16_t maxLifetimeInDays,
|
||||
Input encodedResponse,
|
||||
/* out */ bool& expired,
|
||||
/* optional out */ Time* thisUpdate = nullptr,
|
||||
/* optional out */ Time* validThrough = nullptr);
|
||||
Result VerifyEncodedOCSPResponse(
|
||||
TrustDomain& trustDomain, const CertID& certID, Time time,
|
||||
uint16_t maxLifetimeInDays, Input encodedResponse,
|
||||
/* out */ bool& expired,
|
||||
/* optional out */ Time* thisUpdate = nullptr,
|
||||
/* optional out */ Time* validThrough = nullptr);
|
||||
|
||||
// Check that the TLSFeature extensions in a given end-entity cert (which is
|
||||
// assumed to have been already validated with BuildCertChain) are satisfied.
|
||||
@@ -154,7 +136,7 @@ Result VerifyEncodedOCSPResponse(TrustDomain& trustDomain,
|
||||
// requirement for another value. Empty extensions are also rejected.
|
||||
Result CheckTLSFeaturesAreSatisfied(Input& cert,
|
||||
const Input* stapledOCSPResponse);
|
||||
}
|
||||
} // namespace mozilla::pkix
|
||||
|
||||
} } // namespace mozilla::pkix
|
||||
|
||||
#endif // mozilla_pkix_pkix_h
|
||||
#endif // mozilla_pkix_pkix_h
|
||||
|
||||
@@ -1,44 +1,26 @@
|
||||
/* -*- 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_pkixcheck_h
|
||||
#define mozilla_pkix_pkixcheck_h
|
||||
|
||||
#include "pkix/pkixtypes.h"
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
namespace mozilla {
|
||||
namespace pkix {
|
||||
|
||||
class BackCert;
|
||||
|
||||
Result CheckIssuerIndependentProperties(
|
||||
TrustDomain& trustDomain,
|
||||
const BackCert& cert,
|
||||
Time time,
|
||||
KeyUsage requiredKeyUsageIfPresent,
|
||||
KeyPurposeId requiredEKUIfPresent,
|
||||
const CertPolicyId& requiredPolicy,
|
||||
unsigned int subCACount,
|
||||
/*out*/ TrustLevel& trustLevel);
|
||||
Result CheckIssuerIndependentProperties(TrustDomain& trustDomain,
|
||||
const BackCert& cert, Time time,
|
||||
KeyUsage requiredKeyUsageIfPresent,
|
||||
KeyPurposeId requiredEKUIfPresent,
|
||||
const CertPolicyId& requiredPolicy,
|
||||
unsigned int subCACount,
|
||||
/*out*/ TrustLevel& trustLevel);
|
||||
|
||||
Result CheckNameConstraints(Input encodedNameConstraints,
|
||||
const BackCert& firstChild,
|
||||
@@ -59,7 +41,7 @@ Result CheckValidity(Time time, Time notBefore, Time notAfter);
|
||||
// Check that a subject has TLS Feature (rfc7633) requirements that match its
|
||||
// potential issuer
|
||||
Result CheckTLSFeatures(const BackCert& subject, BackCert& potentialIssuer);
|
||||
}
|
||||
} // namespace mozilla::pkix
|
||||
|
||||
} } // namespace mozilla::pkix
|
||||
|
||||
#endif // mozilla_pkix_pkixcheck_h
|
||||
#endif // mozilla_pkix_pkixcheck_h
|
||||
@@ -1,25 +1,8 @@
|
||||
/* -*- 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_pkixder_h
|
||||
#define mozilla_pkix_pkixder_h
|
||||
@@ -39,23 +22,20 @@
|
||||
#include "pkix/Input.h"
|
||||
#include "pkix/pkixtypes.h"
|
||||
|
||||
namespace mozilla { namespace pkix { namespace der {
|
||||
namespace mozilla {
|
||||
namespace pkix {
|
||||
namespace der {
|
||||
|
||||
enum Class : uint8_t
|
||||
{
|
||||
UNIVERSAL = 0 << 6,
|
||||
// APPLICATION = 1 << 6, // unused
|
||||
CONTEXT_SPECIFIC = 2 << 6,
|
||||
// PRIVATE = 3 << 6 // unused
|
||||
enum Class : uint8_t {
|
||||
UNIVERSAL = 0 << 6,
|
||||
// APPLICATION = 1 << 6, // unused
|
||||
CONTEXT_SPECIFIC = 2 << 6,
|
||||
// PRIVATE = 3 << 6 // unused
|
||||
};
|
||||
|
||||
enum Constructed
|
||||
{
|
||||
CONSTRUCTED = 1 << 5
|
||||
};
|
||||
enum Constructed { CONSTRUCTED = 1 << 5 };
|
||||
|
||||
enum Tag : uint8_t
|
||||
{
|
||||
enum Tag : uint8_t {
|
||||
BOOLEAN = UNIVERSAL | 0x01,
|
||||
INTEGER = UNIVERSAL | 0x02,
|
||||
BIT_STRING = UNIVERSAL | 0x03,
|
||||
@@ -64,8 +44,8 @@ enum Tag : uint8_t
|
||||
OIDTag = UNIVERSAL | 0x06,
|
||||
ENUMERATED = UNIVERSAL | 0x0a,
|
||||
UTF8String = UNIVERSAL | 0x0c,
|
||||
SEQUENCE = UNIVERSAL | CONSTRUCTED | 0x10, // 0x30
|
||||
SET = UNIVERSAL | CONSTRUCTED | 0x11, // 0x31
|
||||
SEQUENCE = UNIVERSAL | CONSTRUCTED | 0x10, // 0x30
|
||||
SET = UNIVERSAL | CONSTRUCTED | 0x11, // 0x31
|
||||
PrintableString = UNIVERSAL | 0x13,
|
||||
TeletexString = UNIVERSAL | 0x14,
|
||||
IA5String = UNIVERSAL | 0x16,
|
||||
@@ -79,9 +59,8 @@ Result ReadTagAndGetValue(Reader& input, /*out*/ uint8_t& tag,
|
||||
/*out*/ Input& value);
|
||||
Result End(Reader& input);
|
||||
|
||||
inline Result
|
||||
ExpectTagAndGetValue(Reader& input, uint8_t tag, /*out*/ Input& value)
|
||||
{
|
||||
inline Result ExpectTagAndGetValue(Reader& input, uint8_t tag,
|
||||
/*out*/ Input& value) {
|
||||
uint8_t actualTag;
|
||||
Result rv = ReadTagAndGetValue(input, actualTag, value);
|
||||
if (rv != Success) {
|
||||
@@ -93,9 +72,8 @@ ExpectTagAndGetValue(Reader& input, uint8_t tag, /*out*/ Input& value)
|
||||
return Success;
|
||||
}
|
||||
|
||||
inline Result
|
||||
ExpectTagAndGetValue(Reader& input, uint8_t tag, /*out*/ Reader& value)
|
||||
{
|
||||
inline Result ExpectTagAndGetValue(Reader& input, uint8_t tag,
|
||||
/*out*/ Reader& value) {
|
||||
Input valueInput;
|
||||
Result rv = ExpectTagAndGetValue(input, tag, valueInput);
|
||||
if (rv != Success) {
|
||||
@@ -104,9 +82,7 @@ ExpectTagAndGetValue(Reader& input, uint8_t tag, /*out*/ Reader& value)
|
||||
return value.Init(valueInput);
|
||||
}
|
||||
|
||||
inline Result
|
||||
ExpectTagAndEmptyValue(Reader& input, uint8_t tag)
|
||||
{
|
||||
inline Result ExpectTagAndEmptyValue(Reader& input, uint8_t tag) {
|
||||
Reader value;
|
||||
Result rv = ExpectTagAndGetValue(input, tag, value);
|
||||
if (rv != Success) {
|
||||
@@ -115,18 +91,26 @@ ExpectTagAndEmptyValue(Reader& input, uint8_t tag)
|
||||
return End(value);
|
||||
}
|
||||
|
||||
inline Result
|
||||
ExpectTagAndSkipValue(Reader& input, uint8_t tag)
|
||||
{
|
||||
inline Result ExpectTagAndSkipValue(Reader& input, uint8_t tag) {
|
||||
Input ignoredValue;
|
||||
return ExpectTagAndGetValue(input, tag, ignoredValue);
|
||||
}
|
||||
|
||||
// This skips IMPLICIT OPTIONAL tags that are "primitive" (not constructed),
|
||||
// given the number in the class of the tag (i.e. the number in the brackets in
|
||||
// `issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL`).
|
||||
inline Result SkipOptionalImplicitPrimitiveTag(Reader& input,
|
||||
uint8_t numberInClass) {
|
||||
if (input.Peek(CONTEXT_SPECIFIC | numberInClass)) {
|
||||
return ExpectTagAndSkipValue(input, CONTEXT_SPECIFIC | numberInClass);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
// Like ExpectTagAndGetValue, except the output Input will contain the
|
||||
// encoded tag and length along with the value.
|
||||
inline Result
|
||||
ExpectTagAndGetTLV(Reader& input, uint8_t tag, /*out*/ Input& tlv)
|
||||
{
|
||||
inline Result ExpectTagAndGetTLV(Reader& input, uint8_t tag,
|
||||
/*out*/ Input& tlv) {
|
||||
Reader::Mark mark(input.GetMark());
|
||||
Result rv = ExpectTagAndSkipValue(input, tag);
|
||||
if (rv != Success) {
|
||||
@@ -135,9 +119,7 @@ ExpectTagAndGetTLV(Reader& input, uint8_t tag, /*out*/ Input& tlv)
|
||||
return input.GetInput(mark, tlv);
|
||||
}
|
||||
|
||||
inline Result
|
||||
End(Reader& input)
|
||||
{
|
||||
inline Result End(Reader& input) {
|
||||
if (!input.AtEnd()) {
|
||||
return Result::ERROR_BAD_DER;
|
||||
}
|
||||
@@ -146,9 +128,7 @@ End(Reader& input)
|
||||
}
|
||||
|
||||
template <typename Decoder>
|
||||
inline Result
|
||||
Nested(Reader& input, uint8_t tag, Decoder decoder)
|
||||
{
|
||||
inline Result Nested(Reader& input, uint8_t tag, Decoder decoder) {
|
||||
Reader nested;
|
||||
Result rv = ExpectTagAndGetValue(input, tag, nested);
|
||||
if (rv != Success) {
|
||||
@@ -162,9 +142,8 @@ Nested(Reader& input, uint8_t tag, Decoder decoder)
|
||||
}
|
||||
|
||||
template <typename Decoder>
|
||||
inline Result
|
||||
Nested(Reader& input, uint8_t outerTag, uint8_t innerTag, Decoder decoder)
|
||||
{
|
||||
inline Result Nested(Reader& input, uint8_t outerTag, uint8_t innerTag,
|
||||
Decoder decoder) {
|
||||
Reader nestedInput;
|
||||
Result rv = ExpectTagAndGetValue(input, outerTag, nestedInput);
|
||||
if (rv != Success) {
|
||||
@@ -205,10 +184,8 @@ Nested(Reader& input, uint8_t outerTag, uint8_t innerTag, Decoder decoder)
|
||||
// foos.
|
||||
//
|
||||
template <typename Decoder>
|
||||
inline Result
|
||||
NestedOf(Reader& input, uint8_t outerTag, uint8_t innerTag,
|
||||
EmptyAllowed mayBeEmpty, Decoder decoder)
|
||||
{
|
||||
inline Result NestedOf(Reader& input, uint8_t outerTag, uint8_t innerTag,
|
||||
EmptyAllowed mayBeEmpty, Decoder decoder) {
|
||||
Reader inner;
|
||||
Result rv = ExpectTagAndGetValue(input, outerTag, inner);
|
||||
if (rv != Success) {
|
||||
@@ -236,10 +213,8 @@ NestedOf(Reader& input, uint8_t outerTag, uint8_t innerTag,
|
||||
// DER-encoded data wrapped in a SEQUENCE (or similar) with nothing after it.
|
||||
// This function reduces the boilerplate necessary for stripping the outermost
|
||||
// SEQUENCE (or similar) and ensuring that nothing follows it.
|
||||
inline Result
|
||||
ExpectTagAndGetValueAtEnd(Reader& outer, uint8_t expectedTag,
|
||||
/*out*/ Reader& inner)
|
||||
{
|
||||
inline Result ExpectTagAndGetValueAtEnd(Reader& outer, uint8_t expectedTag,
|
||||
/*out*/ Reader& inner) {
|
||||
Result rv = der::ExpectTagAndGetValue(outer, expectedTag, inner);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
@@ -248,10 +223,8 @@ ExpectTagAndGetValueAtEnd(Reader& outer, uint8_t expectedTag,
|
||||
}
|
||||
|
||||
// Similar to the above, but takes an Input instead of a Reader&.
|
||||
inline Result
|
||||
ExpectTagAndGetValueAtEnd(Input outer, uint8_t expectedTag,
|
||||
/*out*/ Reader& inner)
|
||||
{
|
||||
inline Result ExpectTagAndGetValueAtEnd(Input outer, uint8_t expectedTag,
|
||||
/*out*/ Reader& inner) {
|
||||
Reader outerReader(outer);
|
||||
return ExpectTagAndGetValueAtEnd(outerReader, expectedTag, inner);
|
||||
}
|
||||
@@ -260,30 +233,26 @@ ExpectTagAndGetValueAtEnd(Input outer, uint8_t expectedTag,
|
||||
|
||||
namespace internal {
|
||||
|
||||
enum class IntegralValueRestriction
|
||||
{
|
||||
enum class IntegralValueRestriction {
|
||||
NoRestriction,
|
||||
MustBePositive,
|
||||
MustBe0To127,
|
||||
};
|
||||
|
||||
Result IntegralBytes(Reader& input, uint8_t tag,
|
||||
IntegralValueRestriction valueRestriction,
|
||||
/*out*/ Input& value,
|
||||
Result IntegralBytes(
|
||||
Reader& input, uint8_t tag, IntegralValueRestriction valueRestriction,
|
||||
/*out*/ Input& value,
|
||||
/*optional out*/ Input::size_type* significantBytes = nullptr);
|
||||
|
||||
// This parser will only parse values between 0..127. If this range is
|
||||
// increased then callers will need to be changed.
|
||||
Result IntegralValue(Reader& input, uint8_t tag, /*out*/ uint8_t& value);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace internal
|
||||
|
||||
Result
|
||||
BitStringWithNoUnusedBits(Reader& input, /*out*/ Input& value);
|
||||
Result BitStringWithNoUnusedBits(Reader& input, /*out*/ Input& value);
|
||||
|
||||
inline Result
|
||||
Boolean(Reader& input, /*out*/ bool& value)
|
||||
{
|
||||
inline Result Boolean(Reader& input, /*out*/ bool& value) {
|
||||
Reader valueReader;
|
||||
Result rv = ExpectTagAndGetValue(input, BOOLEAN, valueReader);
|
||||
if (rv != Success) {
|
||||
@@ -300,8 +269,12 @@ Boolean(Reader& input, /*out*/ bool& value)
|
||||
return rv;
|
||||
}
|
||||
switch (intValue) {
|
||||
case 0: value = false; return Success;
|
||||
case 0xFF: value = true; return Success;
|
||||
case 0:
|
||||
value = false;
|
||||
return Success;
|
||||
case 0xFF:
|
||||
value = true;
|
||||
return Success;
|
||||
default:
|
||||
return Result::ERROR_BAD_DER;
|
||||
}
|
||||
@@ -313,9 +286,7 @@ Boolean(Reader& input, /*out*/ bool& value)
|
||||
// default value." However, it appears to be common that other libraries
|
||||
// incorrectly include the value of a BOOLEAN even when it's equal to the
|
||||
// default value, so we allow invalid explicit encodings here.
|
||||
inline Result
|
||||
OptionalBoolean(Reader& input, /*out*/ bool& value)
|
||||
{
|
||||
inline Result OptionalBoolean(Reader& input, /*out*/ bool& value) {
|
||||
value = false;
|
||||
if (input.Peek(BOOLEAN)) {
|
||||
Result rv = Boolean(input, value);
|
||||
@@ -328,9 +299,7 @@ OptionalBoolean(Reader& input, /*out*/ bool& value)
|
||||
|
||||
// This parser will only parse values between 0..127. If this range is
|
||||
// increased then callers will need to be changed.
|
||||
inline Result
|
||||
Enumerated(Reader& input, uint8_t& value)
|
||||
{
|
||||
inline Result Enumerated(Reader& input, uint8_t& value) {
|
||||
return internal::IntegralValue(input, ENUMERATED | 0, value);
|
||||
}
|
||||
|
||||
@@ -344,23 +313,19 @@ namespace internal {
|
||||
// time formats that start at 1970.
|
||||
Result TimeChoice(Reader& input, uint8_t tag, /*out*/ Time& time);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace internal
|
||||
|
||||
// Only times from 1970-01-01-00:00:00 onward are accepted, in order to
|
||||
// eliminate the chance for complications in converting times to traditional
|
||||
// time formats that start at 1970.
|
||||
inline Result
|
||||
GeneralizedTime(Reader& input, /*out*/ Time& time)
|
||||
{
|
||||
inline Result GeneralizedTime(Reader& input, /*out*/ Time& time) {
|
||||
return internal::TimeChoice(input, GENERALIZED_TIME, time);
|
||||
}
|
||||
|
||||
// Only times from 1970-01-01-00:00:00 onward are accepted, in order to
|
||||
// eliminate the chance for complications in converting times to traditional
|
||||
// time formats that start at 1970.
|
||||
inline Result
|
||||
TimeChoice(Reader& input, /*out*/ Time& time)
|
||||
{
|
||||
inline Result TimeChoice(Reader& input, /*out*/ Time& time) {
|
||||
uint8_t expectedTag = input.Peek(UTCTime) ? UTCTime : GENERALIZED_TIME;
|
||||
return internal::TimeChoice(input, expectedTag, time);
|
||||
}
|
||||
@@ -369,20 +334,17 @@ TimeChoice(Reader& input, /*out*/ Time& time)
|
||||
// zero are rejected. If significantBytes is not null, then it will be set to
|
||||
// the number of significant bytes in the value (the length of the value, less
|
||||
// the length of any leading padding), which is useful for key size checks.
|
||||
inline Result
|
||||
PositiveInteger(Reader& input, /*out*/ Input& value,
|
||||
/*optional out*/ Input::size_type* significantBytes = nullptr)
|
||||
{
|
||||
inline Result PositiveInteger(
|
||||
Reader& input, /*out*/ Input& value,
|
||||
/*optional out*/ Input::size_type* significantBytes = nullptr) {
|
||||
return internal::IntegralBytes(
|
||||
input, INTEGER, internal::IntegralValueRestriction::MustBePositive,
|
||||
value, significantBytes);
|
||||
input, INTEGER, internal::IntegralValueRestriction::MustBePositive, value,
|
||||
significantBytes);
|
||||
}
|
||||
|
||||
// This parser will only parse values between 0..127. If this range is
|
||||
// increased then callers will need to be changed.
|
||||
inline Result
|
||||
Integer(Reader& input, /*out*/ uint8_t& value)
|
||||
{
|
||||
inline Result Integer(Reader& input, /*out*/ uint8_t& value) {
|
||||
return internal::IntegralValue(input, INTEGER, value);
|
||||
}
|
||||
|
||||
@@ -390,9 +352,8 @@ Integer(Reader& input, /*out*/ uint8_t& value)
|
||||
// increased then callers will need to be changed. The default value must be
|
||||
// -1; defaultValue is only a parameter to make it clear in the calling code
|
||||
// what the default value is.
|
||||
inline Result
|
||||
OptionalInteger(Reader& input, long defaultValue, /*out*/ long& value)
|
||||
{
|
||||
inline Result OptionalInteger(Reader& input, long defaultValue,
|
||||
/*out*/ long& value) {
|
||||
// If we need to support a different default value in the future, we need to
|
||||
// test that parsedValue != defaultValue.
|
||||
if (defaultValue != -1) {
|
||||
@@ -413,16 +374,12 @@ OptionalInteger(Reader& input, long defaultValue, /*out*/ long& value)
|
||||
return Success;
|
||||
}
|
||||
|
||||
inline Result
|
||||
Null(Reader& input)
|
||||
{
|
||||
inline Result Null(Reader& input) {
|
||||
return ExpectTagAndEmptyValue(input, NULLTag);
|
||||
}
|
||||
|
||||
template <uint8_t Len>
|
||||
Result
|
||||
OID(Reader& input, const uint8_t (&expectedOid)[Len])
|
||||
{
|
||||
Result OID(Reader& input, const uint8_t (&expectedOid)[Len]) {
|
||||
Reader value;
|
||||
Result rv = ExpectTagAndGetValue(input, OIDTag, value);
|
||||
if (rv != Success) {
|
||||
@@ -436,9 +393,7 @@ OID(Reader& input, const uint8_t (&expectedOid)[Len])
|
||||
|
||||
// PKI-specific types
|
||||
|
||||
inline Result
|
||||
CertificateSerialNumber(Reader& input, /*out*/ Input& value)
|
||||
{
|
||||
inline Result CertificateSerialNumber(Reader& input, /*out*/ Input& value) {
|
||||
// http://tools.ietf.org/html/rfc5280#section-4.1.2.2:
|
||||
//
|
||||
// * "The serial number MUST be a positive integer assigned by the CA to
|
||||
@@ -450,13 +405,12 @@ CertificateSerialNumber(Reader& input, /*out*/ Input& value)
|
||||
// that are negative or zero. Certificate users SHOULD be prepared to
|
||||
// gracefully handle such certificates."
|
||||
return internal::IntegralBytes(
|
||||
input, INTEGER, internal::IntegralValueRestriction::NoRestriction,
|
||||
value);
|
||||
input, INTEGER, internal::IntegralValueRestriction::NoRestriction, value);
|
||||
}
|
||||
|
||||
// x.509 and OCSP both use this same version numbering scheme, though OCSP
|
||||
// only supports v1.
|
||||
enum class Version { v1 = 0, v2 = 1, v3 = 2, v4 = 3 };
|
||||
enum class Version { v1 = 0, v2 = 1, v3 = 2, v4 = 3, Uninitialized = 255 };
|
||||
|
||||
// X.509 Certificate and OCSP ResponseData both use
|
||||
// "[0] EXPLICIT Version DEFAULT v1". Although an explicit encoding of v1 is
|
||||
@@ -465,10 +419,8 @@ enum class Version { v1 = 0, v2 = 1, v3 = 2, v4 = 3 };
|
||||
Result OptionalVersion(Reader& input, /*out*/ Version& version);
|
||||
|
||||
template <typename ExtensionHandler>
|
||||
inline Result
|
||||
OptionalExtensions(Reader& input, uint8_t tag,
|
||||
ExtensionHandler extensionHandler)
|
||||
{
|
||||
inline Result OptionalExtensions(Reader& input, uint8_t tag,
|
||||
ExtensionHandler extensionHandler) {
|
||||
if (!input.Peek(tag)) {
|
||||
return Success;
|
||||
}
|
||||
@@ -479,58 +431,54 @@ OptionalExtensions(Reader& input, uint8_t tag,
|
||||
// TODO(bug 997994): According to the specification, there should never be
|
||||
// an empty sequence of extensions but we've found OCSP responses that have
|
||||
// that (see bug 991898).
|
||||
return NestedOf(tagged, SEQUENCE, SEQUENCE, EmptyAllowed::Yes,
|
||||
[extensionHandler](Reader& extension) -> Result {
|
||||
// Extension ::= SEQUENCE {
|
||||
// extnID OBJECT IDENTIFIER,
|
||||
// critical BOOLEAN DEFAULT FALSE,
|
||||
// extnValue OCTET STRING
|
||||
// }
|
||||
Reader extnID;
|
||||
Result rv = ExpectTagAndGetValue(extension, OIDTag, extnID);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
bool critical;
|
||||
rv = OptionalBoolean(extension, critical);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
Input extnValue;
|
||||
rv = ExpectTagAndGetValue(extension, OCTET_STRING, extnValue);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
bool understood = false;
|
||||
rv = extensionHandler(extnID, extnValue, critical, understood);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
if (critical && !understood) {
|
||||
return Result::ERROR_UNKNOWN_CRITICAL_EXTENSION;
|
||||
}
|
||||
return Success;
|
||||
});
|
||||
return NestedOf(
|
||||
tagged, SEQUENCE, SEQUENCE, EmptyAllowed::Yes,
|
||||
[extensionHandler](Reader& extension) -> Result {
|
||||
// Extension ::= SEQUENCE {
|
||||
// extnID OBJECT IDENTIFIER,
|
||||
// critical BOOLEAN DEFAULT FALSE,
|
||||
// extnValue OCTET STRING
|
||||
// }
|
||||
Reader extnID;
|
||||
Result rv = ExpectTagAndGetValue(extension, OIDTag, extnID);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
bool critical;
|
||||
rv = OptionalBoolean(extension, critical);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
Input extnValue;
|
||||
rv = ExpectTagAndGetValue(extension, OCTET_STRING, extnValue);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
bool understood = false;
|
||||
rv = extensionHandler(extnID, extnValue, critical, understood);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
if (critical && !understood) {
|
||||
return Result::ERROR_UNKNOWN_CRITICAL_EXTENSION;
|
||||
}
|
||||
return Success;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Result DigestAlgorithmIdentifier(Reader& input,
|
||||
/*out*/ DigestAlgorithm& algorithm);
|
||||
|
||||
enum class PublicKeyAlgorithm
|
||||
{
|
||||
RSA_PKCS1,
|
||||
ECDSA,
|
||||
};
|
||||
enum class PublicKeyAlgorithm { RSA_PKCS1, ECDSA, Uninitialized };
|
||||
|
||||
Result SignatureAlgorithmIdentifierValue(
|
||||
Reader& input,
|
||||
/*out*/ PublicKeyAlgorithm& publicKeyAlgorithm,
|
||||
/*out*/ DigestAlgorithm& digestAlgorithm);
|
||||
Reader& input,
|
||||
/*out*/ PublicKeyAlgorithm& publicKeyAlgorithm,
|
||||
/*out*/ DigestAlgorithm& digestAlgorithm);
|
||||
|
||||
struct SignedDataWithSignature final
|
||||
{
|
||||
public:
|
||||
struct SignedDataWithSignature final {
|
||||
public:
|
||||
Input data;
|
||||
Input algorithm;
|
||||
Input signature;
|
||||
@@ -558,7 +506,8 @@ public:
|
||||
// certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
|
||||
Result SignedData(Reader& input, /*out*/ Reader& tbs,
|
||||
/*out*/ SignedDataWithSignature& signedDataWithSignature);
|
||||
}
|
||||
}
|
||||
} // namespace mozilla::pkix::der
|
||||
|
||||
} } } // namespace mozilla::pkix::der
|
||||
|
||||
#endif // mozilla_pkix_pkixder_h
|
||||
#endif // mozilla_pkix_pkixder_h
|
||||
@@ -1,34 +1,18 @@
|
||||
/* -*- 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_pkixnss_h
|
||||
#define mozilla_pkix_pkixnss_h
|
||||
|
||||
#include "pkixtypes.h"
|
||||
#include <seccomon.h>
|
||||
#include "pkix/pkixtypes.h"
|
||||
#include "prerror.h"
|
||||
#include "seccomon.h"
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
namespace mozilla {
|
||||
namespace pkix {
|
||||
|
||||
// Verifies the PKCS#1.5 signature on the given data using the given RSA public
|
||||
// key.
|
||||
@@ -53,10 +37,8 @@ Result VerifyECDSASignedDigestNSS(const SignedDigest& sd,
|
||||
// TODO: Taking the output buffer as (uint8_t*, size_t) is counter to our
|
||||
// other, extensive, memory safety efforts in mozilla::pkix, and we should find
|
||||
// a way to provide a more-obviously-safe interface.
|
||||
Result DigestBufNSS(Input item,
|
||||
DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf,
|
||||
size_t digestBufLen);
|
||||
Result DigestBufNSS(Input item, DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf, size_t digestBufLen);
|
||||
|
||||
Result MapPRErrorCodeToResult(PRErrorCode errorCode);
|
||||
PRErrorCode MapResultToPRErrorCode(Result result);
|
||||
@@ -71,8 +53,7 @@ PRErrorCode MapResultToPRErrorCode(Result result);
|
||||
static const PRErrorCode ERROR_BASE = -0x4000;
|
||||
static const PRErrorCode ERROR_LIMIT = ERROR_BASE + 1000;
|
||||
|
||||
enum ErrorCode
|
||||
{
|
||||
enum ErrorCode {
|
||||
MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE = ERROR_BASE + 0,
|
||||
MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY = ERROR_BASE + 1,
|
||||
MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE = ERROR_BASE + 2,
|
||||
@@ -86,23 +67,22 @@ enum ErrorCode
|
||||
MOZILLA_PKIX_ERROR_REQUIRED_TLS_FEATURE_MISSING = ERROR_BASE + 10,
|
||||
MOZILLA_PKIX_ERROR_INVALID_INTEGER_ENCODING = ERROR_BASE + 11,
|
||||
MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME = ERROR_BASE + 12,
|
||||
MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED = ERROR_BASE + 13,
|
||||
MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT = ERROR_BASE + 14,
|
||||
MOZILLA_PKIX_ERROR_MITM_DETECTED = ERROR_BASE + 15,
|
||||
END_OF_LIST
|
||||
};
|
||||
|
||||
void RegisterErrorTable();
|
||||
|
||||
inline SECItem UnsafeMapInputToSECItem(Input input)
|
||||
{
|
||||
SECItem result = {
|
||||
siBuffer,
|
||||
const_cast<uint8_t*>(input.UnsafeGetData()),
|
||||
input.GetLength()
|
||||
};
|
||||
inline SECItem UnsafeMapInputToSECItem(Input input) {
|
||||
SECItem result = {siBuffer, const_cast<uint8_t*>(input.UnsafeGetData()),
|
||||
input.GetLength()};
|
||||
static_assert(sizeof(decltype(input.GetLength())) <= sizeof(result.len),
|
||||
"input.GetLength() must fit in a SECItem");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} // namespace mozilla::pkix
|
||||
|
||||
} } // namespace mozilla::pkix
|
||||
|
||||
#endif // mozilla_pkix_pkixnss_h
|
||||
#endif // mozilla_pkix_pkixnss_h
|
||||
|
||||
@@ -1,45 +1,29 @@
|
||||
/* -*- 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_pkixtypes_h
|
||||
#define mozilla_pkix_pkixtypes_h
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "pkix/Input.h"
|
||||
#include "pkix/Time.h"
|
||||
#include "stdint.h"
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
namespace mozilla {
|
||||
namespace pkix {
|
||||
|
||||
enum class DigestAlgorithm
|
||||
{
|
||||
enum class DigestAlgorithm {
|
||||
sha512 = 1,
|
||||
sha384 = 2,
|
||||
sha256 = 3,
|
||||
sha1 = 4,
|
||||
};
|
||||
|
||||
enum class NamedCurve
|
||||
{
|
||||
enum class NamedCurve {
|
||||
// secp521r1 (OID 1.3.132.0.35, RFC 5480)
|
||||
secp521r1 = 1,
|
||||
|
||||
@@ -50,8 +34,7 @@ enum class NamedCurve
|
||||
secp256r1 = 3,
|
||||
};
|
||||
|
||||
struct SignedDigest final
|
||||
{
|
||||
struct SignedDigest final {
|
||||
Input digest;
|
||||
DigestAlgorithm digestAlgorithm;
|
||||
Input signature;
|
||||
@@ -61,53 +44,49 @@ struct SignedDigest final
|
||||
|
||||
enum class EndEntityOrCA { MustBeEndEntity = 0, MustBeCA = 1 };
|
||||
|
||||
enum class KeyUsage : uint8_t
|
||||
{
|
||||
enum class KeyUsage : uint8_t {
|
||||
digitalSignature = 0,
|
||||
nonRepudiation = 1,
|
||||
keyEncipherment = 2,
|
||||
nonRepudiation = 1,
|
||||
keyEncipherment = 2,
|
||||
dataEncipherment = 3,
|
||||
keyAgreement = 4,
|
||||
keyCertSign = 5,
|
||||
keyAgreement = 4,
|
||||
keyCertSign = 5,
|
||||
// cRLSign = 6,
|
||||
// encipherOnly = 7,
|
||||
// decipherOnly = 8,
|
||||
noParticularKeyUsageRequired = 0xff,
|
||||
};
|
||||
|
||||
enum class KeyPurposeId
|
||||
{
|
||||
enum class KeyPurposeId {
|
||||
anyExtendedKeyUsage = 0,
|
||||
id_kp_serverAuth = 1, // id-kp-serverAuth
|
||||
id_kp_clientAuth = 2, // id-kp-clientAuth
|
||||
id_kp_codeSigning = 3, // id-kp-codeSigning
|
||||
id_kp_emailProtection = 4, // id-kp-emailProtection
|
||||
id_kp_OCSPSigning = 9, // id-kp-OCSPSigning
|
||||
id_kp_serverAuth = 1, // id-kp-serverAuth
|
||||
id_kp_clientAuth = 2, // id-kp-clientAuth
|
||||
id_kp_codeSigning = 3, // id-kp-codeSigning
|
||||
id_kp_emailProtection = 4, // id-kp-emailProtection
|
||||
id_kp_OCSPSigning = 9, // id-kp-OCSPSigning
|
||||
};
|
||||
|
||||
struct CertPolicyId final
|
||||
{
|
||||
struct CertPolicyId final {
|
||||
uint16_t numBytes;
|
||||
static const uint16_t MAX_BYTES = 24;
|
||||
uint8_t bytes[MAX_BYTES];
|
||||
|
||||
bool IsAnyPolicy() const;
|
||||
bool operator==(const CertPolicyId& other) const;
|
||||
|
||||
static const CertPolicyId anyPolicy;
|
||||
};
|
||||
|
||||
enum class TrustLevel
|
||||
{
|
||||
TrustAnchor = 1, // certificate is a trusted root CA certificate or
|
||||
// equivalent *for the given policy*.
|
||||
ActivelyDistrusted = 2, // certificate is known to be bad
|
||||
InheritsTrust = 3 // certificate must chain to a trust anchor
|
||||
enum class TrustLevel {
|
||||
TrustAnchor = 1, // certificate is a trusted root CA certificate or
|
||||
// equivalent *for the given policy*.
|
||||
ActivelyDistrusted = 2, // certificate is known to be bad
|
||||
InheritsTrust = 3 // certificate must chain to a trust anchor
|
||||
};
|
||||
|
||||
// Extensions extracted during the verification flow.
|
||||
// See TrustDomain::NoteAuxiliaryExtension.
|
||||
enum class AuxiliaryExtension
|
||||
{
|
||||
enum class AuxiliaryExtension {
|
||||
// Certificate Transparency data, specifically Signed Certificate
|
||||
// Timestamps (SCTs). See RFC 6962.
|
||||
|
||||
@@ -130,25 +109,22 @@ enum class AuxiliaryExtension
|
||||
// field from the issuer's certificate. serialNumber is the entire DER-encoded
|
||||
// serial number from the subject certificate (the certificate for which we are
|
||||
// checking the revocation status).
|
||||
struct CertID final
|
||||
{
|
||||
public:
|
||||
CertID(Input issuer, Input issuerSubjectPublicKeyInfo, Input serialNumber)
|
||||
: issuer(issuer)
|
||||
, issuerSubjectPublicKeyInfo(issuerSubjectPublicKeyInfo)
|
||||
, serialNumber(serialNumber)
|
||||
{
|
||||
}
|
||||
struct CertID final {
|
||||
public:
|
||||
CertID(Input aIssuer, Input aIssuerSubjectPublicKeyInfo, Input aSerialNumber)
|
||||
: issuer(aIssuer),
|
||||
issuerSubjectPublicKeyInfo(aIssuerSubjectPublicKeyInfo),
|
||||
serialNumber(aSerialNumber) {}
|
||||
const Input issuer;
|
||||
const Input issuerSubjectPublicKeyInfo;
|
||||
const Input serialNumber;
|
||||
|
||||
void operator=(const CertID&) = delete;
|
||||
};
|
||||
typedef std::unique_ptr<CertID> ScopedCertID;
|
||||
|
||||
class DERArray
|
||||
{
|
||||
public:
|
||||
class DERArray {
|
||||
public:
|
||||
// Returns the number of DER-encoded items in the array.
|
||||
virtual size_t GetLength() const = 0;
|
||||
|
||||
@@ -156,19 +132,19 @@ public:
|
||||
// (0-indexed). The result is guaranteed to be non-null if i < GetLength(),
|
||||
// and the result is guaranteed to be nullptr if i >= GetLength().
|
||||
virtual const Input* GetDER(size_t i) const = 0;
|
||||
protected:
|
||||
DERArray() { }
|
||||
virtual ~DERArray() { }
|
||||
|
||||
protected:
|
||||
DERArray() {}
|
||||
virtual ~DERArray() {}
|
||||
};
|
||||
|
||||
// Applications control the behavior of path building and verification by
|
||||
// implementing the TrustDomain interface. The TrustDomain is used for all
|
||||
// cryptography and for determining which certificates are trusted or
|
||||
// distrusted.
|
||||
class TrustDomain
|
||||
{
|
||||
public:
|
||||
virtual ~TrustDomain() { }
|
||||
class TrustDomain {
|
||||
public:
|
||||
virtual ~TrustDomain() {}
|
||||
|
||||
// Determine the level of trust in the given certificate for the given role.
|
||||
// This will be called for every certificate encountered during path
|
||||
@@ -187,9 +163,8 @@ public:
|
||||
Input candidateCertDER,
|
||||
/*out*/ TrustLevel& trustLevel) = 0;
|
||||
|
||||
class IssuerChecker
|
||||
{
|
||||
public:
|
||||
class IssuerChecker {
|
||||
public:
|
||||
// potentialIssuerDER is the complete DER encoding of the certificate to
|
||||
// be checked as a potential issuer.
|
||||
//
|
||||
@@ -198,9 +173,10 @@ public:
|
||||
// constraints will be checked in addition to any any name constraints
|
||||
// contained in potentialIssuerDER.
|
||||
virtual Result Check(Input potentialIssuerDER,
|
||||
/*optional*/ const Input* additionalNameConstraints,
|
||||
/*out*/ bool& keepGoing) = 0;
|
||||
protected:
|
||||
/*optional*/ const Input* additionalNameConstraints,
|
||||
/*out*/ bool& keepGoing) = 0;
|
||||
|
||||
protected:
|
||||
IssuerChecker();
|
||||
virtual ~IssuerChecker();
|
||||
|
||||
@@ -254,8 +230,8 @@ public:
|
||||
// implementation has an efficient way of filtering potential issuers by name
|
||||
// and/or validity period itself, then it is probably better for performance
|
||||
// for it to do so.
|
||||
virtual Result FindIssuer(Input encodedIssuerName,
|
||||
IssuerChecker& checker, Time time) = 0;
|
||||
virtual Result FindIssuer(Input encodedIssuerName, IssuerChecker& checker,
|
||||
Time time) = 0;
|
||||
|
||||
// Called as soon as we think we have a valid chain but before revocation
|
||||
// checks are done. This function can be used to compute additional checks,
|
||||
@@ -265,7 +241,8 @@ public:
|
||||
//
|
||||
// This function may be called multiple times, regardless of whether it
|
||||
// returns success or failure. It is guaranteed that BuildCertChain will not
|
||||
// return Success unless the last call to IsChainValid returns Success. Further,
|
||||
// return Success unless the last call to IsChainValid returns Success.
|
||||
// Further,
|
||||
// it is guaranteed that when BuildCertChain returns Success the last chain
|
||||
// passed to IsChainValid is the valid chain that should be used for further
|
||||
// operations that require the whole chain.
|
||||
@@ -278,13 +255,15 @@ public:
|
||||
// wrong to assume that the certificate chain is valid.
|
||||
//
|
||||
// certChain.GetDER(0) is the trust anchor.
|
||||
virtual Result IsChainValid(const DERArray& certChain, Time time) = 0;
|
||||
virtual Result IsChainValid(const DERArray& certChain, Time time,
|
||||
const CertPolicyId& requiredPolicy) = 0;
|
||||
|
||||
virtual Result CheckRevocation(EndEntityOrCA endEntityOrCA,
|
||||
const CertID& certID, Time time,
|
||||
Duration validityDuration,
|
||||
/*optional*/ const Input* stapledOCSPresponse,
|
||||
/*optional*/ const Input* aiaExtension) = 0;
|
||||
/*optional*/ const Input* stapledOCSPresponse,
|
||||
/*optional*/ const Input* aiaExtension,
|
||||
/*optional*/ const Input* sctExtension) = 0;
|
||||
|
||||
// Check that the given digest algorithm is acceptable for use in signatures.
|
||||
//
|
||||
@@ -301,8 +280,7 @@ public:
|
||||
// Result::ERROR_INADEQUATE_KEY_SIZE if the key size is not acceptable,
|
||||
// or another error code if another error occurred.
|
||||
virtual Result CheckRSAPublicKeyModulusSizeInBits(
|
||||
EndEntityOrCA endEntityOrCA,
|
||||
unsigned int modulusSizeInBits) = 0;
|
||||
EndEntityOrCA endEntityOrCA, unsigned int modulusSizeInBits) = 0;
|
||||
|
||||
// Verify the given RSA PKCS#1.5 signature on the given digest using the
|
||||
// given RSA public key.
|
||||
@@ -311,9 +289,8 @@ public:
|
||||
// function, so it is not necessary to repeat those checks here. However,
|
||||
// VerifyRSAPKCS1SignedDigest *is* responsible for doing the mathematical
|
||||
// verification of the public key validity as specified in NIST SP 800-56A.
|
||||
virtual Result VerifyRSAPKCS1SignedDigest(
|
||||
const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) = 0;
|
||||
virtual Result VerifyRSAPKCS1SignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) = 0;
|
||||
|
||||
// Check that the given named ECC curve is acceptable for ECDSA signatures.
|
||||
//
|
||||
@@ -368,12 +345,11 @@ public:
|
||||
// TODO: Taking the output buffer as (uint8_t*, size_t) is counter to our
|
||||
// other, extensive, memory safety efforts in mozilla::pkix, and we should
|
||||
// find a way to provide a more-obviously-safe interface.
|
||||
virtual Result DigestBuf(Input item,
|
||||
DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf,
|
||||
size_t digestBufLen) = 0;
|
||||
protected:
|
||||
TrustDomain() { }
|
||||
virtual Result DigestBuf(Input item, DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf, size_t digestBufLen) = 0;
|
||||
|
||||
protected:
|
||||
TrustDomain() {}
|
||||
|
||||
TrustDomain(const TrustDomain&) = delete;
|
||||
void operator=(const TrustDomain&) = delete;
|
||||
@@ -384,25 +360,24 @@ enum class FallBackToSearchWithinSubject { No = 0, Yes = 1 };
|
||||
// Applications control the behavior of matching presented name information from
|
||||
// a certificate against a reference hostname by implementing the
|
||||
// NameMatchingPolicy interface. Used in concert with CheckCertHostname.
|
||||
class NameMatchingPolicy
|
||||
{
|
||||
public:
|
||||
virtual ~NameMatchingPolicy() { }
|
||||
class NameMatchingPolicy {
|
||||
public:
|
||||
virtual ~NameMatchingPolicy() {}
|
||||
|
||||
// Given that the certificate in question has a notBefore field with the given
|
||||
// value, should name matching fall back to searching within the subject
|
||||
// common name field?
|
||||
virtual Result FallBackToCommonName(
|
||||
Time notBefore,
|
||||
/*out*/ FallBackToSearchWithinSubject& fallBackToCommonName) = 0;
|
||||
Time notBefore,
|
||||
/*out*/ FallBackToSearchWithinSubject& fallBackToCommonName) = 0;
|
||||
|
||||
protected:
|
||||
NameMatchingPolicy() { }
|
||||
protected:
|
||||
NameMatchingPolicy() {}
|
||||
|
||||
NameMatchingPolicy(const NameMatchingPolicy&) = delete;
|
||||
void operator=(const NameMatchingPolicy&) = delete;
|
||||
};
|
||||
}
|
||||
} // namespace mozilla::pkix
|
||||
|
||||
} } // namespace mozilla::pkix
|
||||
|
||||
#endif // mozilla_pkix_pkixtypes_h
|
||||
#endif // mozilla_pkix_pkixtypes_h
|
||||
|
||||
@@ -1,32 +1,16 @@
|
||||
/* -*- 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_pkixutil_h
|
||||
#define mozilla_pkix_pkixutil_h
|
||||
|
||||
#include "pkixder.h"
|
||||
#include "pkix/pkixder.h"
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
namespace mozilla {
|
||||
namespace pkix {
|
||||
|
||||
// During path building and verification, we build a linked list of BackCerts
|
||||
// from the current cert toward the end-entity certificate. The linked list
|
||||
@@ -37,17 +21,15 @@ namespace mozilla { namespace pkix {
|
||||
// Each BackCert contains pointers to all the given certificate's extensions
|
||||
// so that we can parse the extension block once and then process the
|
||||
// extensions in an order that may be different than they appear in the cert.
|
||||
class BackCert final
|
||||
{
|
||||
public:
|
||||
class BackCert final {
|
||||
public:
|
||||
// certDER and childCert must be valid for the lifetime of BackCert.
|
||||
BackCert(Input certDER, EndEntityOrCA endEntityOrCA,
|
||||
const BackCert* childCert)
|
||||
: der(certDER)
|
||||
, endEntityOrCA(endEntityOrCA)
|
||||
, childCert(childCert)
|
||||
{
|
||||
}
|
||||
BackCert(Input aCertDER, EndEntityOrCA aEndEntityOrCA,
|
||||
const BackCert* aChildCert)
|
||||
: der(aCertDER),
|
||||
endEntityOrCA(aEndEntityOrCA),
|
||||
childCert(aChildCert),
|
||||
version(der::Version::Uninitialized) {}
|
||||
|
||||
Result Init();
|
||||
|
||||
@@ -65,67 +47,47 @@ public:
|
||||
// RFC 5280 names for everything.
|
||||
const Input GetValidity() const { return validity; }
|
||||
const Input GetSubject() const { return subject; }
|
||||
const Input GetSubjectPublicKeyInfo() const
|
||||
{
|
||||
return subjectPublicKeyInfo;
|
||||
}
|
||||
const Input* GetAuthorityInfoAccess() const
|
||||
{
|
||||
const Input GetSubjectPublicKeyInfo() const { return subjectPublicKeyInfo; }
|
||||
const Input* GetAuthorityInfoAccess() const {
|
||||
return MaybeInput(authorityInfoAccess);
|
||||
}
|
||||
const Input* GetBasicConstraints() const
|
||||
{
|
||||
const Input* GetBasicConstraints() const {
|
||||
return MaybeInput(basicConstraints);
|
||||
}
|
||||
const Input* GetCertificatePolicies() const
|
||||
{
|
||||
const Input* GetCertificatePolicies() const {
|
||||
return MaybeInput(certificatePolicies);
|
||||
}
|
||||
const Input* GetExtKeyUsage() const
|
||||
{
|
||||
return MaybeInput(extKeyUsage);
|
||||
}
|
||||
const Input* GetKeyUsage() const
|
||||
{
|
||||
return MaybeInput(keyUsage);
|
||||
}
|
||||
const Input* GetInhibitAnyPolicy() const
|
||||
{
|
||||
const Input* GetExtKeyUsage() const { return MaybeInput(extKeyUsage); }
|
||||
const Input* GetKeyUsage() const { return MaybeInput(keyUsage); }
|
||||
const Input* GetInhibitAnyPolicy() const {
|
||||
return MaybeInput(inhibitAnyPolicy);
|
||||
}
|
||||
const Input* GetNameConstraints() const
|
||||
{
|
||||
const Input* GetNameConstraints() const {
|
||||
return MaybeInput(nameConstraints);
|
||||
}
|
||||
const Input* GetSubjectAltName() const
|
||||
{
|
||||
return MaybeInput(subjectAltName);
|
||||
}
|
||||
const Input* GetRequiredTLSFeatures() const
|
||||
{
|
||||
const Input* GetSubjectAltName() const { return MaybeInput(subjectAltName); }
|
||||
const Input* GetRequiredTLSFeatures() const {
|
||||
return MaybeInput(requiredTLSFeatures);
|
||||
}
|
||||
const Input* GetSignedCertificateTimestamps() const
|
||||
{
|
||||
const Input* GetSignedCertificateTimestamps() const {
|
||||
return MaybeInput(signedCertificateTimestamps);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
const Input der;
|
||||
|
||||
public:
|
||||
public:
|
||||
const EndEntityOrCA endEntityOrCA;
|
||||
BackCert const* const childCert;
|
||||
|
||||
private:
|
||||
private:
|
||||
// When parsing certificates in BackCert::Init, we don't accept empty
|
||||
// extensions. Consequently, we don't have to store a distinction between
|
||||
// empty extensions and extensions that weren't included. However, when
|
||||
// *processing* extensions, we distinguish between whether an extension was
|
||||
// included or not based on whetehr the GetXXX function for the extension
|
||||
// returns nullptr.
|
||||
static inline const Input* MaybeInput(const Input& item)
|
||||
{
|
||||
static inline const Input* MaybeInput(const Input& item) {
|
||||
return item.GetLength() > 0 ? &item : nullptr;
|
||||
}
|
||||
|
||||
@@ -152,7 +114,7 @@ private:
|
||||
Input subjectAltName;
|
||||
Input criticalNetscapeCertificateType;
|
||||
Input requiredTLSFeatures;
|
||||
Input signedCertificateTimestamps; // RFC 6962 (Certificate Transparency)
|
||||
Input signedCertificateTimestamps; // RFC 6962 (Certificate Transparency)
|
||||
|
||||
Result RememberExtension(Reader& extnID, Input extnValue, bool critical,
|
||||
/*out*/ bool& understood);
|
||||
@@ -161,29 +123,24 @@ private:
|
||||
void operator=(const BackCert&) = delete;
|
||||
};
|
||||
|
||||
class NonOwningDERArray final : public DERArray
|
||||
{
|
||||
public:
|
||||
NonOwningDERArray()
|
||||
: numItems(0)
|
||||
{
|
||||
class NonOwningDERArray final : public DERArray {
|
||||
public:
|
||||
NonOwningDERArray() : numItems(0) {
|
||||
// we don't need to initialize the items array because we always check
|
||||
// numItems before accessing i.
|
||||
}
|
||||
|
||||
size_t GetLength() const override { return numItems; }
|
||||
|
||||
const Input* GetDER(size_t i) const override
|
||||
{
|
||||
const Input* GetDER(size_t i) const override {
|
||||
return i < numItems ? &items[i] : nullptr;
|
||||
}
|
||||
|
||||
Result Append(Input der)
|
||||
{
|
||||
Result Append(Input der) {
|
||||
if (numItems >= MAX_LENGTH) {
|
||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||
}
|
||||
Result rv = items[numItems].Init(der); // structure assignment
|
||||
Result rv = items[numItems].Init(der); // structure assignment
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
@@ -193,8 +150,9 @@ public:
|
||||
|
||||
// Public so we can static_assert on this. Keep in sync with MAX_SUBCA_COUNT.
|
||||
static const size_t MAX_LENGTH = 8;
|
||||
private:
|
||||
Input items[MAX_LENGTH]; // avoids any heap allocations
|
||||
|
||||
private:
|
||||
Input items[MAX_LENGTH]; // avoids any heap allocations
|
||||
size_t numItems;
|
||||
|
||||
NonOwningDERArray(const NonOwningDERArray&) = delete;
|
||||
@@ -203,25 +161,22 @@ private:
|
||||
|
||||
// Extracts the SignedCertificateTimestampList structure which is encoded as an
|
||||
// OCTET STRING within the X.509v3 / OCSP extensions (see RFC 6962 section 3.3).
|
||||
Result
|
||||
ExtractSignedCertificateTimestampListFromExtension(Input extnValue,
|
||||
Input& sctList);
|
||||
Result ExtractSignedCertificateTimestampListFromExtension(Input extnValue,
|
||||
Input& sctList);
|
||||
|
||||
inline unsigned int
|
||||
DaysBeforeYear(unsigned int year)
|
||||
{
|
||||
inline unsigned int DaysBeforeYear(unsigned int year) {
|
||||
assert(year <= 9999);
|
||||
return ((year - 1u) * 365u)
|
||||
+ ((year - 1u) / 4u) // leap years are every 4 years,
|
||||
- ((year - 1u) / 100u) // except years divisible by 100,
|
||||
+ ((year - 1u) / 400u); // except years divisible by 400.
|
||||
return ((year - 1u) * 365u) +
|
||||
((year - 1u) / 4u) // leap years are every 4 years,
|
||||
- ((year - 1u) / 100u) // except years divisible by 100,
|
||||
+ ((year - 1u) / 400u); // except years divisible by 400.
|
||||
}
|
||||
|
||||
static const size_t MAX_DIGEST_SIZE_IN_BYTES = 512 / 8; // sha-512
|
||||
static const size_t MAX_DIGEST_SIZE_IN_BYTES = 512 / 8; // sha-512
|
||||
|
||||
Result DigestSignedData(TrustDomain& trustDomain,
|
||||
const der::SignedDataWithSignature& signedData,
|
||||
/*out*/ uint8_t(&digestBuf)[MAX_DIGEST_SIZE_IN_BYTES],
|
||||
/*out*/ uint8_t (&digestBuf)[MAX_DIGEST_SIZE_IN_BYTES],
|
||||
/*out*/ der::PublicKeyAlgorithm& publicKeyAlg,
|
||||
/*out*/ SignedDigest& signedDigest);
|
||||
|
||||
@@ -237,9 +192,9 @@ Result VerifySignedData(TrustDomain& trustDomain,
|
||||
|
||||
// Extracts the key parameters from |subjectPublicKeyInfo|, invoking
|
||||
// the relevant methods of |trustDomain|.
|
||||
Result
|
||||
CheckSubjectPublicKeyInfo(Input subjectPublicKeyInfo, TrustDomain& trustDomain,
|
||||
EndEntityOrCA endEntityOrCA);
|
||||
Result CheckSubjectPublicKeyInfo(Input subjectPublicKeyInfo,
|
||||
TrustDomain& trustDomain,
|
||||
EndEntityOrCA endEntityOrCA);
|
||||
|
||||
// In a switch over an enum, sometimes some compilers are not satisfied that
|
||||
// all control flow paths have been considered unless there is a default case.
|
||||
@@ -268,21 +223,25 @@ CheckSubjectPublicKeyInfo(Input subjectPublicKeyInfo, TrustDomain& trustDomain,
|
||||
// (-W-covered-switch-default). Versions prior to 3.5 warned about unreachable
|
||||
// code in such default cases (-Wunreachable-code) even when
|
||||
// -W-covered-switch-default was disabled, but that changed in Clang 3.5.
|
||||
#define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM // empty
|
||||
#define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM // empty
|
||||
#elif defined(__GNUC__)
|
||||
// GCC will warn if not all cases are covered (-Wswitch-enum). It does not
|
||||
// assume that the default case is unreachable.
|
||||
#define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM \
|
||||
default: assert(false); __builtin_unreachable();
|
||||
default: \
|
||||
assert(false); \
|
||||
__builtin_unreachable();
|
||||
#elif defined(_MSC_VER)
|
||||
// MSVC will warn if not all cases are covered (C4061, level 4). It does not
|
||||
// assume that the default case is unreachable.
|
||||
#define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM \
|
||||
default: assert(false); __assume(0);
|
||||
default: \
|
||||
assert(false); \
|
||||
__assume(0);
|
||||
#else
|
||||
#error Unsupported compiler for MOZILLA_PKIX_UNREACHABLE_DEFAULT.
|
||||
#endif
|
||||
}
|
||||
} // namespace mozilla::pkix
|
||||
|
||||
} } // namespace mozilla::pkix
|
||||
|
||||
#endif // mozilla_pkix_pkixutil_h
|
||||
#endif // mozilla_pkix_pkixutil_h
|
||||
@@ -1,82 +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_ScopedPtr_h
|
||||
#define mozilla_pkix_ScopedPtr_h
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
|
||||
// A subset polyfill of std::unique_ptr that does not support move construction
|
||||
// or move assignment. This is used instead of std::unique_ptr because some
|
||||
// important toolchains still don't provide std::unique_ptr, including in
|
||||
// particular Android NDK projects with APP_STL=stlport_static or
|
||||
// ALL_STL=stlport_shared.
|
||||
template <typename T, void (&Destroyer)(T*)>
|
||||
class ScopedPtr final
|
||||
{
|
||||
public:
|
||||
explicit ScopedPtr(T* value = nullptr) : mValue(value) { }
|
||||
|
||||
ScopedPtr(const ScopedPtr&) = delete;
|
||||
|
||||
~ScopedPtr()
|
||||
{
|
||||
if (mValue) {
|
||||
Destroyer(mValue);
|
||||
}
|
||||
}
|
||||
|
||||
void operator=(const ScopedPtr&) = delete;
|
||||
|
||||
T& operator*() const { return *mValue; }
|
||||
T* operator->() const { return mValue; }
|
||||
|
||||
explicit operator bool() const { return mValue; }
|
||||
|
||||
T* get() const { return mValue; }
|
||||
|
||||
T* release()
|
||||
{
|
||||
T* result = mValue;
|
||||
mValue = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
void reset(T* newValue = nullptr)
|
||||
{
|
||||
// The C++ standard requires std::unique_ptr to destroy the old value
|
||||
// pointed to by mValue, if any, *after* assigning the new value to mValue.
|
||||
T* oldValue = mValue;
|
||||
mValue = newValue;
|
||||
if (oldValue) {
|
||||
Destroyer(oldValue);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
T* mValue;
|
||||
};
|
||||
|
||||
} } // namespace mozilla::pkix
|
||||
|
||||
#endif // mozilla_pkix_ScopedPtr_h
|
||||
@@ -1,30 +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 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 "pkix/pkix.h"
|
||||
|
||||
#include "pkixcheck.h"
|
||||
#include "pkixutil.h"
|
||||
#include "pkix/pkixcheck.h"
|
||||
#include "pkix/pkixutil.h"
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
|
||||
@@ -35,7 +18,8 @@ static Result BuildForward(TrustDomain& trustDomain,
|
||||
KeyPurposeId requiredEKUIfPresent,
|
||||
const CertPolicyId& requiredPolicy,
|
||||
/*optional*/ const Input* stapledOCSPResponse,
|
||||
unsigned int subCACount);
|
||||
unsigned int subCACount,
|
||||
unsigned int& buildForwardCallBudget);
|
||||
|
||||
TrustDomain::IssuerChecker::IssuerChecker() { }
|
||||
TrustDomain::IssuerChecker::~IssuerChecker() { }
|
||||
@@ -45,21 +29,24 @@ TrustDomain::IssuerChecker::~IssuerChecker() { }
|
||||
class PathBuildingStep final : public TrustDomain::IssuerChecker
|
||||
{
|
||||
public:
|
||||
PathBuildingStep(TrustDomain& trustDomain, const BackCert& subject,
|
||||
Time time, KeyPurposeId requiredEKUIfPresent,
|
||||
const CertPolicyId& requiredPolicy,
|
||||
/*optional*/ const Input* stapledOCSPResponse,
|
||||
unsigned int subCACount, Result deferredSubjectError)
|
||||
: trustDomain(trustDomain)
|
||||
, subject(subject)
|
||||
, time(time)
|
||||
, requiredEKUIfPresent(requiredEKUIfPresent)
|
||||
, requiredPolicy(requiredPolicy)
|
||||
, stapledOCSPResponse(stapledOCSPResponse)
|
||||
, subCACount(subCACount)
|
||||
, deferredSubjectError(deferredSubjectError)
|
||||
PathBuildingStep(TrustDomain& aTrustDomain, const BackCert& aSubject,
|
||||
Time aTime, KeyPurposeId aRequiredEKUIfPresent,
|
||||
const CertPolicyId& aRequiredPolicy,
|
||||
/*optional*/ const Input* aStapledOCSPResponse,
|
||||
unsigned int aSubCACount, Result aDeferredSubjectError,
|
||||
unsigned int& aBuildForwardCallBudget)
|
||||
: trustDomain(aTrustDomain)
|
||||
, subject(aSubject)
|
||||
, time(aTime)
|
||||
, requiredEKUIfPresent(aRequiredEKUIfPresent)
|
||||
, requiredPolicy(aRequiredPolicy)
|
||||
, stapledOCSPResponse(aStapledOCSPResponse)
|
||||
, subCACount(aSubCACount)
|
||||
, deferredSubjectError(aDeferredSubjectError)
|
||||
, subjectSignaturePublicKeyAlg(der::PublicKeyAlgorithm::Uninitialized)
|
||||
, result(Result::FATAL_ERROR_LIBRARY_FAILURE)
|
||||
, resultWasSet(false)
|
||||
, buildForwardCallBudget(aBuildForwardCallBudget)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -87,6 +74,7 @@ private:
|
||||
Result RecordResult(Result currentResult, /*out*/ bool& keepGoing);
|
||||
Result result;
|
||||
bool resultWasSet;
|
||||
unsigned int& buildForwardCallBudget;
|
||||
|
||||
PathBuildingStep(const PathBuildingStep&) = delete;
|
||||
void operator=(const PathBuildingStep&) = delete;
|
||||
@@ -160,9 +148,8 @@ PathBuildingStep::Check(Input potentialIssuerDER,
|
||||
// Loop prevention, done as recommended by RFC4158 Section 5.2
|
||||
// TODO: this doesn't account for subjectAltNames!
|
||||
// TODO(perf): This probably can and should be optimized in some way.
|
||||
bool loopDetected = false;
|
||||
for (const BackCert* prev = potentialIssuer.childCert;
|
||||
!loopDetected && prev != nullptr; prev = prev->childCert) {
|
||||
for (const BackCert* prev = potentialIssuer.childCert; prev;
|
||||
prev = prev->childCert) {
|
||||
if (InputsAreEqual(potentialIssuer.GetSubjectPublicKeyInfo(),
|
||||
prev->GetSubjectPublicKeyInfo()) &&
|
||||
InputsAreEqual(potentialIssuer.GetSubject(), prev->GetSubject())) {
|
||||
@@ -192,11 +179,20 @@ PathBuildingStep::Check(Input potentialIssuerDER,
|
||||
return RecordResult(rv, keepGoing);
|
||||
}
|
||||
|
||||
// If we've ran out of budget, stop searching.
|
||||
if (buildForwardCallBudget == 0) {
|
||||
Result savedRv = RecordResult(Result::ERROR_UNKNOWN_ISSUER, keepGoing);
|
||||
keepGoing = false;
|
||||
return savedRv;
|
||||
}
|
||||
buildForwardCallBudget--;
|
||||
|
||||
// RFC 5280, Section 4.2.1.3: "If the keyUsage extension is present, then the
|
||||
// subject public key MUST NOT be used to verify signatures on certificates
|
||||
// or CRLs unless the corresponding keyCertSign or cRLSign bit is set."
|
||||
rv = BuildForward(trustDomain, potentialIssuer, time, KeyUsage::keyCertSign,
|
||||
requiredEKUIfPresent, requiredPolicy, nullptr, subCACount);
|
||||
requiredEKUIfPresent, requiredPolicy, nullptr, subCACount,
|
||||
buildForwardCallBudget);
|
||||
if (rv != Success) {
|
||||
return RecordResult(rv, keepGoing);
|
||||
}
|
||||
@@ -239,9 +235,15 @@ PathBuildingStep::Check(Input potentialIssuerDER,
|
||||
Duration validityDuration(notAfter, notBefore);
|
||||
rv = trustDomain.CheckRevocation(subject.endEntityOrCA, certID, time,
|
||||
validityDuration, stapledOCSPResponse,
|
||||
subject.GetAuthorityInfoAccess());
|
||||
subject.GetAuthorityInfoAccess(),
|
||||
subject.GetSignedCertificateTimestamps());
|
||||
if (rv != Success) {
|
||||
return RecordResult(rv, keepGoing);
|
||||
// Since this is actually a problem with the current subject certificate
|
||||
// (rather than the issuer), it doesn't make sense to keep going; all
|
||||
// paths through this certificate will fail.
|
||||
Result savedRv = RecordResult(rv, keepGoing);
|
||||
keepGoing = false;
|
||||
return savedRv;
|
||||
}
|
||||
|
||||
if (subject.endEntityOrCA == EndEntityOrCA::MustBeEndEntity) {
|
||||
@@ -251,7 +253,11 @@ PathBuildingStep::Check(Input potentialIssuerDER,
|
||||
rv = ExtractSignedCertificateTimestampListFromExtension(*sctExtension,
|
||||
sctList);
|
||||
if (rv != Success) {
|
||||
return RecordResult(rv, keepGoing);
|
||||
// Again, the problem is with this certificate, and all paths through
|
||||
// it will fail.
|
||||
Result savedRv = RecordResult(rv, keepGoing);
|
||||
keepGoing = false;
|
||||
return savedRv;
|
||||
}
|
||||
trustDomain.NoteAuxiliaryExtension(AuxiliaryExtension::EmbeddedSCTList,
|
||||
sctList);
|
||||
@@ -276,7 +282,8 @@ BuildForward(TrustDomain& trustDomain,
|
||||
KeyPurposeId requiredEKUIfPresent,
|
||||
const CertPolicyId& requiredPolicy,
|
||||
/*optional*/ const Input* stapledOCSPResponse,
|
||||
unsigned int subCACount)
|
||||
unsigned int subCACount,
|
||||
unsigned int& buildForwardCallBudget)
|
||||
{
|
||||
Result rv;
|
||||
|
||||
@@ -311,7 +318,7 @@ BuildForward(TrustDomain& trustDomain,
|
||||
|
||||
// This must be done here, after the chain is built but before any
|
||||
// revocation checks have been done.
|
||||
return trustDomain.IsChainValid(chain, time);
|
||||
return trustDomain.IsChainValid(chain, time, requiredPolicy);
|
||||
}
|
||||
|
||||
if (subject.endEntityOrCA == EndEntityOrCA::MustBeCA) {
|
||||
@@ -334,7 +341,7 @@ BuildForward(TrustDomain& trustDomain,
|
||||
PathBuildingStep pathBuilder(trustDomain, subject, time,
|
||||
requiredEKUIfPresent, requiredPolicy,
|
||||
stapledOCSPResponse, subCACount,
|
||||
deferredEndEntityError);
|
||||
deferredEndEntityError, buildForwardCallBudget);
|
||||
|
||||
// TODO(bug 965136): Add SKI/AKI matching optimizations
|
||||
rv = trustDomain.FindIssuer(subject.GetIssuer(), pathBuilder, time);
|
||||
@@ -373,9 +380,22 @@ BuildCertChain(TrustDomain& trustDomain, Input certDER,
|
||||
return rv;
|
||||
}
|
||||
|
||||
// See bug 1056341 for context. If mozilla::pkix is being used in an
|
||||
// environment where there are many certificates that all have the same
|
||||
// distinguished name as their subject and issuer (but different SPKIs - see
|
||||
// the loop prevention as per RFC4158 Section 5.2 in PathBuildingStep::Check),
|
||||
// the space to search becomes exponential. Because it would be prohibitively
|
||||
// expensive to explore the entire space, we introduce a budget here that,
|
||||
// when exhausted, terminates the search with the result
|
||||
// Result::ERROR_UNKNOWN_ISSUER. Essentially, we limit the total number of
|
||||
// times `BuildForward` can be called. The current value appears to be a good
|
||||
// balance between finding a path when one exists (when the space isn't too
|
||||
// large) and timing out quickly enough when the space is too large or there
|
||||
// is no valid path to a trust anchor.
|
||||
unsigned int buildForwardCallBudget = 200000;
|
||||
return BuildForward(trustDomain, cert, time, requiredKeyUsageIfPresent,
|
||||
requiredEKUIfPresent, requiredPolicy, stapledOCSPResponse,
|
||||
0/*subCACount*/);
|
||||
0/*subCACount*/, buildForwardCallBudget);
|
||||
}
|
||||
|
||||
} } // namespace mozilla::pkix
|
||||
|
||||
@@ -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 2014 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 "pkixutil.h"
|
||||
#include "pkix/pkixutil.h"
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
|
||||
@@ -104,29 +87,24 @@ BackCert::Init()
|
||||
return rv;
|
||||
}
|
||||
|
||||
static const uint8_t CSC = der::CONTEXT_SPECIFIC | der::CONSTRUCTED;
|
||||
|
||||
// According to RFC 5280, all fields below this line are forbidden for
|
||||
// certificate versions less than v3. However, for compatibility reasons,
|
||||
// we parse v1/v2 certificates in the same way as v3 certificates. So if
|
||||
// these fields appear in a v1 certificate, they will be used.
|
||||
|
||||
// Ignore issuerUniqueID if present.
|
||||
if (tbsCertificate.Peek(CSC | 1)) {
|
||||
rv = der::ExpectTagAndSkipValue(tbsCertificate, CSC | 1);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
rv = der::SkipOptionalImplicitPrimitiveTag(tbsCertificate, 1);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Ignore subjectUniqueID if present.
|
||||
if (tbsCertificate.Peek(CSC | 2)) {
|
||||
rv = der::ExpectTagAndSkipValue(tbsCertificate, CSC | 2);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
rv = der::SkipOptionalImplicitPrimitiveTag(tbsCertificate, 2);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
static const uint8_t CSC = der::CONTEXT_SPECIFIC | der::CONSTRUCTED;
|
||||
rv = der::OptionalExtensions(
|
||||
tbsCertificate, CSC | 3,
|
||||
[this](Reader& extnID, const Input& extnValue, bool critical,
|
||||
@@ -156,7 +134,7 @@ BackCert::Init()
|
||||
// SSL Client | false | id_kp_clientAuth
|
||||
// S/MIME Client | false | id_kp_emailProtection
|
||||
// Object Signing | false | id_kp_codeSigning
|
||||
// SSL Server CA | true | id_pk_serverAuth
|
||||
// SSL Server CA | true | id_kp_serverAuth
|
||||
// SSL Client CA | true | id_kp_clientAuth
|
||||
// S/MIME CA | true | id_kp_emailProtection
|
||||
// Object Signing CA | true | id_kp_codeSigning
|
||||
|
||||
@@ -1,30 +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 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 "pkixcheck.h"
|
||||
#include "pkix/pkixcheck.h"
|
||||
|
||||
#include "pkixder.h"
|
||||
#include "pkixutil.h"
|
||||
#include "pkix/pkixder.h"
|
||||
#include "pkix/pkixutil.h"
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
|
||||
@@ -116,7 +99,11 @@ CheckSignatureAlgorithm(TrustDomain& trustDomain,
|
||||
// for any curve that we support, the chances of us encountering a curve
|
||||
// during path building is too low to be worth bothering with.
|
||||
break;
|
||||
|
||||
case der::PublicKeyAlgorithm::Uninitialized:
|
||||
{
|
||||
assert(false);
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
|
||||
}
|
||||
|
||||
@@ -338,15 +325,16 @@ CheckSubjectPublicKeyInfoContents(Reader& input, TrustDomain& trustDomain,
|
||||
[&trustDomain, endEntityOrCA](Reader& r) {
|
||||
Input modulus;
|
||||
Input::size_type modulusSignificantBytes;
|
||||
Result rv = der::PositiveInteger(r, modulus, &modulusSignificantBytes);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
Result nestedRv =
|
||||
der::PositiveInteger(r, modulus, &modulusSignificantBytes);
|
||||
if (nestedRv != Success) {
|
||||
return nestedRv;
|
||||
}
|
||||
// XXX: Should we do additional checks of the modulus?
|
||||
rv = trustDomain.CheckRSAPublicKeyModulusSizeInBits(
|
||||
endEntityOrCA, modulusSignificantBytes * 8u);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
nestedRv = trustDomain.CheckRSAPublicKeyModulusSizeInBits(
|
||||
endEntityOrCA, modulusSignificantBytes * 8u);
|
||||
if (nestedRv != Success) {
|
||||
return nestedRv;
|
||||
}
|
||||
|
||||
// XXX: We don't allow the TrustDomain to validate the exponent.
|
||||
@@ -531,6 +519,13 @@ CertPolicyId::IsAnyPolicy() const {
|
||||
std::equal(bytes, bytes + numBytes, ::mozilla::pkix::anyPolicy);
|
||||
}
|
||||
|
||||
bool
|
||||
CertPolicyId::operator==(const CertPolicyId& other) const
|
||||
{
|
||||
return numBytes == other.numBytes &&
|
||||
std::equal(bytes, bytes + numBytes, other.bytes);
|
||||
}
|
||||
|
||||
// certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
|
||||
Result
|
||||
CheckCertificatePolicies(EndEntityOrCA endEntityOrCA,
|
||||
@@ -644,9 +639,9 @@ CheckBasicConstraints(EndEntityOrCA endEntityOrCA,
|
||||
Reader input(*encodedBasicConstraints);
|
||||
Result rv = der::Nested(input, der::SEQUENCE,
|
||||
[&isCA, &pathLenConstraint](Reader& r) {
|
||||
Result rv = der::OptionalBoolean(r, isCA);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
Result nestedRv = der::OptionalBoolean(r, isCA);
|
||||
if (nestedRv != Success) {
|
||||
return nestedRv;
|
||||
}
|
||||
// TODO(bug 985025): If isCA is false, pathLenConstraint
|
||||
// MUST NOT be included (as per RFC 5280 section
|
||||
|
||||
@@ -1,29 +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 "pkixder.h"
|
||||
|
||||
#include "pkixutil.h"
|
||||
#include "pkix/pkixder.h"
|
||||
#include "pkix/pkixutil.h"
|
||||
|
||||
namespace mozilla { namespace pkix { namespace der {
|
||||
|
||||
@@ -212,7 +194,6 @@ SignatureAlgorithmIdentifierValue(Reader& input,
|
||||
Result
|
||||
DigestAlgorithmIdentifier(Reader& input, /*out*/ DigestAlgorithm& algorithm)
|
||||
{
|
||||
Reader r;
|
||||
return der::Nested(input, SEQUENCE, [&algorithm](Reader& r) -> Result {
|
||||
Reader algorithmID;
|
||||
Result rv = AlgorithmIdentifierValue(r, algorithmID);
|
||||
|
||||
@@ -1,25 +1,8 @@
|
||||
/* -*- 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 2014 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 code implements RFC6125-ish name matching, RFC5280-ish name constraint
|
||||
// checking, and related things.
|
||||
@@ -33,8 +16,10 @@
|
||||
// constraints, the reference identifier is the entire encoded name constraint
|
||||
// extension value.
|
||||
|
||||
#include "pkixcheck.h"
|
||||
#include "pkixutil.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "pkix/pkixcheck.h"
|
||||
#include "pkix/pkixutil.h"
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
|
||||
@@ -1607,12 +1592,12 @@ StartsWithIDNALabel(Input id)
|
||||
{
|
||||
static const uint8_t IDN_ALABEL_PREFIX[4] = { 'x', 'n', '-', '-' };
|
||||
Reader input(id);
|
||||
for (size_t i = 0; i < sizeof(IDN_ALABEL_PREFIX); ++i) {
|
||||
for (const uint8_t prefixByte : IDN_ALABEL_PREFIX) {
|
||||
uint8_t b;
|
||||
if (input.Read(b) != Success) {
|
||||
return false;
|
||||
}
|
||||
if (b != IDN_ALABEL_PREFIX[i]) {
|
||||
if (b != prefixByte) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1704,11 +1689,9 @@ FinishIPv6Address(/*in/out*/ uint8_t (&address)[16], int numComponents,
|
||||
}
|
||||
|
||||
// Shift components that occur after the contraction over.
|
||||
size_t componentsToMove = static_cast<size_t>(numComponents -
|
||||
contractionIndex);
|
||||
memmove(address + (2u * static_cast<size_t>(8 - componentsToMove)),
|
||||
address + (2u * static_cast<size_t>(contractionIndex)),
|
||||
componentsToMove * 2u);
|
||||
std::copy_backward(address + (2u * static_cast<size_t>(contractionIndex)),
|
||||
address + (2u * static_cast<size_t>(numComponents)),
|
||||
address + (2u * 8u));
|
||||
// Fill in the contracted area with zeros.
|
||||
std::fill_n(address + 2u * static_cast<size_t>(contractionIndex),
|
||||
(8u - static_cast<size_t>(numComponents)) * 2u, static_cast<uint8_t>(0u));
|
||||
|
||||
@@ -1,25 +1,8 @@
|
||||
/*- *- 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 "pkix/pkixnss.h"
|
||||
|
||||
@@ -28,9 +11,9 @@
|
||||
#include "cryptohi.h"
|
||||
#include "keyhi.h"
|
||||
#include "pk11pub.h"
|
||||
#include "nss_scoped_ptrs.h"
|
||||
#include "pkix/pkix.h"
|
||||
#include "pkixutil.h"
|
||||
#include "ScopedPtr.h"
|
||||
#include "pkix/pkixutil.h"
|
||||
#include "secerr.h"
|
||||
#include "sslerr.h"
|
||||
|
||||
@@ -55,12 +38,12 @@ VerifySignedDigest(const SignedDigest& sd,
|
||||
|
||||
SECItem subjectPublicKeyInfoSECItem =
|
||||
UnsafeMapInputToSECItem(subjectPublicKeyInfo);
|
||||
ScopedPtr<CERTSubjectPublicKeyInfo, SECKEY_DestroySubjectPublicKeyInfo>
|
||||
ScopedCERTSubjectPublicKeyInfo
|
||||
spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&subjectPublicKeyInfoSECItem));
|
||||
if (!spki) {
|
||||
return MapPRErrorCodeToResult(PR_GetError());
|
||||
}
|
||||
ScopedPtr<SECKEYPublicKey, SECKEY_DestroyPublicKey>
|
||||
ScopedSECKEYPublicKey
|
||||
pubKey(SECKEY_ExtractPublicKey(spki.get()));
|
||||
if (!pubKey) {
|
||||
return MapPRErrorCodeToResult(PR_GetError());
|
||||
@@ -210,6 +193,14 @@ RegisterErrorTable()
|
||||
{ "MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME",
|
||||
"The server presented a certificate with an empty issuer distinguished "
|
||||
"name." },
|
||||
{ "MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED",
|
||||
"An additional policy constraint failed when validating this "
|
||||
"certificate." },
|
||||
{ "MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT",
|
||||
"The certificate is not trusted because it is self-signed." },
|
||||
{ "MOZILLA_PKIX_ERROR_MITM_DETECTED",
|
||||
"Your connection is being intercepted by a TLS proxy. Uninstall it if "
|
||||
"possible or configure your device to trust its root certificate." },
|
||||
};
|
||||
// Note that these error strings are not localizable.
|
||||
// When these strings change, update the localization information too.
|
||||
|
||||
@@ -1,31 +1,14 @@
|
||||
/* -*- 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 <limits>
|
||||
|
||||
#include "pkix/pkix.h"
|
||||
#include "pkixcheck.h"
|
||||
#include "pkixutil.h"
|
||||
#include "pkix/pkixcheck.h"
|
||||
#include "pkix/pkixutil.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -45,16 +28,16 @@ enum class CertStatus : uint8_t {
|
||||
class Context final
|
||||
{
|
||||
public:
|
||||
Context(TrustDomain& trustDomain, const CertID& certID, Time time,
|
||||
uint16_t maxLifetimeInDays, /*optional out*/ Time* thisUpdate,
|
||||
/*optional out*/ Time* validThrough)
|
||||
: trustDomain(trustDomain)
|
||||
, certID(certID)
|
||||
, time(time)
|
||||
, maxLifetimeInDays(maxLifetimeInDays)
|
||||
Context(TrustDomain& aTrustDomain, const CertID& aCertID, Time aTime,
|
||||
uint16_t aMaxLifetimeInDays, /*optional out*/ Time* aThisUpdate,
|
||||
/*optional out*/ Time* aValidThrough)
|
||||
: trustDomain(aTrustDomain)
|
||||
, certID(aCertID)
|
||||
, time(aTime)
|
||||
, maxLifetimeInDays(aMaxLifetimeInDays)
|
||||
, certStatus(CertStatus::Unknown)
|
||||
, thisUpdate(thisUpdate)
|
||||
, validThrough(validThrough)
|
||||
, thisUpdate(aThisUpdate)
|
||||
, validThrough(aValidThrough)
|
||||
, expired(false)
|
||||
, matchFound(false)
|
||||
{
|
||||
@@ -172,9 +155,13 @@ static Result ExtensionNotUnderstood(Reader& extnID, Input extnValue,
|
||||
static Result RememberSingleExtension(Context& context, Reader& extnID,
|
||||
Input extnValue, bool critical,
|
||||
/*out*/ bool& understood);
|
||||
static inline Result CertID(Reader& input,
|
||||
const Context& context,
|
||||
/*out*/ bool& match);
|
||||
// It is convention to name the function after the part of the data structure
|
||||
// we're parsing from the RFC (e.g. OCSPResponse, ResponseBytes).
|
||||
// But since we also have a C++ type called CertID, this function doesn't
|
||||
// follow the convention to prevent shadowing.
|
||||
static inline Result MatchCertID(Reader& input,
|
||||
const Context& context,
|
||||
/*out*/ bool& match);
|
||||
static Result MatchKeyHash(TrustDomain& trustDomain,
|
||||
Input issuerKeyHash,
|
||||
Input issuerSubjectPublicKeyInfo,
|
||||
@@ -437,12 +424,13 @@ BasicResponse(Reader& input, Context& context)
|
||||
der::SEQUENCE, [&certs](Reader& certsDER) -> Result {
|
||||
while (!certsDER.AtEnd()) {
|
||||
Input cert;
|
||||
Result rv = der::ExpectTagAndGetTLV(certsDER, der::SEQUENCE, cert);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
Result nestedRv =
|
||||
der::ExpectTagAndGetTLV(certsDER, der::SEQUENCE, cert);
|
||||
if (nestedRv != Success) {
|
||||
return nestedRv;
|
||||
}
|
||||
rv = certs.Append(cert);
|
||||
if (rv != Success) {
|
||||
nestedRv = certs.Append(cert);
|
||||
if (nestedRv != Success) {
|
||||
return Result::ERROR_BAD_DER; // Too many certs
|
||||
}
|
||||
}
|
||||
@@ -537,7 +525,7 @@ SingleResponse(Reader& input, Context& context)
|
||||
{
|
||||
bool match = false;
|
||||
Result rv = der::Nested(input, der::SEQUENCE, [&context, &match](Reader& r) {
|
||||
return CertID(r, context, match);
|
||||
return MatchCertID(r, context, match);
|
||||
});
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
@@ -694,7 +682,7 @@ SingleResponse(Reader& input, Context& context)
|
||||
// issuerKeyHash OCTET STRING, -- Hash of issuer's public key
|
||||
// serialNumber CertificateSerialNumber }
|
||||
static inline Result
|
||||
CertID(Reader& input, const Context& context, /*out*/ bool& match)
|
||||
MatchCertID(Reader& input, const Context& context, /*out*/ bool& match)
|
||||
{
|
||||
match = false;
|
||||
|
||||
@@ -963,8 +951,8 @@ CreateEncodedOCSPRequest(TrustDomain& trustDomain, const struct CertID& certID,
|
||||
*d++ = 0x30; *d++ = totalLen - 10u; // reqCert (CertID SEQUENCE)
|
||||
|
||||
// reqCert.hashAlgorithm
|
||||
for (size_t i = 0; i < sizeof(hashAlgorithm); ++i) {
|
||||
*d++ = hashAlgorithm[i];
|
||||
for (const uint8_t hashAlgorithmByte : hashAlgorithm) {
|
||||
*d++ = hashAlgorithmByte;
|
||||
}
|
||||
|
||||
// reqCert.issuerNameHash (OCTET STRING)
|
||||
|
||||
@@ -1,28 +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 "pkix/Result.h"
|
||||
#include "pkixutil.h"
|
||||
#include "pkix/pkixutil.h"
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
|
||||
|
||||
@@ -1,30 +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 2014 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 "pkix/Time.h"
|
||||
#include "pkixutil.h"
|
||||
#include "pkix/pkixutil.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WINDOWS
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 3)
|
||||
#endif
|
||||
@@ -43,7 +26,7 @@ Now()
|
||||
{
|
||||
uint64_t seconds;
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WINDOWS
|
||||
// "Contains a 64-bit value representing the number of 100-nanosecond
|
||||
// intervals since January 1, 1601 (UTC)."
|
||||
// - http://msdn.microsoft.com/en-us/library/windows/desktop/ms724284(v=vs.85).aspx
|
||||
|
||||
@@ -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 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 "pkixutil.h"
|
||||
#include "pkix/pkixutil.h"
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
|
||||
@@ -78,6 +61,9 @@ VerifySignedDigest(TrustDomain& trustDomain,
|
||||
case der::PublicKeyAlgorithm::RSA_PKCS1:
|
||||
return trustDomain.VerifyRSAPKCS1SignedDigest(signedDigest,
|
||||
signerSubjectPublicKeyInfo);
|
||||
case der::PublicKeyAlgorithm::Uninitialized:
|
||||
assert(false);
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ SOURCES += [
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../nss/cpputil',
|
||||
'include',
|
||||
]
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -24,6 +24,7 @@ import argparse
|
||||
import itertools
|
||||
import sys
|
||||
|
||||
|
||||
def base128(value):
|
||||
"""
|
||||
Given an integral value, returns an array of the base-128 representation
|
||||
@@ -50,6 +51,7 @@ def base128(value):
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def dottedOIDToEncodedArray(dottedOID):
|
||||
"""
|
||||
Takes a dotted OID string (e.g. '1.2.840.10045.4.3.4') as input, and
|
||||
@@ -68,6 +70,7 @@ def dottedOIDToEncodedArray(dottedOID):
|
||||
restBase128 = [base128(x) for x in nodes[2:]]
|
||||
return [firstByte] + list(itertools.chain.from_iterable(restBase128))
|
||||
|
||||
|
||||
def dottedOIDToCArray(dottedOID, mode):
|
||||
"""
|
||||
Takes a dotted OID string (e.g. '1.2.840.10045.4.3.4') as input, and
|
||||
@@ -86,6 +89,7 @@ def dottedOIDToCArray(dottedOID, mode):
|
||||
|
||||
return ", ".join(["0x%.2x" % b for b in bytes])
|
||||
|
||||
|
||||
def specNameToCName(specName):
|
||||
"""
|
||||
Given an string containing an ASN.1 name, returns a string that is a valid
|
||||
@@ -97,6 +101,7 @@ def specNameToCName(specName):
|
||||
"""
|
||||
return specName.replace("-", "_")
|
||||
|
||||
|
||||
def toCode(programName, specName, dottedOID, mode):
|
||||
"""
|
||||
Given an ASN.1 name and a string containing the dotted representation of an
|
||||
@@ -180,11 +185,12 @@ def toCode(programName, specName, dottedOID, mode):
|
||||
" };\n") % (programNameWithOptions, specName, dottedOID, varName,
|
||||
dottedOIDToCArray(dottedOID, mode))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate code snippets to handle OIDs in C++",
|
||||
epilog="example: python %s ecdsa-with-SHA1 1.2.840.10045.4.1"
|
||||
% sys.argv[0])
|
||||
description="Generate code snippets to handle OIDs in C++",
|
||||
epilog="example: python %s ecdsa-with-SHA1 1.2.840.10045.4.1"
|
||||
% sys.argv[0])
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument("--tlv", action='store_true',
|
||||
help="Wrap the encoded OID value with the tag and length")
|
||||
|
||||
Reference in New Issue
Block a user