mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-24 08:07:30 +09:00
imported changes from mozilla NSS:
- Bug 966856 - mozilla::pkix: support SHA-2 hashes in CertIDs in OCSP responses r=jschanck,djackson (78d2f4a3)
This commit is contained in:
parent
c7ec584cf8
commit
a140666918
6 changed files with 194 additions and 58 deletions
|
|
@ -214,9 +214,13 @@ public:
|
||||||
const TestSignatureAlgorithm& signatureAlgorithm,
|
const TestSignatureAlgorithm& signatureAlgorithm,
|
||||||
/*optional*/ const ByteString* certs = nullptr,
|
/*optional*/ const ByteString* certs = nullptr,
|
||||||
/*optional*/ OCSPResponseExtension* singleExtensions = nullptr,
|
/*optional*/ OCSPResponseExtension* singleExtensions = nullptr,
|
||||||
/*optional*/ OCSPResponseExtension* responseExtensions = nullptr)
|
/*optional*/ OCSPResponseExtension* responseExtensions = nullptr,
|
||||||
|
/*optional*/ DigestAlgorithm certIDHashAlgorithm = DigestAlgorithm::sha1,
|
||||||
|
/*optional*/ ByteString certIDHashAlgorithmEncoded = ByteString())
|
||||||
{
|
{
|
||||||
OCSPResponseContext context(certID, producedAt);
|
OCSPResponseContext context(certID, producedAt);
|
||||||
|
context.certIDHashAlgorithm = certIDHashAlgorithm;
|
||||||
|
context.certIDHashAlgorithmEncoded = certIDHashAlgorithmEncoded;
|
||||||
if (signerName) {
|
if (signerName) {
|
||||||
context.signerNameDER = CNToDERName(signerName);
|
context.signerNameDER = CNToDERName(signerName);
|
||||||
EXPECT_FALSE(ENCODING_FAILED(context.signerNameDER));
|
EXPECT_FALSE(ENCODING_FAILED(context.signerNameDER));
|
||||||
|
|
@ -454,6 +458,72 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, ct_extension)
|
||||||
trustDomain.signedCertificateTimestamps);
|
trustDomain.signedCertificateTimestamps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CertIDHashAlgorithm
|
||||||
|
{
|
||||||
|
DigestAlgorithm hashAlgorithm;
|
||||||
|
ByteString encodedHashAlgorithm;
|
||||||
|
Result expectedResult;
|
||||||
|
};
|
||||||
|
|
||||||
|
// python DottedOIDToCode.py --alg id-sha1 1.3.14.3.2.26
|
||||||
|
static const uint8_t alg_id_sha1[] = {
|
||||||
|
0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a
|
||||||
|
};
|
||||||
|
// python DottedOIDToCode.py --alg id-sha256 2.16.840.1.101.3.4.2.1
|
||||||
|
static const uint8_t alg_id_sha256[] = {
|
||||||
|
0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
|
||||||
|
};
|
||||||
|
static const uint8_t not_an_encoded_hash_oid[] = {
|
||||||
|
0x01, 0x02, 0x03, 0x04
|
||||||
|
};
|
||||||
|
|
||||||
|
static const CertIDHashAlgorithm CERTID_HASH_ALGORITHMS[] = {
|
||||||
|
{ DigestAlgorithm::sha1, ByteString(), Success },
|
||||||
|
{ DigestAlgorithm::sha256, ByteString(), Success },
|
||||||
|
{ DigestAlgorithm::sha384, ByteString(), Success },
|
||||||
|
{ DigestAlgorithm::sha512, ByteString(), Success },
|
||||||
|
{ DigestAlgorithm::sha256, BytesToByteString(alg_id_sha1),
|
||||||
|
Result::ERROR_OCSP_MALFORMED_RESPONSE },
|
||||||
|
{ DigestAlgorithm::sha1, BytesToByteString(alg_id_sha256),
|
||||||
|
Result::ERROR_OCSP_MALFORMED_RESPONSE },
|
||||||
|
{ DigestAlgorithm::sha1, BytesToByteString(not_an_encoded_hash_oid),
|
||||||
|
Result::ERROR_OCSP_MALFORMED_RESPONSE },
|
||||||
|
};
|
||||||
|
|
||||||
|
class pkixocsp_VerifyEncodedResponse_CertIDHashAlgorithm
|
||||||
|
: public pkixocsp_VerifyEncodedResponse_successful
|
||||||
|
, public ::testing::WithParamInterface<CertIDHashAlgorithm>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_P(pkixocsp_VerifyEncodedResponse_CertIDHashAlgorithm, CertIDHashAlgorithm)
|
||||||
|
{
|
||||||
|
ByteString responseString(
|
||||||
|
CreateEncodedOCSPSuccessfulResponse(
|
||||||
|
OCSPResponseContext::good, *endEntityCertID, byKey,
|
||||||
|
*rootKeyPair, oneDayBeforeNow,
|
||||||
|
oneDayBeforeNow, &oneDayAfterNow,
|
||||||
|
sha256WithRSAEncryption(),
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
GetParam().hashAlgorithm,
|
||||||
|
GetParam().encodedHashAlgorithm));
|
||||||
|
Input response;
|
||||||
|
ASSERT_EQ(Success,
|
||||||
|
response.Init(responseString.data(), responseString.length()));
|
||||||
|
bool expired;
|
||||||
|
ASSERT_EQ(GetParam().expectedResult,
|
||||||
|
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID,
|
||||||
|
Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS,
|
||||||
|
response, expired));
|
||||||
|
ASSERT_FALSE(expired);
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(pkixocsp_VerifyEncodedResponse_CertIDHashAlgorithm,
|
||||||
|
pkixocsp_VerifyEncodedResponse_CertIDHashAlgorithm,
|
||||||
|
testing::ValuesIn(CERTID_HASH_ALGORITHMS));
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// indirect responses (signed by a delegated OCSP responder cert)
|
// indirect responses (signed by a delegated OCSP responder cert)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -348,6 +348,14 @@ class OCSPResponseContext final {
|
||||||
OCSPResponseContext(const CertID& certID, std::time_t time);
|
OCSPResponseContext(const CertID& certID, std::time_t time);
|
||||||
|
|
||||||
const CertID& certID;
|
const CertID& certID;
|
||||||
|
// What digest algorithm to use to produce issuerNameHash and issuerKeyHash.
|
||||||
|
// Defaults to sha1.
|
||||||
|
DigestAlgorithm certIDHashAlgorithm;
|
||||||
|
// If non-empty, the sequence of bytes to use for hashAlgorithm when encoding
|
||||||
|
// this response. If empty, the sequence of bytes corresponding to
|
||||||
|
// certIDHashAlgorithm will be used. Defaults to empty.
|
||||||
|
ByteString certIDHashAlgorithmEncoded;
|
||||||
|
|
||||||
// TODO(bug 980538): add a way to specify what certificates are included.
|
// TODO(bug 980538): add a way to specify what certificates are included.
|
||||||
|
|
||||||
// The fields below are in the order that they appear in an OCSP response.
|
// The fields below are in the order that they appear in an OCSP response.
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,20 @@ Result CheckSubjectPublicKeyInfo(Input subjectPublicKeyInfo,
|
||||||
#else
|
#else
|
||||||
#error Unsupported compiler for MOZILLA_PKIX_UNREACHABLE_DEFAULT.
|
#error Unsupported compiler for MOZILLA_PKIX_UNREACHABLE_DEFAULT.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
inline size_t DigestAlgorithmToSizeInBytes(DigestAlgorithm digestAlgorithm) {
|
||||||
|
switch (digestAlgorithm) {
|
||||||
|
case DigestAlgorithm::sha1:
|
||||||
|
return 160 / 8;
|
||||||
|
case DigestAlgorithm::sha256:
|
||||||
|
return 256 / 8;
|
||||||
|
case DigestAlgorithm::sha384:
|
||||||
|
return 384 / 8;
|
||||||
|
case DigestAlgorithm::sha512:
|
||||||
|
return 512 / 8;
|
||||||
|
MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace mozilla::pkix
|
} // namespace mozilla::pkix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,12 +27,6 @@
|
||||||
#include "mozpkix/pkixcheck.h"
|
#include "mozpkix/pkixcheck.h"
|
||||||
#include "mozpkix/pkixutil.h"
|
#include "mozpkix/pkixutil.h"
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
const size_t SHA1_DIGEST_LENGTH = 160 / 8;
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace mozilla { namespace pkix {
|
namespace mozilla { namespace pkix {
|
||||||
|
|
||||||
// These values correspond to the tag values in the ASN.1 CertStatus
|
// These values correspond to the tag values in the ASN.1 CertStatus
|
||||||
|
|
@ -180,10 +174,12 @@ static inline Result MatchCertID(Reader& input,
|
||||||
const Context& context,
|
const Context& context,
|
||||||
/*out*/ bool& match);
|
/*out*/ bool& match);
|
||||||
static Result MatchKeyHash(TrustDomain& trustDomain,
|
static Result MatchKeyHash(TrustDomain& trustDomain,
|
||||||
|
DigestAlgorithm hashAlgorithm,
|
||||||
Input issuerKeyHash,
|
Input issuerKeyHash,
|
||||||
Input issuerSubjectPublicKeyInfo,
|
Input issuerSubjectPublicKeyInfo,
|
||||||
/*out*/ bool& match);
|
/*out*/ bool& match);
|
||||||
static Result KeyHash(TrustDomain& trustDomain,
|
static Result KeyHash(TrustDomain& trustDomain,
|
||||||
|
DigestAlgorithm hashAlgorithm,
|
||||||
Input subjectPublicKeyInfo,
|
Input subjectPublicKeyInfo,
|
||||||
/*out*/ uint8_t* hashBuf, size_t hashBufSize);
|
/*out*/ uint8_t* hashBuf, size_t hashBufSize);
|
||||||
|
|
||||||
|
|
@ -212,7 +208,7 @@ MatchResponderID(TrustDomain& trustDomain,
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
return MatchKeyHash(trustDomain, keyHash,
|
return MatchKeyHash(trustDomain, DigestAlgorithm::sha1, keyHash,
|
||||||
potentialSignerSubjectPublicKeyInfo, match);
|
potentialSignerSubjectPublicKeyInfo, match);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -740,36 +736,36 @@ MatchCertID(Reader& input, const Context& context, /*out*/ bool& match)
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: support SHA-2 hashes.
|
size_t hashAlgorithmLength = DigestAlgorithmToSizeInBytes(hashAlgorithm);
|
||||||
|
if (issuerNameHash.GetLength() != hashAlgorithmLength) {
|
||||||
if (hashAlgorithm != DigestAlgorithm::sha1) {
|
|
||||||
// Again, not interested in this response. Consume input, return success.
|
|
||||||
input.SkipToEnd();
|
|
||||||
return Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (issuerNameHash.GetLength() != SHA1_DIGEST_LENGTH) {
|
|
||||||
return Result::ERROR_OCSP_MALFORMED_RESPONSE;
|
return Result::ERROR_OCSP_MALFORMED_RESPONSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// From http://tools.ietf.org/html/rfc6960#section-4.1.1:
|
// From http://tools.ietf.org/html/rfc6960#section-4.1.1:
|
||||||
// "The hash shall be calculated over the DER encoding of the
|
// "The hash shall be calculated over the DER encoding of the
|
||||||
// issuer's name field in the certificate being checked."
|
// issuer's name field in the certificate being checked."
|
||||||
uint8_t hashBuf[SHA1_DIGEST_LENGTH];
|
uint8_t hashBuf[MAX_DIGEST_SIZE_IN_BYTES];
|
||||||
|
if (hashAlgorithmLength > sizeof(hashBuf)) {
|
||||||
|
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||||
|
}
|
||||||
rv = context.trustDomain.DigestBuf(context.certID.issuer,
|
rv = context.trustDomain.DigestBuf(context.certID.issuer,
|
||||||
DigestAlgorithm::sha1, hashBuf,
|
hashAlgorithm, hashBuf,
|
||||||
sizeof(hashBuf));
|
hashAlgorithmLength);
|
||||||
|
if (rv != Success) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
Input computed;
|
||||||
|
rv = computed.Init(hashBuf, hashAlgorithmLength);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
Input computed(hashBuf);
|
|
||||||
if (!InputsAreEqual(computed, issuerNameHash)) {
|
if (!InputsAreEqual(computed, issuerNameHash)) {
|
||||||
// Again, not interested in this response. Consume input, return success.
|
// Again, not interested in this response. Consume input, return success.
|
||||||
input.SkipToEnd();
|
input.SkipToEnd();
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MatchKeyHash(context.trustDomain, issuerKeyHash,
|
return MatchKeyHash(context.trustDomain, hashAlgorithm, issuerKeyHash,
|
||||||
context.certID.issuerSubjectPublicKeyInfo, match);
|
context.certID.issuerSubjectPublicKeyInfo, match);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -783,30 +779,53 @@ MatchCertID(Reader& input, const Context& context, /*out*/ bool& match)
|
||||||
// -- BIT STRING subjectPublicKey [excluding
|
// -- BIT STRING subjectPublicKey [excluding
|
||||||
// -- the tag, length, and number of unused
|
// -- the tag, length, and number of unused
|
||||||
// -- bits] in the responder's certificate)
|
// -- bits] in the responder's certificate)
|
||||||
|
//
|
||||||
|
// From https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1:
|
||||||
|
// CertID ::= SEQUENCE {
|
||||||
|
// hashAlgorithm AlgorithmIdentifier,
|
||||||
|
// issuerNameHash OCTET STRING, -- Hash of issuer's DN
|
||||||
|
// issuerKeyHash OCTET STRING, -- Hash of issuer's public key
|
||||||
|
// serialNumber CertificateSerialNumber }
|
||||||
|
// ...
|
||||||
|
// o hashAlgorithm is the hash algorithm used to generate the
|
||||||
|
// issuerNameHash and issuerKeyHash values.
|
||||||
|
// ...
|
||||||
|
// o issuerKeyHash is the hash of the issuer's public key. The hash
|
||||||
|
// shall be calculated over the value (excluding tag and length) of
|
||||||
|
// the subject public key field in the issuer's certificate.
|
||||||
static Result
|
static Result
|
||||||
MatchKeyHash(TrustDomain& trustDomain, Input keyHash,
|
MatchKeyHash(TrustDomain& trustDomain, DigestAlgorithm hashAlgorithm,
|
||||||
const Input subjectPublicKeyInfo, /*out*/ bool& match)
|
Input keyHash, const Input subjectPublicKeyInfo,
|
||||||
|
/*out*/ bool& match)
|
||||||
{
|
{
|
||||||
if (keyHash.GetLength() != SHA1_DIGEST_LENGTH) {
|
size_t hashLength = DigestAlgorithmToSizeInBytes(hashAlgorithm);
|
||||||
|
if (keyHash.GetLength() != hashLength) {
|
||||||
return Result::ERROR_OCSP_MALFORMED_RESPONSE;
|
return Result::ERROR_OCSP_MALFORMED_RESPONSE;
|
||||||
}
|
}
|
||||||
uint8_t hashBuf[SHA1_DIGEST_LENGTH];
|
uint8_t hashBuf[MAX_DIGEST_SIZE_IN_BYTES];
|
||||||
Result rv = KeyHash(trustDomain, subjectPublicKeyInfo, hashBuf,
|
if (hashLength > MAX_DIGEST_SIZE_IN_BYTES) {
|
||||||
sizeof hashBuf);
|
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||||
|
}
|
||||||
|
Result rv = KeyHash(trustDomain, hashAlgorithm, subjectPublicKeyInfo,
|
||||||
|
hashBuf, hashLength);
|
||||||
|
if (rv != Success) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
Input computed;
|
||||||
|
rv = computed.Init(hashBuf, hashLength);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
Input computed(hashBuf);
|
|
||||||
match = InputsAreEqual(computed, keyHash);
|
match = InputsAreEqual(computed, keyHash);
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bug 966856): support SHA-2 hashes
|
|
||||||
Result
|
Result
|
||||||
KeyHash(TrustDomain& trustDomain, const Input subjectPublicKeyInfo,
|
KeyHash(TrustDomain& trustDomain, DigestAlgorithm hashAlgorithm,
|
||||||
/*out*/ uint8_t* hashBuf, size_t hashBufSize)
|
const Input subjectPublicKeyInfo, /*out*/ uint8_t* hashBuf,
|
||||||
|
size_t hashBufSize)
|
||||||
{
|
{
|
||||||
if (!hashBuf || hashBufSize != SHA1_DIGEST_LENGTH) {
|
if (!hashBuf || hashBufSize != DigestAlgorithmToSizeInBytes(hashAlgorithm)) {
|
||||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -839,8 +858,8 @@ KeyHash(TrustDomain& trustDomain, const Input subjectPublicKeyInfo,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
return trustDomain.DigestBuf(subjectPublicKey, DigestAlgorithm::sha1,
|
return trustDomain.DigestBuf(subjectPublicKey, hashAlgorithm, hashBuf,
|
||||||
hashBuf, hashBufSize);
|
hashBufSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result
|
Result
|
||||||
|
|
@ -920,8 +939,6 @@ CreateEncodedOCSPRequest(TrustDomain& trustDomain, const struct CertID& certID,
|
||||||
// and thus more likely to fit within the 255 byte limit for OCSP GET that
|
// and thus more likely to fit within the 255 byte limit for OCSP GET that
|
||||||
// is specified in RFC 5019 Section 5.
|
// is specified in RFC 5019 Section 5.
|
||||||
|
|
||||||
// Bug 966856: Add the id-pkix-ocsp-pref-sig-algs extension.
|
|
||||||
|
|
||||||
// Since we don't know whether the OCSP responder supports anything other
|
// 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
|
// than SHA-1, we have no choice but to use SHA-1 for issuerNameHash and
|
||||||
// issuerKeyHash.
|
// issuerKeyHash.
|
||||||
|
|
@ -985,7 +1002,8 @@ CreateEncodedOCSPRequest(TrustDomain& trustDomain, const struct CertID& certID,
|
||||||
// reqCert.issuerKeyHash (OCTET STRING)
|
// reqCert.issuerKeyHash (OCTET STRING)
|
||||||
*d++ = 0x04;
|
*d++ = 0x04;
|
||||||
*d++ = hashLen;
|
*d++ = hashLen;
|
||||||
rv = KeyHash(trustDomain, certID.issuerSubjectPublicKeyInfo, d, hashLen);
|
rv = KeyHash(trustDomain, DigestAlgorithm::sha1,
|
||||||
|
certID.issuerSubjectPublicKeyInfo, d, hashLen);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,14 +42,7 @@ DigestSignedData(TrustDomain& trustDomain,
|
||||||
return Result::ERROR_BAD_DER;
|
return Result::ERROR_BAD_DER;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t digestLen;
|
size_t digestLen = DigestAlgorithmToSizeInBytes(signedDigest.digestAlgorithm);
|
||||||
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));
|
assert(digestLen <= sizeof(digestBuf));
|
||||||
|
|
||||||
rv = trustDomain.DigestBuf(signedData.data, signedDigest.digestAlgorithm,
|
rv = trustDomain.DigestBuf(signedData.data, signedDigest.digestAlgorithm,
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,8 @@ OCSPResponseExtension::OCSPResponseExtension()
|
||||||
|
|
||||||
OCSPResponseContext::OCSPResponseContext(const CertID& aCertID, time_t time)
|
OCSPResponseContext::OCSPResponseContext(const CertID& aCertID, time_t time)
|
||||||
: certID(aCertID)
|
: certID(aCertID)
|
||||||
|
, certIDHashAlgorithm(DigestAlgorithm::sha1)
|
||||||
|
, certIDHashAlgorithmEncoded(ByteString())
|
||||||
, responseStatus(successful)
|
, responseStatus(successful)
|
||||||
, skipResponseBytes(false)
|
, skipResponseBytes(false)
|
||||||
, producedAt(time)
|
, producedAt(time)
|
||||||
|
|
@ -183,25 +185,26 @@ static ByteString CertID(OCSPResponseContext& context);
|
||||||
static ByteString CertStatus(OCSPResponseContext& context);
|
static ByteString CertStatus(OCSPResponseContext& context);
|
||||||
|
|
||||||
static ByteString
|
static ByteString
|
||||||
SHA1(const ByteString& toHash)
|
HASH(const ByteString& toHash, DigestAlgorithm digestAlgorithm)
|
||||||
{
|
{
|
||||||
uint8_t digestBuf[20];
|
uint8_t digestBuf[MAX_DIGEST_SIZE_IN_BYTES];
|
||||||
Input input;
|
Input input;
|
||||||
if (input.Init(toHash.data(), toHash.length()) != Success) {
|
if (input.Init(toHash.data(), toHash.length()) != Success) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
Result rv = TestDigestBuf(input, DigestAlgorithm::sha1, digestBuf,
|
size_t digestLen = DigestAlgorithmToSizeInBytes(digestAlgorithm);
|
||||||
sizeof(digestBuf));
|
assert(digestLen <= sizeof(digestBuf));
|
||||||
|
Result rv = TestDigestBuf(input, digestAlgorithm, digestBuf, digestLen);
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
return ByteString(digestBuf, sizeof(digestBuf));
|
return ByteString(digestBuf, digestLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ByteString
|
static ByteString
|
||||||
HashedOctetString(const ByteString& bytes)
|
HashedOctetString(const ByteString& bytes, DigestAlgorithm digestAlgorithm)
|
||||||
{
|
{
|
||||||
ByteString digest(SHA1(bytes));
|
ByteString digest(HASH(bytes, digestAlgorithm));
|
||||||
if (ENCODING_FAILED(digest)) {
|
if (ENCODING_FAILED(digest)) {
|
||||||
return ByteString();
|
return ByteString();
|
||||||
}
|
}
|
||||||
|
|
@ -992,7 +995,7 @@ ResponderID(OCSPResponseContext& context)
|
||||||
ByteString
|
ByteString
|
||||||
KeyHash(const ByteString& subjectPublicKey)
|
KeyHash(const ByteString& subjectPublicKey)
|
||||||
{
|
{
|
||||||
return HashedOctetString(subjectPublicKey);
|
return HashedOctetString(subjectPublicKey, DigestAlgorithm::sha1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SingleResponse ::= SEQUENCE {
|
// SingleResponse ::= SEQUENCE {
|
||||||
|
|
@ -1049,7 +1052,7 @@ CertID(OCSPResponseContext& context)
|
||||||
{
|
{
|
||||||
ByteString issuerName(context.certID.issuer.UnsafeGetData(),
|
ByteString issuerName(context.certID.issuer.UnsafeGetData(),
|
||||||
context.certID.issuer.GetLength());
|
context.certID.issuer.GetLength());
|
||||||
ByteString issuerNameHash(HashedOctetString(issuerName));
|
ByteString issuerNameHash(HashedOctetString(issuerName, context.certIDHashAlgorithm));
|
||||||
if (ENCODING_FAILED(issuerNameHash)) {
|
if (ENCODING_FAILED(issuerNameHash)) {
|
||||||
return ByteString();
|
return ByteString();
|
||||||
}
|
}
|
||||||
|
|
@ -1073,8 +1076,8 @@ CertID(OCSPResponseContext& context)
|
||||||
!= Success) {
|
!= Success) {
|
||||||
return ByteString();
|
return ByteString();
|
||||||
}
|
}
|
||||||
issuerKeyHash = KeyHash(ByteString(subjectPublicKey.UnsafeGetData(),
|
issuerKeyHash = HashedOctetString(ByteString(subjectPublicKey.UnsafeGetData(),
|
||||||
subjectPublicKey.GetLength()));
|
subjectPublicKey.GetLength()), context.certIDHashAlgorithm);
|
||||||
if (ENCODING_FAILED(issuerKeyHash)) {
|
if (ENCODING_FAILED(issuerKeyHash)) {
|
||||||
return ByteString();
|
return ByteString();
|
||||||
}
|
}
|
||||||
|
|
@ -1088,9 +1091,39 @@ CertID(OCSPResponseContext& context)
|
||||||
static const uint8_t alg_id_sha1[] = {
|
static const uint8_t alg_id_sha1[] = {
|
||||||
0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a
|
0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a
|
||||||
};
|
};
|
||||||
|
// python DottedOIDToCode.py --alg id-sha256 2.16.840.1.101.3.4.2.1
|
||||||
|
static const uint8_t alg_id_sha256[] = {
|
||||||
|
0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
|
||||||
|
};
|
||||||
|
// python DottedOIDToCode.py --alg id-sha384 2.16.840.1.101.3.4.2.2
|
||||||
|
static const uint8_t alg_id_sha384[] = {
|
||||||
|
0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
|
||||||
|
};
|
||||||
|
// python DottedOIDToCode.py --alg id-sha512 2.16.840.1.101.3.4.2.3
|
||||||
|
static const uint8_t alg_id_sha512[] = {
|
||||||
|
0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
|
||||||
|
};
|
||||||
|
|
||||||
ByteString value;
|
ByteString value;
|
||||||
value.append(alg_id_sha1, sizeof(alg_id_sha1));
|
if (!context.certIDHashAlgorithmEncoded.empty()) {
|
||||||
|
value.append(context.certIDHashAlgorithmEncoded);
|
||||||
|
} else {
|
||||||
|
switch (context.certIDHashAlgorithm) {
|
||||||
|
case DigestAlgorithm::sha1:
|
||||||
|
value.append(alg_id_sha1, sizeof(alg_id_sha1));
|
||||||
|
break;
|
||||||
|
case DigestAlgorithm::sha256:
|
||||||
|
value.append(alg_id_sha256, sizeof(alg_id_sha256));
|
||||||
|
break;
|
||||||
|
case DigestAlgorithm::sha384:
|
||||||
|
value.append(alg_id_sha384, sizeof(alg_id_sha384));
|
||||||
|
break;
|
||||||
|
case DigestAlgorithm::sha512:
|
||||||
|
value.append(alg_id_sha512, sizeof(alg_id_sha512));
|
||||||
|
break;
|
||||||
|
MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
|
||||||
|
}
|
||||||
|
}
|
||||||
value.append(issuerNameHash);
|
value.append(issuerNameHash);
|
||||||
value.append(issuerKeyHash);
|
value.append(issuerKeyHash);
|
||||||
value.append(serialNumber);
|
value.append(serialNumber);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue