--- a/security/apps/AppTrustDomain.cpp
+++ b/security/apps/AppTrustDomain.cpp
@@ -192,16 +192,23 @@ SECStatus
AppTrustDomain::VerifySignedData(const SignedDataWithSignature& signedData,
const SECItem& subjectPublicKeyInfo)
{
return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
mPinArg);
}
SECStatus
+AppTrustDomain::DigestBuf(const SECItem& item, /*out*/ uint8_t* digestBuf,
+ size_t digestBufLen)
+{
+ return ::mozilla::pkix::DigestBuf(item, digestBuf, digestBufLen);
+}
+
+SECStatus
AppTrustDomain::CheckRevocation(EndEntityOrCA, const CertID&, PRTime time,
/*optional*/ const SECItem*,
/*optional*/ const SECItem*)
{
// We don't currently do revocation checking. If we need to distrust an Apps
// certificate, we will use the active distrust mechanism.
return SECSuccess;
}
--- a/security/apps/AppTrustDomain.h
+++ b/security/apps/AppTrustDomain.h
@@ -22,25 +22,28 @@ public:
SECStatus SetTrustedRoot(AppTrustedRoot trustedRoot);
SECStatus GetCertTrust(mozilla::pkix::EndEntityOrCA endEntityOrCA,
const mozilla::pkix::CertPolicyId& policy,
const SECItem& candidateCertDER,
/*out*/ mozilla::pkix::TrustLevel* trustLevel) MOZ_OVERRIDE;
SECStatus FindIssuer(const SECItem& encodedIssuerName,
IssuerChecker& checker, PRTime time) MOZ_OVERRIDE;
- SECStatus VerifySignedData(
- const mozilla::pkix::SignedDataWithSignature& signedData,
- const SECItem& subjectPublicKeyInfo) MOZ_OVERRIDE;
SECStatus CheckRevocation(mozilla::pkix::EndEntityOrCA endEntityOrCA,
const mozilla::pkix::CertID& certID, PRTime time,
/*optional*/ const SECItem* stapledOCSPresponse,
/*optional*/ const SECItem* aiaExtension);
SECStatus IsChainValid(const mozilla::pkix::DERArray& certChain);
+ SECStatus VerifySignedData(
+ const mozilla::pkix::SignedDataWithSignature& signedData,
+ const SECItem& subjectPublicKeyInfo) MOZ_OVERRIDE;
+ SECStatus DigestBuf(const SECItem& item, /*out*/ uint8_t* digestBuf,
+ size_t digestBufLen) MOZ_OVERRIDE;
+
private:
/*out*/ ScopedCERTCertList& mCertChain;
void* mPinArg; // non-owning!
ScopedCERTCertificate mTrustedRoot;
};
} } // namespace mozilla::psm
--- a/security/certverifier/NSSCertDBTrustDomain.cpp
+++ b/security/certverifier/NSSCertDBTrustDomain.cpp
@@ -219,16 +219,24 @@ NSSCertDBTrustDomain::GetCertTrust(EndEn
SECStatus
NSSCertDBTrustDomain::VerifySignedData(const SignedDataWithSignature& signedData,
const SECItem& subjectPublicKeyInfo)
{
return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
mPinArg);
}
+SECStatus
+NSSCertDBTrustDomain::DigestBuf(const SECItem& item,
+ /*out*/ uint8_t* digestBuf, size_t digestBufLen)
+{
+ return ::mozilla::pkix::DigestBuf(item, digestBuf, digestBufLen);
+}
+
+
static PRIntervalTime
OCSPFetchingTypeToTimeoutTime(NSSCertDBTrustDomain::OCSPFetching ocspFetching)
{
switch (ocspFetching) {
case NSSCertDBTrustDomain::FetchOCSPForDVSoftFail:
return PR_SecondsToInterval(2);
case NSSCertDBTrustDomain::FetchOCSPForEV:
case NSSCertDBTrustDomain::FetchOCSPForDVHardFail:
@@ -484,17 +492,18 @@ NSSCertDBTrustDomain::CheckRevocation(En
}
// Only request a response if we didn't have a cached indication of failure
// (don't keep requesting responses from a failing server).
const SECItem* response = nullptr;
if (cachedResponseErrorCode == 0 ||
cachedResponseErrorCode == SEC_ERROR_OCSP_UNKNOWN_CERT ||
cachedResponseErrorCode == SEC_ERROR_OCSP_OLD_RESPONSE) {
- const SECItem* request(CreateEncodedOCSPRequest(arena.get(), certID));
+ const SECItem* request(CreateEncodedOCSPRequest(*this, arena.get(),
+ certID));
if (!request) {
return SECFailure;
}
response = DoOCSPRequest(arena.get(), url, request,
OCSPFetchingTypeToTimeoutTime(mOCSPFetching),
mOCSPGetConfig == CertVerifier::ocsp_get_enabled);
}
--- a/security/certverifier/NSSCertDBTrustDomain.h
+++ b/security/certverifier/NSSCertDBTrustDomain.h
@@ -61,16 +61,19 @@ public:
const mozilla::pkix::CertPolicyId& policy,
const SECItem& candidateCertDER,
/*out*/ mozilla::pkix::TrustLevel* trustLevel);
virtual SECStatus VerifySignedData(
const mozilla::pkix::SignedDataWithSignature& signedData,
const SECItem& subjectPublicKeyInfo);
+ virtual SECStatus DigestBuf(const SECItem& item, /*out*/ uint8_t* digestBuf,
+ size_t digestBufLen);
+
virtual SECStatus CheckRevocation(mozilla::pkix::EndEntityOrCA endEntityOrCA,
const mozilla::pkix::CertID& certID,
PRTime time,
/*optional*/ const SECItem* stapledOCSPResponse,
/*optional*/ const SECItem* aiaExtension);
virtual SECStatus IsChainValid(const mozilla::pkix::DERArray& certChain);
--- a/security/pkix/include/pkix/pkix.h
+++ b/security/pkix/include/pkix/pkix.h
@@ -98,17 +98,18 @@ SECStatus BuildCertChain(TrustDomain& tr
/*optional*/ const SECItem* stapledOCSPResponse);
// Verify the given signed data using the given public key.
SECStatus VerifySignedData(const SignedDataWithSignature& sd,
const SECItem& subjectPublicKeyInfo,
void* pkcs11PinArg);
// The return value, if non-null, is owned by the arena and MUST NOT be freed.
-SECItem* CreateEncodedOCSPRequest(PLArenaPool* arena, const CertID& certID);
+SECItem* CreateEncodedOCSPRequest(TrustDomain& trustDomain, PLArenaPool* arena,
+ const CertID& certID);
// The out parameter expired will be true if the response has expired. If the
// response also indicates a revoked or unknown certificate, that error
// will be returned by PR_GetError(). Otherwise, SEC_ERROR_OCSP_OLD_RESPONSE
// will be returned by PR_GetError() for an expired response.
// The optional parameter thisUpdate will be the thisUpdate value of
// the encoded response if it is considered trustworthy. Only
// good, unknown, or revoked responses that verify correctly are considered
@@ -119,11 +120,25 @@ SECItem* CreateEncodedOCSPRequest(PLAren
SECStatus VerifyEncodedOCSPResponse(TrustDomain& trustDomain,
const CertID& certID, PRTime time,
uint16_t maxLifetimeInDays,
const SECItem& encodedResponse,
/* out */ bool& expired,
/* optional out */ PRTime* thisUpdate = nullptr,
/* optional out */ PRTime* validThrough = nullptr);
+// Computes the SHA-1 hash of the data in the current item.
+//
+// item contains the data to hash.
+// digestBuf must point to a buffer to where the SHA-1 hash will be written.
+// digestBufLen must be 20 (the length of a SHA-1 hash,
+// TrustDomain::DIGEST_LENGTH).
+//
+// TODO(bug 966856): Add SHA-2 support
+// TODO: Taking the output buffer as (uint8_t*, size_t) is counter to our
+// other, extensive, memory safety efforts in mozilla::pkix, and we should find
+// a way to provide a more-obviously-safe interface.
+SECStatus DigestBuf(const SECItem& item, /*out*/ uint8_t* digestBuf,
+ size_t digestBufLen);
+
} } // namespace mozilla::pkix
#endif // mozilla_pkix__pkix_h
--- a/security/pkix/include/pkix/pkixtypes.h
+++ b/security/pkix/include/pkix/pkixtypes.h
@@ -299,16 +299,31 @@ public:
/*optional*/ const SECItem* aiaExtension) = 0;
// Verify the given signature using the given public key.
//
// Most implementations of this function should probably forward the call
// directly to mozilla::pkix::VerifySignedData.
virtual SECStatus VerifySignedData(const SignedDataWithSignature& signedData,
const SECItem& subjectPublicKeyInfo) = 0;
+
+ // Compute the SHA-1 hash of the data in the current item.
+ //
+ // item contains the data to hash.
+ // digestBuf must point to a buffer to where the SHA-1 hash will be written.
+ // digestBufLen must be DIGEST_LENGTH (20, the length of a SHA-1 hash).
+ //
+ // TODO(bug 966856): Add SHA-2 support
+ // TODO: Taking the output buffer as (uint8_t*, size_t) is counter to our
+ // other, extensive, memory safety efforts in mozilla::pkix, and we should
+ // find a way to provide a more-obviously-safe interface.
+ static const size_t DIGEST_LENGTH = 20; // length of SHA-1 digest
+ virtual SECStatus DigestBuf(const SECItem& item, /*out*/ uint8_t* digestBuf,
+ size_t digestBufLen) = 0;
+
protected:
TrustDomain() { }
private:
TrustDomain(const TrustDomain&) /* = delete */;
void operator=(const TrustDomain&) /* = delete */;
};
--- a/security/pkix/lib/pkixkey.cpp
+++ b/security/pkix/lib/pkixkey.cpp
@@ -23,16 +23,17 @@
*/
#include <limits>
#include <stdint.h>
#include "cert.h"
#include "cryptohi.h"
#include "keyhi.h"
+#include "pk11pub.h"
#include "pkix/pkix.h"
#include "pkix/ScopedPtr.h"
#include "prerror.h"
#include "secerr.h"
namespace mozilla { namespace pkix {
SECStatus
@@ -113,9 +114,29 @@ VerifySignedData(const SignedDataWithSig
// The static_cast is safe according to the check above that references
// bug 921585.
return VFY_VerifyDataDirect(sd.data.data, static_cast<int>(sd.data.len),
pubKey.get(), &sd.signature, pubKeyAlg,
digestAlg, nullptr, pkcs11PinArg);
}
+SECStatus
+DigestBuf(const SECItem& item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
+{
+ static_assert(TrustDomain::DIGEST_LENGTH == SHA1_LENGTH,
+ "TrustDomain::DIGEST_LENGTH must be 20 (SHA-1 digest length)");
+ if (digestBufLen != TrustDomain::DIGEST_LENGTH) {
+ PR_NOT_REACHED("invalid hash length");
+ PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
+ return SECFailure;
+ }
+ if (item.len >
+ static_cast<decltype(item.len)>(std::numeric_limits<int32_t>::max())) {
+ PR_NOT_REACHED("large OCSP responses should have already been rejected");
+ PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
+ return SECFailure;
+ }
+ return PK11_HashBuf(SEC_OID_SHA1, digestBuf, item.data,
+ static_cast<int32_t>(item.len));
+}
+
} } // namespace mozilla::pkix
--- a/security/pkix/lib/pkixocsp.cpp
+++ b/security/pkix/lib/pkixocsp.cpp
@@ -19,18 +19,16 @@
* 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 "hasht.h"
-#include "pk11pub.h"
#include "pkix/bind.h"
#include "pkix/pkix.h"
#include "pkixcheck.h"
#include "pkixder.h"
// TODO: use typed/qualified typedefs everywhere?
// TODO: When should we return SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE?
@@ -79,35 +77,16 @@ public:
PRTime* validThrough;
bool expired;
private:
Context(const Context&); // delete
void operator=(const Context&); // delete
};
-static der::Result
-HashBuf(const SECItem& item, /*out*/ uint8_t *hashBuf, size_t hashBufLen)
-{
- if (hashBufLen != SHA1_LENGTH) {
- PR_NOT_REACHED("invalid hash length");
- return der::Fail(SEC_ERROR_INVALID_ARGS);
- }
- if (item.len >
- static_cast<decltype(item.len)>(std::numeric_limits<int32_t>::max())) {
- PR_NOT_REACHED("large OCSP responses should have already been rejected");
- return der::Fail(SEC_ERROR_INVALID_ARGS);
- }
- if (PK11_HashBuf(SEC_OID_SHA1, hashBuf, item.data,
- static_cast<int32_t>(item.len)) != SECSuccess) {
- return der::Fail(PR_GetError());
- }
- return der::Success;
-}
-
// Verify that potentialSigner is a valid delegated OCSP response signing cert
// according to RFC 6960 section 4.2.2.2.
static Result
CheckOCSPResponseSignerCert(TrustDomain& trustDomain,
BackCert& potentialSigner,
const SECItem& issuerSubject,
const SECItem& issuerSubjectPublicKeyInfo,
PRTime time)
@@ -184,25 +163,28 @@ static inline der::Result ResponseData(
static inline der::Result SingleResponse(der::Input& input,
Context& context);
static der::Result ExtensionNotUnderstood(der::Input& extnID,
const SECItem& extnValue,
/*out*/ bool& understood);
static inline der::Result CertID(der::Input& input,
const Context& context,
/*out*/ bool& match);
-static Result MatchKeyHash(const SECItem& issuerKeyHash,
+static Result MatchKeyHash(TrustDomain& trustDomain,
+ const SECItem& issuerKeyHash,
const SECItem& issuerSubjectPublicKeyInfo,
/*out*/ bool& match);
-static Result KeyHash(const SECItem& subjectPublicKeyInfo,
+static Result KeyHash(TrustDomain& trustDomain,
+ const SECItem& subjectPublicKeyInfo,
/*out*/ uint8_t* hashBuf, size_t hashBufSize);
static Result
-MatchResponderID(ResponderIDType responderIDType,
+MatchResponderID(TrustDomain& trustDomain,
+ ResponderIDType responderIDType,
const SECItem& responderIDItem,
const SECItem& potentialSignerSubject,
const SECItem& potentialSignerSubjectPublicKeyInfo,
/*out*/ bool& match)
{
match = false;
switch (responderIDType) {
@@ -219,17 +201,18 @@ MatchResponderID(ResponderIDType respond
!= der::Success) {
return RecoverableError;
}
SECItem keyHash;
if (der::ExpectTagAndGetValue(responderID, der::OCTET_STRING, keyHash)
!= der::Success) {
return RecoverableError;
}
- return MatchKeyHash(keyHash, potentialSignerSubjectPublicKeyInfo, match);
+ return MatchKeyHash(trustDomain, keyHash,
+ potentialSignerSubjectPublicKeyInfo, match);
}
default:
return Fail(RecoverableError, SEC_ERROR_OCSP_MALFORMED_RESPONSE);
}
}
static Result
@@ -254,35 +237,35 @@ VerifyOCSPSignedData(TrustDomain& trustD
// *directly* to issuerCert.
static Result
VerifySignature(Context& context, ResponderIDType responderIDType,
const SECItem& responderID, const SECItem* certs,
size_t numCerts,
const SignedDataWithSignature& signedResponseData)
{
bool match;
- Result rv = MatchResponderID(responderIDType, responderID,
- context.certID.issuer,
+ Result rv = MatchResponderID(context.trustDomain, responderIDType,
+ responderID, context.certID.issuer,
context.certID.issuerSubjectPublicKeyInfo,
match);
if (rv != Success) {
return rv;
}
if (match) {
return VerifyOCSPSignedData(context.trustDomain, signedResponseData,
context.certID.issuerSubjectPublicKeyInfo);
}
for (size_t i = 0; i < numCerts; ++i) {
BackCert cert(certs[i], EndEntityOrCA::MustBeEndEntity, nullptr);
rv = cert.Init();
if (rv != Success) {
return rv;
}
- rv = MatchResponderID(responderIDType, responderID,
+ rv = MatchResponderID(context.trustDomain, responderIDType, responderID,
cert.GetSubject(), cert.GetSubjectPublicKeyInfo(),
match);
if (rv == FatalError) {
return rv;
}
if (rv == RecoverableError) {
continue;
}
@@ -717,36 +700,37 @@ CertID(der::Input& input, const Context&
// TODO: support SHA-2 hashes.
if (hashAlgorithm != DigestAlgorithm::sha1) {
// Again, not interested in this response. Consume input, return success.
input.SkipToEnd();
return der::Success;
}
- if (issuerNameHash.len != SHA1_LENGTH) {
+ if (issuerNameHash.len != TrustDomain::DIGEST_LENGTH) {
return der::Fail(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
}
// From http://tools.ietf.org/html/rfc6960#section-4.1.1:
// "The hash shall be calculated over the DER encoding of the
// issuer's name field in the certificate being checked."
- uint8_t hashBuf[SHA1_LENGTH];
- if (HashBuf(context.certID.issuer, hashBuf, sizeof(hashBuf))
- != der::Success) {
+ uint8_t hashBuf[TrustDomain::DIGEST_LENGTH];
+ if (context.trustDomain.DigestBuf(context.certID.issuer, hashBuf,
+ sizeof(hashBuf)) != SECSuccess) {
return der::Failure;
}
if (memcmp(hashBuf, issuerNameHash.data, issuerNameHash.len)) {
// Again, not interested in this response. Consume input, return success.
input.SkipToEnd();
return der::Success;
}
- if (MatchKeyHash(issuerKeyHash, context.certID.issuerSubjectPublicKeyInfo,
- match) != Success) {
+ if (MatchKeyHash(context.trustDomain, issuerKeyHash,
+ context.certID.issuerSubjectPublicKeyInfo, match)
+ != Success) {
return der::Failure;
}
return der::Success;
}
// From http://tools.ietf.org/html/rfc6960#section-4.1.1:
// "The hash shall be calculated over the value (excluding tag and length) of
@@ -754,37 +738,38 @@ CertID(der::Input& input, const Context&
//
// From http://tools.ietf.org/html/rfc6960#appendix-B.1:
// KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
// -- (i.e., the SHA-1 hash of the value of the
// -- BIT STRING subjectPublicKey [excluding
// -- the tag, length, and number of unused
// -- bits] in the responder's certificate)
static Result
-MatchKeyHash(const SECItem& keyHash, const SECItem& subjectPublicKeyInfo,
- /*out*/ bool& match)
+MatchKeyHash(TrustDomain& trustDomain, const SECItem& keyHash,
+ const SECItem& subjectPublicKeyInfo, /*out*/ bool& match)
{
- if (keyHash.len != SHA1_LENGTH) {
+ if (keyHash.len != TrustDomain::DIGEST_LENGTH) {
return Fail(RecoverableError, SEC_ERROR_OCSP_MALFORMED_RESPONSE);
}
- static uint8_t hashBuf[SHA1_LENGTH];
- Result rv = KeyHash(subjectPublicKeyInfo, hashBuf, sizeof hashBuf);
+ static uint8_t hashBuf[TrustDomain::DIGEST_LENGTH];
+ Result rv = KeyHash(trustDomain, subjectPublicKeyInfo, hashBuf,
+ sizeof hashBuf);
if (rv != Success) {
return rv;
}
match = !memcmp(hashBuf, keyHash.data, keyHash.len);
return Success;
}
// TODO(bug 966856): support SHA-2 hashes
Result
-KeyHash(const SECItem& subjectPublicKeyInfo, /*out*/ uint8_t* hashBuf,
- size_t hashBufSize)
+KeyHash(TrustDomain& trustDomain, const SECItem& subjectPublicKeyInfo,
+ /*out*/ uint8_t* hashBuf, size_t hashBufSize)
{
- if (!hashBuf || hashBufSize != SHA1_LENGTH) {
+ if (!hashBuf || hashBufSize != TrustDomain::DIGEST_LENGTH) {
return Fail(FatalError, SEC_ERROR_LIBRARY_FAILURE);
}
// RFC 5280 Section 4.1
//
// SubjectPublicKeyInfo ::= SEQUENCE {
// algorithm AlgorithmIdentifier,
// subjectPublicKey BIT STRING }
@@ -825,17 +810,18 @@ KeyHash(const SECItem& subjectPublicKeyI
// Assume/require that the number of unused bits in the public key is zero.
if (subjectPublicKey.len == 0 || subjectPublicKey.data[0] != 0) {
return Fail(RecoverableError, SEC_ERROR_BAD_DER);
}
++subjectPublicKey.data;
--subjectPublicKey.len;
- if (HashBuf(subjectPublicKey, hashBuf, hashBufSize) != der::Success) {
+ if (trustDomain.DigestBuf(subjectPublicKey, hashBuf, hashBufSize)
+ != SECSuccess) {
return MapSECStatus(SECFailure);
}
return Success;
}
der::Result
ExtensionNotUnderstood(der::Input& /*extnID*/, const SECItem& /*extnValue*/,
/*out*/ bool& understood)
@@ -863,17 +849,18 @@ ExtensionNotUnderstood(der::Input& /*ext
// SHOULD be considered unreliable.
//
// If nextUpdate is not set, the responder is indicating that newer
// revocation information is available all the time.
//
// http://tools.ietf.org/html/rfc5019#section-4
SECItem*
-CreateEncodedOCSPRequest(PLArenaPool* arena, const struct CertID& certID)
+CreateEncodedOCSPRequest(TrustDomain& trustDomain, PLArenaPool* arena,
+ const struct CertID& certID)
{
if (!arena) {
PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
return nullptr;
}
// We do not add any extensions to the request.
@@ -891,17 +878,17 @@ CreateEncodedOCSPRequest(PLArenaPool* ar
// Since we don't know whether the OCSP responder supports anything other
// than SHA-1, we have no choice but to use SHA-1 for issuerNameHash and
// issuerKeyHash.
static const uint8_t hashAlgorithm[11] = {
0x30, 0x09, // SEQUENCE
0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJECT IDENTIFIER id-sha1
0x05, 0x00, // NULL
};
- static const uint8_t hashLen = SHA1_LENGTH;
+ static const uint8_t hashLen = TrustDomain::DIGEST_LENGTH;
static const unsigned int totalLenWithoutSerialNumberData
= 2 // OCSPRequest
+ 2 // tbsRequest
+ 2 // requestList
+ 2 // Request
+ 2 // reqCert (CertID)
+ PR_ARRAY_SIZE(hashAlgorithm) // hashAlgorithm
@@ -938,25 +925,26 @@ CreateEncodedOCSPRequest(PLArenaPool* ar
// reqCert.hashAlgorithm
for (size_t i = 0; i < PR_ARRAY_SIZE(hashAlgorithm); ++i) {
*d++ = hashAlgorithm[i];
}
// reqCert.issuerNameHash (OCTET STRING)
*d++ = 0x04;
*d++ = hashLen;
- if (HashBuf(certID.issuer, d, hashLen) != der::Success) {
+ if (trustDomain.DigestBuf(certID.issuer, d, hashLen) != SECSuccess) {
return nullptr;
}
d += hashLen;
// reqCert.issuerKeyHash (OCTET STRING)
*d++ = 0x04;
*d++ = hashLen;
- if (KeyHash(certID.issuerSubjectPublicKeyInfo, d, hashLen) != Success) {
+ if (KeyHash(trustDomain, certID.issuerSubjectPublicKeyInfo, d, hashLen)
+ != Success) {
return nullptr;
}
d += hashLen;
// reqCert.serialNumber (INTEGER)
*d++ = 0x02; // INTEGER
*d++ = static_cast<uint8_t>(certID.serialNumber.len);
for (size_t i = 0; i < certID.serialNumber.len; ++i) {
--- a/security/pkix/test/gtest/pkixbuild_tests.cpp
+++ b/security/pkix/test/gtest/pkixbuild_tests.cpp
@@ -145,35 +145,43 @@ private:
break;
}
}
}
return SECSuccess;
}
- SECStatus VerifySignedData(const SignedDataWithSignature& signedData,
- const SECItem& subjectPublicKeyInfo)
- {
- return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
- nullptr);
- }
-
SECStatus CheckRevocation(EndEntityOrCA, const CertID&, PRTime,
/*optional*/ const SECItem*,
/*optional*/ const SECItem*)
{
return SECSuccess;
}
virtual SECStatus IsChainValid(const DERArray&)
{
return SECSuccess;
}
+ SECStatus VerifySignedData(const SignedDataWithSignature& signedData,
+ const SECItem& subjectPublicKeyInfo)
+ {
+ return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
+ nullptr);
+ }
+
+ virtual SECStatus DigestBuf(const SECItem& item, /*out*/ uint8_t *digestBuf,
+ size_t digestBufLen)
+ {
+ ADD_FAILURE();
+ PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
+ return SECFailure;
+ }
+
// We hold references to CERTCertificates in the cert chain tail so that we
// CERT_CreateSubjectCertList can find them.
ScopedCERTCertificate certChainTail[7];
public:
ScopedSECKEYPrivateKey leafCAKey;
CERTCertificate* GetLeafCACert() const
{
--- a/security/pkix/test/gtest/pkixcert_extension_tests.cpp
+++ b/security/pkix/test/gtest/pkixcert_extension_tests.cpp
@@ -80,39 +80,46 @@ private:
{
*trustLevel = TrustLevel::TrustAnchor;
return SECSuccess;
}
SECStatus FindIssuer(const SECItem& /*encodedIssuerName*/,
IssuerChecker& /*checker*/, PRTime /*time*/)
{
- PR_NOT_REACHED("FindIssuer should not be called");
+ ADD_FAILURE();
PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
return SECFailure;
}
- SECStatus VerifySignedData(const SignedDataWithSignature& signedData,
- const SECItem& subjectPublicKeyInfo)
- {
- return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
- nullptr);
- }
-
SECStatus CheckRevocation(EndEntityOrCA, const CertID&, PRTime,
/*optional*/ const SECItem*,
/*optional*/ const SECItem*)
{
return SECSuccess;
}
virtual SECStatus IsChainValid(const DERArray&)
{
return SECSuccess;
}
+
+ SECStatus VerifySignedData(const SignedDataWithSignature& signedData,
+ const SECItem& subjectPublicKeyInfo)
+ {
+ return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
+ nullptr);
+ }
+
+ SECStatus DigestBuf(const SECItem&, /*out*/ uint8_t *, size_t)
+ {
+ ADD_FAILURE();
+ PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
+ return SECFailure;
+ }
};
class pkixcert_extension: public NSSTest
{
public:
static void SetUpTestCase()
{
NSSTest::SetUpTestCase();
--- a/security/pkix/test/gtest/pkixocsp_CreateEncodedOCSPRequest_tests.cpp
+++ b/security/pkix/test/gtest/pkixocsp_CreateEncodedOCSPRequest_tests.cpp
@@ -26,16 +26,64 @@
#include "pkix/pkix.h"
#include "pkixder.h"
#include "prerror.h"
#include "secerr.h"
using namespace mozilla::pkix;
using namespace mozilla::pkix::test;
+class CreateEncodedOCSPRequestTrustDomain : public TrustDomain
+{
+private:
+ virtual SECStatus GetCertTrust(EndEntityOrCA, const CertPolicyId&,
+ const SECItem&, /*out*/ TrustLevel*)
+ {
+ ADD_FAILURE();
+ PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
+ return SECFailure;
+ }
+
+ virtual SECStatus FindIssuer(const SECItem&, IssuerChecker&, PRTime)
+ {
+ ADD_FAILURE();
+ PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
+ return SECFailure;
+ }
+
+ virtual SECStatus CheckRevocation(EndEntityOrCA, const CertID&, PRTime,
+ const SECItem*, const SECItem*)
+ {
+ ADD_FAILURE();
+ PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
+ return SECFailure;
+ }
+
+ virtual SECStatus IsChainValid(const DERArray&)
+ {
+ ADD_FAILURE();
+ PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
+ return SECFailure;
+ }
+
+ virtual SECStatus VerifySignedData(const SignedDataWithSignature&,
+ const SECItem&)
+ {
+ ADD_FAILURE();
+ PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
+ return SECFailure;
+ }
+
+ virtual SECStatus DigestBuf(const SECItem& item, /*out*/ uint8_t *digestBuf,
+ size_t digestBufLen)
+ {
+ return ::mozilla::pkix::DigestBuf(item, digestBuf, digestBufLen);
+ }
+};
+
class pkixocsp_CreateEncodedOCSPRequest : public NSSTest
{
protected:
// These SECItems are allocated in arena, and so will be auto-cleaned.
SECItem* unsupportedLongSerialNumber;
SECItem* longestRequiredSerialNumber;
void SetUp()
@@ -81,36 +129,37 @@ protected:
issuerSPKI = SECKEY_EncodeDERSubjectPublicKeyInfo(issuerPublicKey.get());
if (!issuerSPKI) {
return SECFailure;
}
return SECSuccess;
}
+ CreateEncodedOCSPRequestTrustDomain trustDomain;
};
// Test that the large length of the child serial number causes
// CreateEncodedOCSPRequest to fail.
TEST_F(pkixocsp_CreateEncodedOCSPRequest, ChildCertLongSerialNumberTest)
{
const SECItem* issuerDER;
ScopedSECItem issuerSPKI;
ASSERT_EQ(SECSuccess,
MakeIssuerCertIDComponents("CN=CA", issuerDER, issuerSPKI));
- ASSERT_FALSE(CreateEncodedOCSPRequest(arena.get(),
+ ASSERT_FALSE(CreateEncodedOCSPRequest(trustDomain, arena.get(),
CertID(*issuerDER, *issuerSPKI,
*unsupportedLongSerialNumber)));
ASSERT_EQ(SEC_ERROR_BAD_DATA, PR_GetError());
}
// Test that CreateEncodedOCSPRequest handles the longest serial number that
// it's required to support (i.e. 20 octets).
TEST_F(pkixocsp_CreateEncodedOCSPRequest, LongestSupportedSerialNumberTest)
{
const SECItem* issuerDER;
ScopedSECItem issuerSPKI;
ASSERT_EQ(SECSuccess,
MakeIssuerCertIDComponents("CN=CA", issuerDER, issuerSPKI));
- ASSERT_TRUE(CreateEncodedOCSPRequest(arena.get(),
+ ASSERT_TRUE(CreateEncodedOCSPRequest(trustDomain, arena.get(),
CertID(*issuerDER, *issuerSPKI,
*longestRequiredSerialNumber)));
}