mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-04 22:37:29 +09:00
Merge remote-tracking branch 'origin/master' into custom
This commit is contained in:
commit
4992a2fd18
38 changed files with 924 additions and 1420 deletions
|
|
@ -292,6 +292,7 @@ AppTrustDomain::DigestBuf(Input item,
|
||||||
|
|
||||||
Result
|
Result
|
||||||
AppTrustDomain::CheckRevocation(EndEntityOrCA, const CertID&, Time, Duration,
|
AppTrustDomain::CheckRevocation(EndEntityOrCA, const CertID&, Time, Duration,
|
||||||
|
/*optional*/ const Input*,
|
||||||
/*optional*/ const Input*,
|
/*optional*/ const Input*,
|
||||||
/*optional*/ const Input*)
|
/*optional*/ const Input*)
|
||||||
{
|
{
|
||||||
|
|
@ -301,7 +302,8 @@ AppTrustDomain::CheckRevocation(EndEntityOrCA, const CertID&, Time, Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
Result
|
Result
|
||||||
AppTrustDomain::IsChainValid(const DERArray& certChain, Time time)
|
AppTrustDomain::IsChainValid(const DERArray& certChain, Time time,
|
||||||
|
const CertPolicyId& requiredPolicy)
|
||||||
{
|
{
|
||||||
SECStatus srv = ConstructCERTCertListFromReversedDERArray(certChain,
|
SECStatus srv = ConstructCERTCertListFromReversedDERArray(certChain,
|
||||||
mCertChain);
|
mCertChain);
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,11 @@ public:
|
||||||
mozilla::pkix::Time time,
|
mozilla::pkix::Time time,
|
||||||
mozilla::pkix::Duration validityDuration,
|
mozilla::pkix::Duration validityDuration,
|
||||||
/*optional*/ const mozilla::pkix::Input* stapledOCSPresponse,
|
/*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,
|
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(
|
virtual Result CheckSignatureDigestAlgorithm(
|
||||||
mozilla::pkix::DigestAlgorithm digestAlg,
|
mozilla::pkix::DigestAlgorithm digestAlg,
|
||||||
mozilla::pkix::EndEntityOrCA endEntityOrCA,
|
mozilla::pkix::EndEntityOrCA endEntityOrCA,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
#include "mozilla/ArrayUtils.h"
|
#include "mozilla/ArrayUtils.h"
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include "pkix/pkixnss.h"
|
#include "pkix/pkixnss.h"
|
||||||
#include "pkixutil.h"
|
#include "pkix/pkixutil.h"
|
||||||
|
|
||||||
namespace mozilla { namespace ct {
|
namespace mozilla { namespace ct {
|
||||||
|
|
||||||
|
|
@ -42,12 +42,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CheckRevocation(EndEntityOrCA, const CertID&, Time, Duration,
|
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;
|
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;
|
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
#include "mozilla/RangedPtr.h"
|
#include "mozilla/RangedPtr.h"
|
||||||
#include "mozilla/Vector.h"
|
#include "mozilla/Vector.h"
|
||||||
#include "pkix/pkixnss.h"
|
#include "pkix/pkixnss.h"
|
||||||
#include "pkixutil.h"
|
#include "pkix/pkixutil.h"
|
||||||
|
|
||||||
namespace mozilla { namespace ct {
|
namespace mozilla { namespace ct {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -348,7 +348,8 @@ NSSCertDBTrustDomain::CheckRevocation(EndEntityOrCA endEntityOrCA,
|
||||||
const CertID& certID, Time time,
|
const CertID& certID, Time time,
|
||||||
Duration validityDuration,
|
Duration validityDuration,
|
||||||
/*optional*/ const Input* stapledOCSPResponse,
|
/*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
|
// Actively distrusted certificates will have already been blocked by
|
||||||
// GetCertTrust.
|
// GetCertTrust.
|
||||||
|
|
@ -788,7 +789,9 @@ CheckForStartComOrWoSign(const UniqueCERTCertList& certChain)
|
||||||
}
|
}
|
||||||
|
|
||||||
Result
|
Result
|
||||||
NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray, Time time)
|
NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray,
|
||||||
|
Time time,
|
||||||
|
const CertPolicyId& requiredPolicy)
|
||||||
{
|
{
|
||||||
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
|
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
|
||||||
("NSSCertDBTrustDomain: IsChainValid"));
|
("NSSCertDBTrustDomain: IsChainValid"));
|
||||||
|
|
|
||||||
|
|
@ -134,11 +134,13 @@ public:
|
||||||
mozilla::pkix::Time time,
|
mozilla::pkix::Time time,
|
||||||
mozilla::pkix::Duration validityDuration,
|
mozilla::pkix::Duration validityDuration,
|
||||||
/*optional*/ const mozilla::pkix::Input* stapledOCSPResponse,
|
/*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;
|
override;
|
||||||
|
|
||||||
virtual Result IsChainValid(const mozilla::pkix::DERArray& certChain,
|
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(
|
virtual void NoteAuxiliaryExtension(
|
||||||
mozilla::pkix::AuxiliaryExtension extension,
|
mozilla::pkix::AuxiliaryExtension extension,
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ OCSPVerificationTrustDomain::FindIssuer(Input, IssuerChecker&, Time)
|
||||||
}
|
}
|
||||||
|
|
||||||
Result
|
Result
|
||||||
OCSPVerificationTrustDomain::IsChainValid(const DERArray&, Time)
|
OCSPVerificationTrustDomain::IsChainValid(const DERArray&, Time, const CertPolicyId&)
|
||||||
{
|
{
|
||||||
// We do not expect this to be called for OCSP signers
|
// We do not expect this to be called for OCSP signers
|
||||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||||
|
|
@ -44,7 +44,7 @@ OCSPVerificationTrustDomain::IsChainValid(const DERArray&, Time)
|
||||||
Result
|
Result
|
||||||
OCSPVerificationTrustDomain::CheckRevocation(EndEntityOrCA, const CertID&,
|
OCSPVerificationTrustDomain::CheckRevocation(EndEntityOrCA, const CertID&,
|
||||||
Time, Duration, const Input*,
|
Time, Duration, const Input*,
|
||||||
const Input*)
|
const Input*, const Input*)
|
||||||
{
|
{
|
||||||
// We do not expect this to be called for OCSP signers
|
// We do not expect this to be called for OCSP signers
|
||||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||||
|
|
|
||||||
|
|
@ -68,11 +68,13 @@ public:
|
||||||
mozilla::pkix::Time time,
|
mozilla::pkix::Time time,
|
||||||
mozilla::pkix::Duration validityDuration,
|
mozilla::pkix::Duration validityDuration,
|
||||||
/*optional*/ const mozilla::pkix::Input* stapledOCSPResponse,
|
/*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;
|
override;
|
||||||
|
|
||||||
virtual Result IsChainValid(const mozilla::pkix::DERArray& certChain,
|
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(
|
virtual void NoteAuxiliaryExtension(
|
||||||
mozilla::pkix::AuxiliaryExtension extension,
|
mozilla::pkix::AuxiliaryExtension extension,
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,6 @@ if not CONFIG['NSS_NO_EV_CERTS']:
|
||||||
LOCAL_INCLUDES += [
|
LOCAL_INCLUDES += [
|
||||||
'/security/manager/ssl',
|
'/security/manager/ssl',
|
||||||
'/security/pkix/include',
|
'/security/pkix/include',
|
||||||
'/security/pkix/lib',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
DIRS += [
|
DIRS += [
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,8 @@ CSTrustDomain::CheckRevocation(EndEntityOrCA endEntityOrCA,
|
||||||
const CertID& certID, Time time,
|
const CertID& certID, Time time,
|
||||||
Duration validityDuration,
|
Duration validityDuration,
|
||||||
/*optional*/ const Input* stapledOCSPresponse,
|
/*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
|
// We're relying solely on the CertBlocklist for revocation - and we're
|
||||||
// performing checks on this in GetCertTrust (as per nsNSSCertDBTrustDomain)
|
// performing checks on this in GetCertTrust (as per nsNSSCertDBTrustDomain)
|
||||||
|
|
@ -137,7 +138,8 @@ CSTrustDomain::CheckRevocation(EndEntityOrCA endEntityOrCA,
|
||||||
}
|
}
|
||||||
|
|
||||||
Result
|
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
|
// Check that our chain is not empty
|
||||||
if (certChain.GetLength() == 0) {
|
if (certChain.GetLength() == 0) {
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,11 @@ public:
|
||||||
const mozilla::pkix::CertID& certID, mozilla::pkix::Time time,
|
const mozilla::pkix::CertID& certID, mozilla::pkix::Time time,
|
||||||
mozilla::pkix::Duration validityDuration,
|
mozilla::pkix::Duration validityDuration,
|
||||||
/*optional*/ const mozilla::pkix::Input* stapledOCSPresponse,
|
/*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,
|
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(
|
virtual Result CheckSignatureDigestAlgorithm(
|
||||||
mozilla::pkix::DigestAlgorithm digestAlg,
|
mozilla::pkix::DigestAlgorithm digestAlg,
|
||||||
mozilla::pkix::EndEntityOrCA endEntityOrCA,
|
mozilla::pkix::EndEntityOrCA endEntityOrCA,
|
||||||
|
|
|
||||||
30
security/pkix/include/pkix-test/pkixtestnss.h
Normal file
30
security/pkix/include/pkix-test/pkixtestnss.h
Normal file
|
|
@ -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
|
||||||
|
|
@ -1,47 +1,29 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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
|
#ifndef mozilla_pkix_test_pkixtestutil_h
|
||||||
#define mozilla_pkix_test_pkixtestutils_h
|
#define mozilla_pkix_test_pkixtestutil_h
|
||||||
|
|
||||||
#include <ctime>
|
#include <cstdint>
|
||||||
#include <stdint.h> // Some Mozilla-supported compilers lack <cstdint>
|
|
||||||
#include <string>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <ctime>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "pkix/pkixtypes.h"
|
#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;
|
typedef std::basic_string<uint8_t> ByteString;
|
||||||
|
|
||||||
inline bool ENCODING_FAILED(const ByteString& bs) { return bs.empty(); }
|
inline bool ENCODING_FAILED(const ByteString& bs) { return bs.empty(); }
|
||||||
|
|
||||||
template <size_t L>
|
template <size_t L>
|
||||||
inline ByteString
|
inline ByteString BytesToByteString(const uint8_t (&bytes)[L]) {
|
||||||
BytesToByteString(const uint8_t (&bytes)[L])
|
|
||||||
{
|
|
||||||
return ByteString(bytes, L);
|
return ByteString(bytes, L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,17 +46,14 @@ bool InputEqualsByteString(Input input, const ByteString& bs);
|
||||||
ByteString InputToByteString(Input input);
|
ByteString InputToByteString(Input input);
|
||||||
|
|
||||||
// python DottedOIDToCode.py --tlv id-kp-OCSPSigning 1.3.6.1.5.5.7.3.9
|
// python DottedOIDToCode.py --tlv id-kp-OCSPSigning 1.3.6.1.5.5.7.3.9
|
||||||
static const uint8_t tlv_id_kp_OCSPSigning[] = {
|
static const uint8_t tlv_id_kp_OCSPSigning[] = {0x06, 0x08, 0x2b, 0x06, 0x01,
|
||||||
0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x09
|
0x05, 0x05, 0x07, 0x03, 0x09};
|
||||||
};
|
|
||||||
|
|
||||||
// python DottedOIDToCode.py --tlv id-kp-serverAuth 1.3.6.1.5.5.7.3.1
|
// python DottedOIDToCode.py --tlv id-kp-serverAuth 1.3.6.1.5.5.7.3.1
|
||||||
static const uint8_t tlv_id_kp_serverAuth[] = {
|
static const uint8_t tlv_id_kp_serverAuth[] = {0x06, 0x08, 0x2b, 0x06, 0x01,
|
||||||
0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01
|
0x05, 0x05, 0x07, 0x03, 0x01};
|
||||||
};
|
|
||||||
|
|
||||||
enum class TestDigestAlgorithmID
|
enum class TestDigestAlgorithmID {
|
||||||
{
|
|
||||||
MD2,
|
MD2,
|
||||||
MD5,
|
MD5,
|
||||||
SHA1,
|
SHA1,
|
||||||
|
|
@ -84,12 +63,10 @@ enum class TestDigestAlgorithmID
|
||||||
SHA512,
|
SHA512,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TestPublicKeyAlgorithm
|
struct TestPublicKeyAlgorithm {
|
||||||
{
|
explicit TestPublicKeyAlgorithm(const ByteString& aAlgorithmIdentifier)
|
||||||
explicit TestPublicKeyAlgorithm(const ByteString& algorithmIdentifier)
|
: algorithmIdentifier(aAlgorithmIdentifier) {}
|
||||||
: algorithmIdentifier(algorithmIdentifier) { }
|
bool operator==(const TestPublicKeyAlgorithm& other) const {
|
||||||
bool operator==(const TestPublicKeyAlgorithm& other) const
|
|
||||||
{
|
|
||||||
return algorithmIdentifier == other.algorithmIdentifier;
|
return algorithmIdentifier == other.algorithmIdentifier;
|
||||||
}
|
}
|
||||||
ByteString algorithmIdentifier;
|
ByteString algorithmIdentifier;
|
||||||
|
|
@ -102,12 +79,10 @@ ByteString DSS_G();
|
||||||
TestPublicKeyAlgorithm DSS();
|
TestPublicKeyAlgorithm DSS();
|
||||||
TestPublicKeyAlgorithm RSA_PKCS1();
|
TestPublicKeyAlgorithm RSA_PKCS1();
|
||||||
|
|
||||||
struct TestSignatureAlgorithm
|
struct TestSignatureAlgorithm {
|
||||||
{
|
|
||||||
TestSignatureAlgorithm(const TestPublicKeyAlgorithm& publicKeyAlg,
|
TestSignatureAlgorithm(const TestPublicKeyAlgorithm& publicKeyAlg,
|
||||||
TestDigestAlgorithmID digestAlg,
|
TestDigestAlgorithmID digestAlg,
|
||||||
const ByteString& algorithmIdentifier,
|
const ByteString& algorithmIdentifier, bool accepted);
|
||||||
bool accepted);
|
|
||||||
|
|
||||||
TestPublicKeyAlgorithm publicKeyAlg;
|
TestPublicKeyAlgorithm publicKeyAlg;
|
||||||
TestDigestAlgorithmID digestAlg;
|
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);
|
ByteString TLV(uint8_t tag, size_t length, const ByteString& value);
|
||||||
|
|
||||||
inline ByteString
|
inline ByteString TLV(uint8_t tag, const ByteString& value) {
|
||||||
TLV(uint8_t tag, const ByteString& value)
|
|
||||||
{
|
|
||||||
return TLV(tag, value.length(), 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.
|
// string literals as the last parameter to the following two functions.
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
inline ByteString
|
inline ByteString TLV(uint8_t tag, const char (&value)[N]) {
|
||||||
TLV(uint8_t tag, const char(&value)[N])
|
|
||||||
{
|
|
||||||
static_assert(N > 0, "cannot have string literal of size 0");
|
static_assert(N > 0, "cannot have string literal of size 0");
|
||||||
assert(value[N - 1] == 0);
|
assert(value[N - 1] == 0);
|
||||||
return TLV(tag, ByteString(reinterpret_cast<const uint8_t*>(&value), N - 1));
|
return TLV(tag, ByteString(reinterpret_cast<const uint8_t*>(&value), N - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
inline ByteString
|
inline ByteString TLV(uint8_t tag, size_t length, const char (&value)[N]) {
|
||||||
TLV(uint8_t tag, size_t length, const char(&value)[N])
|
|
||||||
{
|
|
||||||
static_assert(N > 0, "cannot have string literal of size 0");
|
static_assert(N > 0, "cannot have string literal of size 0");
|
||||||
assert(value[N - 1] == 0);
|
assert(value[N - 1] == 0);
|
||||||
return TLV(tag, length,
|
return TLV(tag, length,
|
||||||
|
|
@ -160,29 +129,27 @@ ByteString Integer(long value);
|
||||||
|
|
||||||
ByteString CN(const ByteString&, uint8_t encodingTag = 0x0c /*UTF8String*/);
|
ByteString CN(const ByteString&, uint8_t encodingTag = 0x0c /*UTF8String*/);
|
||||||
|
|
||||||
inline ByteString
|
inline ByteString CN(const char* value,
|
||||||
CN(const char* value, uint8_t encodingTag = 0x0c /*UTF8String*/)
|
uint8_t encodingTag = 0x0c /*UTF8String*/) {
|
||||||
{
|
return CN(
|
||||||
return CN(ByteString(reinterpret_cast<const uint8_t*>(value),
|
ByteString(reinterpret_cast<const uint8_t*>(value), std::strlen(value)),
|
||||||
std::strlen(value)), encodingTag);
|
encodingTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteString OU(const ByteString&, uint8_t encodingTag = 0x0c /*UTF8String*/);
|
ByteString OU(const ByteString&, uint8_t encodingTag = 0x0c /*UTF8String*/);
|
||||||
|
|
||||||
inline ByteString
|
inline ByteString OU(const char* value,
|
||||||
OU(const char* value, uint8_t encodingTag = 0x0c /*UTF8String*/)
|
uint8_t encodingTag = 0x0c /*UTF8String*/) {
|
||||||
{
|
return OU(
|
||||||
return OU(ByteString(reinterpret_cast<const uint8_t*>(value),
|
ByteString(reinterpret_cast<const uint8_t*>(value), std::strlen(value)),
|
||||||
std::strlen(value)), encodingTag);
|
encodingTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteString emailAddress(const ByteString&);
|
ByteString emailAddress(const ByteString&);
|
||||||
|
|
||||||
inline ByteString
|
inline ByteString emailAddress(const char* value) {
|
||||||
emailAddress(const char* value)
|
return emailAddress(
|
||||||
{
|
ByteString(reinterpret_cast<const uint8_t*>(value), std::strlen(value)));
|
||||||
return emailAddress(ByteString(reinterpret_cast<const uint8_t*>(value),
|
|
||||||
std::strlen(value)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RelativeDistinguishedName ::=
|
// RelativeDistinguishedName ::=
|
||||||
|
|
@ -197,17 +164,11 @@ ByteString RDN(const ByteString& avas);
|
||||||
//
|
//
|
||||||
ByteString Name(const ByteString& rdns);
|
ByteString Name(const ByteString& rdns);
|
||||||
|
|
||||||
inline ByteString
|
inline ByteString CNToDERName(const ByteString& cn) {
|
||||||
CNToDERName(const ByteString& cn)
|
|
||||||
{
|
|
||||||
return Name(RDN(CN(cn)));
|
return Name(RDN(CN(cn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ByteString
|
inline ByteString CNToDERName(const char* cn) { return Name(RDN(CN(cn))); }
|
||||||
CNToDERName(const char* cn)
|
|
||||||
{
|
|
||||||
return Name(RDN(CN(cn)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// GeneralName ::= CHOICE {
|
// GeneralName ::= CHOICE {
|
||||||
// otherName [0] OtherName,
|
// otherName [0] OtherName,
|
||||||
|
|
@ -220,55 +181,40 @@ CNToDERName(const char* cn)
|
||||||
// iPAddress [7] OCTET STRING,
|
// iPAddress [7] OCTET STRING,
|
||||||
// registeredID [8] OBJECT IDENTIFIER }
|
// registeredID [8] OBJECT IDENTIFIER }
|
||||||
|
|
||||||
inline ByteString
|
inline ByteString RFC822Name(const ByteString& name) {
|
||||||
RFC822Name(const ByteString& name)
|
|
||||||
{
|
|
||||||
// (2 << 6) means "context-specific", 1 is the GeneralName tag.
|
// (2 << 6) means "context-specific", 1 is the GeneralName tag.
|
||||||
return TLV((2 << 6) | 1, name);
|
return TLV((2 << 6) | 1, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t L>
|
template <size_t L>
|
||||||
inline ByteString
|
inline ByteString RFC822Name(const char (&bytes)[L]) {
|
||||||
RFC822Name(const char (&bytes)[L])
|
return RFC822Name(
|
||||||
{
|
ByteString(reinterpret_cast<const uint8_t*>(&bytes), L - 1));
|
||||||
return RFC822Name(ByteString(reinterpret_cast<const uint8_t*>(&bytes),
|
|
||||||
L - 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ByteString
|
inline ByteString DNSName(const ByteString& name) {
|
||||||
DNSName(const ByteString& name)
|
|
||||||
{
|
|
||||||
// (2 << 6) means "context-specific", 2 is the GeneralName tag.
|
// (2 << 6) means "context-specific", 2 is the GeneralName tag.
|
||||||
return TLV((2 << 6) | 2, name);
|
return TLV((2 << 6) | 2, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t L>
|
template <size_t L>
|
||||||
inline ByteString
|
inline ByteString DNSName(const char (&bytes)[L]) {
|
||||||
DNSName(const char (&bytes)[L])
|
return DNSName(ByteString(reinterpret_cast<const uint8_t*>(&bytes), L - 1));
|
||||||
{
|
|
||||||
return DNSName(ByteString(reinterpret_cast<const uint8_t*>(&bytes),
|
|
||||||
L - 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ByteString
|
inline ByteString DirectoryName(const ByteString& name) {
|
||||||
DirectoryName(const ByteString& name)
|
|
||||||
{
|
|
||||||
// (2 << 6) means "context-specific", (1 << 5) means "constructed", and 4 is
|
// (2 << 6) means "context-specific", (1 << 5) means "constructed", and 4 is
|
||||||
// the DirectoryName tag.
|
// the DirectoryName tag.
|
||||||
return TLV((2 << 6) | (1 << 5) | 4, name);
|
return TLV((2 << 6) | (1 << 5) | 4, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ByteString
|
inline ByteString IPAddress() {
|
||||||
IPAddress()
|
|
||||||
{
|
|
||||||
// (2 << 6) means "context-specific", 7 is the GeneralName tag.
|
// (2 << 6) means "context-specific", 7 is the GeneralName tag.
|
||||||
return TLV((2 << 6) | 7, ByteString());
|
return TLV((2 << 6) | 7, ByteString());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t L>
|
template <size_t L>
|
||||||
inline ByteString
|
inline ByteString IPAddress(const uint8_t (&bytes)[L]) {
|
||||||
IPAddress(const uint8_t (&bytes)[L])
|
|
||||||
{
|
|
||||||
// (2 << 6) means "context-specific", 7 is the GeneralName tag.
|
// (2 << 6) means "context-specific", 7 is the GeneralName tag.
|
||||||
return TLV((2 << 6) | 7, ByteString(bytes, L));
|
return TLV((2 << 6) | 7, ByteString(bytes, L));
|
||||||
}
|
}
|
||||||
|
|
@ -282,10 +228,9 @@ IPAddress(const uint8_t (&bytes)[L])
|
||||||
ByteString CreateEncodedSubjectAltName(const ByteString& names);
|
ByteString CreateEncodedSubjectAltName(const ByteString& names);
|
||||||
ByteString CreateEncodedEmptySubjectAltName();
|
ByteString CreateEncodedEmptySubjectAltName();
|
||||||
|
|
||||||
class TestKeyPair
|
class TestKeyPair {
|
||||||
{
|
public:
|
||||||
public:
|
virtual ~TestKeyPair() {}
|
||||||
virtual ~TestKeyPair() { }
|
|
||||||
|
|
||||||
const TestPublicKeyAlgorithm publicKeyAlg;
|
const TestPublicKeyAlgorithm publicKeyAlg;
|
||||||
|
|
||||||
|
|
@ -302,8 +247,10 @@ public:
|
||||||
/*out*/ ByteString& signature) const = 0;
|
/*out*/ ByteString& signature) const = 0;
|
||||||
|
|
||||||
virtual TestKeyPair* Clone() 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;
|
TestKeyPair(const TestKeyPair&) = delete;
|
||||||
void operator=(const TestKeyPair&) = delete;
|
void operator=(const TestKeyPair&) = delete;
|
||||||
};
|
};
|
||||||
|
|
@ -312,7 +259,7 @@ TestKeyPair* CloneReusedKeyPair();
|
||||||
TestKeyPair* GenerateKeyPair();
|
TestKeyPair* GenerateKeyPair();
|
||||||
TestKeyPair* GenerateDSSKeyPair();
|
TestKeyPair* GenerateDSSKeyPair();
|
||||||
inline void DeleteTestKeyPair(TestKeyPair* keyPair) { delete keyPair; }
|
inline void DeleteTestKeyPair(TestKeyPair* keyPair) { delete keyPair; }
|
||||||
typedef ScopedPtr<TestKeyPair, DeleteTestKeyPair> ScopedTestKeyPair;
|
typedef std::unique_ptr<TestKeyPair> ScopedTestKeyPair;
|
||||||
|
|
||||||
Result TestVerifyECDSASignedDigest(const SignedDigest& signedDigest,
|
Result TestVerifyECDSASignedDigest(const SignedDigest& signedDigest,
|
||||||
Input subjectPublicKeyInfo);
|
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
|
// 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
|
// ByteString. (If the first item of the array is empty then an empty
|
||||||
// Extensions sequence will be encoded.)
|
// Extensions sequence will be encoded.)
|
||||||
ByteString CreateEncodedCertificate(long version,
|
ByteString CreateEncodedCertificate(
|
||||||
const TestSignatureAlgorithm& signature,
|
long version, const TestSignatureAlgorithm& signature,
|
||||||
const ByteString& serialNumber,
|
const ByteString& serialNumber, const ByteString& issuerNameDER,
|
||||||
const ByteString& issuerNameDER,
|
time_t notBefore, time_t notAfter, const ByteString& subjectNameDER,
|
||||||
time_t notBefore, time_t notAfter,
|
|
||||||
const ByteString& subjectNameDER,
|
|
||||||
const TestKeyPair& subjectKeyPair,
|
const TestKeyPair& subjectKeyPair,
|
||||||
/*optional*/ const ByteString* extensions,
|
/*optional*/ const ByteString* extensions, const TestKeyPair& issuerKeyPair,
|
||||||
const TestKeyPair& issuerKeyPair,
|
|
||||||
const TestSignatureAlgorithm& signatureAlgorithm);
|
const TestSignatureAlgorithm& signatureAlgorithm);
|
||||||
|
|
||||||
ByteString CreateEncodedSerialNumber(long value);
|
ByteString CreateEncodedSerialNumber(long value);
|
||||||
|
|
||||||
enum class Critical { No = 0, Yes = 1 };
|
enum class Critical { No = 0, Yes = 1 };
|
||||||
|
|
||||||
ByteString CreateEncodedBasicConstraints(bool isCA,
|
ByteString CreateEncodedBasicConstraints(
|
||||||
/*optional*/ long* pathLenConstraint,
|
bool isCA,
|
||||||
Critical critical);
|
/*optional in*/ const long* pathLenConstraint, Critical critical);
|
||||||
|
|
||||||
// Creates a DER-encoded extKeyUsage extension with one EKU OID.
|
// Creates a DER-encoded extKeyUsage extension with one EKU OID.
|
||||||
ByteString CreateEncodedEKUExtension(Input eku, Critical critical);
|
ByteString CreateEncodedEKUExtension(Input eku, Critical critical);
|
||||||
|
|
@ -372,9 +316,8 @@ ByteString CreateEncodedEKUExtension(Input eku, Critical critical);
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Encode OCSP responses
|
// Encode OCSP responses
|
||||||
|
|
||||||
class OCSPResponseExtension final
|
class OCSPResponseExtension final {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
OCSPResponseExtension();
|
OCSPResponseExtension();
|
||||||
|
|
||||||
ByteString id;
|
ByteString id;
|
||||||
|
|
@ -383,9 +326,8 @@ public:
|
||||||
OCSPResponseExtension* next;
|
OCSPResponseExtension* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
class OCSPResponseContext final
|
class OCSPResponseContext final {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
OCSPResponseContext(const CertID& certID, std::time_t time);
|
OCSPResponseContext(const CertID& certID, std::time_t time);
|
||||||
|
|
||||||
const CertID& certID;
|
const CertID& certID;
|
||||||
|
|
@ -393,8 +335,7 @@ public:
|
||||||
|
|
||||||
// The fields below are in the order that they appear in an OCSP response.
|
// The fields below are in the order that they appear in an OCSP response.
|
||||||
|
|
||||||
enum OCSPResponseStatus
|
enum OCSPResponseStatus {
|
||||||
{
|
|
||||||
successful = 0,
|
successful = 0,
|
||||||
malformedRequest = 1,
|
malformedRequest = 1,
|
||||||
internalError = 2,
|
internalError = 2,
|
||||||
|
|
@ -427,8 +368,7 @@ public:
|
||||||
|
|
||||||
// The following fields are on a per-SingleResponse basis. In the future we
|
// The following fields are on a per-SingleResponse basis. In the future we
|
||||||
// may support including multiple SingleResponses per response.
|
// may support including multiple SingleResponses per response.
|
||||||
enum CertStatus
|
enum CertStatus {
|
||||||
{
|
|
||||||
good = 0,
|
good = 0,
|
||||||
revoked = 1,
|
revoked = 1,
|
||||||
unknown = 2,
|
unknown = 2,
|
||||||
|
|
@ -441,7 +381,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
ByteString CreateEncodedOCSPResponse(OCSPResponseContext& context);
|
ByteString CreateEncodedOCSPResponse(OCSPResponseContext& context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace mozilla::pkix::test
|
||||||
|
|
||||||
} } } // namespace mozilla::pkix::test
|
#endif // mozilla_pkix_test_pkixtestutil_h
|
||||||
|
|
||||||
#endif // mozilla_pkix_test_pkixtestutils_h
|
|
||||||
|
|
@ -1,25 +1,8 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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
|
#ifndef mozilla_pkix_Input_h
|
||||||
#define mozilla_pkix_Input_h
|
#define mozilla_pkix_Input_h
|
||||||
|
|
@ -29,7 +12,8 @@
|
||||||
#include "pkix/Result.h"
|
#include "pkix/Result.h"
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
|
|
||||||
namespace mozilla { namespace pkix {
|
namespace mozilla {
|
||||||
|
namespace pkix {
|
||||||
|
|
||||||
class Reader;
|
class Reader;
|
||||||
|
|
||||||
|
|
@ -48,9 +32,8 @@ class Reader;
|
||||||
//
|
//
|
||||||
// Note that in the example, GoodExample has the same performance
|
// Note that in the example, GoodExample has the same performance
|
||||||
// characteristics as WorseExample, but with much better safety guarantees.
|
// characteristics as WorseExample, but with much better safety guarantees.
|
||||||
class Input final
|
class Input final {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
typedef uint16_t size_type;
|
typedef uint16_t size_type;
|
||||||
|
|
||||||
// This constructor is useful for inputs that are statically known to be of a
|
// This constructor is useful for inputs that are statically known to be of a
|
||||||
|
|
@ -65,37 +48,28 @@ public:
|
||||||
// Input expected;
|
// Input expected;
|
||||||
// Result rv = expected.Init(EXPECTED_BYTES, sizeof EXPECTED_BYTES);
|
// Result rv = expected.Init(EXPECTED_BYTES, sizeof EXPECTED_BYTES);
|
||||||
template <size_type N>
|
template <size_type N>
|
||||||
explicit Input(const uint8_t (&data)[N])
|
explicit Input(const uint8_t (&aData)[N]) : data(aData), len(N) {}
|
||||||
: data(data)
|
|
||||||
, len(N)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct a valid, empty, Init-able Input.
|
// Construct a valid, empty, Init-able Input.
|
||||||
Input()
|
Input() : data(nullptr), len(0u) {}
|
||||||
: data(nullptr)
|
|
||||||
, len(0u)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is intentionally not explicit in order to allow value semantics.
|
// This is intentionally not explicit in order to allow value semantics.
|
||||||
Input(const Input&) = default;
|
Input(const Input&) = default;
|
||||||
|
|
||||||
// Initialize the input. data must be non-null and len must be less than
|
// Initialize the input. data must be non-null and len must be less than
|
||||||
// 65536. Init may not be called more than once.
|
// 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) {
|
if (this->data) {
|
||||||
// already initialized
|
// already initialized
|
||||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||||
}
|
}
|
||||||
if (!data || len > 0xffffu) {
|
if (!aData || aLen > 0xffffu) {
|
||||||
// input too large
|
// input too large
|
||||||
return Result::ERROR_BAD_DER;
|
return Result::ERROR_BAD_DER;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->data = data;
|
this->data = aData;
|
||||||
this->len = len;
|
this->len = aLen;
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
@ -106,10 +80,7 @@ public:
|
||||||
// This is basically operator=, but it wasn't given that name because
|
// This is basically operator=, but it wasn't given that name because
|
||||||
// normally callers do not check the result of operator=, and normally
|
// normally callers do not check the result of operator=, and normally
|
||||||
// operator= can be used multiple times.
|
// operator= can be used multiple times.
|
||||||
Result Init(Input other)
|
Result Init(Input other) { return Init(other.data, other.len); }
|
||||||
{
|
|
||||||
return Init(other.data, other.len);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the length of the input.
|
// Returns the length of the input.
|
||||||
//
|
//
|
||||||
|
|
@ -121,18 +92,17 @@ public:
|
||||||
// don't want to declare in this header file.
|
// don't want to declare in this header file.
|
||||||
const uint8_t* UnsafeGetData() const { return data; }
|
const uint8_t* UnsafeGetData() const { return data; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const uint8_t* data;
|
const uint8_t* data;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
void operator=(const Input&) = delete; // Use Init instead.
|
void operator=(const Input&) = delete; // Use Init instead.
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool
|
inline bool InputsAreEqual(const Input& a, const Input& b) {
|
||||||
InputsAreEqual(const Input& a, const Input& b)
|
|
||||||
{
|
|
||||||
return a.GetLength() == b.GetLength() &&
|
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
|
// 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.
|
// In general, Reader allows for one byte of lookahead and no backtracking.
|
||||||
// However, the Match* functions internally may have more lookahead.
|
// However, the Match* functions internally may have more lookahead.
|
||||||
class Reader final
|
class Reader final {
|
||||||
{
|
public:
|
||||||
public:
|
Reader() : input(nullptr), end(nullptr) {}
|
||||||
Reader()
|
|
||||||
: input(nullptr)
|
|
||||||
, end(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit Reader(Input input)
|
explicit Reader(Input aInput)
|
||||||
: input(input.UnsafeGetData())
|
: input(aInput.UnsafeGetData()),
|
||||||
, end(input.UnsafeGetData() + input.GetLength())
|
end(aInput.UnsafeGetData() + aInput.GetLength()) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Result Init(Input input)
|
Result Init(Input aInput) {
|
||||||
{
|
|
||||||
if (this->input) {
|
if (this->input) {
|
||||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||||
}
|
}
|
||||||
this->input = input.UnsafeGetData();
|
this->input = aInput.UnsafeGetData();
|
||||||
this->end = input.UnsafeGetData() + input.GetLength();
|
this->end = aInput.UnsafeGetData() + aInput.GetLength();
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Peek(uint8_t expectedByte) const
|
bool Peek(uint8_t expectedByte) const {
|
||||||
{
|
|
||||||
return input < end && *input == expectedByte;
|
return input < end && *input == expectedByte;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Read(uint8_t& out)
|
Result Read(uint8_t& out) {
|
||||||
{
|
|
||||||
Result rv = EnsureLength(1);
|
Result rv = EnsureLength(1);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return rv;
|
return rv;
|
||||||
|
|
@ -183,8 +143,7 @@ public:
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Read(uint16_t& out)
|
Result Read(uint16_t& out) {
|
||||||
{
|
|
||||||
Result rv = EnsureLength(2);
|
Result rv = EnsureLength(2);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return rv;
|
return rv;
|
||||||
|
|
@ -196,8 +155,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <Input::size_type N>
|
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
|
// Normally we use EnsureLength which compares (input + len < end), but
|
||||||
// here we want to be sure that there is nothing following the matched
|
// here we want to be sure that there is nothing following the matched
|
||||||
// bytes
|
// bytes
|
||||||
|
|
@ -211,8 +169,7 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MatchRest(Input toMatch)
|
bool MatchRest(Input toMatch) {
|
||||||
{
|
|
||||||
// Normally we use EnsureLength which compares (input + len < end), but
|
// Normally we use EnsureLength which compares (input + len < end), but
|
||||||
// here we want to be sure that there is nothing following the matched
|
// here we want to be sure that there is nothing following the matched
|
||||||
// bytes
|
// bytes
|
||||||
|
|
@ -227,8 +184,7 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Skip(Input::size_type len)
|
Result Skip(Input::size_type len) {
|
||||||
{
|
|
||||||
Result rv = EnsureLength(len);
|
Result rv = EnsureLength(len);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return rv;
|
return rv;
|
||||||
|
|
@ -237,8 +193,7 @@ public:
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Skip(Input::size_type len, Reader& skipped)
|
Result Skip(Input::size_type len, Reader& skipped) {
|
||||||
{
|
|
||||||
Result rv = EnsureLength(len);
|
Result rv = EnsureLength(len);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return rv;
|
return rv;
|
||||||
|
|
@ -251,8 +206,7 @@ public:
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Skip(Input::size_type len, /*out*/ Input& skipped)
|
Result Skip(Input::size_type len, /*out*/ Input& skipped) {
|
||||||
{
|
|
||||||
Result rv = EnsureLength(len);
|
Result rv = EnsureLength(len);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return rv;
|
return rv;
|
||||||
|
|
@ -265,18 +219,13 @@ public:
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkipToEnd()
|
void SkipToEnd() { input = end; }
|
||||||
{
|
|
||||||
input = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result SkipToEnd(/*out*/ Input& skipped)
|
Result SkipToEnd(/*out*/ Input& skipped) {
|
||||||
{
|
|
||||||
return Skip(static_cast<Input::size_type>(end - 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) {
|
if (static_cast<size_t>(end - input) < len) {
|
||||||
return Result::ERROR_BAD_DER;
|
return Result::ERROR_BAD_DER;
|
||||||
}
|
}
|
||||||
|
|
@ -285,13 +234,13 @@ public:
|
||||||
|
|
||||||
bool AtEnd() const { return input == end; }
|
bool AtEnd() const { return input == end; }
|
||||||
|
|
||||||
class Mark final
|
class Mark final {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Mark(const Mark&) = default; // Intentionally not explicit.
|
Mark(const Mark&) = default; // Intentionally not explicit.
|
||||||
private:
|
private:
|
||||||
friend class Reader;
|
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 Reader& input;
|
||||||
const uint8_t* const mark;
|
const uint8_t* const mark;
|
||||||
void operator=(const Mark&) = delete;
|
void operator=(const Mark&) = delete;
|
||||||
|
|
@ -299,8 +248,7 @@ public:
|
||||||
|
|
||||||
Mark GetMark() const { return Mark(*this, input); }
|
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) {
|
if (&mark.input != this || mark.mark > input) {
|
||||||
return NotReached("invalid mark", Result::FATAL_ERROR_INVALID_ARGS);
|
return NotReached("invalid mark", Result::FATAL_ERROR_INVALID_ARGS);
|
||||||
}
|
}
|
||||||
|
|
@ -308,9 +256,8 @@ public:
|
||||||
static_cast<Input::size_type>(input - mark.mark));
|
static_cast<Input::size_type>(input - mark.mark));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Result Init(const uint8_t* data, Input::size_type len)
|
Result Init(const uint8_t* data, Input::size_type len) {
|
||||||
{
|
|
||||||
if (input) {
|
if (input) {
|
||||||
// already initialized
|
// already initialized
|
||||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||||
|
|
@ -327,9 +274,7 @@ private:
|
||||||
void operator=(const Reader&) = delete;
|
void operator=(const Reader&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool
|
inline bool InputContains(const Input& input, uint8_t toFind) {
|
||||||
InputContains(const Input& input, uint8_t toFind)
|
|
||||||
{
|
|
||||||
Reader reader(input);
|
Reader reader(input);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint8_t b;
|
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
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,16 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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
|
#ifndef mozilla_pkix_Result_h
|
||||||
#define mozilla_pkix_Result_h
|
#define mozilla_pkix_Result_h
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace mozilla { namespace pkix {
|
namespace mozilla {
|
||||||
|
namespace pkix {
|
||||||
|
|
||||||
static const unsigned int FATAL_ERROR_FLAG = 0x800;
|
static const unsigned int FATAL_ERROR_FLAG = 0x800;
|
||||||
|
|
||||||
|
|
@ -84,20 +68,16 @@ static const unsigned int FATAL_ERROR_FLAG = 0x800;
|
||||||
// NSS/NSPR error codes in pkixnss.cpp.
|
// NSS/NSPR error codes in pkixnss.cpp.
|
||||||
#define MOZILLA_PKIX_MAP_LIST \
|
#define MOZILLA_PKIX_MAP_LIST \
|
||||||
MOZILLA_PKIX_MAP(Success, 0, 0) \
|
MOZILLA_PKIX_MAP(Success, 0, 0) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_BAD_DER, 1, \
|
MOZILLA_PKIX_MAP(ERROR_BAD_DER, 1, SEC_ERROR_BAD_DER) \
|
||||||
SEC_ERROR_BAD_DER) \
|
MOZILLA_PKIX_MAP(ERROR_CA_CERT_INVALID, 2, SEC_ERROR_CA_CERT_INVALID) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_CA_CERT_INVALID, 2, \
|
MOZILLA_PKIX_MAP(ERROR_BAD_SIGNATURE, 3, SEC_ERROR_BAD_SIGNATURE) \
|
||||||
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, \
|
MOZILLA_PKIX_MAP(ERROR_CERT_BAD_ACCESS_LOCATION, 4, \
|
||||||
SEC_ERROR_CERT_BAD_ACCESS_LOCATION) \
|
SEC_ERROR_CERT_BAD_ACCESS_LOCATION) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_CERT_NOT_IN_NAME_SPACE, 5, \
|
MOZILLA_PKIX_MAP(ERROR_CERT_NOT_IN_NAME_SPACE, 5, \
|
||||||
SEC_ERROR_CERT_NOT_IN_NAME_SPACE) \
|
SEC_ERROR_CERT_NOT_IN_NAME_SPACE) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED, 6, \
|
MOZILLA_PKIX_MAP(ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED, 6, \
|
||||||
SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) \
|
SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_CONNECT_REFUSED, 7, \
|
MOZILLA_PKIX_MAP(ERROR_CONNECT_REFUSED, 7, PR_CONNECT_REFUSED_ERROR) \
|
||||||
PR_CONNECT_REFUSED_ERROR) \
|
|
||||||
MOZILLA_PKIX_MAP(ERROR_EXPIRED_CERTIFICATE, 8, \
|
MOZILLA_PKIX_MAP(ERROR_EXPIRED_CERTIFICATE, 8, \
|
||||||
SEC_ERROR_EXPIRED_CERTIFICATE) \
|
SEC_ERROR_EXPIRED_CERTIFICATE) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_EXTENSION_VALUE_INVALID, 9, \
|
MOZILLA_PKIX_MAP(ERROR_EXTENSION_VALUE_INVALID, 9, \
|
||||||
|
|
@ -106,10 +86,8 @@ static const unsigned int FATAL_ERROR_FLAG = 0x800;
|
||||||
SEC_ERROR_INADEQUATE_CERT_TYPE) \
|
SEC_ERROR_INADEQUATE_CERT_TYPE) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_INADEQUATE_KEY_USAGE, 11, \
|
MOZILLA_PKIX_MAP(ERROR_INADEQUATE_KEY_USAGE, 11, \
|
||||||
SEC_ERROR_INADEQUATE_KEY_USAGE) \
|
SEC_ERROR_INADEQUATE_KEY_USAGE) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_INVALID_ALGORITHM, 12, \
|
MOZILLA_PKIX_MAP(ERROR_INVALID_ALGORITHM, 12, SEC_ERROR_INVALID_ALGORITHM) \
|
||||||
SEC_ERROR_INVALID_ALGORITHM) \
|
MOZILLA_PKIX_MAP(ERROR_INVALID_DER_TIME, 13, SEC_ERROR_INVALID_TIME) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_INVALID_DER_TIME, 13, \
|
|
||||||
SEC_ERROR_INVALID_TIME) \
|
|
||||||
MOZILLA_PKIX_MAP(ERROR_KEY_PINNING_FAILURE, 14, \
|
MOZILLA_PKIX_MAP(ERROR_KEY_PINNING_FAILURE, 14, \
|
||||||
MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE) \
|
MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_PATH_LEN_CONSTRAINT_INVALID, 15, \
|
MOZILLA_PKIX_MAP(ERROR_PATH_LEN_CONSTRAINT_INVALID, 15, \
|
||||||
|
|
@ -120,44 +98,34 @@ static const unsigned int FATAL_ERROR_FLAG = 0x800;
|
||||||
SEC_ERROR_REVOKED_CERTIFICATE) \
|
SEC_ERROR_REVOKED_CERTIFICATE) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_UNKNOWN_CRITICAL_EXTENSION, 18, \
|
MOZILLA_PKIX_MAP(ERROR_UNKNOWN_CRITICAL_EXTENSION, 18, \
|
||||||
SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION) \
|
SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_UNKNOWN_ERROR, 19, \
|
MOZILLA_PKIX_MAP(ERROR_UNKNOWN_ERROR, 19, PR_UNKNOWN_ERROR) \
|
||||||
PR_UNKNOWN_ERROR) \
|
MOZILLA_PKIX_MAP(ERROR_UNKNOWN_ISSUER, 20, SEC_ERROR_UNKNOWN_ISSUER) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_UNKNOWN_ISSUER, 20, \
|
MOZILLA_PKIX_MAP(ERROR_UNTRUSTED_CERT, 21, SEC_ERROR_UNTRUSTED_CERT) \
|
||||||
SEC_ERROR_UNKNOWN_ISSUER) \
|
MOZILLA_PKIX_MAP(ERROR_UNTRUSTED_ISSUER, 22, SEC_ERROR_UNTRUSTED_ISSUER) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_UNTRUSTED_CERT, 21, \
|
MOZILLA_PKIX_MAP(ERROR_OCSP_BAD_SIGNATURE, 23, SEC_ERROR_OCSP_BAD_SIGNATURE) \
|
||||||
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, \
|
MOZILLA_PKIX_MAP(ERROR_OCSP_INVALID_SIGNING_CERT, 24, \
|
||||||
SEC_ERROR_OCSP_INVALID_SIGNING_CERT) \
|
SEC_ERROR_OCSP_INVALID_SIGNING_CERT) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_OCSP_MALFORMED_REQUEST, 25, \
|
MOZILLA_PKIX_MAP(ERROR_OCSP_MALFORMED_REQUEST, 25, \
|
||||||
SEC_ERROR_OCSP_MALFORMED_REQUEST) \
|
SEC_ERROR_OCSP_MALFORMED_REQUEST) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_OCSP_MALFORMED_RESPONSE, 26, \
|
MOZILLA_PKIX_MAP(ERROR_OCSP_MALFORMED_RESPONSE, 26, \
|
||||||
SEC_ERROR_OCSP_MALFORMED_RESPONSE) \
|
SEC_ERROR_OCSP_MALFORMED_RESPONSE) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_OCSP_OLD_RESPONSE, 27, \
|
MOZILLA_PKIX_MAP(ERROR_OCSP_OLD_RESPONSE, 27, SEC_ERROR_OCSP_OLD_RESPONSE) \
|
||||||
SEC_ERROR_OCSP_OLD_RESPONSE) \
|
|
||||||
MOZILLA_PKIX_MAP(ERROR_OCSP_REQUEST_NEEDS_SIG, 28, \
|
MOZILLA_PKIX_MAP(ERROR_OCSP_REQUEST_NEEDS_SIG, 28, \
|
||||||
SEC_ERROR_OCSP_REQUEST_NEEDS_SIG) \
|
SEC_ERROR_OCSP_REQUEST_NEEDS_SIG) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_OCSP_RESPONDER_CERT_INVALID, 29, \
|
MOZILLA_PKIX_MAP(ERROR_OCSP_RESPONDER_CERT_INVALID, 29, \
|
||||||
SEC_ERROR_OCSP_RESPONDER_CERT_INVALID) \
|
SEC_ERROR_OCSP_RESPONDER_CERT_INVALID) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_OCSP_SERVER_ERROR, 30, \
|
MOZILLA_PKIX_MAP(ERROR_OCSP_SERVER_ERROR, 30, SEC_ERROR_OCSP_SERVER_ERROR) \
|
||||||
SEC_ERROR_OCSP_SERVER_ERROR) \
|
|
||||||
MOZILLA_PKIX_MAP(ERROR_OCSP_TRY_SERVER_LATER, 31, \
|
MOZILLA_PKIX_MAP(ERROR_OCSP_TRY_SERVER_LATER, 31, \
|
||||||
SEC_ERROR_OCSP_TRY_SERVER_LATER) \
|
SEC_ERROR_OCSP_TRY_SERVER_LATER) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_OCSP_UNAUTHORIZED_REQUEST, 32, \
|
MOZILLA_PKIX_MAP(ERROR_OCSP_UNAUTHORIZED_REQUEST, 32, \
|
||||||
SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST) \
|
SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, 33, \
|
MOZILLA_PKIX_MAP(ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, 33, \
|
||||||
SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS) \
|
SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_OCSP_UNKNOWN_CERT, 34, \
|
MOZILLA_PKIX_MAP(ERROR_OCSP_UNKNOWN_CERT, 34, SEC_ERROR_OCSP_UNKNOWN_CERT) \
|
||||||
SEC_ERROR_OCSP_UNKNOWN_CERT) \
|
|
||||||
MOZILLA_PKIX_MAP(ERROR_OCSP_FUTURE_RESPONSE, 35, \
|
MOZILLA_PKIX_MAP(ERROR_OCSP_FUTURE_RESPONSE, 35, \
|
||||||
SEC_ERROR_OCSP_FUTURE_RESPONSE) \
|
SEC_ERROR_OCSP_FUTURE_RESPONSE) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_INVALID_KEY, 36, \
|
MOZILLA_PKIX_MAP(ERROR_INVALID_KEY, 36, SEC_ERROR_INVALID_KEY) \
|
||||||
SEC_ERROR_INVALID_KEY) \
|
MOZILLA_PKIX_MAP(ERROR_UNSUPPORTED_KEYALG, 37, SEC_ERROR_UNSUPPORTED_KEYALG) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_UNSUPPORTED_KEYALG, 37, \
|
|
||||||
SEC_ERROR_UNSUPPORTED_KEYALG) \
|
|
||||||
MOZILLA_PKIX_MAP(ERROR_EXPIRED_ISSUER_CERTIFICATE, 38, \
|
MOZILLA_PKIX_MAP(ERROR_EXPIRED_ISSUER_CERTIFICATE, 38, \
|
||||||
SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE) \
|
SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_CA_CERT_USED_AS_END_ENTITY, 39, \
|
MOZILLA_PKIX_MAP(ERROR_CA_CERT_USED_AS_END_ENTITY, 39, \
|
||||||
|
|
@ -166,8 +134,7 @@ static const unsigned int FATAL_ERROR_FLAG = 0x800;
|
||||||
MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE) \
|
MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_V1_CERT_USED_AS_CA, 41, \
|
MOZILLA_PKIX_MAP(ERROR_V1_CERT_USED_AS_CA, 41, \
|
||||||
MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA) \
|
MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_BAD_CERT_DOMAIN, 42, \
|
MOZILLA_PKIX_MAP(ERROR_BAD_CERT_DOMAIN, 42, SSL_ERROR_BAD_CERT_DOMAIN) \
|
||||||
SSL_ERROR_BAD_CERT_DOMAIN) \
|
|
||||||
MOZILLA_PKIX_MAP(ERROR_NO_RFC822NAME_MATCH, 43, \
|
MOZILLA_PKIX_MAP(ERROR_NO_RFC822NAME_MATCH, 43, \
|
||||||
MOZILLA_PKIX_ERROR_NO_RFC822NAME_MATCH) \
|
MOZILLA_PKIX_ERROR_NO_RFC822NAME_MATCH) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_UNSUPPORTED_ELLIPTIC_CURVE, 44, \
|
MOZILLA_PKIX_MAP(ERROR_UNSUPPORTED_ELLIPTIC_CURVE, 44, \
|
||||||
|
|
@ -190,6 +157,11 @@ static const unsigned int FATAL_ERROR_FLAG = 0x800;
|
||||||
MOZILLA_PKIX_ERROR_INVALID_INTEGER_ENCODING) \
|
MOZILLA_PKIX_ERROR_INVALID_INTEGER_ENCODING) \
|
||||||
MOZILLA_PKIX_MAP(ERROR_EMPTY_ISSUER_NAME, 53, \
|
MOZILLA_PKIX_MAP(ERROR_EMPTY_ISSUER_NAME, 53, \
|
||||||
MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME) \
|
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, \
|
MOZILLA_PKIX_MAP(FATAL_ERROR_INVALID_ARGS, FATAL_ERROR_FLAG | 1, \
|
||||||
SEC_ERROR_INVALID_ARGS) \
|
SEC_ERROR_INVALID_ARGS) \
|
||||||
MOZILLA_PKIX_MAP(FATAL_ERROR_INVALID_STATE, FATAL_ERROR_FLAG | 2, \
|
MOZILLA_PKIX_MAP(FATAL_ERROR_INVALID_STATE, FATAL_ERROR_FLAG | 2, \
|
||||||
|
|
@ -198,10 +170,9 @@ static const unsigned int FATAL_ERROR_FLAG = 0x800;
|
||||||
SEC_ERROR_LIBRARY_FAILURE) \
|
SEC_ERROR_LIBRARY_FAILURE) \
|
||||||
MOZILLA_PKIX_MAP(FATAL_ERROR_NO_MEMORY, FATAL_ERROR_FLAG | 4, \
|
MOZILLA_PKIX_MAP(FATAL_ERROR_NO_MEMORY, FATAL_ERROR_FLAG | 4, \
|
||||||
SEC_ERROR_NO_MEMORY) \
|
SEC_ERROR_NO_MEMORY) \
|
||||||
/* nothing here */
|
/* nothing here */
|
||||||
|
|
||||||
enum class Result
|
enum class Result {
|
||||||
{
|
|
||||||
#define MOZILLA_PKIX_MAP(name, value, nss_name) name = value,
|
#define MOZILLA_PKIX_MAP(name, value, nss_name) name = value,
|
||||||
MOZILLA_PKIX_MAP_LIST
|
MOZILLA_PKIX_MAP_LIST
|
||||||
#undef MOZILLA_PKIX_MAP
|
#undef MOZILLA_PKIX_MAP
|
||||||
|
|
@ -216,19 +187,15 @@ const char* MapResultToName(Result result);
|
||||||
// results in less line wrapping.
|
// results in less line wrapping.
|
||||||
static const Result Success = Result::Success;
|
static const Result Success = Result::Success;
|
||||||
|
|
||||||
inline bool
|
inline bool IsFatalError(Result rv) {
|
||||||
IsFatalError(Result rv)
|
|
||||||
{
|
|
||||||
return (static_cast<unsigned int>(rv) & FATAL_ERROR_FLAG) != 0;
|
return (static_cast<unsigned int>(rv) & FATAL_ERROR_FLAG) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Result
|
inline Result NotReached(const char* /*explanation*/, Result result) {
|
||||||
NotReached(const char* /*explanation*/, Result result)
|
|
||||||
{
|
|
||||||
assert(false);
|
assert(false);
|
||||||
return result;
|
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 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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
|
#ifndef mozilla_pkix_Time_h
|
||||||
#define mozilla_pkix_Time_h
|
#define mozilla_pkix_Time_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "pkix/Result.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
|
// 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
|
// 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.
|
// OCSP. This type has second-level precision. The time zone is always UTC.
|
||||||
//
|
//
|
||||||
// Pass by value, not by reference.
|
// Pass by value, not by reference.
|
||||||
class Time final
|
class Time final {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// Construct an uninitialized instance.
|
// Construct an uninitialized instance.
|
||||||
//
|
//
|
||||||
// This will fail to compile because there is no default constructor:
|
// This will fail to compile because there is no default constructor:
|
||||||
|
|
@ -48,41 +31,33 @@ public:
|
||||||
// This will succeed, leaving the time uninitialized:
|
// This will succeed, leaving the time uninitialized:
|
||||||
// Time x(Time::uninitialized);
|
// Time x(Time::uninitialized);
|
||||||
enum Uninitialized { 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;
|
return elapsedSecondsAD == other.elapsedSecondsAD;
|
||||||
}
|
}
|
||||||
bool operator>(const Time& other) const
|
bool operator>(const Time& other) const {
|
||||||
{
|
|
||||||
return elapsedSecondsAD > other.elapsedSecondsAD;
|
return elapsedSecondsAD > other.elapsedSecondsAD;
|
||||||
}
|
}
|
||||||
bool operator>=(const Time& other) const
|
bool operator>=(const Time& other) const {
|
||||||
{
|
|
||||||
return elapsedSecondsAD >= other.elapsedSecondsAD;
|
return elapsedSecondsAD >= other.elapsedSecondsAD;
|
||||||
}
|
}
|
||||||
bool operator<(const Time& other) const
|
bool operator<(const Time& other) const {
|
||||||
{
|
|
||||||
return elapsedSecondsAD < other.elapsedSecondsAD;
|
return elapsedSecondsAD < other.elapsedSecondsAD;
|
||||||
}
|
}
|
||||||
bool operator<=(const Time& other) const
|
bool operator<=(const Time& other) const {
|
||||||
{
|
|
||||||
return elapsedSecondsAD <= other.elapsedSecondsAD;
|
return elapsedSecondsAD <= other.elapsedSecondsAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result AddSeconds(uint64_t seconds)
|
Result AddSeconds(uint64_t seconds) {
|
||||||
{
|
if (std::numeric_limits<uint64_t>::max() - elapsedSecondsAD < seconds) {
|
||||||
if (std::numeric_limits<uint64_t>::max() - elapsedSecondsAD
|
|
||||||
< seconds) {
|
|
||||||
return Result::FATAL_ERROR_INVALID_ARGS; // integer overflow
|
return Result::FATAL_ERROR_INVALID_ARGS; // integer overflow
|
||||||
}
|
}
|
||||||
elapsedSecondsAD += seconds;
|
elapsedSecondsAD += seconds;
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result SubtractSeconds(uint64_t seconds)
|
Result SubtractSeconds(uint64_t seconds) {
|
||||||
{
|
|
||||||
if (seconds > elapsedSecondsAD) {
|
if (seconds > elapsedSecondsAD) {
|
||||||
return Result::FATAL_ERROR_INVALID_ARGS; // integer overflow
|
return Result::FATAL_ERROR_INVALID_ARGS; // integer overflow
|
||||||
}
|
}
|
||||||
|
|
@ -90,10 +65,10 @@ public:
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint64_t ONE_DAY_IN_SECONDS
|
static const uint64_t ONE_DAY_IN_SECONDS =
|
||||||
= UINT64_C(24) * UINT64_C(60) * UINT64_C(60);
|
UINT64_C(24) * UINT64_C(60) * UINT64_C(60);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This constructor is hidden to prevent accidents like this:
|
// This constructor is hidden to prevent accidents like this:
|
||||||
//
|
//
|
||||||
// Time foo(time_t t)
|
// Time foo(time_t t)
|
||||||
|
|
@ -101,19 +76,16 @@ private:
|
||||||
// // WRONG! 1970-01-01-00:00:00 == time_t(0), but not Time(0)!
|
// // WRONG! 1970-01-01-00:00:00 == time_t(0), but not Time(0)!
|
||||||
// return Time(t);
|
// return Time(t);
|
||||||
// }
|
// }
|
||||||
explicit Time(uint64_t elapsedSecondsAD)
|
explicit Time(uint64_t aElapsedSecondsAD)
|
||||||
: elapsedSecondsAD(elapsedSecondsAD)
|
: elapsedSecondsAD(aElapsedSecondsAD) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
friend Time TimeFromElapsedSecondsAD(uint64_t);
|
friend Time TimeFromElapsedSecondsAD(uint64_t);
|
||||||
friend class Duration;
|
friend class Duration;
|
||||||
|
|
||||||
uint64_t elapsedSecondsAD;
|
uint64_t elapsedSecondsAD;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Time TimeFromElapsedSecondsAD(uint64_t elapsedSecondsAD)
|
inline Time TimeFromElapsedSecondsAD(uint64_t aElapsedSecondsAD) {
|
||||||
{
|
return Time(aElapsedSecondsAD);
|
||||||
return Time(elapsedSecondsAD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Time Now();
|
Time Now();
|
||||||
|
|
@ -121,34 +93,27 @@ Time Now();
|
||||||
// Note the epoch is the unix epoch (ie 00:00:00 UTC, 1 January 1970)
|
// Note the epoch is the unix epoch (ie 00:00:00 UTC, 1 January 1970)
|
||||||
Time TimeFromEpochInSeconds(uint64_t secondsSinceEpoch);
|
Time TimeFromEpochInSeconds(uint64_t secondsSinceEpoch);
|
||||||
|
|
||||||
class Duration final
|
class Duration final {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
Duration(Time timeA, Time timeB)
|
Duration(Time timeA, Time timeB)
|
||||||
: durationInSeconds(timeA < timeB
|
: durationInSeconds(
|
||||||
? timeB.elapsedSecondsAD - timeA.elapsedSecondsAD
|
timeA < timeB ? timeB.elapsedSecondsAD - timeA.elapsedSecondsAD
|
||||||
: timeA.elapsedSecondsAD - timeB.elapsedSecondsAD)
|
: timeA.elapsedSecondsAD - timeB.elapsedSecondsAD) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit Duration(uint64_t durationInSeconds)
|
explicit Duration(uint64_t aDurationInSeconds)
|
||||||
: durationInSeconds(durationInSeconds)
|
: durationInSeconds(aDurationInSeconds) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator>(const Duration& other) const
|
bool operator>(const Duration& other) const {
|
||||||
{
|
|
||||||
return durationInSeconds > other.durationInSeconds;
|
return durationInSeconds > other.durationInSeconds;
|
||||||
}
|
}
|
||||||
bool operator<(const Duration& other) const
|
bool operator<(const Duration& other) const {
|
||||||
{
|
|
||||||
return durationInSeconds < other.durationInSeconds;
|
return durationInSeconds < other.durationInSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t durationInSeconds;
|
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 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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
|
#ifndef mozilla_pkix_pkix_h
|
||||||
#define 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
|
// LIMITED SUPPORT FOR CERTIFICATE POLICIES
|
||||||
|
|
@ -102,8 +86,8 @@ namespace mozilla { namespace pkix {
|
||||||
// requiredPolicy:
|
// requiredPolicy:
|
||||||
// This is the policy to apply; typically included in EV certificates.
|
// This is the policy to apply; typically included in EV certificates.
|
||||||
// If there is no policy, pass in CertPolicyId::anyPolicy.
|
// If there is no policy, pass in CertPolicyId::anyPolicy.
|
||||||
Result BuildCertChain(TrustDomain& trustDomain, Input cert,
|
Result BuildCertChain(TrustDomain& trustDomain, Input cert, Time time,
|
||||||
Time time, EndEntityOrCA endEntityOrCA,
|
EndEntityOrCA endEntityOrCA,
|
||||||
KeyUsage requiredKeyUsageIfPresent,
|
KeyUsage requiredKeyUsageIfPresent,
|
||||||
KeyPurposeId requiredEKUIfPresent,
|
KeyPurposeId requiredEKUIfPresent,
|
||||||
const CertPolicyId& requiredPolicy,
|
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
|
// Construct an RFC-6960-encoded OCSP request, ready for submission to a
|
||||||
// responder, for the provided CertID. The request has no extensions.
|
// responder, for the provided CertID. The request has no extensions.
|
||||||
static const size_t OCSP_REQUEST_MAX_LENGTH = 127;
|
static const size_t OCSP_REQUEST_MAX_LENGTH = 127;
|
||||||
Result CreateEncodedOCSPRequest(TrustDomain& trustDomain,
|
Result CreateEncodedOCSPRequest(TrustDomain& trustDomain, const CertID& certID,
|
||||||
const CertID& certID,
|
|
||||||
/*out*/ uint8_t (&out)[OCSP_REQUEST_MAX_LENGTH],
|
/*out*/ uint8_t (&out)[OCSP_REQUEST_MAX_LENGTH],
|
||||||
/*out*/ size_t& outLen);
|
/*out*/ size_t& outLen);
|
||||||
|
|
||||||
|
|
@ -139,10 +122,9 @@ Result CreateEncodedOCSPRequest(TrustDomain& trustDomain,
|
||||||
// which the encoded response is considered trustworthy (that is, as long as
|
// 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 given time at which to validate is less than or equal to validThrough,
|
||||||
// the response will be considered trustworthy).
|
// the response will be considered trustworthy).
|
||||||
Result VerifyEncodedOCSPResponse(TrustDomain& trustDomain,
|
Result VerifyEncodedOCSPResponse(
|
||||||
const CertID& certID, Time time,
|
TrustDomain& trustDomain, const CertID& certID, Time time,
|
||||||
uint16_t maxLifetimeInDays,
|
uint16_t maxLifetimeInDays, Input encodedResponse,
|
||||||
Input encodedResponse,
|
|
||||||
/* out */ bool& expired,
|
/* out */ bool& expired,
|
||||||
/* optional out */ Time* thisUpdate = nullptr,
|
/* optional out */ Time* thisUpdate = nullptr,
|
||||||
/* optional out */ Time* validThrough = nullptr);
|
/* optional out */ Time* validThrough = nullptr);
|
||||||
|
|
@ -154,7 +136,7 @@ Result VerifyEncodedOCSPResponse(TrustDomain& trustDomain,
|
||||||
// requirement for another value. Empty extensions are also rejected.
|
// requirement for another value. Empty extensions are also rejected.
|
||||||
Result CheckTLSFeaturesAreSatisfied(Input& cert,
|
Result CheckTLSFeaturesAreSatisfied(Input& cert,
|
||||||
const Input* stapledOCSPResponse);
|
const Input* stapledOCSPResponse);
|
||||||
|
}
|
||||||
} } // namespace mozilla::pkix
|
} // namespace mozilla::pkix
|
||||||
|
|
||||||
#endif // mozilla_pkix_pkix_h
|
#endif // mozilla_pkix_pkix_h
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,21 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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
|
#ifndef mozilla_pkix_pkixcheck_h
|
||||||
#define mozilla_pkix_pkixcheck_h
|
#define mozilla_pkix_pkixcheck_h
|
||||||
|
|
||||||
#include "pkix/pkixtypes.h"
|
#include "pkix/pkixtypes.h"
|
||||||
|
|
||||||
namespace mozilla { namespace pkix {
|
namespace mozilla {
|
||||||
|
namespace pkix {
|
||||||
|
|
||||||
class BackCert;
|
class BackCert;
|
||||||
|
|
||||||
Result CheckIssuerIndependentProperties(
|
Result CheckIssuerIndependentProperties(TrustDomain& trustDomain,
|
||||||
TrustDomain& trustDomain,
|
const BackCert& cert, Time time,
|
||||||
const BackCert& cert,
|
|
||||||
Time time,
|
|
||||||
KeyUsage requiredKeyUsageIfPresent,
|
KeyUsage requiredKeyUsageIfPresent,
|
||||||
KeyPurposeId requiredEKUIfPresent,
|
KeyPurposeId requiredEKUIfPresent,
|
||||||
const CertPolicyId& requiredPolicy,
|
const CertPolicyId& requiredPolicy,
|
||||||
|
|
@ -59,7 +41,7 @@ Result CheckValidity(Time time, Time notBefore, Time notAfter);
|
||||||
// Check that a subject has TLS Feature (rfc7633) requirements that match its
|
// Check that a subject has TLS Feature (rfc7633) requirements that match its
|
||||||
// potential issuer
|
// potential issuer
|
||||||
Result CheckTLSFeatures(const BackCert& subject, BackCert& potentialIssuer);
|
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 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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
|
#ifndef mozilla_pkix_pkixder_h
|
||||||
#define mozilla_pkix_pkixder_h
|
#define mozilla_pkix_pkixder_h
|
||||||
|
|
@ -39,23 +22,20 @@
|
||||||
#include "pkix/Input.h"
|
#include "pkix/Input.h"
|
||||||
#include "pkix/pkixtypes.h"
|
#include "pkix/pkixtypes.h"
|
||||||
|
|
||||||
namespace mozilla { namespace pkix { namespace der {
|
namespace mozilla {
|
||||||
|
namespace pkix {
|
||||||
|
namespace der {
|
||||||
|
|
||||||
enum Class : uint8_t
|
enum Class : uint8_t {
|
||||||
{
|
|
||||||
UNIVERSAL = 0 << 6,
|
UNIVERSAL = 0 << 6,
|
||||||
// APPLICATION = 1 << 6, // unused
|
// APPLICATION = 1 << 6, // unused
|
||||||
CONTEXT_SPECIFIC = 2 << 6,
|
CONTEXT_SPECIFIC = 2 << 6,
|
||||||
// PRIVATE = 3 << 6 // unused
|
// PRIVATE = 3 << 6 // unused
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Constructed
|
enum Constructed { CONSTRUCTED = 1 << 5 };
|
||||||
{
|
|
||||||
CONSTRUCTED = 1 << 5
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Tag : uint8_t
|
enum Tag : uint8_t {
|
||||||
{
|
|
||||||
BOOLEAN = UNIVERSAL | 0x01,
|
BOOLEAN = UNIVERSAL | 0x01,
|
||||||
INTEGER = UNIVERSAL | 0x02,
|
INTEGER = UNIVERSAL | 0x02,
|
||||||
BIT_STRING = UNIVERSAL | 0x03,
|
BIT_STRING = UNIVERSAL | 0x03,
|
||||||
|
|
@ -79,9 +59,8 @@ Result ReadTagAndGetValue(Reader& input, /*out*/ uint8_t& tag,
|
||||||
/*out*/ Input& value);
|
/*out*/ Input& value);
|
||||||
Result End(Reader& input);
|
Result End(Reader& input);
|
||||||
|
|
||||||
inline Result
|
inline Result ExpectTagAndGetValue(Reader& input, uint8_t tag,
|
||||||
ExpectTagAndGetValue(Reader& input, uint8_t tag, /*out*/ Input& value)
|
/*out*/ Input& value) {
|
||||||
{
|
|
||||||
uint8_t actualTag;
|
uint8_t actualTag;
|
||||||
Result rv = ReadTagAndGetValue(input, actualTag, value);
|
Result rv = ReadTagAndGetValue(input, actualTag, value);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
|
|
@ -93,9 +72,8 @@ ExpectTagAndGetValue(Reader& input, uint8_t tag, /*out*/ Input& value)
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Result
|
inline Result ExpectTagAndGetValue(Reader& input, uint8_t tag,
|
||||||
ExpectTagAndGetValue(Reader& input, uint8_t tag, /*out*/ Reader& value)
|
/*out*/ Reader& value) {
|
||||||
{
|
|
||||||
Input valueInput;
|
Input valueInput;
|
||||||
Result rv = ExpectTagAndGetValue(input, tag, valueInput);
|
Result rv = ExpectTagAndGetValue(input, tag, valueInput);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
|
|
@ -104,9 +82,7 @@ ExpectTagAndGetValue(Reader& input, uint8_t tag, /*out*/ Reader& value)
|
||||||
return value.Init(valueInput);
|
return value.Init(valueInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Result
|
inline Result ExpectTagAndEmptyValue(Reader& input, uint8_t tag) {
|
||||||
ExpectTagAndEmptyValue(Reader& input, uint8_t tag)
|
|
||||||
{
|
|
||||||
Reader value;
|
Reader value;
|
||||||
Result rv = ExpectTagAndGetValue(input, tag, value);
|
Result rv = ExpectTagAndGetValue(input, tag, value);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
|
|
@ -115,9 +91,7 @@ ExpectTagAndEmptyValue(Reader& input, uint8_t tag)
|
||||||
return End(value);
|
return End(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Result
|
inline Result ExpectTagAndSkipValue(Reader& input, uint8_t tag) {
|
||||||
ExpectTagAndSkipValue(Reader& input, uint8_t tag)
|
|
||||||
{
|
|
||||||
Input ignoredValue;
|
Input ignoredValue;
|
||||||
return ExpectTagAndGetValue(input, tag, ignoredValue);
|
return ExpectTagAndGetValue(input, tag, ignoredValue);
|
||||||
}
|
}
|
||||||
|
|
@ -135,9 +109,8 @@ inline Result SkipOptionalImplicitPrimitiveTag(Reader& input,
|
||||||
|
|
||||||
// Like ExpectTagAndGetValue, except the output Input will contain the
|
// Like ExpectTagAndGetValue, except the output Input will contain the
|
||||||
// encoded tag and length along with the value.
|
// encoded tag and length along with the value.
|
||||||
inline Result
|
inline Result ExpectTagAndGetTLV(Reader& input, uint8_t tag,
|
||||||
ExpectTagAndGetTLV(Reader& input, uint8_t tag, /*out*/ Input& tlv)
|
/*out*/ Input& tlv) {
|
||||||
{
|
|
||||||
Reader::Mark mark(input.GetMark());
|
Reader::Mark mark(input.GetMark());
|
||||||
Result rv = ExpectTagAndSkipValue(input, tag);
|
Result rv = ExpectTagAndSkipValue(input, tag);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
|
|
@ -146,9 +119,7 @@ ExpectTagAndGetTLV(Reader& input, uint8_t tag, /*out*/ Input& tlv)
|
||||||
return input.GetInput(mark, tlv);
|
return input.GetInput(mark, tlv);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Result
|
inline Result End(Reader& input) {
|
||||||
End(Reader& input)
|
|
||||||
{
|
|
||||||
if (!input.AtEnd()) {
|
if (!input.AtEnd()) {
|
||||||
return Result::ERROR_BAD_DER;
|
return Result::ERROR_BAD_DER;
|
||||||
}
|
}
|
||||||
|
|
@ -157,9 +128,7 @@ End(Reader& input)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Decoder>
|
template <typename Decoder>
|
||||||
inline Result
|
inline Result Nested(Reader& input, uint8_t tag, Decoder decoder) {
|
||||||
Nested(Reader& input, uint8_t tag, Decoder decoder)
|
|
||||||
{
|
|
||||||
Reader nested;
|
Reader nested;
|
||||||
Result rv = ExpectTagAndGetValue(input, tag, nested);
|
Result rv = ExpectTagAndGetValue(input, tag, nested);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
|
|
@ -173,9 +142,8 @@ Nested(Reader& input, uint8_t tag, Decoder decoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Decoder>
|
template <typename Decoder>
|
||||||
inline Result
|
inline Result Nested(Reader& input, uint8_t outerTag, uint8_t innerTag,
|
||||||
Nested(Reader& input, uint8_t outerTag, uint8_t innerTag, Decoder decoder)
|
Decoder decoder) {
|
||||||
{
|
|
||||||
Reader nestedInput;
|
Reader nestedInput;
|
||||||
Result rv = ExpectTagAndGetValue(input, outerTag, nestedInput);
|
Result rv = ExpectTagAndGetValue(input, outerTag, nestedInput);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
|
|
@ -216,10 +184,8 @@ Nested(Reader& input, uint8_t outerTag, uint8_t innerTag, Decoder decoder)
|
||||||
// foos.
|
// foos.
|
||||||
//
|
//
|
||||||
template <typename Decoder>
|
template <typename Decoder>
|
||||||
inline Result
|
inline Result NestedOf(Reader& input, uint8_t outerTag, uint8_t innerTag,
|
||||||
NestedOf(Reader& input, uint8_t outerTag, uint8_t innerTag,
|
EmptyAllowed mayBeEmpty, Decoder decoder) {
|
||||||
EmptyAllowed mayBeEmpty, Decoder decoder)
|
|
||||||
{
|
|
||||||
Reader inner;
|
Reader inner;
|
||||||
Result rv = ExpectTagAndGetValue(input, outerTag, inner);
|
Result rv = ExpectTagAndGetValue(input, outerTag, inner);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
|
|
@ -247,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.
|
// DER-encoded data wrapped in a SEQUENCE (or similar) with nothing after it.
|
||||||
// This function reduces the boilerplate necessary for stripping the outermost
|
// This function reduces the boilerplate necessary for stripping the outermost
|
||||||
// SEQUENCE (or similar) and ensuring that nothing follows it.
|
// SEQUENCE (or similar) and ensuring that nothing follows it.
|
||||||
inline Result
|
inline Result ExpectTagAndGetValueAtEnd(Reader& outer, uint8_t expectedTag,
|
||||||
ExpectTagAndGetValueAtEnd(Reader& outer, uint8_t expectedTag,
|
/*out*/ Reader& inner) {
|
||||||
/*out*/ Reader& inner)
|
|
||||||
{
|
|
||||||
Result rv = der::ExpectTagAndGetValue(outer, expectedTag, inner);
|
Result rv = der::ExpectTagAndGetValue(outer, expectedTag, inner);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return rv;
|
return rv;
|
||||||
|
|
@ -259,10 +223,8 @@ ExpectTagAndGetValueAtEnd(Reader& outer, uint8_t expectedTag,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Similar to the above, but takes an Input instead of a Reader&.
|
// Similar to the above, but takes an Input instead of a Reader&.
|
||||||
inline Result
|
inline Result ExpectTagAndGetValueAtEnd(Input outer, uint8_t expectedTag,
|
||||||
ExpectTagAndGetValueAtEnd(Input outer, uint8_t expectedTag,
|
/*out*/ Reader& inner) {
|
||||||
/*out*/ Reader& inner)
|
|
||||||
{
|
|
||||||
Reader outerReader(outer);
|
Reader outerReader(outer);
|
||||||
return ExpectTagAndGetValueAtEnd(outerReader, expectedTag, inner);
|
return ExpectTagAndGetValueAtEnd(outerReader, expectedTag, inner);
|
||||||
}
|
}
|
||||||
|
|
@ -271,15 +233,14 @@ ExpectTagAndGetValueAtEnd(Input outer, uint8_t expectedTag,
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
enum class IntegralValueRestriction
|
enum class IntegralValueRestriction {
|
||||||
{
|
|
||||||
NoRestriction,
|
NoRestriction,
|
||||||
MustBePositive,
|
MustBePositive,
|
||||||
MustBe0To127,
|
MustBe0To127,
|
||||||
};
|
};
|
||||||
|
|
||||||
Result IntegralBytes(Reader& input, uint8_t tag,
|
Result IntegralBytes(
|
||||||
IntegralValueRestriction valueRestriction,
|
Reader& input, uint8_t tag, IntegralValueRestriction valueRestriction,
|
||||||
/*out*/ Input& value,
|
/*out*/ Input& value,
|
||||||
/*optional out*/ Input::size_type* significantBytes = nullptr);
|
/*optional out*/ Input::size_type* significantBytes = nullptr);
|
||||||
|
|
||||||
|
|
@ -289,12 +250,9 @@ Result IntegralValue(Reader& input, uint8_t tag, /*out*/ uint8_t& value);
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
Result
|
Result BitStringWithNoUnusedBits(Reader& input, /*out*/ Input& value);
|
||||||
BitStringWithNoUnusedBits(Reader& input, /*out*/ Input& value);
|
|
||||||
|
|
||||||
inline Result
|
inline Result Boolean(Reader& input, /*out*/ bool& value) {
|
||||||
Boolean(Reader& input, /*out*/ bool& value)
|
|
||||||
{
|
|
||||||
Reader valueReader;
|
Reader valueReader;
|
||||||
Result rv = ExpectTagAndGetValue(input, BOOLEAN, valueReader);
|
Result rv = ExpectTagAndGetValue(input, BOOLEAN, valueReader);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
|
|
@ -311,8 +269,12 @@ Boolean(Reader& input, /*out*/ bool& value)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
switch (intValue) {
|
switch (intValue) {
|
||||||
case 0: value = false; return Success;
|
case 0:
|
||||||
case 0xFF: value = true; return Success;
|
value = false;
|
||||||
|
return Success;
|
||||||
|
case 0xFF:
|
||||||
|
value = true;
|
||||||
|
return Success;
|
||||||
default:
|
default:
|
||||||
return Result::ERROR_BAD_DER;
|
return Result::ERROR_BAD_DER;
|
||||||
}
|
}
|
||||||
|
|
@ -324,9 +286,7 @@ Boolean(Reader& input, /*out*/ bool& value)
|
||||||
// default value." However, it appears to be common that other libraries
|
// 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
|
// incorrectly include the value of a BOOLEAN even when it's equal to the
|
||||||
// default value, so we allow invalid explicit encodings here.
|
// default value, so we allow invalid explicit encodings here.
|
||||||
inline Result
|
inline Result OptionalBoolean(Reader& input, /*out*/ bool& value) {
|
||||||
OptionalBoolean(Reader& input, /*out*/ bool& value)
|
|
||||||
{
|
|
||||||
value = false;
|
value = false;
|
||||||
if (input.Peek(BOOLEAN)) {
|
if (input.Peek(BOOLEAN)) {
|
||||||
Result rv = Boolean(input, value);
|
Result rv = Boolean(input, value);
|
||||||
|
|
@ -339,9 +299,7 @@ OptionalBoolean(Reader& input, /*out*/ bool& value)
|
||||||
|
|
||||||
// This parser will only parse values between 0..127. If this range is
|
// This parser will only parse values between 0..127. If this range is
|
||||||
// increased then callers will need to be changed.
|
// increased then callers will need to be changed.
|
||||||
inline Result
|
inline Result Enumerated(Reader& input, uint8_t& value) {
|
||||||
Enumerated(Reader& input, uint8_t& value)
|
|
||||||
{
|
|
||||||
return internal::IntegralValue(input, ENUMERATED | 0, value);
|
return internal::IntegralValue(input, ENUMERATED | 0, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -360,18 +318,14 @@ Result TimeChoice(Reader& input, uint8_t tag, /*out*/ Time& time);
|
||||||
// Only times from 1970-01-01-00:00:00 onward are accepted, in order to
|
// 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
|
// eliminate the chance for complications in converting times to traditional
|
||||||
// time formats that start at 1970.
|
// time formats that start at 1970.
|
||||||
inline Result
|
inline Result GeneralizedTime(Reader& input, /*out*/ Time& time) {
|
||||||
GeneralizedTime(Reader& input, /*out*/ Time& time)
|
|
||||||
{
|
|
||||||
return internal::TimeChoice(input, GENERALIZED_TIME, time);
|
return internal::TimeChoice(input, GENERALIZED_TIME, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only times from 1970-01-01-00:00:00 onward are accepted, in order to
|
// 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
|
// eliminate the chance for complications in converting times to traditional
|
||||||
// time formats that start at 1970.
|
// time formats that start at 1970.
|
||||||
inline Result
|
inline Result TimeChoice(Reader& input, /*out*/ Time& time) {
|
||||||
TimeChoice(Reader& input, /*out*/ Time& time)
|
|
||||||
{
|
|
||||||
uint8_t expectedTag = input.Peek(UTCTime) ? UTCTime : GENERALIZED_TIME;
|
uint8_t expectedTag = input.Peek(UTCTime) ? UTCTime : GENERALIZED_TIME;
|
||||||
return internal::TimeChoice(input, expectedTag, time);
|
return internal::TimeChoice(input, expectedTag, time);
|
||||||
}
|
}
|
||||||
|
|
@ -380,20 +334,17 @@ TimeChoice(Reader& input, /*out*/ Time& time)
|
||||||
// zero are rejected. If significantBytes is not null, then it will be set to
|
// 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 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.
|
// the length of any leading padding), which is useful for key size checks.
|
||||||
inline Result
|
inline Result PositiveInteger(
|
||||||
PositiveInteger(Reader& input, /*out*/ Input& value,
|
Reader& input, /*out*/ Input& value,
|
||||||
/*optional out*/ Input::size_type* significantBytes = nullptr)
|
/*optional out*/ Input::size_type* significantBytes = nullptr) {
|
||||||
{
|
|
||||||
return internal::IntegralBytes(
|
return internal::IntegralBytes(
|
||||||
input, INTEGER, internal::IntegralValueRestriction::MustBePositive,
|
input, INTEGER, internal::IntegralValueRestriction::MustBePositive, value,
|
||||||
value, significantBytes);
|
significantBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This parser will only parse values between 0..127. If this range is
|
// This parser will only parse values between 0..127. If this range is
|
||||||
// increased then callers will need to be changed.
|
// increased then callers will need to be changed.
|
||||||
inline Result
|
inline Result Integer(Reader& input, /*out*/ uint8_t& value) {
|
||||||
Integer(Reader& input, /*out*/ uint8_t& value)
|
|
||||||
{
|
|
||||||
return internal::IntegralValue(input, INTEGER, value);
|
return internal::IntegralValue(input, INTEGER, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -401,9 +352,8 @@ Integer(Reader& input, /*out*/ uint8_t& value)
|
||||||
// increased then callers will need to be changed. The default value must be
|
// 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
|
// -1; defaultValue is only a parameter to make it clear in the calling code
|
||||||
// what the default value is.
|
// what the default value is.
|
||||||
inline Result
|
inline Result OptionalInteger(Reader& input, long defaultValue,
|
||||||
OptionalInteger(Reader& input, long defaultValue, /*out*/ long& value)
|
/*out*/ long& value) {
|
||||||
{
|
|
||||||
// If we need to support a different default value in the future, we need to
|
// If we need to support a different default value in the future, we need to
|
||||||
// test that parsedValue != defaultValue.
|
// test that parsedValue != defaultValue.
|
||||||
if (defaultValue != -1) {
|
if (defaultValue != -1) {
|
||||||
|
|
@ -424,16 +374,12 @@ OptionalInteger(Reader& input, long defaultValue, /*out*/ long& value)
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Result
|
inline Result Null(Reader& input) {
|
||||||
Null(Reader& input)
|
|
||||||
{
|
|
||||||
return ExpectTagAndEmptyValue(input, NULLTag);
|
return ExpectTagAndEmptyValue(input, NULLTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <uint8_t Len>
|
template <uint8_t Len>
|
||||||
Result
|
Result OID(Reader& input, const uint8_t (&expectedOid)[Len]) {
|
||||||
OID(Reader& input, const uint8_t (&expectedOid)[Len])
|
|
||||||
{
|
|
||||||
Reader value;
|
Reader value;
|
||||||
Result rv = ExpectTagAndGetValue(input, OIDTag, value);
|
Result rv = ExpectTagAndGetValue(input, OIDTag, value);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
|
|
@ -447,9 +393,7 @@ OID(Reader& input, const uint8_t (&expectedOid)[Len])
|
||||||
|
|
||||||
// PKI-specific types
|
// PKI-specific types
|
||||||
|
|
||||||
inline Result
|
inline Result CertificateSerialNumber(Reader& input, /*out*/ Input& value) {
|
||||||
CertificateSerialNumber(Reader& input, /*out*/ Input& value)
|
|
||||||
{
|
|
||||||
// http://tools.ietf.org/html/rfc5280#section-4.1.2.2:
|
// http://tools.ietf.org/html/rfc5280#section-4.1.2.2:
|
||||||
//
|
//
|
||||||
// * "The serial number MUST be a positive integer assigned by the CA to
|
// * "The serial number MUST be a positive integer assigned by the CA to
|
||||||
|
|
@ -461,13 +405,12 @@ CertificateSerialNumber(Reader& input, /*out*/ Input& value)
|
||||||
// that are negative or zero. Certificate users SHOULD be prepared to
|
// that are negative or zero. Certificate users SHOULD be prepared to
|
||||||
// gracefully handle such certificates."
|
// gracefully handle such certificates."
|
||||||
return internal::IntegralBytes(
|
return internal::IntegralBytes(
|
||||||
input, INTEGER, internal::IntegralValueRestriction::NoRestriction,
|
input, INTEGER, internal::IntegralValueRestriction::NoRestriction, value);
|
||||||
value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// x.509 and OCSP both use this same version numbering scheme, though OCSP
|
// x.509 and OCSP both use this same version numbering scheme, though OCSP
|
||||||
// only supports v1.
|
// 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
|
// X.509 Certificate and OCSP ResponseData both use
|
||||||
// "[0] EXPLICIT Version DEFAULT v1". Although an explicit encoding of v1 is
|
// "[0] EXPLICIT Version DEFAULT v1". Although an explicit encoding of v1 is
|
||||||
|
|
@ -476,10 +419,8 @@ enum class Version { v1 = 0, v2 = 1, v3 = 2, v4 = 3 };
|
||||||
Result OptionalVersion(Reader& input, /*out*/ Version& version);
|
Result OptionalVersion(Reader& input, /*out*/ Version& version);
|
||||||
|
|
||||||
template <typename ExtensionHandler>
|
template <typename ExtensionHandler>
|
||||||
inline Result
|
inline Result OptionalExtensions(Reader& input, uint8_t tag,
|
||||||
OptionalExtensions(Reader& input, uint8_t tag,
|
ExtensionHandler extensionHandler) {
|
||||||
ExtensionHandler extensionHandler)
|
|
||||||
{
|
|
||||||
if (!input.Peek(tag)) {
|
if (!input.Peek(tag)) {
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
@ -490,7 +431,8 @@ OptionalExtensions(Reader& input, uint8_t tag,
|
||||||
// TODO(bug 997994): According to the specification, there should never be
|
// TODO(bug 997994): According to the specification, there should never be
|
||||||
// an empty sequence of extensions but we've found OCSP responses that have
|
// an empty sequence of extensions but we've found OCSP responses that have
|
||||||
// that (see bug 991898).
|
// that (see bug 991898).
|
||||||
return NestedOf(tagged, SEQUENCE, SEQUENCE, EmptyAllowed::Yes,
|
return NestedOf(
|
||||||
|
tagged, SEQUENCE, SEQUENCE, EmptyAllowed::Yes,
|
||||||
[extensionHandler](Reader& extension) -> Result {
|
[extensionHandler](Reader& extension) -> Result {
|
||||||
// Extension ::= SEQUENCE {
|
// Extension ::= SEQUENCE {
|
||||||
// extnID OBJECT IDENTIFIER,
|
// extnID OBJECT IDENTIFIER,
|
||||||
|
|
@ -528,20 +470,15 @@ OptionalExtensions(Reader& input, uint8_t tag,
|
||||||
Result DigestAlgorithmIdentifier(Reader& input,
|
Result DigestAlgorithmIdentifier(Reader& input,
|
||||||
/*out*/ DigestAlgorithm& algorithm);
|
/*out*/ DigestAlgorithm& algorithm);
|
||||||
|
|
||||||
enum class PublicKeyAlgorithm
|
enum class PublicKeyAlgorithm { RSA_PKCS1, ECDSA, Uninitialized };
|
||||||
{
|
|
||||||
RSA_PKCS1,
|
|
||||||
ECDSA,
|
|
||||||
};
|
|
||||||
|
|
||||||
Result SignatureAlgorithmIdentifierValue(
|
Result SignatureAlgorithmIdentifierValue(
|
||||||
Reader& input,
|
Reader& input,
|
||||||
/*out*/ PublicKeyAlgorithm& publicKeyAlgorithm,
|
/*out*/ PublicKeyAlgorithm& publicKeyAlgorithm,
|
||||||
/*out*/ DigestAlgorithm& digestAlgorithm);
|
/*out*/ DigestAlgorithm& digestAlgorithm);
|
||||||
|
|
||||||
struct SignedDataWithSignature final
|
struct SignedDataWithSignature final {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
Input data;
|
Input data;
|
||||||
Input algorithm;
|
Input algorithm;
|
||||||
Input signature;
|
Input signature;
|
||||||
|
|
@ -569,7 +506,8 @@ public:
|
||||||
// certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
|
// certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
|
||||||
Result SignedData(Reader& input, /*out*/ Reader& tbs,
|
Result SignedData(Reader& input, /*out*/ Reader& tbs,
|
||||||
/*out*/ SignedDataWithSignature& signedDataWithSignature);
|
/*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 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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
|
#ifndef mozilla_pkix_pkixnss_h
|
||||||
#define mozilla_pkix_pkixnss_h
|
#define mozilla_pkix_pkixnss_h
|
||||||
|
|
||||||
#include "pkixtypes.h"
|
#include <seccomon.h>
|
||||||
|
#include "pkix/pkixtypes.h"
|
||||||
#include "prerror.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
|
// Verifies the PKCS#1.5 signature on the given data using the given RSA public
|
||||||
// key.
|
// key.
|
||||||
|
|
@ -53,10 +37,8 @@ Result VerifyECDSASignedDigestNSS(const SignedDigest& sd,
|
||||||
// TODO: Taking the output buffer as (uint8_t*, size_t) is counter to our
|
// 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
|
// other, extensive, memory safety efforts in mozilla::pkix, and we should find
|
||||||
// a way to provide a more-obviously-safe interface.
|
// a way to provide a more-obviously-safe interface.
|
||||||
Result DigestBufNSS(Input item,
|
Result DigestBufNSS(Input item, DigestAlgorithm digestAlg,
|
||||||
DigestAlgorithm digestAlg,
|
/*out*/ uint8_t* digestBuf, size_t digestBufLen);
|
||||||
/*out*/ uint8_t* digestBuf,
|
|
||||||
size_t digestBufLen);
|
|
||||||
|
|
||||||
Result MapPRErrorCodeToResult(PRErrorCode errorCode);
|
Result MapPRErrorCodeToResult(PRErrorCode errorCode);
|
||||||
PRErrorCode MapResultToPRErrorCode(Result result);
|
PRErrorCode MapResultToPRErrorCode(Result result);
|
||||||
|
|
@ -71,8 +53,7 @@ PRErrorCode MapResultToPRErrorCode(Result result);
|
||||||
static const PRErrorCode ERROR_BASE = -0x4000;
|
static const PRErrorCode ERROR_BASE = -0x4000;
|
||||||
static const PRErrorCode ERROR_LIMIT = ERROR_BASE + 1000;
|
static const PRErrorCode ERROR_LIMIT = ERROR_BASE + 1000;
|
||||||
|
|
||||||
enum ErrorCode
|
enum ErrorCode {
|
||||||
{
|
|
||||||
MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE = ERROR_BASE + 0,
|
MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE = ERROR_BASE + 0,
|
||||||
MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY = ERROR_BASE + 1,
|
MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY = ERROR_BASE + 1,
|
||||||
MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE = ERROR_BASE + 2,
|
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_REQUIRED_TLS_FEATURE_MISSING = ERROR_BASE + 10,
|
||||||
MOZILLA_PKIX_ERROR_INVALID_INTEGER_ENCODING = ERROR_BASE + 11,
|
MOZILLA_PKIX_ERROR_INVALID_INTEGER_ENCODING = ERROR_BASE + 11,
|
||||||
MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME = ERROR_BASE + 12,
|
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
|
END_OF_LIST
|
||||||
};
|
};
|
||||||
|
|
||||||
void RegisterErrorTable();
|
void RegisterErrorTable();
|
||||||
|
|
||||||
inline SECItem UnsafeMapInputToSECItem(Input input)
|
inline SECItem UnsafeMapInputToSECItem(Input input) {
|
||||||
{
|
SECItem result = {siBuffer, const_cast<uint8_t*>(input.UnsafeGetData()),
|
||||||
SECItem result = {
|
input.GetLength()};
|
||||||
siBuffer,
|
|
||||||
const_cast<uint8_t*>(input.UnsafeGetData()),
|
|
||||||
input.GetLength()
|
|
||||||
};
|
|
||||||
static_assert(sizeof(decltype(input.GetLength())) <= sizeof(result.len),
|
static_assert(sizeof(decltype(input.GetLength())) <= sizeof(result.len),
|
||||||
"input.GetLength() must fit in a SECItem");
|
"input.GetLength() must fit in a SECItem");
|
||||||
return result;
|
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 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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
|
#ifndef mozilla_pkix_pkixtypes_h
|
||||||
#define mozilla_pkix_pkixtypes_h
|
#define mozilla_pkix_pkixtypes_h
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "pkix/Input.h"
|
#include "pkix/Input.h"
|
||||||
#include "pkix/Time.h"
|
#include "pkix/Time.h"
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
|
|
||||||
namespace mozilla { namespace pkix {
|
namespace mozilla {
|
||||||
|
namespace pkix {
|
||||||
|
|
||||||
enum class DigestAlgorithm
|
enum class DigestAlgorithm {
|
||||||
{
|
|
||||||
sha512 = 1,
|
sha512 = 1,
|
||||||
sha384 = 2,
|
sha384 = 2,
|
||||||
sha256 = 3,
|
sha256 = 3,
|
||||||
sha1 = 4,
|
sha1 = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class NamedCurve
|
enum class NamedCurve {
|
||||||
{
|
|
||||||
// secp521r1 (OID 1.3.132.0.35, RFC 5480)
|
// secp521r1 (OID 1.3.132.0.35, RFC 5480)
|
||||||
secp521r1 = 1,
|
secp521r1 = 1,
|
||||||
|
|
||||||
|
|
@ -50,8 +34,7 @@ enum class NamedCurve
|
||||||
secp256r1 = 3,
|
secp256r1 = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SignedDigest final
|
struct SignedDigest final {
|
||||||
{
|
|
||||||
Input digest;
|
Input digest;
|
||||||
DigestAlgorithm digestAlgorithm;
|
DigestAlgorithm digestAlgorithm;
|
||||||
Input signature;
|
Input signature;
|
||||||
|
|
@ -61,8 +44,7 @@ struct SignedDigest final
|
||||||
|
|
||||||
enum class EndEntityOrCA { MustBeEndEntity = 0, MustBeCA = 1 };
|
enum class EndEntityOrCA { MustBeEndEntity = 0, MustBeCA = 1 };
|
||||||
|
|
||||||
enum class KeyUsage : uint8_t
|
enum class KeyUsage : uint8_t {
|
||||||
{
|
|
||||||
digitalSignature = 0,
|
digitalSignature = 0,
|
||||||
nonRepudiation = 1,
|
nonRepudiation = 1,
|
||||||
keyEncipherment = 2,
|
keyEncipherment = 2,
|
||||||
|
|
@ -75,8 +57,7 @@ enum class KeyUsage : uint8_t
|
||||||
noParticularKeyUsageRequired = 0xff,
|
noParticularKeyUsageRequired = 0xff,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class KeyPurposeId
|
enum class KeyPurposeId {
|
||||||
{
|
|
||||||
anyExtendedKeyUsage = 0,
|
anyExtendedKeyUsage = 0,
|
||||||
id_kp_serverAuth = 1, // id-kp-serverAuth
|
id_kp_serverAuth = 1, // id-kp-serverAuth
|
||||||
id_kp_clientAuth = 2, // id-kp-clientAuth
|
id_kp_clientAuth = 2, // id-kp-clientAuth
|
||||||
|
|
@ -85,19 +66,18 @@ enum class KeyPurposeId
|
||||||
id_kp_OCSPSigning = 9, // id-kp-OCSPSigning
|
id_kp_OCSPSigning = 9, // id-kp-OCSPSigning
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CertPolicyId final
|
struct CertPolicyId final {
|
||||||
{
|
|
||||||
uint16_t numBytes;
|
uint16_t numBytes;
|
||||||
static const uint16_t MAX_BYTES = 24;
|
static const uint16_t MAX_BYTES = 24;
|
||||||
uint8_t bytes[MAX_BYTES];
|
uint8_t bytes[MAX_BYTES];
|
||||||
|
|
||||||
bool IsAnyPolicy() const;
|
bool IsAnyPolicy() const;
|
||||||
|
bool operator==(const CertPolicyId& other) const;
|
||||||
|
|
||||||
static const CertPolicyId anyPolicy;
|
static const CertPolicyId anyPolicy;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class TrustLevel
|
enum class TrustLevel {
|
||||||
{
|
|
||||||
TrustAnchor = 1, // certificate is a trusted root CA certificate or
|
TrustAnchor = 1, // certificate is a trusted root CA certificate or
|
||||||
// equivalent *for the given policy*.
|
// equivalent *for the given policy*.
|
||||||
ActivelyDistrusted = 2, // certificate is known to be bad
|
ActivelyDistrusted = 2, // certificate is known to be bad
|
||||||
|
|
@ -106,8 +86,7 @@ enum class TrustLevel
|
||||||
|
|
||||||
// Extensions extracted during the verification flow.
|
// Extensions extracted during the verification flow.
|
||||||
// See TrustDomain::NoteAuxiliaryExtension.
|
// See TrustDomain::NoteAuxiliaryExtension.
|
||||||
enum class AuxiliaryExtension
|
enum class AuxiliaryExtension {
|
||||||
{
|
|
||||||
// Certificate Transparency data, specifically Signed Certificate
|
// Certificate Transparency data, specifically Signed Certificate
|
||||||
// Timestamps (SCTs). See RFC 6962.
|
// Timestamps (SCTs). See RFC 6962.
|
||||||
|
|
||||||
|
|
@ -130,25 +109,22 @@ enum class AuxiliaryExtension
|
||||||
// field from the issuer's certificate. serialNumber is the entire DER-encoded
|
// field from the issuer's certificate. serialNumber is the entire DER-encoded
|
||||||
// serial number from the subject certificate (the certificate for which we are
|
// serial number from the subject certificate (the certificate for which we are
|
||||||
// checking the revocation status).
|
// checking the revocation status).
|
||||||
struct CertID final
|
struct CertID final {
|
||||||
{
|
public:
|
||||||
public:
|
CertID(Input aIssuer, Input aIssuerSubjectPublicKeyInfo, Input aSerialNumber)
|
||||||
CertID(Input issuer, Input issuerSubjectPublicKeyInfo, Input serialNumber)
|
: issuer(aIssuer),
|
||||||
: issuer(issuer)
|
issuerSubjectPublicKeyInfo(aIssuerSubjectPublicKeyInfo),
|
||||||
, issuerSubjectPublicKeyInfo(issuerSubjectPublicKeyInfo)
|
serialNumber(aSerialNumber) {}
|
||||||
, serialNumber(serialNumber)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
const Input issuer;
|
const Input issuer;
|
||||||
const Input issuerSubjectPublicKeyInfo;
|
const Input issuerSubjectPublicKeyInfo;
|
||||||
const Input serialNumber;
|
const Input serialNumber;
|
||||||
|
|
||||||
void operator=(const CertID&) = delete;
|
void operator=(const CertID&) = delete;
|
||||||
};
|
};
|
||||||
|
typedef std::unique_ptr<CertID> ScopedCertID;
|
||||||
|
|
||||||
class DERArray
|
class DERArray {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// Returns the number of DER-encoded items in the array.
|
// Returns the number of DER-encoded items in the array.
|
||||||
virtual size_t GetLength() const = 0;
|
virtual size_t GetLength() const = 0;
|
||||||
|
|
||||||
|
|
@ -156,19 +132,19 @@ public:
|
||||||
// (0-indexed). The result is guaranteed to be non-null if i < GetLength(),
|
// (0-indexed). The result is guaranteed to be non-null if i < GetLength(),
|
||||||
// and the result is guaranteed to be nullptr if i >= GetLength().
|
// and the result is guaranteed to be nullptr if i >= GetLength().
|
||||||
virtual const Input* GetDER(size_t i) const = 0;
|
virtual const Input* GetDER(size_t i) const = 0;
|
||||||
protected:
|
|
||||||
DERArray() { }
|
protected:
|
||||||
virtual ~DERArray() { }
|
DERArray() {}
|
||||||
|
virtual ~DERArray() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Applications control the behavior of path building and verification by
|
// Applications control the behavior of path building and verification by
|
||||||
// implementing the TrustDomain interface. The TrustDomain is used for all
|
// implementing the TrustDomain interface. The TrustDomain is used for all
|
||||||
// cryptography and for determining which certificates are trusted or
|
// cryptography and for determining which certificates are trusted or
|
||||||
// distrusted.
|
// distrusted.
|
||||||
class TrustDomain
|
class TrustDomain {
|
||||||
{
|
public:
|
||||||
public:
|
virtual ~TrustDomain() {}
|
||||||
virtual ~TrustDomain() { }
|
|
||||||
|
|
||||||
// Determine the level of trust in the given certificate for the given role.
|
// Determine the level of trust in the given certificate for the given role.
|
||||||
// This will be called for every certificate encountered during path
|
// This will be called for every certificate encountered during path
|
||||||
|
|
@ -187,8 +163,7 @@ public:
|
||||||
Input candidateCertDER,
|
Input candidateCertDER,
|
||||||
/*out*/ TrustLevel& trustLevel) = 0;
|
/*out*/ TrustLevel& trustLevel) = 0;
|
||||||
|
|
||||||
class IssuerChecker
|
class IssuerChecker {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
// potentialIssuerDER is the complete DER encoding of the certificate to
|
// potentialIssuerDER is the complete DER encoding of the certificate to
|
||||||
// be checked as a potential issuer.
|
// be checked as a potential issuer.
|
||||||
|
|
@ -200,6 +175,7 @@ public:
|
||||||
virtual Result Check(Input potentialIssuerDER,
|
virtual Result Check(Input potentialIssuerDER,
|
||||||
/*optional*/ const Input* additionalNameConstraints,
|
/*optional*/ const Input* additionalNameConstraints,
|
||||||
/*out*/ bool& keepGoing) = 0;
|
/*out*/ bool& keepGoing) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
IssuerChecker();
|
IssuerChecker();
|
||||||
virtual ~IssuerChecker();
|
virtual ~IssuerChecker();
|
||||||
|
|
@ -254,8 +230,8 @@ public:
|
||||||
// implementation has an efficient way of filtering potential issuers by name
|
// implementation has an efficient way of filtering potential issuers by name
|
||||||
// and/or validity period itself, then it is probably better for performance
|
// and/or validity period itself, then it is probably better for performance
|
||||||
// for it to do so.
|
// for it to do so.
|
||||||
virtual Result FindIssuer(Input encodedIssuerName,
|
virtual Result FindIssuer(Input encodedIssuerName, IssuerChecker& checker,
|
||||||
IssuerChecker& checker, Time time) = 0;
|
Time time) = 0;
|
||||||
|
|
||||||
// Called as soon as we think we have a valid chain but before revocation
|
// 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,
|
// 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
|
// This function may be called multiple times, regardless of whether it
|
||||||
// returns success or failure. It is guaranteed that BuildCertChain will not
|
// 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
|
// it is guaranteed that when BuildCertChain returns Success the last chain
|
||||||
// passed to IsChainValid is the valid chain that should be used for further
|
// passed to IsChainValid is the valid chain that should be used for further
|
||||||
// operations that require the whole chain.
|
// operations that require the whole chain.
|
||||||
|
|
@ -278,13 +255,15 @@ public:
|
||||||
// wrong to assume that the certificate chain is valid.
|
// wrong to assume that the certificate chain is valid.
|
||||||
//
|
//
|
||||||
// certChain.GetDER(0) is the trust anchor.
|
// 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,
|
virtual Result CheckRevocation(EndEntityOrCA endEntityOrCA,
|
||||||
const CertID& certID, Time time,
|
const CertID& certID, Time time,
|
||||||
Duration validityDuration,
|
Duration validityDuration,
|
||||||
/*optional*/ const Input* stapledOCSPresponse,
|
/*optional*/ const Input* stapledOCSPresponse,
|
||||||
/*optional*/ const Input* aiaExtension) = 0;
|
/*optional*/ const Input* aiaExtension,
|
||||||
|
/*optional*/ const Input* sctExtension) = 0;
|
||||||
|
|
||||||
// Check that the given digest algorithm is acceptable for use in signatures.
|
// 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,
|
// Result::ERROR_INADEQUATE_KEY_SIZE if the key size is not acceptable,
|
||||||
// or another error code if another error occurred.
|
// or another error code if another error occurred.
|
||||||
virtual Result CheckRSAPublicKeyModulusSizeInBits(
|
virtual Result CheckRSAPublicKeyModulusSizeInBits(
|
||||||
EndEntityOrCA endEntityOrCA,
|
EndEntityOrCA endEntityOrCA, unsigned int modulusSizeInBits) = 0;
|
||||||
unsigned int modulusSizeInBits) = 0;
|
|
||||||
|
|
||||||
// Verify the given RSA PKCS#1.5 signature on the given digest using the
|
// Verify the given RSA PKCS#1.5 signature on the given digest using the
|
||||||
// given RSA public key.
|
// given RSA public key.
|
||||||
|
|
@ -311,8 +289,7 @@ public:
|
||||||
// function, so it is not necessary to repeat those checks here. However,
|
// function, so it is not necessary to repeat those checks here. However,
|
||||||
// VerifyRSAPKCS1SignedDigest *is* responsible for doing the mathematical
|
// VerifyRSAPKCS1SignedDigest *is* responsible for doing the mathematical
|
||||||
// verification of the public key validity as specified in NIST SP 800-56A.
|
// verification of the public key validity as specified in NIST SP 800-56A.
|
||||||
virtual Result VerifyRSAPKCS1SignedDigest(
|
virtual Result VerifyRSAPKCS1SignedDigest(const SignedDigest& signedDigest,
|
||||||
const SignedDigest& signedDigest,
|
|
||||||
Input subjectPublicKeyInfo) = 0;
|
Input subjectPublicKeyInfo) = 0;
|
||||||
|
|
||||||
// Check that the given named ECC curve is acceptable for ECDSA signatures.
|
// 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
|
// 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
|
// other, extensive, memory safety efforts in mozilla::pkix, and we should
|
||||||
// find a way to provide a more-obviously-safe interface.
|
// find a way to provide a more-obviously-safe interface.
|
||||||
virtual Result DigestBuf(Input item,
|
virtual Result DigestBuf(Input item, DigestAlgorithm digestAlg,
|
||||||
DigestAlgorithm digestAlg,
|
/*out*/ uint8_t* digestBuf, size_t digestBufLen) = 0;
|
||||||
/*out*/ uint8_t* digestBuf,
|
|
||||||
size_t digestBufLen) = 0;
|
protected:
|
||||||
protected:
|
TrustDomain() {}
|
||||||
TrustDomain() { }
|
|
||||||
|
|
||||||
TrustDomain(const TrustDomain&) = delete;
|
TrustDomain(const TrustDomain&) = delete;
|
||||||
void operator=(const TrustDomain&) = delete;
|
void operator=(const TrustDomain&) = delete;
|
||||||
|
|
@ -384,10 +360,9 @@ enum class FallBackToSearchWithinSubject { No = 0, Yes = 1 };
|
||||||
// Applications control the behavior of matching presented name information from
|
// Applications control the behavior of matching presented name information from
|
||||||
// a certificate against a reference hostname by implementing the
|
// a certificate against a reference hostname by implementing the
|
||||||
// NameMatchingPolicy interface. Used in concert with CheckCertHostname.
|
// NameMatchingPolicy interface. Used in concert with CheckCertHostname.
|
||||||
class NameMatchingPolicy
|
class NameMatchingPolicy {
|
||||||
{
|
public:
|
||||||
public:
|
virtual ~NameMatchingPolicy() {}
|
||||||
virtual ~NameMatchingPolicy() { }
|
|
||||||
|
|
||||||
// Given that the certificate in question has a notBefore field with the given
|
// Given that the certificate in question has a notBefore field with the given
|
||||||
// value, should name matching fall back to searching within the subject
|
// value, should name matching fall back to searching within the subject
|
||||||
|
|
@ -396,13 +371,13 @@ public:
|
||||||
Time notBefore,
|
Time notBefore,
|
||||||
/*out*/ FallBackToSearchWithinSubject& fallBackToCommonName) = 0;
|
/*out*/ FallBackToSearchWithinSubject& fallBackToCommonName) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NameMatchingPolicy() { }
|
NameMatchingPolicy() {}
|
||||||
|
|
||||||
NameMatchingPolicy(const NameMatchingPolicy&) = delete;
|
NameMatchingPolicy(const NameMatchingPolicy&) = delete;
|
||||||
void operator=(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 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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
|
#ifndef mozilla_pkix_pkixutil_h
|
||||||
#define 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
|
// During path building and verification, we build a linked list of BackCerts
|
||||||
// from the current cert toward the end-entity certificate. The linked list
|
// 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
|
// Each BackCert contains pointers to all the given certificate's extensions
|
||||||
// so that we can parse the extension block once and then process the
|
// 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.
|
// extensions in an order that may be different than they appear in the cert.
|
||||||
class BackCert final
|
class BackCert final {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// certDER and childCert must be valid for the lifetime of BackCert.
|
// certDER and childCert must be valid for the lifetime of BackCert.
|
||||||
BackCert(Input certDER, EndEntityOrCA endEntityOrCA,
|
BackCert(Input aCertDER, EndEntityOrCA aEndEntityOrCA,
|
||||||
const BackCert* childCert)
|
const BackCert* aChildCert)
|
||||||
: der(certDER)
|
: der(aCertDER),
|
||||||
, endEntityOrCA(endEntityOrCA)
|
endEntityOrCA(aEndEntityOrCA),
|
||||||
, childCert(childCert)
|
childCert(aChildCert),
|
||||||
{
|
version(der::Version::Uninitialized) {}
|
||||||
}
|
|
||||||
|
|
||||||
Result Init();
|
Result Init();
|
||||||
|
|
||||||
|
|
@ -65,67 +47,47 @@ public:
|
||||||
// RFC 5280 names for everything.
|
// RFC 5280 names for everything.
|
||||||
const Input GetValidity() const { return validity; }
|
const Input GetValidity() const { return validity; }
|
||||||
const Input GetSubject() const { return subject; }
|
const Input GetSubject() const { return subject; }
|
||||||
const Input GetSubjectPublicKeyInfo() const
|
const Input GetSubjectPublicKeyInfo() const { return subjectPublicKeyInfo; }
|
||||||
{
|
const Input* GetAuthorityInfoAccess() const {
|
||||||
return subjectPublicKeyInfo;
|
|
||||||
}
|
|
||||||
const Input* GetAuthorityInfoAccess() const
|
|
||||||
{
|
|
||||||
return MaybeInput(authorityInfoAccess);
|
return MaybeInput(authorityInfoAccess);
|
||||||
}
|
}
|
||||||
const Input* GetBasicConstraints() const
|
const Input* GetBasicConstraints() const {
|
||||||
{
|
|
||||||
return MaybeInput(basicConstraints);
|
return MaybeInput(basicConstraints);
|
||||||
}
|
}
|
||||||
const Input* GetCertificatePolicies() const
|
const Input* GetCertificatePolicies() const {
|
||||||
{
|
|
||||||
return MaybeInput(certificatePolicies);
|
return MaybeInput(certificatePolicies);
|
||||||
}
|
}
|
||||||
const Input* GetExtKeyUsage() const
|
const Input* GetExtKeyUsage() const { return MaybeInput(extKeyUsage); }
|
||||||
{
|
const Input* GetKeyUsage() const { return MaybeInput(keyUsage); }
|
||||||
return MaybeInput(extKeyUsage);
|
const Input* GetInhibitAnyPolicy() const {
|
||||||
}
|
|
||||||
const Input* GetKeyUsage() const
|
|
||||||
{
|
|
||||||
return MaybeInput(keyUsage);
|
|
||||||
}
|
|
||||||
const Input* GetInhibitAnyPolicy() const
|
|
||||||
{
|
|
||||||
return MaybeInput(inhibitAnyPolicy);
|
return MaybeInput(inhibitAnyPolicy);
|
||||||
}
|
}
|
||||||
const Input* GetNameConstraints() const
|
const Input* GetNameConstraints() const {
|
||||||
{
|
|
||||||
return MaybeInput(nameConstraints);
|
return MaybeInput(nameConstraints);
|
||||||
}
|
}
|
||||||
const Input* GetSubjectAltName() const
|
const Input* GetSubjectAltName() const { return MaybeInput(subjectAltName); }
|
||||||
{
|
const Input* GetRequiredTLSFeatures() const {
|
||||||
return MaybeInput(subjectAltName);
|
|
||||||
}
|
|
||||||
const Input* GetRequiredTLSFeatures() const
|
|
||||||
{
|
|
||||||
return MaybeInput(requiredTLSFeatures);
|
return MaybeInput(requiredTLSFeatures);
|
||||||
}
|
}
|
||||||
const Input* GetSignedCertificateTimestamps() const
|
const Input* GetSignedCertificateTimestamps() const {
|
||||||
{
|
|
||||||
return MaybeInput(signedCertificateTimestamps);
|
return MaybeInput(signedCertificateTimestamps);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Input der;
|
const Input der;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const EndEntityOrCA endEntityOrCA;
|
const EndEntityOrCA endEntityOrCA;
|
||||||
BackCert const* const childCert;
|
BackCert const* const childCert;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// When parsing certificates in BackCert::Init, we don't accept empty
|
// When parsing certificates in BackCert::Init, we don't accept empty
|
||||||
// extensions. Consequently, we don't have to store a distinction between
|
// extensions. Consequently, we don't have to store a distinction between
|
||||||
// empty extensions and extensions that weren't included. However, when
|
// empty extensions and extensions that weren't included. However, when
|
||||||
// *processing* extensions, we distinguish between whether an extension was
|
// *processing* extensions, we distinguish between whether an extension was
|
||||||
// included or not based on whetehr the GetXXX function for the extension
|
// included or not based on whetehr the GetXXX function for the extension
|
||||||
// returns nullptr.
|
// returns nullptr.
|
||||||
static inline const Input* MaybeInput(const Input& item)
|
static inline const Input* MaybeInput(const Input& item) {
|
||||||
{
|
|
||||||
return item.GetLength() > 0 ? &item : nullptr;
|
return item.GetLength() > 0 ? &item : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -161,25 +123,20 @@ private:
|
||||||
void operator=(const BackCert&) = delete;
|
void operator=(const BackCert&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NonOwningDERArray final : public DERArray
|
class NonOwningDERArray final : public DERArray {
|
||||||
{
|
public:
|
||||||
public:
|
NonOwningDERArray() : numItems(0) {
|
||||||
NonOwningDERArray()
|
|
||||||
: numItems(0)
|
|
||||||
{
|
|
||||||
// we don't need to initialize the items array because we always check
|
// we don't need to initialize the items array because we always check
|
||||||
// numItems before accessing i.
|
// numItems before accessing i.
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetLength() const override { return numItems; }
|
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;
|
return i < numItems ? &items[i] : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Append(Input der)
|
Result Append(Input der) {
|
||||||
{
|
|
||||||
if (numItems >= MAX_LENGTH) {
|
if (numItems >= MAX_LENGTH) {
|
||||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||||
}
|
}
|
||||||
|
|
@ -193,7 +150,8 @@ public:
|
||||||
|
|
||||||
// Public so we can static_assert on this. Keep in sync with MAX_SUBCA_COUNT.
|
// Public so we can static_assert on this. Keep in sync with MAX_SUBCA_COUNT.
|
||||||
static const size_t MAX_LENGTH = 8;
|
static const size_t MAX_LENGTH = 8;
|
||||||
private:
|
|
||||||
|
private:
|
||||||
Input items[MAX_LENGTH]; // avoids any heap allocations
|
Input items[MAX_LENGTH]; // avoids any heap allocations
|
||||||
size_t numItems;
|
size_t numItems;
|
||||||
|
|
||||||
|
|
@ -203,16 +161,13 @@ private:
|
||||||
|
|
||||||
// Extracts the SignedCertificateTimestampList structure which is encoded as an
|
// Extracts the SignedCertificateTimestampList structure which is encoded as an
|
||||||
// OCTET STRING within the X.509v3 / OCSP extensions (see RFC 6962 section 3.3).
|
// OCTET STRING within the X.509v3 / OCSP extensions (see RFC 6962 section 3.3).
|
||||||
Result
|
Result ExtractSignedCertificateTimestampListFromExtension(Input extnValue,
|
||||||
ExtractSignedCertificateTimestampListFromExtension(Input extnValue,
|
|
||||||
Input& sctList);
|
Input& sctList);
|
||||||
|
|
||||||
inline unsigned int
|
inline unsigned int DaysBeforeYear(unsigned int year) {
|
||||||
DaysBeforeYear(unsigned int year)
|
|
||||||
{
|
|
||||||
assert(year <= 9999);
|
assert(year <= 9999);
|
||||||
return ((year - 1u) * 365u)
|
return ((year - 1u) * 365u) +
|
||||||
+ ((year - 1u) / 4u) // leap years are every 4 years,
|
((year - 1u) / 4u) // leap years are every 4 years,
|
||||||
- ((year - 1u) / 100u) // except years divisible by 100,
|
- ((year - 1u) / 100u) // except years divisible by 100,
|
||||||
+ ((year - 1u) / 400u); // except years divisible by 400.
|
+ ((year - 1u) / 400u); // except years divisible by 400.
|
||||||
}
|
}
|
||||||
|
|
@ -221,7 +176,7 @@ static const size_t MAX_DIGEST_SIZE_IN_BYTES = 512 / 8; // sha-512
|
||||||
|
|
||||||
Result DigestSignedData(TrustDomain& trustDomain,
|
Result DigestSignedData(TrustDomain& trustDomain,
|
||||||
const der::SignedDataWithSignature& signedData,
|
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*/ der::PublicKeyAlgorithm& publicKeyAlg,
|
||||||
/*out*/ SignedDigest& signedDigest);
|
/*out*/ SignedDigest& signedDigest);
|
||||||
|
|
||||||
|
|
@ -237,8 +192,8 @@ Result VerifySignedData(TrustDomain& trustDomain,
|
||||||
|
|
||||||
// Extracts the key parameters from |subjectPublicKeyInfo|, invoking
|
// Extracts the key parameters from |subjectPublicKeyInfo|, invoking
|
||||||
// the relevant methods of |trustDomain|.
|
// the relevant methods of |trustDomain|.
|
||||||
Result
|
Result CheckSubjectPublicKeyInfo(Input subjectPublicKeyInfo,
|
||||||
CheckSubjectPublicKeyInfo(Input subjectPublicKeyInfo, TrustDomain& trustDomain,
|
TrustDomain& trustDomain,
|
||||||
EndEntityOrCA endEntityOrCA);
|
EndEntityOrCA endEntityOrCA);
|
||||||
|
|
||||||
// In a switch over an enum, sometimes some compilers are not satisfied that
|
// In a switch over an enum, sometimes some compilers are not satisfied that
|
||||||
|
|
@ -273,16 +228,20 @@ CheckSubjectPublicKeyInfo(Input subjectPublicKeyInfo, TrustDomain& trustDomain,
|
||||||
// GCC will warn if not all cases are covered (-Wswitch-enum). It does not
|
// GCC will warn if not all cases are covered (-Wswitch-enum). It does not
|
||||||
// assume that the default case is unreachable.
|
// assume that the default case is unreachable.
|
||||||
#define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM \
|
#define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM \
|
||||||
default: assert(false); __builtin_unreachable();
|
default: \
|
||||||
|
assert(false); \
|
||||||
|
__builtin_unreachable();
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
// MSVC will warn if not all cases are covered (C4061, level 4). It does not
|
// MSVC will warn if not all cases are covered (C4061, level 4). It does not
|
||||||
// assume that the default case is unreachable.
|
// assume that the default case is unreachable.
|
||||||
#define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM \
|
#define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM \
|
||||||
default: assert(false); __assume(0);
|
default: \
|
||||||
|
assert(false); \
|
||||||
|
__assume(0);
|
||||||
#else
|
#else
|
||||||
#error Unsupported compiler for MOZILLA_PKIX_UNREACHABLE_DEFAULT.
|
#error Unsupported compiler for MOZILLA_PKIX_UNREACHABLE_DEFAULT.
|
||||||
#endif
|
#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 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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 "pkix/pkix.h"
|
||||||
|
|
||||||
#include "pkixcheck.h"
|
#include "pkix/pkixcheck.h"
|
||||||
#include "pkixutil.h"
|
#include "pkix/pkixutil.h"
|
||||||
|
|
||||||
namespace mozilla { namespace pkix {
|
namespace mozilla { namespace pkix {
|
||||||
|
|
||||||
|
|
@ -35,7 +18,8 @@ static Result BuildForward(TrustDomain& trustDomain,
|
||||||
KeyPurposeId requiredEKUIfPresent,
|
KeyPurposeId requiredEKUIfPresent,
|
||||||
const CertPolicyId& requiredPolicy,
|
const CertPolicyId& requiredPolicy,
|
||||||
/*optional*/ const Input* stapledOCSPResponse,
|
/*optional*/ const Input* stapledOCSPResponse,
|
||||||
unsigned int subCACount);
|
unsigned int subCACount,
|
||||||
|
unsigned int& buildForwardCallBudget);
|
||||||
|
|
||||||
TrustDomain::IssuerChecker::IssuerChecker() { }
|
TrustDomain::IssuerChecker::IssuerChecker() { }
|
||||||
TrustDomain::IssuerChecker::~IssuerChecker() { }
|
TrustDomain::IssuerChecker::~IssuerChecker() { }
|
||||||
|
|
@ -45,21 +29,24 @@ TrustDomain::IssuerChecker::~IssuerChecker() { }
|
||||||
class PathBuildingStep final : public TrustDomain::IssuerChecker
|
class PathBuildingStep final : public TrustDomain::IssuerChecker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PathBuildingStep(TrustDomain& trustDomain, const BackCert& subject,
|
PathBuildingStep(TrustDomain& aTrustDomain, const BackCert& aSubject,
|
||||||
Time time, KeyPurposeId requiredEKUIfPresent,
|
Time aTime, KeyPurposeId aRequiredEKUIfPresent,
|
||||||
const CertPolicyId& requiredPolicy,
|
const CertPolicyId& aRequiredPolicy,
|
||||||
/*optional*/ const Input* stapledOCSPResponse,
|
/*optional*/ const Input* aStapledOCSPResponse,
|
||||||
unsigned int subCACount, Result deferredSubjectError)
|
unsigned int aSubCACount, Result aDeferredSubjectError,
|
||||||
: trustDomain(trustDomain)
|
unsigned int& aBuildForwardCallBudget)
|
||||||
, subject(subject)
|
: trustDomain(aTrustDomain)
|
||||||
, time(time)
|
, subject(aSubject)
|
||||||
, requiredEKUIfPresent(requiredEKUIfPresent)
|
, time(aTime)
|
||||||
, requiredPolicy(requiredPolicy)
|
, requiredEKUIfPresent(aRequiredEKUIfPresent)
|
||||||
, stapledOCSPResponse(stapledOCSPResponse)
|
, requiredPolicy(aRequiredPolicy)
|
||||||
, subCACount(subCACount)
|
, stapledOCSPResponse(aStapledOCSPResponse)
|
||||||
, deferredSubjectError(deferredSubjectError)
|
, subCACount(aSubCACount)
|
||||||
|
, deferredSubjectError(aDeferredSubjectError)
|
||||||
|
, subjectSignaturePublicKeyAlg(der::PublicKeyAlgorithm::Uninitialized)
|
||||||
, result(Result::FATAL_ERROR_LIBRARY_FAILURE)
|
, result(Result::FATAL_ERROR_LIBRARY_FAILURE)
|
||||||
, resultWasSet(false)
|
, resultWasSet(false)
|
||||||
|
, buildForwardCallBudget(aBuildForwardCallBudget)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,6 +74,7 @@ private:
|
||||||
Result RecordResult(Result currentResult, /*out*/ bool& keepGoing);
|
Result RecordResult(Result currentResult, /*out*/ bool& keepGoing);
|
||||||
Result result;
|
Result result;
|
||||||
bool resultWasSet;
|
bool resultWasSet;
|
||||||
|
unsigned int& buildForwardCallBudget;
|
||||||
|
|
||||||
PathBuildingStep(const PathBuildingStep&) = delete;
|
PathBuildingStep(const PathBuildingStep&) = delete;
|
||||||
void operator=(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
|
// Loop prevention, done as recommended by RFC4158 Section 5.2
|
||||||
// TODO: this doesn't account for subjectAltNames!
|
// TODO: this doesn't account for subjectAltNames!
|
||||||
// TODO(perf): This probably can and should be optimized in some way.
|
// TODO(perf): This probably can and should be optimized in some way.
|
||||||
bool loopDetected = false;
|
for (const BackCert* prev = potentialIssuer.childCert; prev;
|
||||||
for (const BackCert* prev = potentialIssuer.childCert;
|
prev = prev->childCert) {
|
||||||
!loopDetected && prev != nullptr; prev = prev->childCert) {
|
|
||||||
if (InputsAreEqual(potentialIssuer.GetSubjectPublicKeyInfo(),
|
if (InputsAreEqual(potentialIssuer.GetSubjectPublicKeyInfo(),
|
||||||
prev->GetSubjectPublicKeyInfo()) &&
|
prev->GetSubjectPublicKeyInfo()) &&
|
||||||
InputsAreEqual(potentialIssuer.GetSubject(), prev->GetSubject())) {
|
InputsAreEqual(potentialIssuer.GetSubject(), prev->GetSubject())) {
|
||||||
|
|
@ -192,11 +179,20 @@ PathBuildingStep::Check(Input potentialIssuerDER,
|
||||||
return RecordResult(rv, keepGoing);
|
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
|
// 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
|
// subject public key MUST NOT be used to verify signatures on certificates
|
||||||
// or CRLs unless the corresponding keyCertSign or cRLSign bit is set."
|
// or CRLs unless the corresponding keyCertSign or cRLSign bit is set."
|
||||||
rv = BuildForward(trustDomain, potentialIssuer, time, KeyUsage::keyCertSign,
|
rv = BuildForward(trustDomain, potentialIssuer, time, KeyUsage::keyCertSign,
|
||||||
requiredEKUIfPresent, requiredPolicy, nullptr, subCACount);
|
requiredEKUIfPresent, requiredPolicy, nullptr, subCACount,
|
||||||
|
buildForwardCallBudget);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return RecordResult(rv, keepGoing);
|
return RecordResult(rv, keepGoing);
|
||||||
}
|
}
|
||||||
|
|
@ -239,9 +235,15 @@ PathBuildingStep::Check(Input potentialIssuerDER,
|
||||||
Duration validityDuration(notAfter, notBefore);
|
Duration validityDuration(notAfter, notBefore);
|
||||||
rv = trustDomain.CheckRevocation(subject.endEntityOrCA, certID, time,
|
rv = trustDomain.CheckRevocation(subject.endEntityOrCA, certID, time,
|
||||||
validityDuration, stapledOCSPResponse,
|
validityDuration, stapledOCSPResponse,
|
||||||
subject.GetAuthorityInfoAccess());
|
subject.GetAuthorityInfoAccess(),
|
||||||
|
subject.GetSignedCertificateTimestamps());
|
||||||
if (rv != Success) {
|
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) {
|
if (subject.endEntityOrCA == EndEntityOrCA::MustBeEndEntity) {
|
||||||
|
|
@ -251,7 +253,11 @@ PathBuildingStep::Check(Input potentialIssuerDER,
|
||||||
rv = ExtractSignedCertificateTimestampListFromExtension(*sctExtension,
|
rv = ExtractSignedCertificateTimestampListFromExtension(*sctExtension,
|
||||||
sctList);
|
sctList);
|
||||||
if (rv != Success) {
|
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,
|
trustDomain.NoteAuxiliaryExtension(AuxiliaryExtension::EmbeddedSCTList,
|
||||||
sctList);
|
sctList);
|
||||||
|
|
@ -276,7 +282,8 @@ BuildForward(TrustDomain& trustDomain,
|
||||||
KeyPurposeId requiredEKUIfPresent,
|
KeyPurposeId requiredEKUIfPresent,
|
||||||
const CertPolicyId& requiredPolicy,
|
const CertPolicyId& requiredPolicy,
|
||||||
/*optional*/ const Input* stapledOCSPResponse,
|
/*optional*/ const Input* stapledOCSPResponse,
|
||||||
unsigned int subCACount)
|
unsigned int subCACount,
|
||||||
|
unsigned int& buildForwardCallBudget)
|
||||||
{
|
{
|
||||||
Result rv;
|
Result rv;
|
||||||
|
|
||||||
|
|
@ -311,7 +318,7 @@ BuildForward(TrustDomain& trustDomain,
|
||||||
|
|
||||||
// This must be done here, after the chain is built but before any
|
// This must be done here, after the chain is built but before any
|
||||||
// revocation checks have been done.
|
// revocation checks have been done.
|
||||||
return trustDomain.IsChainValid(chain, time);
|
return trustDomain.IsChainValid(chain, time, requiredPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subject.endEntityOrCA == EndEntityOrCA::MustBeCA) {
|
if (subject.endEntityOrCA == EndEntityOrCA::MustBeCA) {
|
||||||
|
|
@ -334,7 +341,7 @@ BuildForward(TrustDomain& trustDomain,
|
||||||
PathBuildingStep pathBuilder(trustDomain, subject, time,
|
PathBuildingStep pathBuilder(trustDomain, subject, time,
|
||||||
requiredEKUIfPresent, requiredPolicy,
|
requiredEKUIfPresent, requiredPolicy,
|
||||||
stapledOCSPResponse, subCACount,
|
stapledOCSPResponse, subCACount,
|
||||||
deferredEndEntityError);
|
deferredEndEntityError, buildForwardCallBudget);
|
||||||
|
|
||||||
// TODO(bug 965136): Add SKI/AKI matching optimizations
|
// TODO(bug 965136): Add SKI/AKI matching optimizations
|
||||||
rv = trustDomain.FindIssuer(subject.GetIssuer(), pathBuilder, time);
|
rv = trustDomain.FindIssuer(subject.GetIssuer(), pathBuilder, time);
|
||||||
|
|
@ -373,9 +380,22 @@ BuildCertChain(TrustDomain& trustDomain, Input certDER,
|
||||||
return rv;
|
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,
|
return BuildForward(trustDomain, cert, time, requiredKeyUsageIfPresent,
|
||||||
requiredEKUIfPresent, requiredPolicy, stapledOCSPResponse,
|
requiredEKUIfPresent, requiredPolicy, stapledOCSPResponse,
|
||||||
0/*subCACount*/);
|
0/*subCACount*/, buildForwardCallBudget);
|
||||||
}
|
}
|
||||||
|
|
||||||
} } // namespace mozilla::pkix
|
} } // namespace mozilla::pkix
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,10 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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 {
|
namespace mozilla { namespace pkix {
|
||||||
|
|
||||||
|
|
@ -151,7 +134,7 @@ BackCert::Init()
|
||||||
// SSL Client | false | id_kp_clientAuth
|
// SSL Client | false | id_kp_clientAuth
|
||||||
// S/MIME Client | false | id_kp_emailProtection
|
// S/MIME Client | false | id_kp_emailProtection
|
||||||
// Object Signing | false | id_kp_codeSigning
|
// 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
|
// SSL Client CA | true | id_kp_clientAuth
|
||||||
// S/MIME CA | true | id_kp_emailProtection
|
// S/MIME CA | true | id_kp_emailProtection
|
||||||
// Object Signing CA | true | id_kp_codeSigning
|
// Object Signing CA | true | id_kp_codeSigning
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,13 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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 "pkix/pkixder.h"
|
||||||
#include "pkixutil.h"
|
#include "pkix/pkixutil.h"
|
||||||
|
|
||||||
namespace mozilla { namespace pkix {
|
namespace mozilla { namespace pkix {
|
||||||
|
|
||||||
|
|
@ -116,7 +99,11 @@ CheckSignatureAlgorithm(TrustDomain& trustDomain,
|
||||||
// for any curve that we support, the chances of us encountering a curve
|
// for any curve that we support, the chances of us encountering a curve
|
||||||
// during path building is too low to be worth bothering with.
|
// during path building is too low to be worth bothering with.
|
||||||
break;
|
break;
|
||||||
|
case der::PublicKeyAlgorithm::Uninitialized:
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||||
|
}
|
||||||
MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
|
MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -338,15 +325,16 @@ CheckSubjectPublicKeyInfoContents(Reader& input, TrustDomain& trustDomain,
|
||||||
[&trustDomain, endEntityOrCA](Reader& r) {
|
[&trustDomain, endEntityOrCA](Reader& r) {
|
||||||
Input modulus;
|
Input modulus;
|
||||||
Input::size_type modulusSignificantBytes;
|
Input::size_type modulusSignificantBytes;
|
||||||
Result rv = der::PositiveInteger(r, modulus, &modulusSignificantBytes);
|
Result nestedRv =
|
||||||
if (rv != Success) {
|
der::PositiveInteger(r, modulus, &modulusSignificantBytes);
|
||||||
return rv;
|
if (nestedRv != Success) {
|
||||||
|
return nestedRv;
|
||||||
}
|
}
|
||||||
// XXX: Should we do additional checks of the modulus?
|
// XXX: Should we do additional checks of the modulus?
|
||||||
rv = trustDomain.CheckRSAPublicKeyModulusSizeInBits(
|
nestedRv = trustDomain.CheckRSAPublicKeyModulusSizeInBits(
|
||||||
endEntityOrCA, modulusSignificantBytes * 8u);
|
endEntityOrCA, modulusSignificantBytes * 8u);
|
||||||
if (rv != Success) {
|
if (nestedRv != Success) {
|
||||||
return rv;
|
return nestedRv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: We don't allow the TrustDomain to validate the exponent.
|
// 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);
|
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
|
// certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
|
||||||
Result
|
Result
|
||||||
CheckCertificatePolicies(EndEntityOrCA endEntityOrCA,
|
CheckCertificatePolicies(EndEntityOrCA endEntityOrCA,
|
||||||
|
|
@ -644,9 +639,9 @@ CheckBasicConstraints(EndEntityOrCA endEntityOrCA,
|
||||||
Reader input(*encodedBasicConstraints);
|
Reader input(*encodedBasicConstraints);
|
||||||
Result rv = der::Nested(input, der::SEQUENCE,
|
Result rv = der::Nested(input, der::SEQUENCE,
|
||||||
[&isCA, &pathLenConstraint](Reader& r) {
|
[&isCA, &pathLenConstraint](Reader& r) {
|
||||||
Result rv = der::OptionalBoolean(r, isCA);
|
Result nestedRv = der::OptionalBoolean(r, isCA);
|
||||||
if (rv != Success) {
|
if (nestedRv != Success) {
|
||||||
return rv;
|
return nestedRv;
|
||||||
}
|
}
|
||||||
// TODO(bug 985025): If isCA is false, pathLenConstraint
|
// TODO(bug 985025): If isCA is false, pathLenConstraint
|
||||||
// MUST NOT be included (as per RFC 5280 section
|
// 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 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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 "pkix/pkixder.h"
|
||||||
|
#include "pkix/pkixutil.h"
|
||||||
#include "pkixutil.h"
|
|
||||||
|
|
||||||
namespace mozilla { namespace pkix { namespace der {
|
namespace mozilla { namespace pkix { namespace der {
|
||||||
|
|
||||||
|
|
@ -212,7 +194,6 @@ SignatureAlgorithmIdentifierValue(Reader& input,
|
||||||
Result
|
Result
|
||||||
DigestAlgorithmIdentifier(Reader& input, /*out*/ DigestAlgorithm& algorithm)
|
DigestAlgorithmIdentifier(Reader& input, /*out*/ DigestAlgorithm& algorithm)
|
||||||
{
|
{
|
||||||
Reader r;
|
|
||||||
return der::Nested(input, SEQUENCE, [&algorithm](Reader& r) -> Result {
|
return der::Nested(input, SEQUENCE, [&algorithm](Reader& r) -> Result {
|
||||||
Reader algorithmID;
|
Reader algorithmID;
|
||||||
Result rv = AlgorithmIdentifierValue(r, algorithmID);
|
Result rv = AlgorithmIdentifierValue(r, algorithmID);
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,8 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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
|
// This code implements RFC6125-ish name matching, RFC5280-ish name constraint
|
||||||
// checking, and related things.
|
// checking, and related things.
|
||||||
|
|
@ -33,8 +16,10 @@
|
||||||
// constraints, the reference identifier is the entire encoded name constraint
|
// constraints, the reference identifier is the entire encoded name constraint
|
||||||
// extension value.
|
// extension value.
|
||||||
|
|
||||||
#include "pkixcheck.h"
|
#include <algorithm>
|
||||||
#include "pkixutil.h"
|
|
||||||
|
#include "pkix/pkixcheck.h"
|
||||||
|
#include "pkix/pkixutil.h"
|
||||||
|
|
||||||
namespace mozilla { namespace pkix {
|
namespace mozilla { namespace pkix {
|
||||||
|
|
||||||
|
|
@ -1607,12 +1592,12 @@ StartsWithIDNALabel(Input id)
|
||||||
{
|
{
|
||||||
static const uint8_t IDN_ALABEL_PREFIX[4] = { 'x', 'n', '-', '-' };
|
static const uint8_t IDN_ALABEL_PREFIX[4] = { 'x', 'n', '-', '-' };
|
||||||
Reader input(id);
|
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;
|
uint8_t b;
|
||||||
if (input.Read(b) != Success) {
|
if (input.Read(b) != Success) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (b != IDN_ALABEL_PREFIX[i]) {
|
if (b != prefixByte) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1704,11 +1689,9 @@ FinishIPv6Address(/*in/out*/ uint8_t (&address)[16], int numComponents,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shift components that occur after the contraction over.
|
// Shift components that occur after the contraction over.
|
||||||
size_t componentsToMove = static_cast<size_t>(numComponents -
|
std::copy_backward(address + (2u * static_cast<size_t>(contractionIndex)),
|
||||||
contractionIndex);
|
address + (2u * static_cast<size_t>(numComponents)),
|
||||||
memmove(address + (2u * static_cast<size_t>(8 - componentsToMove)),
|
address + (2u * 8u));
|
||||||
address + (2u * static_cast<size_t>(contractionIndex)),
|
|
||||||
componentsToMove * 2u);
|
|
||||||
// Fill in the contracted area with zeros.
|
// Fill in the contracted area with zeros.
|
||||||
std::fill_n(address + 2u * static_cast<size_t>(contractionIndex),
|
std::fill_n(address + 2u * static_cast<size_t>(contractionIndex),
|
||||||
(8u - static_cast<size_t>(numComponents)) * 2u, static_cast<uint8_t>(0u));
|
(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 -*- */
|
/*- *- 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
|
/* 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
|
* 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/.
|
* 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"
|
#include "pkix/pkixnss.h"
|
||||||
|
|
||||||
|
|
@ -28,9 +11,9 @@
|
||||||
#include "cryptohi.h"
|
#include "cryptohi.h"
|
||||||
#include "keyhi.h"
|
#include "keyhi.h"
|
||||||
#include "pk11pub.h"
|
#include "pk11pub.h"
|
||||||
|
#include "nss_scoped_ptrs.h"
|
||||||
#include "pkix/pkix.h"
|
#include "pkix/pkix.h"
|
||||||
#include "pkixutil.h"
|
#include "pkix/pkixutil.h"
|
||||||
#include "ScopedPtr.h"
|
|
||||||
#include "secerr.h"
|
#include "secerr.h"
|
||||||
#include "sslerr.h"
|
#include "sslerr.h"
|
||||||
|
|
||||||
|
|
@ -55,12 +38,12 @@ VerifySignedDigest(const SignedDigest& sd,
|
||||||
|
|
||||||
SECItem subjectPublicKeyInfoSECItem =
|
SECItem subjectPublicKeyInfoSECItem =
|
||||||
UnsafeMapInputToSECItem(subjectPublicKeyInfo);
|
UnsafeMapInputToSECItem(subjectPublicKeyInfo);
|
||||||
ScopedPtr<CERTSubjectPublicKeyInfo, SECKEY_DestroySubjectPublicKeyInfo>
|
ScopedCERTSubjectPublicKeyInfo
|
||||||
spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&subjectPublicKeyInfoSECItem));
|
spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&subjectPublicKeyInfoSECItem));
|
||||||
if (!spki) {
|
if (!spki) {
|
||||||
return MapPRErrorCodeToResult(PR_GetError());
|
return MapPRErrorCodeToResult(PR_GetError());
|
||||||
}
|
}
|
||||||
ScopedPtr<SECKEYPublicKey, SECKEY_DestroyPublicKey>
|
ScopedSECKEYPublicKey
|
||||||
pubKey(SECKEY_ExtractPublicKey(spki.get()));
|
pubKey(SECKEY_ExtractPublicKey(spki.get()));
|
||||||
if (!pubKey) {
|
if (!pubKey) {
|
||||||
return MapPRErrorCodeToResult(PR_GetError());
|
return MapPRErrorCodeToResult(PR_GetError());
|
||||||
|
|
@ -210,6 +193,14 @@ RegisterErrorTable()
|
||||||
{ "MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME",
|
{ "MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME",
|
||||||
"The server presented a certificate with an empty issuer distinguished "
|
"The server presented a certificate with an empty issuer distinguished "
|
||||||
"name." },
|
"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.
|
// Note that these error strings are not localizable.
|
||||||
// When these strings change, update the localization information too.
|
// 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 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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 <limits>
|
||||||
|
|
||||||
#include "pkix/pkix.h"
|
#include "pkix/pkix.h"
|
||||||
#include "pkixcheck.h"
|
#include "pkix/pkixcheck.h"
|
||||||
#include "pkixutil.h"
|
#include "pkix/pkixutil.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
|
@ -45,16 +28,16 @@ enum class CertStatus : uint8_t {
|
||||||
class Context final
|
class Context final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Context(TrustDomain& trustDomain, const CertID& certID, Time time,
|
Context(TrustDomain& aTrustDomain, const CertID& aCertID, Time aTime,
|
||||||
uint16_t maxLifetimeInDays, /*optional out*/ Time* thisUpdate,
|
uint16_t aMaxLifetimeInDays, /*optional out*/ Time* aThisUpdate,
|
||||||
/*optional out*/ Time* validThrough)
|
/*optional out*/ Time* aValidThrough)
|
||||||
: trustDomain(trustDomain)
|
: trustDomain(aTrustDomain)
|
||||||
, certID(certID)
|
, certID(aCertID)
|
||||||
, time(time)
|
, time(aTime)
|
||||||
, maxLifetimeInDays(maxLifetimeInDays)
|
, maxLifetimeInDays(aMaxLifetimeInDays)
|
||||||
, certStatus(CertStatus::Unknown)
|
, certStatus(CertStatus::Unknown)
|
||||||
, thisUpdate(thisUpdate)
|
, thisUpdate(aThisUpdate)
|
||||||
, validThrough(validThrough)
|
, validThrough(aValidThrough)
|
||||||
, expired(false)
|
, expired(false)
|
||||||
, matchFound(false)
|
, matchFound(false)
|
||||||
{
|
{
|
||||||
|
|
@ -172,7 +155,11 @@ static Result ExtensionNotUnderstood(Reader& extnID, Input extnValue,
|
||||||
static Result RememberSingleExtension(Context& context, Reader& extnID,
|
static Result RememberSingleExtension(Context& context, Reader& extnID,
|
||||||
Input extnValue, bool critical,
|
Input extnValue, bool critical,
|
||||||
/*out*/ bool& understood);
|
/*out*/ bool& understood);
|
||||||
static inline Result CertID(Reader& input,
|
// 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,
|
const Context& context,
|
||||||
/*out*/ bool& match);
|
/*out*/ bool& match);
|
||||||
static Result MatchKeyHash(TrustDomain& trustDomain,
|
static Result MatchKeyHash(TrustDomain& trustDomain,
|
||||||
|
|
@ -437,12 +424,13 @@ BasicResponse(Reader& input, Context& context)
|
||||||
der::SEQUENCE, [&certs](Reader& certsDER) -> Result {
|
der::SEQUENCE, [&certs](Reader& certsDER) -> Result {
|
||||||
while (!certsDER.AtEnd()) {
|
while (!certsDER.AtEnd()) {
|
||||||
Input cert;
|
Input cert;
|
||||||
Result rv = der::ExpectTagAndGetTLV(certsDER, der::SEQUENCE, cert);
|
Result nestedRv =
|
||||||
if (rv != Success) {
|
der::ExpectTagAndGetTLV(certsDER, der::SEQUENCE, cert);
|
||||||
return rv;
|
if (nestedRv != Success) {
|
||||||
|
return nestedRv;
|
||||||
}
|
}
|
||||||
rv = certs.Append(cert);
|
nestedRv = certs.Append(cert);
|
||||||
if (rv != Success) {
|
if (nestedRv != Success) {
|
||||||
return Result::ERROR_BAD_DER; // Too many certs
|
return Result::ERROR_BAD_DER; // Too many certs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -537,7 +525,7 @@ SingleResponse(Reader& input, Context& context)
|
||||||
{
|
{
|
||||||
bool match = false;
|
bool match = false;
|
||||||
Result rv = der::Nested(input, der::SEQUENCE, [&context, &match](Reader& r) {
|
Result rv = der::Nested(input, der::SEQUENCE, [&context, &match](Reader& r) {
|
||||||
return CertID(r, context, match);
|
return MatchCertID(r, context, match);
|
||||||
});
|
});
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return rv;
|
return rv;
|
||||||
|
|
@ -694,7 +682,7 @@ SingleResponse(Reader& input, Context& context)
|
||||||
// issuerKeyHash OCTET STRING, -- Hash of issuer's public key
|
// issuerKeyHash OCTET STRING, -- Hash of issuer's public key
|
||||||
// serialNumber CertificateSerialNumber }
|
// serialNumber CertificateSerialNumber }
|
||||||
static inline Result
|
static inline Result
|
||||||
CertID(Reader& input, const Context& context, /*out*/ bool& match)
|
MatchCertID(Reader& input, const Context& context, /*out*/ bool& match)
|
||||||
{
|
{
|
||||||
match = false;
|
match = false;
|
||||||
|
|
||||||
|
|
@ -963,8 +951,8 @@ CreateEncodedOCSPRequest(TrustDomain& trustDomain, const struct CertID& certID,
|
||||||
*d++ = 0x30; *d++ = totalLen - 10u; // reqCert (CertID SEQUENCE)
|
*d++ = 0x30; *d++ = totalLen - 10u; // reqCert (CertID SEQUENCE)
|
||||||
|
|
||||||
// reqCert.hashAlgorithm
|
// reqCert.hashAlgorithm
|
||||||
for (size_t i = 0; i < sizeof(hashAlgorithm); ++i) {
|
for (const uint8_t hashAlgorithmByte : hashAlgorithm) {
|
||||||
*d++ = hashAlgorithm[i];
|
*d++ = hashAlgorithmByte;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reqCert.issuerNameHash (OCTET STRING)
|
// reqCert.issuerNameHash (OCTET STRING)
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,11 @@
|
||||||
/*- *- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/*- *- 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
|
/* 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
|
* 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/.
|
* 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 "pkix/Result.h"
|
||||||
#include "pkixutil.h"
|
#include "pkix/pkixutil.h"
|
||||||
|
|
||||||
namespace mozilla { namespace pkix {
|
namespace mozilla { namespace pkix {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,13 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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 "pkix/Time.h"
|
||||||
#include "pkixutil.h"
|
#include "pkix/pkixutil.h"
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef _WINDOWS
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(push, 3)
|
#pragma warning(push, 3)
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -43,7 +26,7 @@ Now()
|
||||||
{
|
{
|
||||||
uint64_t seconds;
|
uint64_t seconds;
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef _WINDOWS
|
||||||
// "Contains a 64-bit value representing the number of 100-nanosecond
|
// "Contains a 64-bit value representing the number of 100-nanosecond
|
||||||
// intervals since January 1, 1601 (UTC)."
|
// intervals since January 1, 1601 (UTC)."
|
||||||
// - http://msdn.microsoft.com/en-us/library/windows/desktop/ms724284(v=vs.85).aspx
|
// - 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 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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 {
|
namespace mozilla { namespace pkix {
|
||||||
|
|
||||||
|
|
@ -78,6 +61,9 @@ VerifySignedDigest(TrustDomain& trustDomain,
|
||||||
case der::PublicKeyAlgorithm::RSA_PKCS1:
|
case der::PublicKeyAlgorithm::RSA_PKCS1:
|
||||||
return trustDomain.VerifyRSAPKCS1SignedDigest(signedDigest,
|
return trustDomain.VerifyRSAPKCS1SignedDigest(signedDigest,
|
||||||
signerSubjectPublicKeyInfo);
|
signerSubjectPublicKeyInfo);
|
||||||
|
case der::PublicKeyAlgorithm::Uninitialized:
|
||||||
|
assert(false);
|
||||||
|
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||||
MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
|
MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ SOURCES += [
|
||||||
]
|
]
|
||||||
|
|
||||||
LOCAL_INCLUDES += [
|
LOCAL_INCLUDES += [
|
||||||
|
'../nss/cpputil',
|
||||||
'include',
|
'include',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,13 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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
|
// python DottedOIDToCode.py --prefixdefine PREFIX_1_2_840_10040 1.2.840.10040
|
||||||
#define PREFIX_1_2_840_10040 0x2a, 0x86, 0x48, 0xce, 0x38
|
#define PREFIX_1_2_840_10040 0x2a, 0x86, 0x48, 0xce, 0x38
|
||||||
|
|
@ -136,14 +120,14 @@ static const uint8_t DSS_G_RAW[] =
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TestSignatureAlgorithm::TestSignatureAlgorithm(
|
TestSignatureAlgorithm::TestSignatureAlgorithm(
|
||||||
const TestPublicKeyAlgorithm& publicKeyAlg,
|
const TestPublicKeyAlgorithm& aPublicKeyAlg,
|
||||||
TestDigestAlgorithmID digestAlg,
|
TestDigestAlgorithmID aDigestAlg,
|
||||||
const ByteString& algorithmIdentifier,
|
const ByteString& aAlgorithmIdentifier,
|
||||||
bool accepted)
|
bool aAccepted)
|
||||||
: publicKeyAlg(publicKeyAlg)
|
: publicKeyAlg(aPublicKeyAlg)
|
||||||
, digestAlg(digestAlg)
|
, digestAlg(aDigestAlg)
|
||||||
, algorithmIdentifier(algorithmIdentifier)
|
, algorithmIdentifier(aAlgorithmIdentifier)
|
||||||
, accepted(accepted)
|
, accepted(aAccepted)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,11 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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>
|
#include <limits>
|
||||||
|
|
||||||
|
|
@ -30,9 +14,10 @@
|
||||||
#include "nss.h"
|
#include "nss.h"
|
||||||
#include "pk11pqg.h"
|
#include "pk11pqg.h"
|
||||||
#include "pk11pub.h"
|
#include "pk11pub.h"
|
||||||
|
#include "nss_scoped_ptrs.h"
|
||||||
#include "pkix/pkixnss.h"
|
#include "pkix/pkixnss.h"
|
||||||
#include "pkixder.h"
|
#include "pkix/pkixder.h"
|
||||||
#include "pkixutil.h"
|
#include "pkix/pkixutil.h"
|
||||||
#include "prinit.h"
|
#include "prinit.h"
|
||||||
#include "secerr.h"
|
#include "secerr.h"
|
||||||
#include "secitem.h"
|
#include "secitem.h"
|
||||||
|
|
@ -41,19 +26,6 @@ namespace mozilla { namespace pkix { namespace test {
|
||||||
|
|
||||||
namespace {
|
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();
|
TestKeyPair* GenerateKeyPairInner();
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -77,12 +49,15 @@ InitReusedKeyPair()
|
||||||
class NSSTestKeyPair final : public TestKeyPair
|
class NSSTestKeyPair final : public TestKeyPair
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// NSSTestKeyPair takes ownership of privateKey.
|
NSSTestKeyPair(const TestPublicKeyAlgorithm& aPublicKeyAlg,
|
||||||
NSSTestKeyPair(const TestPublicKeyAlgorithm& publicKeyAlg,
|
|
||||||
const ByteString& spk,
|
const ByteString& spk,
|
||||||
SECKEYPrivateKey* privateKey)
|
const ByteString& aEncryptedPrivateKey,
|
||||||
: TestKeyPair(publicKeyAlg, spk)
|
const ByteString& aEncryptionAlgorithm,
|
||||||
, privateKey(privateKey)
|
const ByteString& aEncryptionParams)
|
||||||
|
: TestKeyPair(aPublicKeyAlg, spk)
|
||||||
|
, encryptedPrivateKey(aEncryptedPrivateKey)
|
||||||
|
, encryptionAlgorithm(aEncryptionAlgorithm)
|
||||||
|
, encryptionParams(aEncryptionParams)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,10 +95,50 @@ public:
|
||||||
abort();
|
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;
|
SECItem signatureItem;
|
||||||
if (SEC_SignData(&signatureItem, tbs.data(),
|
if (SEC_SignData(&signatureItem, tbs.data(),
|
||||||
static_cast<int>(tbs.length()),
|
static_cast<int>(tbs.length()),
|
||||||
privateKey.get(), oidTag) != SECSuccess) {
|
scopedPrivateKey.get(), oidTag) != SECSuccess) {
|
||||||
return MapPRErrorCodeToResult(PR_GetError());
|
return MapPRErrorCodeToResult(PR_GetError());
|
||||||
}
|
}
|
||||||
signature.assign(signatureItem.data, signatureItem.len);
|
signature.assign(signatureItem.data, signatureItem.len);
|
||||||
|
|
@ -133,40 +148,63 @@ public:
|
||||||
|
|
||||||
TestKeyPair* Clone() const override
|
TestKeyPair* Clone() const override
|
||||||
{
|
{
|
||||||
ScopedSECKEYPrivateKey
|
|
||||||
privateKeyCopy(SECKEY_CopyPrivateKey(privateKey.get()));
|
|
||||||
if (!privateKeyCopy) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return new (std::nothrow) NSSTestKeyPair(publicKeyAlg,
|
return new (std::nothrow) NSSTestKeyPair(publicKeyAlg,
|
||||||
subjectPublicKey,
|
subjectPublicKey,
|
||||||
privateKeyCopy.release());
|
encryptedPrivateKey,
|
||||||
|
encryptionAlgorithm,
|
||||||
|
encryptionParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ScopedSECKEYPrivateKey privateKey;
|
const ByteString encryptedPrivateKey;
|
||||||
|
const ByteString encryptionAlgorithm;
|
||||||
|
const ByteString encryptionParams;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// This private function is also used by Gecko's PSM test framework
|
// This private function is also used by Gecko's PSM test framework
|
||||||
// (OCSPCommon.cpp).
|
// (OCSPCommon.cpp).
|
||||||
//
|
|
||||||
// Ownership of privateKey is transfered.
|
|
||||||
TestKeyPair* CreateTestKeyPair(const TestPublicKeyAlgorithm publicKeyAlg,
|
TestKeyPair* CreateTestKeyPair(const TestPublicKeyAlgorithm publicKeyAlg,
|
||||||
const SECKEYPublicKey& publicKey,
|
const ScopedSECKEYPublicKey& publicKey,
|
||||||
SECKEYPrivateKey* privateKey)
|
const ScopedSECKEYPrivateKey& privateKey)
|
||||||
{
|
{
|
||||||
ScopedPtr<CERTSubjectPublicKeyInfo, SECKEY_DestroySubjectPublicKeyInfo>
|
ScopedCERTSubjectPublicKeyInfo
|
||||||
spki(SECKEY_CreateSubjectPublicKeyInfo(&publicKey));
|
spki(SECKEY_CreateSubjectPublicKeyInfo(publicKey.get()));
|
||||||
if (!spki) {
|
if (!spki) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
SECItem spkDER = spki->subjectPublicKey;
|
SECItem spkDER = spki->subjectPublicKey;
|
||||||
DER_ConvertBitString(&spkDER); // bits to bytes
|
DER_ConvertBitString(&spkDER); // bits to bytes
|
||||||
return new (std::nothrow) NSSTestKeyPair(publicKeyAlg,
|
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(spkDER.data, spkDER.len),
|
||||||
privateKey);
|
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 {
|
namespace {
|
||||||
|
|
@ -174,18 +212,18 @@ namespace {
|
||||||
TestKeyPair*
|
TestKeyPair*
|
||||||
GenerateKeyPairInner()
|
GenerateKeyPairInner()
|
||||||
{
|
{
|
||||||
ScopedPtr<PK11SlotInfo, PK11_FreeSlot> slot(PK11_GetInternalSlot());
|
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
|
||||||
if (!slot) {
|
if (!slot) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
PK11RSAGenParams params;
|
||||||
|
params.keySizeInBits = 2048;
|
||||||
|
params.pe = 65537;
|
||||||
|
|
||||||
// Bug 1012786: PK11_GenerateKeyPair can fail if there is insufficient
|
// Bug 1012786: PK11_GenerateKeyPair can fail if there is insufficient
|
||||||
// entropy to generate a random key. Attempting to add some entropy and
|
// entropy to generate a random key. Attempting to add some entropy and
|
||||||
// retrying appears to solve this issue.
|
// retrying appears to solve this issue.
|
||||||
for (uint32_t retries = 0; retries < 10; retries++) {
|
for (uint32_t retries = 0; retries < 10; retries++) {
|
||||||
PK11RSAGenParams params;
|
|
||||||
params.keySizeInBits = 2048;
|
|
||||||
params.pe = 3;
|
|
||||||
SECKEYPublicKey* publicKeyTemp = nullptr;
|
SECKEYPublicKey* publicKeyTemp = nullptr;
|
||||||
ScopedSECKEYPrivateKey
|
ScopedSECKEYPrivateKey
|
||||||
privateKey(PK11_GenerateKeyPair(slot.get(), CKM_RSA_PKCS_KEY_PAIR_GEN,
|
privateKey(PK11_GenerateKeyPair(slot.get(), CKM_RSA_PKCS_KEY_PAIR_GEN,
|
||||||
|
|
@ -193,7 +231,7 @@ GenerateKeyPairInner()
|
||||||
nullptr));
|
nullptr));
|
||||||
ScopedSECKEYPublicKey publicKey(publicKeyTemp);
|
ScopedSECKEYPublicKey publicKey(publicKeyTemp);
|
||||||
if (privateKey) {
|
if (privateKey) {
|
||||||
return CreateTestKeyPair(RSA_PKCS1(), *publicKey, privateKey.release());
|
return CreateTestKeyPair(RSA_PKCS1(), publicKey, privateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!publicKeyTemp);
|
assert(!publicKeyTemp);
|
||||||
|
|
@ -206,7 +244,8 @@ GenerateKeyPairInner()
|
||||||
// random keys.
|
// random keys.
|
||||||
// https://xkcd.com/221/
|
// https://xkcd.com/221/
|
||||||
static const uint8_t RANDOM_NUMBER[] = { 4, 4, 4, 4, 4, 4, 4, 4 };
|
static const uint8_t RANDOM_NUMBER[] = { 4, 4, 4, 4, 4, 4, 4, 4 };
|
||||||
if (PK11_RandomUpdate((void*) &RANDOM_NUMBER,
|
if (PK11_RandomUpdate(
|
||||||
|
const_cast<void*>(reinterpret_cast<const void*>(RANDOM_NUMBER)),
|
||||||
sizeof(RANDOM_NUMBER)) != SECSuccess) {
|
sizeof(RANDOM_NUMBER)) != SECSuccess) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -240,7 +279,7 @@ GenerateDSSKeyPair()
|
||||||
{
|
{
|
||||||
InitNSSIfNeeded();
|
InitNSSIfNeeded();
|
||||||
|
|
||||||
ScopedPtr<PK11SlotInfo, PK11_FreeSlot> slot(PK11_GetInternalSlot());
|
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
|
||||||
if (!slot) {
|
if (!slot) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -274,7 +313,7 @@ GenerateDSSKeyPair()
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
ScopedSECKEYPublicKey publicKey(publicKeyTemp);
|
ScopedSECKEYPublicKey publicKey(publicKeyTemp);
|
||||||
return CreateTestKeyPair(DSS(), *publicKey, privateKey.release());
|
return CreateTestKeyPair(DSS(), publicKey, privateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result
|
Result
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,10 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- 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
|
/* 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
|
* 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/.
|
* 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 <cerrno>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
@ -30,8 +13,8 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#include "pkixder.h"
|
#include "pkix/pkixder.h"
|
||||||
#include "pkixutil.h"
|
#include "pkix/pkixutil.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
@ -39,12 +22,14 @@ namespace mozilla { namespace pkix { namespace test {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
inline void
|
struct ScopedMaybeDeleteFile {
|
||||||
fclose_void(FILE* file) {
|
void operator()(FILE* f) {
|
||||||
(void) fclose(file);
|
if (f) {
|
||||||
}
|
(void)fclose(f);
|
||||||
|
}
|
||||||
typedef mozilla::pkix::ScopedPtr<FILE, fclose_void> ScopedFILE;
|
}
|
||||||
|
};
|
||||||
|
typedef std::unique_ptr<FILE, ScopedMaybeDeleteFile> ScopedFILE;
|
||||||
|
|
||||||
FILE*
|
FILE*
|
||||||
OpenFile(const string& dir, const string& filename, const string& mode)
|
OpenFile(const string& dir, const string& filename, const string& mode)
|
||||||
|
|
@ -151,8 +136,8 @@ OCSPResponseExtension::OCSPResponseExtension()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
OCSPResponseContext::OCSPResponseContext(const CertID& certID, time_t time)
|
OCSPResponseContext::OCSPResponseContext(const CertID& aCertID, time_t time)
|
||||||
: certID(certID)
|
: certID(aCertID)
|
||||||
, responseStatus(successful)
|
, responseStatus(successful)
|
||||||
, skipResponseBytes(false)
|
, skipResponseBytes(false)
|
||||||
, producedAt(time)
|
, producedAt(time)
|
||||||
|
|
@ -248,7 +233,7 @@ Integer(long value)
|
||||||
enum TimeEncoding { UTCTime = 0, GeneralizedTime = 1 };
|
enum TimeEncoding { UTCTime = 0, GeneralizedTime = 1 };
|
||||||
|
|
||||||
// Windows doesn't provide gmtime_r, but it provides something very similar.
|
// 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*
|
static tm*
|
||||||
gmtime_r(const time_t* t, /*out*/ tm* exploded)
|
gmtime_r(const time_t* t, /*out*/ tm* exploded)
|
||||||
{
|
{
|
||||||
|
|
@ -738,7 +723,7 @@ CreateEncodedSerialNumber(long serialNumberValue)
|
||||||
// pathLenConstraint INTEGER (0..MAX) OPTIONAL }
|
// pathLenConstraint INTEGER (0..MAX) OPTIONAL }
|
||||||
ByteString
|
ByteString
|
||||||
CreateEncodedBasicConstraints(bool isCA,
|
CreateEncodedBasicConstraints(bool isCA,
|
||||||
/*optional*/ long* pathLenConstraintValue,
|
/*optional in*/ const long* pathLenConstraintValue,
|
||||||
Critical critical)
|
Critical critical)
|
||||||
{
|
{
|
||||||
ByteString value;
|
ByteString value;
|
||||||
|
|
@ -1139,11 +1124,11 @@ CertStatus(OCSPResponseContext& context)
|
||||||
static const ByteString NO_UNUSED_BITS(1, 0x00);
|
static const ByteString NO_UNUSED_BITS(1, 0x00);
|
||||||
|
|
||||||
// The SubjectPublicKeyInfo syntax is specified in RFC 5280 Section 4.1.
|
// The SubjectPublicKeyInfo syntax is specified in RFC 5280 Section 4.1.
|
||||||
TestKeyPair::TestKeyPair(const TestPublicKeyAlgorithm& publicKeyAlg,
|
TestKeyPair::TestKeyPair(const TestPublicKeyAlgorithm& aPublicKeyAlg,
|
||||||
const ByteString& spk)
|
const ByteString& spk)
|
||||||
: publicKeyAlg(publicKeyAlg)
|
: publicKeyAlg(aPublicKeyAlg)
|
||||||
, subjectPublicKeyInfo(TLV(der::SEQUENCE,
|
, subjectPublicKeyInfo(TLV(der::SEQUENCE,
|
||||||
publicKeyAlg.algorithmIdentifier +
|
aPublicKeyAlg.algorithmIdentifier +
|
||||||
TLV(der::BIT_STRING, NO_UNUSED_BITS + spk)))
|
TLV(der::BIT_STRING, NO_UNUSED_BITS + spk)))
|
||||||
, subjectPublicKey(spk)
|
, subjectPublicKey(spk)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import argparse
|
||||||
import itertools
|
import itertools
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
def base128(value):
|
def base128(value):
|
||||||
"""
|
"""
|
||||||
Given an integral value, returns an array of the base-128 representation
|
Given an integral value, returns an array of the base-128 representation
|
||||||
|
|
@ -50,6 +51,7 @@ def base128(value):
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def dottedOIDToEncodedArray(dottedOID):
|
def dottedOIDToEncodedArray(dottedOID):
|
||||||
"""
|
"""
|
||||||
Takes a dotted OID string (e.g. '1.2.840.10045.4.3.4') as input, and
|
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:]]
|
restBase128 = [base128(x) for x in nodes[2:]]
|
||||||
return [firstByte] + list(itertools.chain.from_iterable(restBase128))
|
return [firstByte] + list(itertools.chain.from_iterable(restBase128))
|
||||||
|
|
||||||
|
|
||||||
def dottedOIDToCArray(dottedOID, mode):
|
def dottedOIDToCArray(dottedOID, mode):
|
||||||
"""
|
"""
|
||||||
Takes a dotted OID string (e.g. '1.2.840.10045.4.3.4') as input, and
|
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])
|
return ", ".join(["0x%.2x" % b for b in bytes])
|
||||||
|
|
||||||
|
|
||||||
def specNameToCName(specName):
|
def specNameToCName(specName):
|
||||||
"""
|
"""
|
||||||
Given an string containing an ASN.1 name, returns a string that is a valid
|
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("-", "_")
|
return specName.replace("-", "_")
|
||||||
|
|
||||||
|
|
||||||
def toCode(programName, specName, dottedOID, mode):
|
def toCode(programName, specName, dottedOID, mode):
|
||||||
"""
|
"""
|
||||||
Given an ASN.1 name and a string containing the dotted representation of an
|
Given an ASN.1 name and a string containing the dotted representation of an
|
||||||
|
|
@ -180,6 +185,7 @@ def toCode(programName, specName, dottedOID, mode):
|
||||||
" };\n") % (programNameWithOptions, specName, dottedOID, varName,
|
" };\n") % (programNameWithOptions, specName, dottedOID, varName,
|
||||||
dottedOIDToCArray(dottedOID, mode))
|
dottedOIDToCArray(dottedOID, mode))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="Generate code snippets to handle OIDs in C++",
|
description="Generate code snippets to handle OIDs in C++",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue