mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1130754: Avoid recalculating tbsCertificate digest, r=keeler
--HG-- extra : rebase_source : 85266413568df928cb1eaf1cd59b52ee9d4259e6 extra : histedit_source : 767e3263d28926435c6d2f4610c7d8b01e9ba87d
This commit is contained in:
parent
40b925ba79
commit
242431f427
2
config/external/nss/nss.def
vendored
2
config/external/nss/nss.def
vendored
@ -677,7 +677,7 @@ VFY_DestroyContext
|
||||
VFY_End
|
||||
VFY_Update
|
||||
VFY_VerifyData
|
||||
VFY_VerifyDataDirect
|
||||
VFY_VerifyDataWithAlgorithmID
|
||||
VFY_VerifyDigestDirect
|
||||
_SGN_VerifyPKCS1DigestInfo
|
||||
PK11_PQG_ParamGenV2
|
||||
|
@ -214,17 +214,12 @@ AppTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
|
||||
}
|
||||
|
||||
Result
|
||||
AppTrustDomain::VerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
return VerifySignedDataNSS(signedData, subjectPublicKeyInfo, mPinArg);
|
||||
}
|
||||
|
||||
Result
|
||||
AppTrustDomain::DigestBuf(Input item, /*out*/ uint8_t* digestBuf,
|
||||
AppTrustDomain::DigestBuf(Input item,
|
||||
DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf,
|
||||
size_t digestBufLen)
|
||||
{
|
||||
return DigestBufNSS(item, digestBuf, digestBufLen);
|
||||
return DigestBufNSS(item, digestAlg, digestBuf, digestBufLen);
|
||||
}
|
||||
|
||||
Result
|
||||
@ -258,6 +253,14 @@ AppTrustDomain::CheckRSAPublicKeyModulusSizeInBits(
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result
|
||||
AppTrustDomain::VerifyRSAPKCS1SignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
return VerifyRSAPKCS1SignedDigestNSS(signedDigest, subjectPublicKeyInfo,
|
||||
mPinArg);
|
||||
}
|
||||
|
||||
Result
|
||||
AppTrustDomain::CheckECDSACurveIsAcceptable(EndEntityOrCA /*endEntityOrCA*/,
|
||||
NamedCurve curve)
|
||||
@ -272,4 +275,12 @@ AppTrustDomain::CheckECDSACurveIsAcceptable(EndEntityOrCA /*endEntityOrCA*/,
|
||||
return Result::ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
|
||||
}
|
||||
|
||||
Result
|
||||
AppTrustDomain::VerifyECDSASignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
return VerifyECDSASignedDigestNSS(signedDigest, subjectPublicKeyInfo,
|
||||
mPinArg);
|
||||
}
|
||||
|
||||
} } // namespace mozilla::psm
|
||||
|
@ -41,13 +41,17 @@ public:
|
||||
virtual Result CheckRSAPublicKeyModulusSizeInBits(
|
||||
mozilla::pkix::EndEntityOrCA endEntityOrCA,
|
||||
unsigned int modulusSizeInBits) MOZ_OVERRIDE;
|
||||
virtual Result VerifyRSAPKCS1SignedDigest(
|
||||
const mozilla::pkix::SignedDigest& signedDigest,
|
||||
mozilla::pkix::Input subjectPublicKeyInfo) MOZ_OVERRIDE;
|
||||
virtual Result CheckECDSACurveIsAcceptable(
|
||||
mozilla::pkix::EndEntityOrCA endEntityOrCA,
|
||||
mozilla::pkix::NamedCurve curve) MOZ_OVERRIDE;
|
||||
virtual Result VerifySignedData(
|
||||
const mozilla::pkix::SignedDataWithSignature& signedData,
|
||||
mozilla::pkix::Input subjectPublicKeyInfo) MOZ_OVERRIDE;
|
||||
virtual Result VerifyECDSASignedDigest(
|
||||
const mozilla::pkix::SignedDigest& signedDigest,
|
||||
mozilla::pkix::Input subjectPublicKeyInfo) MOZ_OVERRIDE;
|
||||
virtual Result DigestBuf(mozilla::pkix::Input item,
|
||||
mozilla::pkix::DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf,
|
||||
size_t digestBufLen) MOZ_OVERRIDE;
|
||||
|
||||
|
@ -257,17 +257,10 @@ NSSCertDBTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
|
||||
}
|
||||
|
||||
Result
|
||||
NSSCertDBTrustDomain::VerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
return VerifySignedDataNSS(signedData, subjectPublicKeyInfo, mPinArg);
|
||||
}
|
||||
|
||||
Result
|
||||
NSSCertDBTrustDomain::DigestBuf(Input item,
|
||||
NSSCertDBTrustDomain::DigestBuf(Input item, DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf, size_t digestBufLen)
|
||||
{
|
||||
return DigestBufNSS(item, digestBuf, digestBufLen);
|
||||
return DigestBufNSS(item, digestAlg, digestBuf, digestBufLen);
|
||||
}
|
||||
|
||||
|
||||
@ -729,6 +722,15 @@ NSSCertDBTrustDomain::CheckRSAPublicKeyModulusSizeInBits(
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result
|
||||
NSSCertDBTrustDomain::VerifyRSAPKCS1SignedDigest(
|
||||
const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
return VerifyRSAPKCS1SignedDigestNSS(signedDigest, subjectPublicKeyInfo,
|
||||
mPinArg);
|
||||
}
|
||||
|
||||
Result
|
||||
NSSCertDBTrustDomain::CheckECDSACurveIsAcceptable(
|
||||
EndEntityOrCA /*endEntityOrCA*/, NamedCurve curve)
|
||||
@ -743,6 +745,14 @@ NSSCertDBTrustDomain::CheckECDSACurveIsAcceptable(
|
||||
return Result::ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
|
||||
}
|
||||
|
||||
Result
|
||||
NSSCertDBTrustDomain::VerifyECDSASignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
return VerifyECDSASignedDigestNSS(signedDigest, subjectPublicKeyInfo,
|
||||
mPinArg);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
static char*
|
||||
|
@ -74,16 +74,20 @@ public:
|
||||
mozilla::pkix::EndEntityOrCA endEntityOrCA,
|
||||
unsigned int modulusSizeInBits) MOZ_OVERRIDE;
|
||||
|
||||
virtual Result VerifyRSAPKCS1SignedDigest(
|
||||
const mozilla::pkix::SignedDigest& signedDigest,
|
||||
mozilla::pkix::Input subjectPublicKeyInfo) MOZ_OVERRIDE;
|
||||
|
||||
virtual Result CheckECDSACurveIsAcceptable(
|
||||
mozilla::pkix::EndEntityOrCA endEntityOrCA,
|
||||
mozilla::pkix::NamedCurve curve) MOZ_OVERRIDE;
|
||||
|
||||
virtual Result VerifySignedData(
|
||||
const mozilla::pkix::SignedDataWithSignature& signedData,
|
||||
mozilla::pkix::Input subjectPublicKeyInfo)
|
||||
MOZ_OVERRIDE;
|
||||
virtual Result VerifyECDSASignedDigest(
|
||||
const mozilla::pkix::SignedDigest& signedDigest,
|
||||
mozilla::pkix::Input subjectPublicKeyInfo) MOZ_OVERRIDE;
|
||||
|
||||
virtual Result DigestBuf(mozilla::pkix::Input item,
|
||||
mozilla::pkix::DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf,
|
||||
size_t digestBufLen) MOZ_OVERRIDE;
|
||||
|
||||
|
@ -31,23 +31,32 @@
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
|
||||
// Verify the given signed data using the given public key.
|
||||
Result VerifySignedDataNSS(const SignedDataWithSignature& sd,
|
||||
Input subjectPublicKeyInfo,
|
||||
void* pkcs11PinArg);
|
||||
// Verifies the PKCS#1.5 signature on the given data using the given RSA public
|
||||
// key.
|
||||
Result VerifyRSAPKCS1SignedDigestNSS(const SignedDigest& sd,
|
||||
Input subjectPublicKeyInfo,
|
||||
void* pkcs11PinArg);
|
||||
|
||||
// Computes the SHA-1 hash of the data in the current item.
|
||||
// Verifies the ECDSA signature on the given data using the given ECC public
|
||||
// key.
|
||||
Result VerifyECDSASignedDigestNSS(const SignedDigest& sd,
|
||||
Input subjectPublicKeyInfo,
|
||||
void* pkcs11PinArg);
|
||||
|
||||
// Computes the digest of the given data using the given digest algorithm.
|
||||
//
|
||||
// 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).
|
||||
// digestBuf must point to a buffer to where the digest will be written.
|
||||
// digestBufLen must be the size of the buffer, which must be exactly equal
|
||||
// to the size of the digest output (20 for SHA-1, 32 for SHA-256,
|
||||
// etc.)
|
||||
//
|
||||
// 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.
|
||||
Result DigestBufNSS(Input item, /*out*/ uint8_t* digestBuf,
|
||||
Result DigestBufNSS(Input item,
|
||||
DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf,
|
||||
size_t digestBufLen);
|
||||
|
||||
Result MapPRErrorCodeToResult(PRErrorCode errorCode);
|
||||
@ -83,6 +92,8 @@ inline SECItem UnsafeMapInputToSECItem(Input input)
|
||||
const_cast<uint8_t*>(input.UnsafeGetData()),
|
||||
input.GetLength()
|
||||
};
|
||||
static_assert(sizeof(decltype(input.GetLength())) <= sizeof(result.len),
|
||||
"input.GetLength() must fit in a SECItem");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -51,44 +51,13 @@ enum class NamedCurve
|
||||
secp256r1 = 3,
|
||||
};
|
||||
|
||||
enum class SignatureAlgorithm
|
||||
struct SignedDigest final
|
||||
{
|
||||
// ecdsa-with-SHA512 (OID 1.2.840.10045.4.3.4, RFC 5758 Section 3.2)
|
||||
ecdsa_with_sha512 = 1,
|
||||
|
||||
// ecdsa-with-SHA384 (OID 1.2.840.10045.4.3.3, RFC 5758 Section 3.2)
|
||||
ecdsa_with_sha384 = 4,
|
||||
|
||||
// ecdsa-with-SHA256 (OID 1.2.840.10045.4.3.2, RFC 5758 Section 3.2)
|
||||
ecdsa_with_sha256 = 7,
|
||||
|
||||
// ecdsa-with-SHA1 (OID 1.2.840.10045.4.1, RFC 3279 Section 2.2.3)
|
||||
ecdsa_with_sha1 = 10,
|
||||
|
||||
// sha512WithRSAEncryption (OID 1.2.840.113549.1.1.13, RFC 4055 Section 5)
|
||||
rsa_pkcs1_with_sha512 = 13,
|
||||
|
||||
// sha384WithRSAEncryption (OID 1.2.840.113549.1.1.12, RFC 4055 Section 5)
|
||||
rsa_pkcs1_with_sha384 = 14,
|
||||
|
||||
// sha256WithRSAEncryption (OID 1.2.840.113549.1.1.11, RFC 4055 Section 5)
|
||||
rsa_pkcs1_with_sha256 = 15,
|
||||
|
||||
// sha-1WithRSAEncryption (OID 1.2.840.113549.1.1.5, RFC 3279 Section 2.2.1)
|
||||
rsa_pkcs1_with_sha1 = 16,
|
||||
|
||||
// Used to indicate any unsupported algorithm.
|
||||
unsupported_algorithm = 19,
|
||||
};
|
||||
|
||||
struct SignedDataWithSignature final
|
||||
{
|
||||
public:
|
||||
Input data;
|
||||
SignatureAlgorithm algorithm;
|
||||
Input digest;
|
||||
DigestAlgorithm digestAlgorithm;
|
||||
Input signature;
|
||||
|
||||
void operator=(const SignedDataWithSignature&) = delete;
|
||||
void operator=(const SignedDigest&) = delete;
|
||||
};
|
||||
|
||||
enum class EndEntityOrCA { MustBeEndEntity = 0, MustBeCA = 1 };
|
||||
@ -311,6 +280,17 @@ public:
|
||||
EndEntityOrCA endEntityOrCA,
|
||||
unsigned int modulusSizeInBits) = 0;
|
||||
|
||||
// Verify the given RSA PKCS#1.5 signature on the given digest using the
|
||||
// given RSA public key.
|
||||
//
|
||||
// CheckRSAPublicKeyModulusSizeInBits will be called before calling this
|
||||
// function, so it is not necessary to repeat those checks here. However,
|
||||
// VerifyRSAPKCS1SignedDigest *is* responsible for doing the mathematical
|
||||
// verification of the public key validity as specified in NIST SP 800-56A.
|
||||
virtual Result VerifyRSAPKCS1SignedDigest(
|
||||
const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) = 0;
|
||||
|
||||
// Check that the given named ECC curve is acceptable for ECDSA signatures.
|
||||
//
|
||||
// Return Success if the curve is acceptable,
|
||||
@ -319,31 +299,29 @@ public:
|
||||
virtual Result CheckECDSACurveIsAcceptable(EndEntityOrCA endEntityOrCA,
|
||||
NamedCurve curve) = 0;
|
||||
|
||||
// Verify the given signature using the given public key.
|
||||
// Verify the given ECDSA signature on the given digest using the given ECC
|
||||
// public key.
|
||||
//
|
||||
// Most implementations of this function should probably forward the call
|
||||
// directly to mozilla::pkix::VerifySignedData.
|
||||
//
|
||||
// CheckRSAPublicKeyModulusSizeInBits or CheckECDSACurveIsAcceptable will
|
||||
// be called before calling this function, so it is not necessary to repeat
|
||||
// those checks in VerifySignedData. However, VerifySignedData *is*
|
||||
// responsible for doing the mathematical verification of the public key
|
||||
// validity as specified in NIST SP 800-56A.
|
||||
virtual Result VerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo) = 0;
|
||||
// CheckECDSACurveIsAcceptable will be called before calling this function,
|
||||
// so it is not necessary to repeat that check here. However,
|
||||
// VerifyECDSASignedDigest *is* responsible for doing the mathematical
|
||||
// verification of the public key validity as specified in NIST SP 800-56A.
|
||||
virtual Result VerifyECDSASignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) = 0;
|
||||
|
||||
// Compute the SHA-1 hash of the data in the current item.
|
||||
// Compute a digest of the data in item using the given digest algorithm.
|
||||
//
|
||||
// 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).
|
||||
// digestBuf points to a buffer to where the digest will be written.
|
||||
// digestBufLen will be the size of the digest output (20 for SHA-1,
|
||||
// 32 for SHA-256, etc.).
|
||||
//
|
||||
// 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 Result DigestBuf(Input item, /*out*/ uint8_t* digestBuf,
|
||||
virtual Result DigestBuf(Input item,
|
||||
DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf,
|
||||
size_t digestBufLen) = 0;
|
||||
protected:
|
||||
TrustDomain() { }
|
||||
|
@ -80,6 +80,11 @@ private:
|
||||
const unsigned int subCACount;
|
||||
const Result deferredSubjectError;
|
||||
|
||||
// Initialized lazily.
|
||||
uint8_t subjectSignatureDigestBuf[MAX_DIGEST_SIZE_IN_BYTES];
|
||||
der::PublicKeyAlgorithm subjectSignaturePublicKeyAlg;
|
||||
SignedDigest subjectSignature;
|
||||
|
||||
Result RecordResult(Result currentResult, /*out*/ bool& keepGoing);
|
||||
Result result;
|
||||
bool resultWasSet;
|
||||
@ -192,8 +197,22 @@ PathBuildingStep::Check(Input potentialIssuerDER,
|
||||
return RecordResult(rv, keepGoing);
|
||||
}
|
||||
|
||||
rv = WrappedVerifySignedData(trustDomain, subject.GetSignedData(),
|
||||
potentialIssuer.GetSubjectPublicKeyInfo());
|
||||
// Calculate the digest of the subject's signed data if we haven't already
|
||||
// done so. We do this lazily to avoid doing it at all if we backtrack before
|
||||
// getting to this point. We cache the result to avoid recalculating it if we
|
||||
// backtrack after getting to this point.
|
||||
if (subjectSignature.digest.GetLength() == 0) {
|
||||
rv = DigestSignedData(trustDomain, subject.GetSignedData(),
|
||||
subjectSignatureDigestBuf,
|
||||
subjectSignaturePublicKeyAlg, subjectSignature);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
rv = VerifySignedDigest(trustDomain, subjectSignaturePublicKeyAlg,
|
||||
subjectSignature,
|
||||
potentialIssuer.GetSubjectPublicKeyInfo());
|
||||
if (rv != Success) {
|
||||
return RecordResult(rv, keepGoing);
|
||||
}
|
||||
|
@ -82,8 +82,7 @@ BackCert::Init()
|
||||
// XXX: Ignored. What are we supposed to check? This seems totally redundant
|
||||
// with Certificate.signatureAlgorithm. Is it important to check that they
|
||||
// are consistent with each other? It doesn't seem to matter!
|
||||
SignatureAlgorithm signature;
|
||||
rv = der::SignatureAlgorithmIdentifier(tbsCertificate, signature);
|
||||
rv = der::ExpectTagAndGetValue(tbsCertificate, der::SEQUENCE, signature);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -95,48 +95,28 @@ OptionalNull(Reader& input)
|
||||
namespace {
|
||||
|
||||
Result
|
||||
DigestAlgorithmOIDValue(Reader& algorithmID,
|
||||
/*out*/ DigestAlgorithm& algorithm)
|
||||
AlgorithmIdentifierValue(Reader& input, /*out*/ Reader& algorithmOIDValue)
|
||||
{
|
||||
// RFC 4055 Section 2.1
|
||||
// python DottedOIDToCode.py id-sha1 1.3.14.3.2.26
|
||||
static const uint8_t id_sha1[] = {
|
||||
0x2b, 0x0e, 0x03, 0x02, 0x1a
|
||||
};
|
||||
// python DottedOIDToCode.py id-sha256 2.16.840.1.101.3.4.2.1
|
||||
static const uint8_t id_sha256[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
|
||||
};
|
||||
// python DottedOIDToCode.py id-sha384 2.16.840.1.101.3.4.2.2
|
||||
static const uint8_t id_sha384[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
|
||||
};
|
||||
// python DottedOIDToCode.py id-sha512 2.16.840.1.101.3.4.2.3
|
||||
static const uint8_t id_sha512[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
|
||||
};
|
||||
|
||||
// Matching is attempted based on a rough estimate of the commonality of the
|
||||
// algorithm, to minimize the number of MatchRest calls.
|
||||
if (algorithmID.MatchRest(id_sha1)) {
|
||||
algorithm = DigestAlgorithm::sha1;
|
||||
} else if (algorithmID.MatchRest(id_sha256)) {
|
||||
algorithm = DigestAlgorithm::sha256;
|
||||
} else if (algorithmID.MatchRest(id_sha384)) {
|
||||
algorithm = DigestAlgorithm::sha384;
|
||||
} else if (algorithmID.MatchRest(id_sha512)) {
|
||||
algorithm = DigestAlgorithm::sha512;
|
||||
} else {
|
||||
return Result::ERROR_INVALID_ALGORITHM;
|
||||
Result rv = ExpectTagAndGetValue(input, der::OIDTag, algorithmOIDValue);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return Success;
|
||||
return OptionalNull(input);
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
Result
|
||||
SignatureAlgorithmOIDValue(Reader& algorithmID,
|
||||
/*out*/ SignatureAlgorithm& algorithm)
|
||||
SignatureAlgorithmIdentifierValue(Reader& input,
|
||||
/*out*/ PublicKeyAlgorithm& publicKeyAlgorithm,
|
||||
/*out*/ DigestAlgorithm& digestAlgorithm)
|
||||
{
|
||||
Reader algorithmID;
|
||||
Result rv = AlgorithmIdentifierValue(input, algorithmID);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// RFC 5758 Section 3.2 (ecdsa-with-SHA224 is intentionally excluded)
|
||||
// python DottedOIDToCode.py ecdsa-with-SHA256 1.2.840.10045.4.3.2
|
||||
static const uint8_t ecdsa_with_SHA256[] = {
|
||||
@ -198,73 +178,85 @@ SignatureAlgorithmOIDValue(Reader& algorithmID,
|
||||
// Matching is attempted based on a rough estimate of the commonality of the
|
||||
// algorithm, to minimize the number of MatchRest calls.
|
||||
if (algorithmID.MatchRest(sha256WithRSAEncryption)) {
|
||||
algorithm = SignatureAlgorithm::rsa_pkcs1_with_sha256;
|
||||
publicKeyAlgorithm = PublicKeyAlgorithm::RSA_PKCS1;
|
||||
digestAlgorithm = DigestAlgorithm::sha256;
|
||||
} else if (algorithmID.MatchRest(ecdsa_with_SHA256)) {
|
||||
algorithm = SignatureAlgorithm::ecdsa_with_sha256;
|
||||
publicKeyAlgorithm = PublicKeyAlgorithm::ECDSA;
|
||||
digestAlgorithm = DigestAlgorithm::sha256;
|
||||
} else if (algorithmID.MatchRest(sha_1WithRSAEncryption)) {
|
||||
algorithm = SignatureAlgorithm::rsa_pkcs1_with_sha1;
|
||||
publicKeyAlgorithm = PublicKeyAlgorithm::RSA_PKCS1;
|
||||
digestAlgorithm = DigestAlgorithm::sha1;
|
||||
} else if (algorithmID.MatchRest(ecdsa_with_SHA1)) {
|
||||
algorithm = SignatureAlgorithm::ecdsa_with_sha1;
|
||||
publicKeyAlgorithm = PublicKeyAlgorithm::ECDSA;
|
||||
digestAlgorithm = DigestAlgorithm::sha1;
|
||||
} else if (algorithmID.MatchRest(ecdsa_with_SHA384)) {
|
||||
algorithm = SignatureAlgorithm::ecdsa_with_sha384;
|
||||
publicKeyAlgorithm = PublicKeyAlgorithm::ECDSA;
|
||||
digestAlgorithm = DigestAlgorithm::sha384;
|
||||
} else if (algorithmID.MatchRest(ecdsa_with_SHA512)) {
|
||||
algorithm = SignatureAlgorithm::ecdsa_with_sha512;
|
||||
publicKeyAlgorithm = PublicKeyAlgorithm::ECDSA;
|
||||
digestAlgorithm = DigestAlgorithm::sha512;
|
||||
} else if (algorithmID.MatchRest(sha384WithRSAEncryption)) {
|
||||
algorithm = SignatureAlgorithm::rsa_pkcs1_with_sha384;
|
||||
publicKeyAlgorithm = PublicKeyAlgorithm::RSA_PKCS1;
|
||||
digestAlgorithm = DigestAlgorithm::sha384;
|
||||
} else if (algorithmID.MatchRest(sha512WithRSAEncryption)) {
|
||||
algorithm = SignatureAlgorithm::rsa_pkcs1_with_sha512;
|
||||
publicKeyAlgorithm = PublicKeyAlgorithm::RSA_PKCS1;
|
||||
digestAlgorithm = DigestAlgorithm::sha512;
|
||||
} else if (algorithmID.MatchRest(sha1WithRSASignature)) {
|
||||
// XXX(bug 1042479): recognize this old OID for compatibility.
|
||||
algorithm = SignatureAlgorithm::rsa_pkcs1_with_sha1;
|
||||
publicKeyAlgorithm = PublicKeyAlgorithm::RSA_PKCS1;
|
||||
digestAlgorithm = DigestAlgorithm::sha1;
|
||||
} else {
|
||||
algorithm = SignatureAlgorithm::unsupported_algorithm;
|
||||
return Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
template <typename OidValueParser, typename Algorithm>
|
||||
Result
|
||||
AlgorithmIdentifier(OidValueParser oidValueParser, Reader& input,
|
||||
/*out*/ Algorithm& algorithm)
|
||||
{
|
||||
Reader value;
|
||||
Result rv = ExpectTagAndGetValue(input, SEQUENCE, value);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
Reader algorithmID;
|
||||
rv = ExpectTagAndGetValue(value, der::OIDTag, algorithmID);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
rv = oidValueParser(algorithmID, algorithm);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = OptionalNull(value);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return End(value);
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
Result
|
||||
SignatureAlgorithmIdentifier(Reader& input,
|
||||
/*out*/ SignatureAlgorithm& algorithm)
|
||||
{
|
||||
return AlgorithmIdentifier(SignatureAlgorithmOIDValue, input, algorithm);
|
||||
}
|
||||
|
||||
Result
|
||||
DigestAlgorithmIdentifier(Reader& input, /*out*/ DigestAlgorithm& algorithm)
|
||||
{
|
||||
return AlgorithmIdentifier(DigestAlgorithmOIDValue, input, algorithm);
|
||||
Reader r;
|
||||
return der::Nested(input, SEQUENCE, [&algorithm](Reader& r) -> Result {
|
||||
Reader algorithmID;
|
||||
Result rv = AlgorithmIdentifierValue(r, algorithmID);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// RFC 4055 Section 2.1
|
||||
// python DottedOIDToCode.py id-sha1 1.3.14.3.2.26
|
||||
static const uint8_t id_sha1[] = {
|
||||
0x2b, 0x0e, 0x03, 0x02, 0x1a
|
||||
};
|
||||
// python DottedOIDToCode.py id-sha256 2.16.840.1.101.3.4.2.1
|
||||
static const uint8_t id_sha256[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
|
||||
};
|
||||
// python DottedOIDToCode.py id-sha384 2.16.840.1.101.3.4.2.2
|
||||
static const uint8_t id_sha384[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
|
||||
};
|
||||
// python DottedOIDToCode.py id-sha512 2.16.840.1.101.3.4.2.3
|
||||
static const uint8_t id_sha512[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
|
||||
};
|
||||
|
||||
// Matching is attempted based on a rough estimate of the commonality of the
|
||||
// algorithm, to minimize the number of MatchRest calls.
|
||||
if (algorithmID.MatchRest(id_sha1)) {
|
||||
algorithm = DigestAlgorithm::sha1;
|
||||
} else if (algorithmID.MatchRest(id_sha256)) {
|
||||
algorithm = DigestAlgorithm::sha256;
|
||||
} else if (algorithmID.MatchRest(id_sha384)) {
|
||||
algorithm = DigestAlgorithm::sha384;
|
||||
} else if (algorithmID.MatchRest(id_sha512)) {
|
||||
algorithm = DigestAlgorithm::sha512;
|
||||
} else {
|
||||
return Result::ERROR_INVALID_ALGORITHM;
|
||||
}
|
||||
|
||||
return Success;
|
||||
});
|
||||
}
|
||||
|
||||
Result
|
||||
@ -284,7 +276,7 @@ SignedData(Reader& input, /*out*/ Reader& tbs,
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = SignatureAlgorithmIdentifier(input, signedData.algorithm);
|
||||
rv = ExpectTagAndGetValue(input, der::SEQUENCE, signedData.algorithm);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -600,8 +600,26 @@ OptionalExtensions(Reader& input, uint8_t tag,
|
||||
Result DigestAlgorithmIdentifier(Reader& input,
|
||||
/*out*/ DigestAlgorithm& algorithm);
|
||||
|
||||
Result SignatureAlgorithmIdentifier(Reader& input,
|
||||
/*out*/ SignatureAlgorithm& algorithm);
|
||||
enum PublicKeyAlgorithm
|
||||
{
|
||||
RSA_PKCS1,
|
||||
ECDSA,
|
||||
};
|
||||
|
||||
Result SignatureAlgorithmIdentifierValue(
|
||||
Reader& input,
|
||||
/*out*/ PublicKeyAlgorithm& publicKeyAlgorithm,
|
||||
/*out*/ DigestAlgorithm& digestAlgorithm);
|
||||
|
||||
struct SignedDataWithSignature final
|
||||
{
|
||||
public:
|
||||
Input data;
|
||||
Input algorithm;
|
||||
Input signature;
|
||||
|
||||
void operator=(const SignedDataWithSignature&) = delete;
|
||||
};
|
||||
|
||||
// Parses a SEQUENCE into tbs and then parses an AlgorithmIdentifier followed
|
||||
// by a BIT STRING into signedData. This handles the commonality between
|
||||
@ -609,6 +627,8 @@ Result SignatureAlgorithmIdentifier(Reader& input,
|
||||
// the case of an OCSP response, the caller needs to parse the certs
|
||||
// separately.
|
||||
//
|
||||
// Note that signatureAlgorithm is NOT parsed or validated.
|
||||
//
|
||||
// Certificate ::= SEQUENCE {
|
||||
// tbsCertificate TBSCertificate,
|
||||
// signatureAlgorithm AlgorithmIdentifier,
|
||||
|
@ -37,48 +37,20 @@
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
|
||||
namespace {
|
||||
|
||||
Result
|
||||
VerifySignedDataNSS(const SignedDataWithSignature& sd,
|
||||
Input subjectPublicKeyInfo, void* pkcs11PinArg)
|
||||
VerifySignedDigest(const SignedDigest& sd,
|
||||
Input subjectPublicKeyInfo,
|
||||
SECOidTag pubKeyAlg,
|
||||
void* pkcs11PinArg)
|
||||
{
|
||||
SECOidTag pubKeyAlg;
|
||||
SECOidTag digestAlg;
|
||||
switch (sd.algorithm) {
|
||||
case SignatureAlgorithm::ecdsa_with_sha512:
|
||||
pubKeyAlg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
|
||||
digestAlg = SEC_OID_SHA512;
|
||||
break;
|
||||
case SignatureAlgorithm::ecdsa_with_sha384:
|
||||
pubKeyAlg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
|
||||
digestAlg = SEC_OID_SHA384;
|
||||
break;
|
||||
case SignatureAlgorithm::ecdsa_with_sha256:
|
||||
pubKeyAlg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
|
||||
digestAlg = SEC_OID_SHA256;
|
||||
break;
|
||||
case SignatureAlgorithm::ecdsa_with_sha1:
|
||||
pubKeyAlg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
|
||||
digestAlg = SEC_OID_SHA1;
|
||||
break;
|
||||
case SignatureAlgorithm::rsa_pkcs1_with_sha512:
|
||||
pubKeyAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
|
||||
digestAlg = SEC_OID_SHA512;
|
||||
break;
|
||||
case SignatureAlgorithm::rsa_pkcs1_with_sha384:
|
||||
pubKeyAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
|
||||
digestAlg = SEC_OID_SHA384;
|
||||
break;
|
||||
case SignatureAlgorithm::rsa_pkcs1_with_sha256:
|
||||
pubKeyAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
|
||||
digestAlg = SEC_OID_SHA256;
|
||||
break;
|
||||
case SignatureAlgorithm::rsa_pkcs1_with_sha1:
|
||||
pubKeyAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
|
||||
digestAlg = SEC_OID_SHA1;
|
||||
break;
|
||||
case SignatureAlgorithm::unsupported_algorithm: // fall through
|
||||
return NotReached("unknown signature algorithm",
|
||||
Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
|
||||
switch (sd.digestAlgorithm) {
|
||||
case DigestAlgorithm::sha512: digestAlg = SEC_OID_SHA512; break;
|
||||
case DigestAlgorithm::sha384: digestAlg = SEC_OID_SHA384; break;
|
||||
case DigestAlgorithm::sha256: digestAlg = SEC_OID_SHA256; break;
|
||||
case DigestAlgorithm::sha1: digestAlg = SEC_OID_SHA1; break;
|
||||
MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
|
||||
}
|
||||
|
||||
@ -95,19 +67,11 @@ VerifySignedDataNSS(const SignedDataWithSignature& sd,
|
||||
return MapPRErrorCodeToResult(PR_GetError());
|
||||
}
|
||||
|
||||
// The static_cast is safe as long as the length of the data in sd.data can
|
||||
// fit in an int. Right now that length is stored as a uint16_t, so this
|
||||
// works. In the future this may change, hence the assertion.
|
||||
// See also bug 921585.
|
||||
static_assert(sizeof(decltype(sd.data.GetLength())) < sizeof(int),
|
||||
"sd.data.GetLength() must fit in an int");
|
||||
SECItem dataSECItem(UnsafeMapInputToSECItem(sd.data));
|
||||
SECItem digestSECItem(UnsafeMapInputToSECItem(sd.digest));
|
||||
SECItem signatureSECItem(UnsafeMapInputToSECItem(sd.signature));
|
||||
SECStatus srv = VFY_VerifyDataDirect(dataSECItem.data,
|
||||
static_cast<int>(dataSECItem.len),
|
||||
pubKey.get(), &signatureSECItem,
|
||||
pubKeyAlg, digestAlg, nullptr,
|
||||
pkcs11PinArg);
|
||||
SECStatus srv = VFY_VerifyDigestDirect(&digestSECItem, pubKey.get(),
|
||||
&signatureSECItem, pubKeyAlg,
|
||||
digestAlg, pkcs11PinArg);
|
||||
if (srv != SECSuccess) {
|
||||
return MapPRErrorCodeToResult(PR_GetError());
|
||||
}
|
||||
@ -115,14 +79,45 @@ VerifySignedDataNSS(const SignedDataWithSignature& sd,
|
||||
return Success;
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
Result
|
||||
DigestBufNSS(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
|
||||
VerifyRSAPKCS1SignedDigestNSS(const SignedDigest& sd,
|
||||
Input subjectPublicKeyInfo,
|
||||
void* pkcs11PinArg)
|
||||
{
|
||||
static_assert(TrustDomain::DIGEST_LENGTH == SHA1_LENGTH,
|
||||
"TrustDomain::DIGEST_LENGTH must be 20 (SHA-1 digest length)");
|
||||
if (digestBufLen != TrustDomain::DIGEST_LENGTH) {
|
||||
return NotReached("invalid hash length", Result::FATAL_ERROR_INVALID_ARGS);
|
||||
return VerifySignedDigest(sd, subjectPublicKeyInfo,
|
||||
SEC_OID_PKCS1_RSA_ENCRYPTION, pkcs11PinArg);
|
||||
}
|
||||
|
||||
Result
|
||||
VerifyECDSASignedDigestNSS(const SignedDigest& sd,
|
||||
Input subjectPublicKeyInfo,
|
||||
void* pkcs11PinArg)
|
||||
{
|
||||
return VerifySignedDigest(sd, subjectPublicKeyInfo,
|
||||
SEC_OID_ANSIX962_EC_PUBLIC_KEY, pkcs11PinArg);
|
||||
}
|
||||
|
||||
Result
|
||||
DigestBufNSS(Input item,
|
||||
DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf,
|
||||
size_t digestBufLen)
|
||||
{
|
||||
SECOidTag oid;
|
||||
size_t bits;
|
||||
switch (digestAlg) {
|
||||
case DigestAlgorithm::sha512: oid = SEC_OID_SHA512; bits = 512; break;
|
||||
case DigestAlgorithm::sha384: oid = SEC_OID_SHA384; bits = 384; break;
|
||||
case DigestAlgorithm::sha256: oid = SEC_OID_SHA256; bits = 256; break;
|
||||
case DigestAlgorithm::sha1: oid = SEC_OID_SHA1; bits = 160; break;
|
||||
MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
|
||||
}
|
||||
if (digestBufLen != bits / 8) {
|
||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
SECItem itemSECItem = UnsafeMapInputToSECItem(item);
|
||||
if (itemSECItem.len >
|
||||
static_cast<decltype(itemSECItem.len)>(
|
||||
@ -130,7 +125,7 @@ DigestBufNSS(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
|
||||
PR_NOT_REACHED("large items should not be possible here");
|
||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||
}
|
||||
SECStatus srv = PK11_HashBuf(SEC_OID_SHA1, digestBuf, itemSECItem.data,
|
||||
SECStatus srv = PK11_HashBuf(oid, digestBuf, itemSECItem.data,
|
||||
static_cast<int32_t>(itemSECItem.len));
|
||||
if (srv != SECSuccess) {
|
||||
return MapPRErrorCodeToResult(PR_GetError());
|
||||
|
@ -27,7 +27,12 @@
|
||||
#include "pkix/pkix.h"
|
||||
#include "pkixcheck.h"
|
||||
#include "pkixutil.h"
|
||||
#include "pkixder.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const size_t SHA1_DIGEST_LENGTH = 160 / 8;
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
|
||||
@ -128,8 +133,9 @@ CheckOCSPResponseSignerCert(TrustDomain& trustDomain,
|
||||
}
|
||||
|
||||
// TODO(bug 926260): check name constraints
|
||||
rv = WrappedVerifySignedData(trustDomain, potentialSigner.GetSignedData(),
|
||||
issuerSubjectPublicKeyInfo);
|
||||
|
||||
rv = VerifySignedData(trustDomain, potentialSigner.GetSignedData(),
|
||||
issuerSubjectPublicKeyInfo);
|
||||
|
||||
// TODO: check for revocation of the OCSP responder certificate unless no-check
|
||||
// or the caller forcing no-check. To properly support the no-check policy, we'd
|
||||
@ -150,7 +156,7 @@ static inline Result BasicResponse(Reader&, Context&);
|
||||
static inline Result ResponseData(
|
||||
Reader& tbsResponseData,
|
||||
Context& context,
|
||||
const SignedDataWithSignature& signedResponseData,
|
||||
const der::SignedDataWithSignature& signedResponseData,
|
||||
const DERArray& certs);
|
||||
static inline Result SingleResponse(Reader& input, Context& context);
|
||||
static Result ExtensionNotUnderstood(Reader& extnID, Input extnValue,
|
||||
@ -201,10 +207,10 @@ MatchResponderID(TrustDomain& trustDomain,
|
||||
|
||||
static Result
|
||||
VerifyOCSPSignedData(TrustDomain& trustDomain,
|
||||
const SignedDataWithSignature& signedResponseData,
|
||||
const der::SignedDataWithSignature& signedResponseData,
|
||||
Input spki)
|
||||
{
|
||||
Result rv = WrappedVerifySignedData(trustDomain, signedResponseData, spki);
|
||||
Result rv = VerifySignedData(trustDomain, signedResponseData, spki);
|
||||
if (rv == Result::ERROR_BAD_SIGNATURE) {
|
||||
rv = Result::ERROR_OCSP_BAD_SIGNATURE;
|
||||
}
|
||||
@ -220,7 +226,7 @@ VerifyOCSPSignedData(TrustDomain& trustDomain,
|
||||
static Result
|
||||
VerifySignature(Context& context, ResponderIDType responderIDType,
|
||||
Input responderID, const DERArray& certs,
|
||||
const SignedDataWithSignature& signedResponseData)
|
||||
const der::SignedDataWithSignature& signedResponseData)
|
||||
{
|
||||
bool match;
|
||||
Result rv = MatchResponderID(context.trustDomain, responderIDType,
|
||||
@ -391,7 +397,7 @@ Result
|
||||
BasicResponse(Reader& input, Context& context)
|
||||
{
|
||||
Reader tbsResponseData;
|
||||
SignedDataWithSignature signedData;
|
||||
der::SignedDataWithSignature signedData;
|
||||
Result rv = der::SignedData(input, tbsResponseData, signedData);
|
||||
if (rv != Success) {
|
||||
if (rv == Result::ERROR_BAD_SIGNATURE) {
|
||||
@ -448,7 +454,7 @@ BasicResponse(Reader& input, Context& context)
|
||||
// responseExtensions [1] EXPLICIT Extensions OPTIONAL }
|
||||
static inline Result
|
||||
ResponseData(Reader& input, Context& context,
|
||||
const SignedDataWithSignature& signedResponseData,
|
||||
const der::SignedDataWithSignature& signedResponseData,
|
||||
const DERArray& certs)
|
||||
{
|
||||
der::Version version;
|
||||
@ -718,15 +724,16 @@ CertID(Reader& input, const Context& context, /*out*/ bool& match)
|
||||
return Success;
|
||||
}
|
||||
|
||||
if (issuerNameHash.GetLength() != TrustDomain::DIGEST_LENGTH) {
|
||||
if (issuerNameHash.GetLength() != SHA1_DIGEST_LENGTH) {
|
||||
return Result::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[TrustDomain::DIGEST_LENGTH];
|
||||
rv = context.trustDomain.DigestBuf(context.certID.issuer, hashBuf,
|
||||
uint8_t hashBuf[SHA1_DIGEST_LENGTH];
|
||||
rv = context.trustDomain.DigestBuf(context.certID.issuer,
|
||||
DigestAlgorithm::sha1, hashBuf,
|
||||
sizeof(hashBuf));
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
@ -756,10 +763,10 @@ static Result
|
||||
MatchKeyHash(TrustDomain& trustDomain, Input keyHash,
|
||||
const Input subjectPublicKeyInfo, /*out*/ bool& match)
|
||||
{
|
||||
if (keyHash.GetLength() != TrustDomain::DIGEST_LENGTH) {
|
||||
if (keyHash.GetLength() != SHA1_DIGEST_LENGTH) {
|
||||
return Result::ERROR_OCSP_MALFORMED_RESPONSE;
|
||||
}
|
||||
static uint8_t hashBuf[TrustDomain::DIGEST_LENGTH];
|
||||
static uint8_t hashBuf[SHA1_DIGEST_LENGTH];
|
||||
Result rv = KeyHash(trustDomain, subjectPublicKeyInfo, hashBuf,
|
||||
sizeof hashBuf);
|
||||
if (rv != Success) {
|
||||
@ -775,7 +782,7 @@ Result
|
||||
KeyHash(TrustDomain& trustDomain, const Input subjectPublicKeyInfo,
|
||||
/*out*/ uint8_t* hashBuf, size_t hashBufSize)
|
||||
{
|
||||
if (!hashBuf || hashBufSize != TrustDomain::DIGEST_LENGTH) {
|
||||
if (!hashBuf || hashBufSize != SHA1_DIGEST_LENGTH) {
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
@ -808,7 +815,8 @@ KeyHash(TrustDomain& trustDomain, const Input subjectPublicKeyInfo,
|
||||
return rv;
|
||||
}
|
||||
|
||||
return trustDomain.DigestBuf(subjectPublicKey, hashBuf, hashBufSize);
|
||||
return trustDomain.DigestBuf(subjectPublicKey, DigestAlgorithm::sha1,
|
||||
hashBuf, hashBufSize);
|
||||
}
|
||||
|
||||
Result
|
||||
@ -868,7 +876,7 @@ CreateEncodedOCSPRequest(TrustDomain& trustDomain, const struct CertID& certID,
|
||||
0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJECT IDENTIFIER id-sha1
|
||||
0x05, 0x00, // NULL
|
||||
};
|
||||
static const uint8_t hashLen = TrustDomain::DIGEST_LENGTH;
|
||||
static const uint8_t hashLen = 160 / 8;
|
||||
|
||||
static const unsigned int totalLenWithoutSerialNumberData
|
||||
= 2 // OCSPRequest
|
||||
@ -913,7 +921,8 @@ CreateEncodedOCSPRequest(TrustDomain& trustDomain, const struct CertID& certID,
|
||||
// reqCert.issuerNameHash (OCTET STRING)
|
||||
*d++ = 0x04;
|
||||
*d++ = hashLen;
|
||||
Result rv = trustDomain.DigestBuf(certID.issuer, d, hashLen);
|
||||
Result rv = trustDomain.DigestBuf(certID.issuer, DigestAlgorithm::sha1, d,
|
||||
hashLen);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -54,7 +54,9 @@ public:
|
||||
|
||||
const Input GetDER() const { return der; }
|
||||
der::Version GetVersion() const { return version; }
|
||||
const SignedDataWithSignature& GetSignedData() const { return signedData; }
|
||||
const der::SignedDataWithSignature& GetSignedData() const {
|
||||
return signedData;
|
||||
}
|
||||
const Input GetIssuer() const { return issuer; }
|
||||
// XXX: "validity" is a horrible name for the structure that holds
|
||||
// notBefore & notAfter, but that is the name used in RFC 5280 and we use the
|
||||
@ -107,8 +109,6 @@ public:
|
||||
BackCert const* const childCert;
|
||||
|
||||
private:
|
||||
der::Version version;
|
||||
|
||||
// When parsing certificates in BackCert::Init, we don't accept empty
|
||||
// extensions. Consequently, we don't have to store a distinction between
|
||||
// empty extensions and extensions that weren't included. However, when
|
||||
@ -120,13 +120,16 @@ private:
|
||||
return item.GetLength() > 0 ? &item : nullptr;
|
||||
}
|
||||
|
||||
SignedDataWithSignature signedData;
|
||||
der::SignedDataWithSignature signedData;
|
||||
|
||||
der::Version version;
|
||||
Input serialNumber;
|
||||
Input signature;
|
||||
Input issuer;
|
||||
// XXX: "validity" is a horrible name for the structure that holds
|
||||
// notBefore & notAfter, but that is the name used in RFC 5280 and we use the
|
||||
// RFC 5280 names for everything.
|
||||
Input validity;
|
||||
Input serialNumber;
|
||||
Input subject;
|
||||
Input subjectPublicKeyInfo;
|
||||
|
||||
@ -197,19 +200,23 @@ DaysBeforeYear(unsigned int year)
|
||||
+ ((year - 1u) / 400u); // except years divisible by 400.
|
||||
}
|
||||
|
||||
// Ensures that we do not call the TrustDomain's VerifySignedData function if
|
||||
// the algorithm is unsupported.
|
||||
inline Result
|
||||
WrappedVerifySignedData(TrustDomain& trustDomain,
|
||||
const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
if (signedData.algorithm == SignatureAlgorithm::unsupported_algorithm) {
|
||||
return Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED;
|
||||
}
|
||||
static const size_t MAX_DIGEST_SIZE_IN_BYTES = 512 / 8; // sha-512
|
||||
|
||||
return trustDomain.VerifySignedData(signedData, subjectPublicKeyInfo);
|
||||
}
|
||||
Result DigestSignedData(TrustDomain& trustDomain,
|
||||
const der::SignedDataWithSignature& signedData,
|
||||
/*out*/ uint8_t(&digestBuf)[MAX_DIGEST_SIZE_IN_BYTES],
|
||||
/*out*/ der::PublicKeyAlgorithm& publicKeyAlg,
|
||||
/*out*/ SignedDigest& signedDigest);
|
||||
|
||||
Result VerifySignedDigest(TrustDomain& trustDomain,
|
||||
der::PublicKeyAlgorithm publicKeyAlg,
|
||||
const SignedDigest& signedDigest,
|
||||
Input signerSubjectPublicKeyInfo);
|
||||
|
||||
// Combines DigestSignedData and VerifySignedDigest
|
||||
Result VerifySignedData(TrustDomain& trustDomain,
|
||||
const der::SignedDataWithSignature& signedData,
|
||||
Input signerSubjectPublicKeyInfo);
|
||||
|
||||
// In a switch over an enum, sometimes some compilers are not satisfied that
|
||||
// all control flow paths have been considered unless there is a default case.
|
||||
|
103
security/pkix/lib/pkixverify.cpp
Normal file
103
security/pkix/lib/pkixverify.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This code is made available to you under your choice of the following sets
|
||||
* of licensing terms:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
/* Copyright 2015 Mozilla Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "pkixutil.h"
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
|
||||
Result
|
||||
DigestSignedData(TrustDomain& trustDomain,
|
||||
const der::SignedDataWithSignature& signedData,
|
||||
/*out*/ uint8_t(&digestBuf)[MAX_DIGEST_SIZE_IN_BYTES],
|
||||
/*out*/ der::PublicKeyAlgorithm& publicKeyAlg,
|
||||
/*out*/ SignedDigest& signedDigest)
|
||||
{
|
||||
Reader signatureAlg(signedData.algorithm);
|
||||
Result rv = der::SignatureAlgorithmIdentifierValue(
|
||||
signatureAlg, publicKeyAlg, signedDigest.digestAlgorithm);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
if (!signatureAlg.AtEnd()) {
|
||||
return Result::ERROR_BAD_DER;
|
||||
}
|
||||
|
||||
size_t digestLen;
|
||||
switch (signedDigest.digestAlgorithm) {
|
||||
case DigestAlgorithm::sha512: digestLen = 512 / 8; break;
|
||||
case DigestAlgorithm::sha384: digestLen = 384 / 8; break;
|
||||
case DigestAlgorithm::sha256: digestLen = 256 / 8; break;
|
||||
case DigestAlgorithm::sha1: digestLen = 160 / 8; break;
|
||||
MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
|
||||
}
|
||||
assert(digestLen <= sizeof(digestBuf));
|
||||
|
||||
rv = trustDomain.DigestBuf(signedData.data, signedDigest.digestAlgorithm,
|
||||
digestBuf, digestLen);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
rv = signedDigest.digest.Init(digestBuf, digestLen);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return signedDigest.signature.Init(signedData.signature);
|
||||
}
|
||||
|
||||
Result
|
||||
VerifySignedDigest(TrustDomain& trustDomain,
|
||||
der::PublicKeyAlgorithm publicKeyAlg,
|
||||
const SignedDigest& signedDigest,
|
||||
Input signerSubjectPublicKeyInfo)
|
||||
{
|
||||
switch (publicKeyAlg) {
|
||||
case der::PublicKeyAlgorithm::ECDSA:
|
||||
return trustDomain.VerifyECDSASignedDigest(signedDigest,
|
||||
signerSubjectPublicKeyInfo);
|
||||
case der::PublicKeyAlgorithm::RSA_PKCS1:
|
||||
return trustDomain.VerifyRSAPKCS1SignedDigest(signedDigest,
|
||||
signerSubjectPublicKeyInfo);
|
||||
MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
|
||||
}
|
||||
}
|
||||
|
||||
Result
|
||||
VerifySignedData(TrustDomain& trustDomain,
|
||||
const der::SignedDataWithSignature& signedData,
|
||||
Input signerSubjectPublicKeyInfo)
|
||||
{
|
||||
uint8_t digestBuf[MAX_DIGEST_SIZE_IN_BYTES];
|
||||
der::PublicKeyAlgorithm publicKeyAlg;
|
||||
SignedDigest signedDigest;
|
||||
Result rv = DigestSignedData(trustDomain, signedData, digestBuf,
|
||||
publicKeyAlg, signedDigest);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
return VerifySignedDigest(trustDomain, publicKeyAlg, signedDigest,
|
||||
signerSubjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
} } // namespace mozilla::pkix
|
@ -14,6 +14,7 @@ SOURCES += [
|
||||
'lib/pkixocsp.cpp',
|
||||
'lib/pkixresult.cpp',
|
||||
'lib/pkixtime.cpp',
|
||||
'lib/pkixverify.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
|
@ -153,16 +153,10 @@ private:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo) override
|
||||
Result DigestBuf(Input input, DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf, size_t digestLen) override
|
||||
{
|
||||
return TestVerifySignedData(signedData, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
Result DigestBuf(Input, /*out*/ uint8_t*, size_t) override
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
return TestDigestBuf(input, digestAlg, digestBuf, digestLen);
|
||||
}
|
||||
|
||||
Result CheckRSAPublicKeyModulusSizeInBits(EndEntityOrCA, unsigned int)
|
||||
@ -171,11 +165,23 @@ private:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifyRSAPKCS1SignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) override
|
||||
{
|
||||
return TestVerifyRSAPKCS1SignedDigest(signedDigest, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
Result CheckECDSACurveIsAcceptable(EndEntityOrCA, NamedCurve) override
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifyECDSASignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) override
|
||||
{
|
||||
return TestVerifyECDSASignedDigest(signedDigest, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
|
||||
std::map<ByteString, ByteString> subjectDERToCertDER;
|
||||
ByteString leafCACertDER;
|
||||
@ -322,16 +328,10 @@ public:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo) override
|
||||
Result DigestBuf(Input input, DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf, size_t digestLen) override
|
||||
{
|
||||
return TestVerifySignedData(signedData, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
Result DigestBuf(Input, /*out*/uint8_t*, size_t) override
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
return TestDigestBuf(input, digestAlg, digestBuf, digestLen);
|
||||
}
|
||||
|
||||
Result CheckRSAPublicKeyModulusSizeInBits(EndEntityOrCA, unsigned int)
|
||||
@ -340,11 +340,23 @@ public:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifyRSAPKCS1SignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) override
|
||||
{
|
||||
return TestVerifyRSAPKCS1SignedDigest(signedDigest, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
Result CheckECDSACurveIsAcceptable(EndEntityOrCA, NamedCurve) override
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifyECDSASignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) override
|
||||
{
|
||||
return TestVerifyECDSASignedDigest(signedDigest, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
private:
|
||||
ByteString rootDER;
|
||||
};
|
||||
@ -411,13 +423,7 @@ public:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifySignedData(const SignedDataWithSignature&, Input) override
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
Result DigestBuf(Input, /*out*/uint8_t*, size_t) override
|
||||
Result DigestBuf(Input, DigestAlgorithm, /*out*/uint8_t*, size_t) override
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
@ -426,12 +432,26 @@ public:
|
||||
Result CheckRSAPublicKeyModulusSizeInBits(EndEntityOrCA, unsigned int)
|
||||
override
|
||||
{
|
||||
return Success;
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
Result VerifyRSAPKCS1SignedDigest(const SignedDigest&, Input) override
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
Result CheckECDSACurveIsAcceptable(EndEntityOrCA, NamedCurve) override
|
||||
{
|
||||
return Success;
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
Result VerifyECDSASignedDigest(const SignedDigest&, Input) override
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
};
|
||||
|
||||
@ -514,16 +534,10 @@ public:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo) override
|
||||
Result DigestBuf(Input input, DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf, size_t digestLen) override
|
||||
{
|
||||
return TestVerifySignedData(signedData, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
Result DigestBuf(Input, /*out*/uint8_t*, size_t) override
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
return TestDigestBuf(input, digestAlg, digestBuf, digestLen);
|
||||
}
|
||||
|
||||
Result CheckRSAPublicKeyModulusSizeInBits(EndEntityOrCA, unsigned int)
|
||||
@ -532,11 +546,23 @@ public:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifyRSAPKCS1SignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) override
|
||||
{
|
||||
return TestVerifyRSAPKCS1SignedDigest(signedDigest, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
Result CheckECDSACurveIsAcceptable(EndEntityOrCA, NamedCurve) override
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifyECDSASignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) override
|
||||
{
|
||||
return TestVerifyECDSASignedDigest(signedDigest, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
private:
|
||||
const ByteString issuer;
|
||||
const bool expectedKeepGoing;
|
||||
|
@ -89,16 +89,10 @@ private:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo) override
|
||||
Result DigestBuf(Input input, DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf, size_t digestLen) override
|
||||
{
|
||||
return TestVerifySignedData(signedData, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
Result DigestBuf(Input, /*out*/ uint8_t*, size_t) override
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
return TestDigestBuf(input, digestAlg, digestBuf, digestLen);
|
||||
}
|
||||
|
||||
Result CheckRSAPublicKeyModulusSizeInBits(EndEntityOrCA, unsigned int)
|
||||
@ -107,10 +101,23 @@ private:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifyRSAPKCS1SignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) override
|
||||
{
|
||||
return TestVerifyRSAPKCS1SignedDigest(signedDigest, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
Result CheckECDSACurveIsAcceptable(EndEntityOrCA, NamedCurve) override
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifyECDSASignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) override
|
||||
{
|
||||
return TestVerifyECDSASignedDigest(signedDigest, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// python DottedOIDToCode.py --tlv unknownExtensionOID 1.3.6.1.4.1.13769.666.666.666.1.500.9.3
|
||||
|
@ -103,17 +103,10 @@ private:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo) override
|
||||
Result DigestBuf(Input input, DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf, size_t digestLen) override
|
||||
{
|
||||
EXPECT_NE(SignatureAlgorithm::unsupported_algorithm, signedData.algorithm);
|
||||
return TestVerifySignedData(signedData, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
Result DigestBuf(Input, uint8_t*, size_t) override
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
return TestDigestBuf(input, digestAlg, digestBuf, digestLen);
|
||||
}
|
||||
|
||||
Result CheckRSAPublicKeyModulusSizeInBits(EndEntityOrCA, unsigned int)
|
||||
@ -122,11 +115,23 @@ private:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifyRSAPKCS1SignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) override
|
||||
{
|
||||
return TestVerifyRSAPKCS1SignedDigest(signedDigest, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
Result CheckECDSACurveIsAcceptable(EndEntityOrCA, NamedCurve) override
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifyECDSASignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) override
|
||||
{
|
||||
return TestVerifyECDSASignedDigest(signedDigest, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
ByteString rootDER;
|
||||
ByteString rootSubjectDER;
|
||||
ByteString intDER;
|
||||
|
@ -190,23 +190,28 @@ TEST_F(pkixder_pki_types_tests, OptionalVersionMissing)
|
||||
|
||||
static const size_t MAX_ALGORITHM_OID_DER_LENGTH = 13;
|
||||
|
||||
template <typename T>
|
||||
struct AlgorithmIdentifierTestInfo
|
||||
struct InvalidAlgorithmIdentifierTestInfo
|
||||
{
|
||||
T algorithm;
|
||||
uint8_t der[MAX_ALGORITHM_OID_DER_LENGTH];
|
||||
size_t derLength;
|
||||
};
|
||||
|
||||
class pkixder_DigestAlgorithmIdentifier
|
||||
struct ValidDigestAlgorithmIdentifierTestInfo
|
||||
{
|
||||
DigestAlgorithm algorithm;
|
||||
uint8_t der[MAX_ALGORITHM_OID_DER_LENGTH];
|
||||
size_t derLength;
|
||||
};
|
||||
|
||||
class pkixder_DigestAlgorithmIdentifier_Valid
|
||||
: public ::testing::Test
|
||||
, public ::testing::WithParamInterface<
|
||||
AlgorithmIdentifierTestInfo<DigestAlgorithm>>
|
||||
, public ::testing::WithParamInterface<ValidDigestAlgorithmIdentifierTestInfo>
|
||||
{
|
||||
};
|
||||
|
||||
static const AlgorithmIdentifierTestInfo<DigestAlgorithm>
|
||||
DIGEST_ALGORITHM_TEST_INFO[] = {
|
||||
static const ValidDigestAlgorithmIdentifierTestInfo
|
||||
VALID_DIGEST_ALGORITHM_TEST_INFO[] =
|
||||
{
|
||||
{ DigestAlgorithm::sha512,
|
||||
{ 0x30, 0x0b, 0x06, 0x09,
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03 },
|
||||
@ -229,9 +234,9 @@ DIGEST_ALGORITHM_TEST_INFO[] = {
|
||||
},
|
||||
};
|
||||
|
||||
TEST_P(pkixder_DigestAlgorithmIdentifier, Valid)
|
||||
TEST_P(pkixder_DigestAlgorithmIdentifier_Valid, Valid)
|
||||
{
|
||||
const AlgorithmIdentifierTestInfo<DigestAlgorithm>& param(GetParam());
|
||||
const ValidDigestAlgorithmIdentifierTestInfo& param(GetParam());
|
||||
|
||||
{
|
||||
Input input;
|
||||
@ -260,165 +265,218 @@ TEST_P(pkixder_DigestAlgorithmIdentifier, Valid)
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(pkixder_DigestAlgorithmIdentifier,
|
||||
pkixder_DigestAlgorithmIdentifier,
|
||||
testing::ValuesIn(DIGEST_ALGORITHM_TEST_INFO));
|
||||
INSTANTIATE_TEST_CASE_P(pkixder_DigestAlgorithmIdentifier_Valid,
|
||||
pkixder_DigestAlgorithmIdentifier_Valid,
|
||||
testing::ValuesIn(VALID_DIGEST_ALGORITHM_TEST_INFO));
|
||||
|
||||
TEST_F(pkixder_DigestAlgorithmIdentifier, Invalid_MD5)
|
||||
class pkixder_DigestAlgorithmIdentifier_Invalid
|
||||
: public ::testing::Test
|
||||
, public ::testing::WithParamInterface<InvalidAlgorithmIdentifierTestInfo>
|
||||
{
|
||||
// The OID identifies MD5 (1.2.840.113549.2.5). It is invalid because we
|
||||
// don't accept MD5 as a hash algorithm.
|
||||
static const uint8_t DER[] = {
|
||||
0x30, 0x0a, 0x06, 0x08,
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05
|
||||
};
|
||||
Input input(DER);
|
||||
Reader reader(input);
|
||||
};
|
||||
|
||||
DigestAlgorithm alg;
|
||||
ASSERT_EQ(Result::ERROR_INVALID_ALGORITHM,
|
||||
DigestAlgorithmIdentifier(reader, alg));
|
||||
}
|
||||
|
||||
TEST_F(pkixder_DigestAlgorithmIdentifier, Invalid_Digest_ECDSA_WITH_SHA256)
|
||||
static const InvalidAlgorithmIdentifierTestInfo
|
||||
INVALID_DIGEST_ALGORITHM_TEST_INFO[] =
|
||||
{
|
||||
// The OID identifies ecdsa-with-SHA256 (1.2.840.10045.4.3.2). It is invalid
|
||||
// because ECDSA-with-SHA256 is not a hash algorithm.
|
||||
static const uint8_t DER[] = {
|
||||
0x30, 0x0a, 0x06, 0x08,
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, //
|
||||
};
|
||||
Input input(DER);
|
||||
Reader reader(input);
|
||||
|
||||
DigestAlgorithm alg;
|
||||
ASSERT_EQ(Result::ERROR_INVALID_ALGORITHM,
|
||||
DigestAlgorithmIdentifier(reader, alg));
|
||||
}
|
||||
|
||||
static const AlgorithmIdentifierTestInfo<SignatureAlgorithm>
|
||||
SIGNATURE_ALGORITHM_TEST_INFO[] =
|
||||
{
|
||||
{ SignatureAlgorithm::ecdsa_with_sha512,
|
||||
{ // MD5
|
||||
{ 0x30, 0x0a, 0x06, 0x08,
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04 },
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05 },
|
||||
12,
|
||||
},
|
||||
{ SignatureAlgorithm::ecdsa_with_sha384,
|
||||
{ 0x30, 0x0a, 0x06, 0x08,
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03 },
|
||||
12,
|
||||
},
|
||||
{ SignatureAlgorithm::ecdsa_with_sha256,
|
||||
{ // ecdsa-with-SHA256 (1.2.840.10045.4.3.2) (not a hash algorithm)
|
||||
{ 0x30, 0x0a, 0x06, 0x08,
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02 },
|
||||
12,
|
||||
},
|
||||
{ SignatureAlgorithm::ecdsa_with_sha1,
|
||||
{ 0x30, 0x09, 0x06, 0x07,
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01 },
|
||||
11,
|
||||
},
|
||||
};
|
||||
|
||||
// RSA
|
||||
{ SignatureAlgorithm::rsa_pkcs1_with_sha512,
|
||||
{ 0x30, 0x0b, 0x06, 0x09,
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d },
|
||||
13,
|
||||
TEST_P(pkixder_DigestAlgorithmIdentifier_Invalid, Invalid)
|
||||
{
|
||||
const InvalidAlgorithmIdentifierTestInfo& param(GetParam());
|
||||
Input input;
|
||||
ASSERT_EQ(Success, input.Init(param.der, param.derLength));
|
||||
Reader reader(input);
|
||||
DigestAlgorithm alg;
|
||||
ASSERT_EQ(Result::ERROR_INVALID_ALGORITHM,
|
||||
DigestAlgorithmIdentifier(reader, alg));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(pkixder_DigestAlgorithmIdentifier_Invalid,
|
||||
pkixder_DigestAlgorithmIdentifier_Invalid,
|
||||
testing::ValuesIn(INVALID_DIGEST_ALGORITHM_TEST_INFO));
|
||||
|
||||
struct ValidSignatureAlgorithmIdentifierValueTestInfo
|
||||
{
|
||||
PublicKeyAlgorithm publicKeyAlg;
|
||||
DigestAlgorithm digestAlg;
|
||||
uint8_t der[MAX_ALGORITHM_OID_DER_LENGTH];
|
||||
size_t derLength;
|
||||
};
|
||||
|
||||
static const ValidSignatureAlgorithmIdentifierValueTestInfo
|
||||
VALID_SIGNATURE_ALGORITHM_VALUE_TEST_INFO[] =
|
||||
{
|
||||
// ECDSA
|
||||
{ PublicKeyAlgorithm::ECDSA,
|
||||
DigestAlgorithm::sha512,
|
||||
{ 0x06, 0x08,
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04 },
|
||||
10,
|
||||
},
|
||||
{ SignatureAlgorithm::rsa_pkcs1_with_sha384,
|
||||
{ 0x30, 0x0b, 0x06, 0x09,
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c },
|
||||
13,
|
||||
{ PublicKeyAlgorithm::ECDSA,
|
||||
DigestAlgorithm::sha384,
|
||||
{ 0x06, 0x08,
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03 },
|
||||
10,
|
||||
},
|
||||
{ SignatureAlgorithm::rsa_pkcs1_with_sha256,
|
||||
{ 0x30, 0x0b, 0x06, 0x09,
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b },
|
||||
13,
|
||||
{ PublicKeyAlgorithm::ECDSA,
|
||||
DigestAlgorithm::sha256,
|
||||
{ 0x06, 0x08,
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02 },
|
||||
10,
|
||||
},
|
||||
{ SignatureAlgorithm::rsa_pkcs1_with_sha1,
|
||||
// IETF Standard OID
|
||||
{ 0x30, 0x0b, 0x06, 0x09,
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05 },
|
||||
13,
|
||||
},
|
||||
{ SignatureAlgorithm::rsa_pkcs1_with_sha1,
|
||||
// Legacy OIW OID (bug 1042479)
|
||||
{ 0x30, 0x07, 0x06, 0x05,
|
||||
0x2b, 0x0e, 0x03, 0x02, 0x1d },
|
||||
{ PublicKeyAlgorithm::ECDSA,
|
||||
DigestAlgorithm::sha1,
|
||||
{ 0x06, 0x07,
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01 },
|
||||
9,
|
||||
},
|
||||
|
||||
// id-dsa-with-sha256 (2.16.840.1.101.3.4.3.2)
|
||||
{ SignatureAlgorithm::unsupported_algorithm,
|
||||
{ 0x30, 0x0b, 0x06, 0x09,
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x02 },
|
||||
13,
|
||||
},
|
||||
|
||||
// id-dsa-with-sha1 (1.2.840.10040.4.3)
|
||||
{ SignatureAlgorithm::unsupported_algorithm,
|
||||
{ 0x30, 0x09, 0x06, 0x07,
|
||||
0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x03 },
|
||||
// RSA
|
||||
{ PublicKeyAlgorithm::RSA_PKCS1,
|
||||
DigestAlgorithm::sha512,
|
||||
{ 0x06, 0x09,
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d },
|
||||
11,
|
||||
},
|
||||
|
||||
// RSA-with-MD5 (1.2.840.113549.1.1.4)
|
||||
{ SignatureAlgorithm::unsupported_algorithm,
|
||||
{ 0x30, 0x0b, 0x06, 0x09,
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04 },
|
||||
13,
|
||||
{ PublicKeyAlgorithm::RSA_PKCS1,
|
||||
DigestAlgorithm::sha384,
|
||||
{ 0x06, 0x09,
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c },
|
||||
11,
|
||||
},
|
||||
|
||||
// id-sha256 (2.16.840.1.101.3.4.2.1). It is invalid because SHA-256 is not
|
||||
// a signature algorithm.
|
||||
{ SignatureAlgorithm::unsupported_algorithm,
|
||||
{ 0x30, 0x0b, 0x06, 0x09,
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 },
|
||||
13,
|
||||
{ PublicKeyAlgorithm::RSA_PKCS1,
|
||||
DigestAlgorithm::sha256,
|
||||
{ 0x06, 0x09,
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b },
|
||||
11,
|
||||
},
|
||||
{ PublicKeyAlgorithm::RSA_PKCS1,
|
||||
DigestAlgorithm::sha1,
|
||||
// IETF Standard OID
|
||||
{ 0x06, 0x09,
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05 },
|
||||
11,
|
||||
},
|
||||
{ PublicKeyAlgorithm::RSA_PKCS1,
|
||||
DigestAlgorithm::sha1,
|
||||
// Legacy OIW OID (bug 1042479)
|
||||
{ 0x06, 0x05,
|
||||
0x2b, 0x0e, 0x03, 0x02, 0x1d },
|
||||
7,
|
||||
},
|
||||
};
|
||||
|
||||
class pkixder_SignatureAlgorithmIdentifier
|
||||
class pkixder_SignatureAlgorithmIdentifierValue_Valid
|
||||
: public ::testing::Test
|
||||
, public ::testing::WithParamInterface<
|
||||
AlgorithmIdentifierTestInfo<SignatureAlgorithm>>
|
||||
ValidSignatureAlgorithmIdentifierValueTestInfo>
|
||||
{
|
||||
};
|
||||
|
||||
TEST_P(pkixder_SignatureAlgorithmIdentifier, ValidAndInvalid)
|
||||
TEST_P(pkixder_SignatureAlgorithmIdentifierValue_Valid, Valid)
|
||||
{
|
||||
const AlgorithmIdentifierTestInfo<SignatureAlgorithm>& param(GetParam());
|
||||
const ValidSignatureAlgorithmIdentifierValueTestInfo& param(GetParam());
|
||||
|
||||
{
|
||||
Input input;
|
||||
ASSERT_EQ(Success, input.Init(param.der, param.derLength));
|
||||
Reader reader(input);
|
||||
SignatureAlgorithm alg;
|
||||
ASSERT_EQ(Success, SignatureAlgorithmIdentifier(reader, alg));
|
||||
ASSERT_EQ(param.algorithm, alg);
|
||||
PublicKeyAlgorithm publicKeyAlg;
|
||||
DigestAlgorithm digestAlg;
|
||||
ASSERT_EQ(Success,
|
||||
SignatureAlgorithmIdentifierValue(reader, publicKeyAlg,
|
||||
digestAlg));
|
||||
ASSERT_EQ(param.publicKeyAlg, publicKeyAlg);
|
||||
ASSERT_EQ(param.digestAlg, digestAlg);
|
||||
ASSERT_EQ(Success, End(reader));
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t derWithNullParam[MAX_ALGORITHM_OID_DER_LENGTH + 2];
|
||||
memcpy(derWithNullParam, param.der, param.derLength);
|
||||
derWithNullParam[1] += 2; // we're going to expand the value by 2 bytes
|
||||
derWithNullParam[param.derLength] = 0x05; // NULL tag
|
||||
derWithNullParam[param.derLength + 1] = 0x00; // length zero
|
||||
|
||||
Input input;
|
||||
ASSERT_EQ(Success, input.Init(derWithNullParam, param.derLength + 2));
|
||||
Reader reader(input);
|
||||
SignatureAlgorithm alg;
|
||||
ASSERT_EQ(Success, SignatureAlgorithmIdentifier(reader, alg));
|
||||
ASSERT_EQ(param.algorithm, alg);
|
||||
PublicKeyAlgorithm publicKeyAlg;
|
||||
DigestAlgorithm digestAlg;
|
||||
ASSERT_EQ(Success,
|
||||
SignatureAlgorithmIdentifierValue(reader, publicKeyAlg,
|
||||
digestAlg));
|
||||
ASSERT_EQ(param.publicKeyAlg, publicKeyAlg);
|
||||
ASSERT_EQ(param.digestAlg, digestAlg);
|
||||
ASSERT_EQ(Success, End(reader));
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(pkixder_SignatureAlgorithmIdentifier,
|
||||
pkixder_SignatureAlgorithmIdentifier,
|
||||
testing::ValuesIn(SIGNATURE_ALGORITHM_TEST_INFO));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
pkixder_SignatureAlgorithmIdentifierValue_Valid,
|
||||
pkixder_SignatureAlgorithmIdentifierValue_Valid,
|
||||
testing::ValuesIn(VALID_SIGNATURE_ALGORITHM_VALUE_TEST_INFO));
|
||||
|
||||
static const InvalidAlgorithmIdentifierTestInfo
|
||||
INVALID_SIGNATURE_ALGORITHM_VALUE_TEST_INFO[] =
|
||||
{
|
||||
// id-dsa-with-sha256 (2.16.840.1.101.3.4.3.2)
|
||||
{ { 0x06, 0x09,
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x02 },
|
||||
11,
|
||||
},
|
||||
|
||||
// id-dsa-with-sha1 (1.2.840.10040.4.3)
|
||||
{ { 0x06, 0x07,
|
||||
0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x03 },
|
||||
9,
|
||||
},
|
||||
|
||||
// RSA-with-MD5 (1.2.840.113549.1.1.4)
|
||||
{ { 0x06, 0x09,
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04 },
|
||||
11,
|
||||
},
|
||||
|
||||
// id-sha256 (2.16.840.1.101.3.4.2.1). It is invalid because SHA-256 is not
|
||||
// a signature algorithm.
|
||||
{ { 0x06, 0x09,
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 },
|
||||
11,
|
||||
},
|
||||
};
|
||||
|
||||
class pkixder_SignatureAlgorithmIdentifier_Invalid
|
||||
: public ::testing::Test
|
||||
, public ::testing::WithParamInterface<InvalidAlgorithmIdentifierTestInfo>
|
||||
{
|
||||
};
|
||||
|
||||
TEST_P(pkixder_SignatureAlgorithmIdentifier_Invalid, Invalid)
|
||||
{
|
||||
const InvalidAlgorithmIdentifierTestInfo& param(GetParam());
|
||||
Input input;
|
||||
ASSERT_EQ(Success, input.Init(param.der, param.derLength));
|
||||
Reader reader(input);
|
||||
der::PublicKeyAlgorithm publicKeyAlg;
|
||||
DigestAlgorithm digestAlg;
|
||||
ASSERT_EQ(Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED,
|
||||
SignatureAlgorithmIdentifierValue(reader, publicKeyAlg, digestAlg));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
pkixder_SignatureAlgorithmIdentifier_Invalid,
|
||||
pkixder_SignatureAlgorithmIdentifier_Invalid,
|
||||
testing::ValuesIn(INVALID_SIGNATURE_ALGORITHM_VALUE_TEST_INFO));
|
||||
|
||||
} // unnamed namespace
|
||||
|
@ -59,27 +59,36 @@ private:
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
Result VerifySignedData(const SignedDataWithSignature&, Input) override
|
||||
Result DigestBuf(Input item, DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t *digestBuf, size_t digestBufLen)
|
||||
override
|
||||
{
|
||||
return TestDigestBuf(item, digestAlg, digestBuf, digestBufLen);
|
||||
}
|
||||
|
||||
Result CheckRSAPublicKeyModulusSizeInBits(EndEntityOrCA, unsigned int)
|
||||
final override
|
||||
{
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
Result DigestBuf(Input item, /*out*/ uint8_t *digestBuf, size_t digestBufLen)
|
||||
override
|
||||
Result VerifyRSAPKCS1SignedDigest(const SignedDigest&, Input) override
|
||||
{
|
||||
return TestDigestBuf(item, digestBuf, digestBufLen);
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
Result CheckRSAPublicKeyModulusSizeInBits(EndEntityOrCA, unsigned int)
|
||||
override
|
||||
Result CheckECDSACurveIsAcceptable(EndEntityOrCA, NamedCurve) final override
|
||||
{
|
||||
return Success;
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
Result CheckECDSACurveIsAcceptable(EndEntityOrCA, NamedCurve) override
|
||||
Result VerifyECDSASignedDigest(const SignedDigest&, Input) override
|
||||
{
|
||||
return Success;
|
||||
ADD_FAILURE();
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -70,16 +70,11 @@ public:
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
Result VerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo) final override
|
||||
{
|
||||
return TestVerifySignedData(signedData, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
Result DigestBuf(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
|
||||
Result DigestBuf(Input item, DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf, size_t digestBufLen)
|
||||
final override
|
||||
{
|
||||
return TestDigestBuf(item, digestBuf, digestBufLen);
|
||||
return TestDigestBuf(item, digestAlg, digestBuf, digestBufLen);
|
||||
}
|
||||
|
||||
Result CheckRSAPublicKeyModulusSizeInBits(EndEntityOrCA, unsigned int)
|
||||
@ -88,11 +83,23 @@ public:
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifyRSAPKCS1SignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) override
|
||||
{
|
||||
return TestVerifyRSAPKCS1SignedDigest(signedDigest, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
Result CheckECDSACurveIsAcceptable(EndEntityOrCA, NamedCurve) final override
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result VerifyECDSASignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo) override
|
||||
{
|
||||
return TestVerifyECDSASignedDigest(signedDigest, subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
OCSPTestTrustDomain(const OCSPTestTrustDomain&) = delete;
|
||||
void operator=(const OCSPTestTrustDomain&) = delete;
|
||||
};
|
||||
|
@ -385,18 +385,31 @@ SHA1(const ByteString& toHash)
|
||||
}
|
||||
|
||||
Result
|
||||
TestVerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo)
|
||||
TestVerifyECDSASignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
InitNSSIfNeeded();
|
||||
return VerifySignedDataNSS(signedData, subjectPublicKeyInfo, nullptr);
|
||||
return VerifyECDSASignedDigestNSS(signedDigest, subjectPublicKeyInfo,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
Result
|
||||
TestDigestBuf(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
|
||||
TestVerifyRSAPKCS1SignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
InitNSSIfNeeded();
|
||||
return DigestBufNSS(item, digestBuf, digestBufLen);
|
||||
return VerifyRSAPKCS1SignedDigestNSS(signedDigest, subjectPublicKeyInfo,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
Result
|
||||
TestDigestBuf(Input item,
|
||||
DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf,
|
||||
size_t digestBufLen)
|
||||
{
|
||||
InitNSSIfNeeded();
|
||||
return DigestBufNSS(item, digestAlg, digestBuf, digestBufLen);
|
||||
}
|
||||
|
||||
} } } // namespace mozilla::pkix::test
|
||||
|
@ -272,11 +272,12 @@ typedef ScopedPtr<TestKeyPair, DeleteTestKeyPair> ScopedTestKeyPair;
|
||||
|
||||
ByteString SHA1(const ByteString& toHash);
|
||||
|
||||
Result TestCheckPublicKey(Input subjectPublicKeyInfo);
|
||||
Result TestVerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo);
|
||||
Result TestDigestBuf(Input item, /*out*/ uint8_t* digestBuf,
|
||||
size_t digestBufLen);
|
||||
Result TestVerifyECDSASignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo);
|
||||
Result TestVerifyRSAPKCS1SignedDigest(const SignedDigest& signedDigest,
|
||||
Input subjectPublicKeyInfo);
|
||||
Result TestDigestBuf(Input item, DigestAlgorithm digestAlg,
|
||||
/*out*/ uint8_t* digestBuf, size_t digestBufLen);
|
||||
|
||||
// Replace one substring in item with another of the same length, but only if
|
||||
// the substring was found exactly once. The "same length" restriction is
|
||||
|
Loading…
Reference in New Issue
Block a user