Bug 1006041: Use mozilla::pkix::der for decoding the extended key usage extension, r=keeler

--HG--
extra : rebase_source : b4b62f117d653784eb6ad058554faf520a1bd90b
This commit is contained in:
Brian Smith 2014-05-14 01:02:34 -07:00
parent f9a6cb7aca
commit ac79ecb683
12 changed files with 282 additions and 82 deletions

View File

@ -605,8 +605,8 @@ VerifySignature(AppTrustedRoot trustedRoot,
}
if (BuildCertChain(trustDomain, signerCert, PR_Now(),
EndEntityOrCA::MustBeEndEntity, KU_DIGITAL_SIGNATURE,
SEC_OID_EXT_KEY_USAGE_CODE_SIGN,
SEC_OID_X509_ANY_POLICY, nullptr, builtChain)
KeyPurposeId::id_kp_codeSigning, SEC_OID_X509_ANY_POLICY,
nullptr, builtChain)
!= SECSuccess) {
return MapSECStatus(SECFailure);
}

View File

@ -300,7 +300,7 @@ destroyCertListThatShouldNotExist(CERTCertList** certChain)
static SECStatus
BuildCertChainForOneKeyUsage(TrustDomain& trustDomain, CERTCertificate* cert,
PRTime time, KeyUsages ku1, KeyUsages ku2,
KeyUsages ku3, SECOidTag eku,
KeyUsages ku3, KeyPurposeId eku,
SECOidTag requiredPolicy,
const SECItem* stapledOCSPResponse,
ScopedCERTCertList& builtChain)
@ -391,9 +391,9 @@ CertVerifier::MozillaPKIXVerifyCert(
pinArg);
rv = BuildCertChain(trustDomain, cert, time,
EndEntityOrCA::MustBeEndEntity, KU_DIGITAL_SIGNATURE,
SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH,
SEC_OID_X509_ANY_POLICY,
stapledOCSPResponse, builtChain);
KeyPurposeId::id_kp_clientAuth,
SEC_OID_X509_ANY_POLICY, stapledOCSPResponse,
builtChain);
break;
}
@ -417,7 +417,7 @@ CertVerifier::MozillaPKIXVerifyCert(
KU_DIGITAL_SIGNATURE, // ECDHE/DHE
KU_KEY_ENCIPHERMENT, // RSA
KU_KEY_AGREEMENT, // ECDH/DH
SEC_OID_EXT_KEY_USAGE_SERVER_AUTH,
KeyPurposeId::id_kp_serverAuth,
evPolicy, stapledOCSPResponse,
builtChain);
if (rv == SECSuccess) {
@ -443,7 +443,7 @@ CertVerifier::MozillaPKIXVerifyCert(
KU_DIGITAL_SIGNATURE, // ECDHE/DHE
KU_KEY_ENCIPHERMENT, // RSA
KU_KEY_AGREEMENT, // ECDH/DH
SEC_OID_EXT_KEY_USAGE_SERVER_AUTH,
KeyPurposeId::id_kp_serverAuth,
SEC_OID_X509_ANY_POLICY,
stapledOCSPResponse, builtChain);
break;
@ -453,8 +453,7 @@ CertVerifier::MozillaPKIXVerifyCert(
NSSCertDBTrustDomain trustDomain(trustSSL, ocspFetching, mOCSPCache,
pinArg);
rv = BuildCertChain(trustDomain, cert, time, EndEntityOrCA::MustBeCA,
KU_KEY_CERT_SIGN,
SEC_OID_EXT_KEY_USAGE_SERVER_AUTH,
KU_KEY_CERT_SIGN, KeyPurposeId::id_kp_serverAuth,
SEC_OID_X509_ANY_POLICY,
stapledOCSPResponse, builtChain);
break;
@ -465,8 +464,7 @@ CertVerifier::MozillaPKIXVerifyCert(
pinArg);
rv = BuildCertChain(trustDomain, cert, time,
EndEntityOrCA::MustBeEndEntity, KU_DIGITAL_SIGNATURE,
SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT,
SEC_OID_X509_ANY_POLICY,
KeyPurposeId::id_kp_emailProtection, SEC_OID_X509_ANY_POLICY,
stapledOCSPResponse, builtChain);
break;
}
@ -481,7 +479,7 @@ CertVerifier::MozillaPKIXVerifyCert(
KU_KEY_ENCIPHERMENT, // RSA
KU_KEY_AGREEMENT, // ECDH/DH
0,
SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT,
KeyPurposeId::id_kp_emailProtection,
SEC_OID_X509_ANY_POLICY,
stapledOCSPResponse, builtChain);
break;
@ -492,8 +490,7 @@ CertVerifier::MozillaPKIXVerifyCert(
mOCSPCache, pinArg);
rv = BuildCertChain(trustDomain, cert, time,
EndEntityOrCA::MustBeEndEntity, KU_DIGITAL_SIGNATURE,
SEC_OID_EXT_KEY_USAGE_CODE_SIGN,
SEC_OID_X509_ANY_POLICY,
KeyPurposeId::id_kp_codeSigning, SEC_OID_X509_ANY_POLICY,
stapledOCSPResponse, builtChain);
break;
}
@ -506,15 +503,15 @@ CertVerifier::MozillaPKIXVerifyCert(
// interesting, we just try them all.
mozilla::pkix::EndEntityOrCA endEntityOrCA;
mozilla::pkix::KeyUsages keyUsage;
SECOidTag eku;
KeyPurposeId eku;
if (usage == certificateUsageVerifyCA) {
endEntityOrCA = EndEntityOrCA::MustBeCA;
keyUsage = KU_KEY_CERT_SIGN;
eku = SEC_OID_UNKNOWN;
eku = KeyPurposeId::anyExtendedKeyUsage;
} else {
endEntityOrCA = EndEntityOrCA::MustBeEndEntity;
keyUsage = KU_DIGITAL_SIGNATURE;
eku = SEC_OID_OCSP_RESPONDER;
eku = KeyPurposeId::id_kp_OCSPSigning;
}
NSSCertDBTrustDomain sslTrust(trustSSL, ocspFetching, mOCSPCache,

View File

@ -24,26 +24,35 @@
// Work around missing std::bind, std::ref, std::cref in older compilers. This
// implementation isn't intended to be complete; rather, it is the minimal
// implementation needed to make our use of std::bind work.
// implementation needed to make our use of std::bind work for compilers that
// lack both C++11 and TR1 support for these features. We cannot even assume
// that rvalue references work, which means we don't get perfect forwarding
// and thus we basically have to define a new overload for every distinct call
// signature.
//
// A positive side-effect of this code is improved debugging usability; it is
// much more convenient to step through code that uses this polyfill than it is
// to step through the many nested layers of a real std::bind implementation.
//
// Build with MOZILLA_PKIX_USE_REAL_FUNCTIONAL defined in order to use the
// compiler's definitions of these functions. This is helpful in order to
// ensure that the calling code is actually compatible with the real std::bind
// and friends.
#ifndef mozilla_pkix__bind_h
#define mozilla_pkix__bind_h
#ifdef _MSC_VER
#pragma warning(disable:4275) //Suppress spurious MSVC warning
#endif
#ifdef MOZILLA_PKIX_USE_REAL_FUNCTIONAL
#include <functional>
#ifdef _MSC_VER
#pragma warning(default:4275)
#endif
namespace mozilla { namespace pkix {
#ifdef _MSC_VER
#ifdef MOZILLA_PKIX_USE_REAL_FUNCTIONAL
using std::bind;
using std::ref;
using std::cref;
using std::ref;
using std::placeholders::_1;
#else
@ -66,6 +75,7 @@ public:
private:
const F f;
B1& b1;
void operator=(const Bind1&) /*= delete*/;
};
template <typename R, typename P1, typename B1, typename B2>
@ -79,6 +89,40 @@ private:
const F f;
B1& b1;
B2& b2;
void operator=(const Bind2&) /*= delete*/;
};
template <typename R, typename P1, typename B1, typename B2, typename B3>
class Bind3
{
public:
typedef R (*F)(P1&, B1&, B2&, B3&);
Bind3(F f, B1& b1, B2& b2, B3& b3) : f(f), b1(b1), b2(b2), b3(b3) { }
R operator()(P1& p1) const { return f(p1, b1, b2, b3); }
private:
const F f;
B1& b1;
B2& b2;
B3& b3;
void operator=(const Bind3&) /*= delete*/;
};
template <typename R, typename P1, typename B1, typename B2, typename B3,
typename B4>
class Bind4
{
public:
typedef R (*F)(P1&, B1, B2, B3&, B4&);
Bind4(F f, B1& b1, B2& b2, B3& b3, B4& b4)
: f(f), b1(b1), b2(b2), b3(b3), b4(b4) { }
R operator()(P1& p1) const { return f(p1, b1, b2, b3, b4); }
private:
const F f;
B1& b1;
B2& b2;
B3& b3;
B4& b4;
void operator=(const Bind4&) /*= delete*/;
};
} // namespace internal
@ -92,12 +136,28 @@ bind(R (*f)(P1&, B1&), Placeholder1&, B1& b1)
template <typename R, typename P1, typename B1, typename B2>
inline internal::Bind2<R, P1, B1, B2>
bind(R (*f)(P1&, B1&, B2&), Placeholder1 &, B1 & b1, B2 & b2)
bind(R (*f)(P1&, B1&, B2&), Placeholder1&, B1& b1, B2& b2)
{
return internal::Bind2<R, P1, B1, B2>(f, b1, b2);
}
#endif // _MSC_VER
template <typename R, typename P1, typename B1, typename B2, typename B3>
inline internal::Bind3<R, P1, B1, B2, B3>
bind(R (*f)(P1&, B1&, B2&, B3&), Placeholder1&, B1& b1, B2& b2, B3& b3)
{
return internal::Bind3<R, P1, B1, B2, B3>(f, b1, b2, b3);
}
template <typename R, typename P1, typename B1, typename B2, typename B3,
typename B4>
inline internal::Bind4<R, P1, const B1, const B2, B3, B4>
bind(R (*f)(P1&, B1, B2, B3&, B4&), Placeholder1&, const B1& b1, const B2& b2,
B3& b3, B4& b4)
{
return internal::Bind4<R, P1, const B1, const B2, B3, B4>(f, b1, b2, b3, b4);
}
#endif
} } // namespace mozilla::pkix

View File

@ -94,7 +94,7 @@ SECStatus BuildCertChain(TrustDomain& trustDomain,
PRTime time,
EndEntityOrCA endEntityOrCA,
/*optional*/ KeyUsages requiredKeyUsagesIfPresent,
/*optional*/ SECOidTag requiredEKUIfPresent,
KeyPurposeId requiredEKUIfPresent,
/*optional*/ SECOidTag requiredPolicy,
/*optional*/ const SECItem* stapledOCSPResponse,
/*out*/ ScopedCERTCertList& results);

View File

@ -41,9 +41,18 @@ typedef ScopedPtr<CERTCertList, CERT_DestroyCertList> ScopedCERTCertList;
typedef ScopedPtr<SECKEYPublicKey, SECKEY_DestroyPublicKey>
ScopedSECKEYPublicKey;
MOZILLA_PKIX_ENUM_CLASS EndEntityOrCA { MustBeEndEntity = 0, MustBeCA = 1 };
typedef unsigned int KeyUsages;
MOZILLA_PKIX_ENUM_CLASS EndEntityOrCA { MustBeEndEntity = 0, MustBeCA = 1 };
MOZILLA_PKIX_ENUM_CLASS KeyPurposeId {
anyExtendedKeyUsage = 0,
id_kp_serverAuth = 1, // id-kp-serverAuth
id_kp_clientAuth = 2, // id-kp-clientAuth
id_kp_codeSigning = 3, // id-kp-codeSigning
id_kp_emailProtection = 4, // id-kp-emailProtection
id_kp_OCSPSigning = 9, // id-kp-OCSPSigning
};
MOZILLA_PKIX_ENUM_CLASS TrustLevel {
TrustAnchor = 1, // certificate is a trusted root CA certificate or

View File

@ -22,7 +22,7 @@
* limitations under the License.
*/
#ifndef _MSC_VER
#ifndef MOZILLA_PKIX_USE_REAL_FUNCTIONAL
#include "pkix/bind.h"
@ -32,4 +32,4 @@ Placeholder1 _1;
} } // namespace mozilla::pkix
#endif // _MSC_VER
#endif

View File

@ -114,7 +114,7 @@ static Result BuildForward(TrustDomain& trustDomain,
PRTime time,
EndEntityOrCA endEntityOrCA,
KeyUsages requiredKeyUsagesIfPresent,
SECOidTag requiredEKUIfPresent,
KeyPurposeId requiredEKUIfPresent,
SECOidTag requiredPolicy,
/*optional*/ const SECItem* stapledOCSPResponse,
unsigned int subCACount,
@ -126,7 +126,7 @@ BuildForwardInner(TrustDomain& trustDomain,
BackCert& subject,
PRTime time,
EndEntityOrCA endEntityOrCA,
SECOidTag requiredEKUIfPresent,
KeyPurposeId requiredEKUIfPresent,
SECOidTag requiredPolicy,
CERTCertificate* potentialIssuerCertToDup,
unsigned int subCACount,
@ -196,7 +196,7 @@ BuildForward(TrustDomain& trustDomain,
PRTime time,
EndEntityOrCA endEntityOrCA,
KeyUsages requiredKeyUsagesIfPresent,
SECOidTag requiredEKUIfPresent,
KeyPurposeId requiredEKUIfPresent,
SECOidTag requiredPolicy,
/*optional*/ const SECItem* stapledOCSPResponse,
unsigned int subCACount,
@ -336,7 +336,7 @@ BuildCertChain(TrustDomain& trustDomain,
PRTime time,
EndEntityOrCA endEntityOrCA,
/*optional*/ KeyUsages requiredKeyUsagesIfPresent,
/*optional*/ SECOidTag requiredEKUIfPresent,
/*optional*/ KeyPurposeId requiredEKUIfPresent,
/*optional*/ SECOidTag requiredPolicy,
/*optional*/ const SECItem* stapledOCSPResponse,
/*out*/ ScopedCERTCertList& results)
@ -355,7 +355,7 @@ BuildCertChain(TrustDomain& trustDomain,
// domain name the certificate is valid for.
BackCert::IncludeCN includeCN
= endEntityOrCA == EndEntityOrCA::MustBeEndEntity &&
requiredEKUIfPresent == SEC_OID_EXT_KEY_USAGE_SERVER_AUTH
requiredEKUIfPresent == KeyPurposeId::id_kp_serverAuth
? BackCert::IncludeCN::Yes
: BackCert::IncludeCN::No;

View File

@ -335,15 +335,97 @@ CheckNameConstraints(BackCert& cert)
}
// 4.2.1.12. Extended Key Usage (id-ce-extKeyUsage)
// 4.2.1.12. Extended Key Usage (id-ce-extKeyUsage)
Result
CheckExtendedKeyUsage(EndEntityOrCA endEntityOrCA, const SECItem* encodedEKUs,
SECOidTag requiredEKU)
{
// TODO: Either do not allow anyExtendedKeyUsage to be passed as requiredEKU,
// or require that callers pass anyExtendedKeyUsage instead of
// SEC_OID_UNKNWON and disallow SEC_OID_UNKNWON.
static der::Result
MatchEKU(der::Input& value, KeyPurposeId requiredEKU,
EndEntityOrCA endEntityOrCA, /*in/out*/ bool& found,
/*in/out*/ bool& foundOCSPSigning)
{
// See Section 5.9 of "A Layman's Guide to a Subset of ASN.1, BER, and DER"
// for a description of ASN.1 DER encoding of OIDs.
// id-pkix OBJECT IDENTIFIER ::=
// { iso(1) identified-organization(3) dod(6) internet(1)
// security(5) mechanisms(5) pkix(7) }
// id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
// id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 }
// id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 }
// id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 }
// id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 }
// id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 }
static const uint8_t server[] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 1 };
static const uint8_t client[] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 2 };
static const uint8_t code [] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 3 };
static const uint8_t email [] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 4 };
static const uint8_t ocsp [] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 9 };
// id-Netscape OBJECT IDENTIFIER ::= { 2 16 840 1 113730 }
// id-Netscape-policy OBJECT IDENTIFIER ::= { id-Netscape 4 }
// id-Netscape-stepUp OBJECT IDENTIFIER ::= { id-Netscape-policy 1 }
static const uint8_t serverStepUp[] =
{ (40*2)+16, 128+6,72, 1, 128+6,128+120,66, 4, 1 };
bool match = false;
if (!found) {
switch (requiredEKU) {
case KeyPurposeId::id_kp_serverAuth:
// Treat CA certs with step-up OID as also having SSL server type.
// Comodo has issued certificates that require this behavior that don't
// expire until June 2020! TODO(bug 982932): Limit this exception to
// old certificates.
match = value.MatchBytes(server) ||
(endEntityOrCA == EndEntityOrCA::MustBeCA &&
value.MatchBytes(serverStepUp));
break;
case KeyPurposeId::id_kp_clientAuth:
match = value.MatchBytes(client);
break;
case KeyPurposeId::id_kp_codeSigning:
match = value.MatchBytes(code);
break;
case KeyPurposeId::id_kp_emailProtection:
match = value.MatchBytes(email);
break;
case KeyPurposeId::id_kp_OCSPSigning:
match = value.MatchBytes(ocsp);
break;
case KeyPurposeId::anyExtendedKeyUsage:
PR_NOT_REACHED("anyExtendedKeyUsage should start with found==true");
return der::Fail(SEC_ERROR_LIBRARY_FAILURE);
default:
PR_NOT_REACHED("unrecognized EKU");
return der::Fail(SEC_ERROR_LIBRARY_FAILURE);
}
}
if (match) {
if (value.AtEnd()) {
found = true;
if (requiredEKU == KeyPurposeId::id_kp_OCSPSigning) {
foundOCSPSigning = true;
}
}
} else if (value.MatchBytes(ocsp) && value.AtEnd()) {
foundOCSPSigning = true;
}
value.SkipToEnd(); // ignore unmatched OIDs.
return der::Success;
}
Result
CheckExtendedKeyUsage(EndEntityOrCA endEntityOrCA,
const SECItem* encodedExtendedKeyUsage,
KeyPurposeId requiredEKU)
{
// XXX: We're using SEC_ERROR_INADEQUATE_CERT_TYPE here so that callers can
// distinguish EKU mismatch from KU mismatch from basic constraints mismatch.
// We should probably add a new error code that is more clear for this type
@ -351,35 +433,22 @@ CheckExtendedKeyUsage(EndEntityOrCA endEntityOrCA, const SECItem* encodedEKUs,
bool foundOCSPSigning = false;
if (encodedEKUs) {
ScopedPtr<CERTOidSequence, CERT_DestroyOidSequence>
seq(CERT_DecodeOidSequence(encodedEKUs));
if (!seq) {
PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0);
return RecoverableError;
if (encodedExtendedKeyUsage) {
bool found = requiredEKU == KeyPurposeId::anyExtendedKeyUsage;
der::Input input;
if (input.Init(encodedExtendedKeyUsage->data,
encodedExtendedKeyUsage->len) != der::Success) {
return Fail(RecoverableError, SEC_ERROR_INADEQUATE_CERT_TYPE);
}
bool found = false;
// XXX: We allow duplicate entries.
for (const SECItem* const* oids = seq->oids; oids && *oids; ++oids) {
SECOidTag oidTag = SECOID_FindOIDTag(*oids);
if (requiredEKU != SEC_OID_UNKNOWN && oidTag == requiredEKU) {
found = true;
} else {
// Treat CA certs with step-up OID as also having SSL server type.
// COMODO has issued certificates that require this behavior
// that don't expire until June 2020!
// TODO 982932: Limit this expection to old certificates
if (endEntityOrCA == EndEntityOrCA::MustBeCA &&
requiredEKU == SEC_OID_EXT_KEY_USAGE_SERVER_AUTH &&
oidTag == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED) {
found = true;
}
}
if (oidTag == SEC_OID_OCSP_RESPONDER) {
foundOCSPSigning = true;
}
if (der::NestedOf(input, der::SEQUENCE, der::OIDTag, der::EmptyAllowed::No,
bind(MatchEKU, _1, requiredEKU, endEntityOrCA,
ref(found), ref(foundOCSPSigning)))
!= der::Success) {
return Fail(RecoverableError, SEC_ERROR_INADEQUATE_CERT_TYPE);
}
if (der::End(input) != der::Success) {
return Fail(RecoverableError, SEC_ERROR_INADEQUATE_CERT_TYPE);
}
// If the EKU extension was included, then the required EKU must be in the
@ -404,9 +473,8 @@ CheckExtendedKeyUsage(EndEntityOrCA endEntityOrCA, const SECItem* encodedEKUs,
// Allowing this exception does not cause any security issues because we
// require delegated OCSP response signing certificates to be end-entity
// certificates.
if (foundOCSPSigning && requiredEKU != SEC_OID_OCSP_RESPONDER) {
PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0);
return RecoverableError;
if (foundOCSPSigning && requiredEKU != KeyPurposeId::id_kp_OCSPSigning) {
return Fail(RecoverableError, SEC_ERROR_INADEQUATE_CERT_TYPE);
}
// http://tools.ietf.org/html/rfc6960#section-4.2.2.2:
// "OCSP signing delegation SHALL be designated by the inclusion of
@ -417,9 +485,8 @@ CheckExtendedKeyUsage(EndEntityOrCA endEntityOrCA, const SECItem* encodedEKUs,
// EKU extension is missing from an end-entity certificate. However, any CA
// certificate can issue a delegated OCSP response signing certificate, so
// we can't require the EKU be explicitly included for CA certificates.
if (!foundOCSPSigning && requiredEKU == SEC_OID_OCSP_RESPONDER) {
PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0);
return RecoverableError;
if (!foundOCSPSigning && requiredEKU == KeyPurposeId::id_kp_OCSPSigning) {
return Fail(RecoverableError, SEC_ERROR_INADEQUATE_CERT_TYPE);
}
}
@ -432,7 +499,7 @@ CheckIssuerIndependentProperties(TrustDomain& trustDomain,
PRTime time,
EndEntityOrCA endEntityOrCA,
KeyUsages requiredKeyUsagesIfPresent,
SECOidTag requiredEKUIfPresent,
KeyPurposeId requiredEKUIfPresent,
SECOidTag requiredPolicy,
unsigned int subCACount,
/*optional out*/ TrustLevel* trustLevelOut)

View File

@ -25,6 +25,7 @@
#ifndef mozilla_pkix__pkixcheck_h
#define mozilla_pkix__pkixcheck_h
#include "pkix/pkixtypes.h"
#include "pkixutil.h"
#include "certt.h"
@ -36,7 +37,7 @@ Result CheckIssuerIndependentProperties(
PRTime time,
EndEntityOrCA endEntityOrCA,
KeyUsages requiredKeyUsagesIfPresent,
SECOidTag requiredEKUIfPresent,
KeyPurposeId requiredEKUIfPresent,
SECOidTag requiredPolicy,
unsigned int subCACount,
/*optional out*/ TrustLevel* trustLevel = nullptr);

View File

@ -138,6 +138,19 @@ public:
return Success;
}
template <uint16_t N>
bool MatchBytes(const uint8_t (&toMatch)[N])
{
if (EnsureLength(N) != Success) {
return false;
}
if (memcmp(input, toMatch, N)) {
return false;
}
input += N;
return true;
}
Result Skip(uint16_t len)
{
if (EnsureLength(len) != Success) {

View File

@ -146,7 +146,7 @@ CheckOCSPResponseSignerCert(TrustDomain& trustDomain,
// are validating for should be passed to CheckIssuerIndependentProperties.
rv = CheckIssuerIndependentProperties(trustDomain, cert, time,
EndEntityOrCA::MustBeEndEntity, 0,
SEC_OID_OCSP_RESPONDER,
KeyPurposeId::id_kp_OCSPSigning,
SEC_OID_X509_ANY_POLICY, 0);
if (rv != Success) {
return rv;

View File

@ -604,4 +604,57 @@ TEST_F(pkixder_input_tests, NestedOfWithTruncatedData)
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
ASSERT_EQ((size_t) 0, readValues.size());
}
TEST_F(pkixder_input_tests, MatchBytesAtEnd)
{
Input input;
static const uint8_t der[1] = { };
ASSERT_EQ(Success, input.Init(der, 0));
ASSERT_TRUE(input.AtEnd());
static const uint8_t toMatch[] = { 1 };
ASSERT_FALSE(input.MatchBytes(toMatch));
}
TEST_F(pkixder_input_tests, MatchBytes1Match)
{
Input input;
static const uint8_t der[] = { 1 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
ASSERT_FALSE(input.AtEnd());
ASSERT_TRUE(input.MatchBytes(der));
ASSERT_TRUE(input.AtEnd());
}
TEST_F(pkixder_input_tests, MatchBytes1Mismatch)
{
Input input;
static const uint8_t der[] = { 1 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
static const uint8_t toMatch[] = { 2 };
ASSERT_FALSE(input.MatchBytes(toMatch));
ASSERT_FALSE(input.AtEnd());
}
TEST_F(pkixder_input_tests, MatchBytes2Match)
{
Input input;
static const uint8_t der[] = { 1, 2, 3 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
static const uint8_t toMatch[] = { 1, 2 };
ASSERT_TRUE(input.MatchBytes(toMatch));
uint8_t followingByte;
ASSERT_EQ(Success, input.Read(followingByte));
ASSERT_EQ(3, followingByte);
}
TEST_F(pkixder_input_tests, MatchBytes2Mismatch)
{
Input input;
static const uint8_t der[] = { 1, 2, 3 };
ASSERT_EQ(Success, input.Init(der, sizeof der));
static const uint8_t toMatchMismatch[] = { 1, 3 };
ASSERT_FALSE(input.MatchBytes(toMatchMismatch));
ASSERT_TRUE(input.MatchBytes(der));
}
} // unnamed namespace