Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/nss/gtests/der_gtest/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 33 kB image not shown  

Quelle  p7_import_unittest.cc

  Sprache: C
 

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */


#include "cert.h"
#include "certdb.h"
#include "nss.h"
#include "pk11pub.h"
#include "secoid.h"
#include "secpkcs7.h"

#include "gtest/gtest.h"
#include "nss_scoped_ptrs.h"

namespace nss_test {

// This is an invalid PKCS7 message. Among other things, it contains some
// unknown hash OIDs. This should fail to parse, but it should be safe to try.
static const uint8_t p7_with_unknown_hashes[] = {
    0x30, 0x4d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
    0x02, 0xa0, 0x40, 0x30, 0x3e, 0x02, 0x01, 0x20, 0x31, 0x27, 0x30, 0x0b,
    0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x05, 0x30,
    0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x05,
    0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
    0x04, 0x30, 0x10, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
    0x07, 0x01, 0xa0, 0x03, 0x04, 0x01, 0x00};

// This is an invalid PKCS7 message. It contains multiple hash OIDs (that's not
// what makes it invalid). When it fails to parse, the associated digest data
// structures should be freed correctly.
static const uint8_t p7_with_multiple_hashes[] = {
    0x30, 0x4d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
    0x02, 0xa0, 0x40, 0x30, 0x3e, 0x02, 0x01, 0x20, 0x31, 0x27, 0x30, 0x0b,
    0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30,
    0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
    0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
    0x04, 0x30, 0x10, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
    0x07, 0x01, 0xa0, 0x03, 0x04, 0x01, 0x00};

// Valid PKCS7 SignedData with digestAlgorithms = [unknown_oid, sha-256],
// content "hi", and empty signerInfos. Tests that digests stay aligned with
// digestAlgorithms when unrecognized algorithms are present.
static const uint8_t p7_mixed_digest_algs[] = {
    0x30, 0x3f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
    0x07, 0x02, 0xa0, 0x32, 0x30, 0x30, 0x02, 0x01, 0x01, 0x31, 0x16,
    0x30, 0x05, 0x06, 0x03, 0x2b, 0x06, 0x01, 0x30, 0x0d, 0x06, 0x09,
    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
    0x30, 0x11, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
    0x07, 0x01, 0xa0, 0x04, 0x04, 0x02, 0x68, 0x69, 0x31, 0x00};

// Valid PKCS7 SignedData with digestAlgorithms = [unknown_oid (1.3.6.1),
// sha-256], content "test", a self-signed P-256 certificate, and a single
// signerInfo with an ECDSA-SHA256 signature (no authenticated attributes).
// This allows exercising the full sec_pkcs7_verify_signature code path with
// misaligned digest indices.
//
// To regenerate: python3 generate_p7_verify_blob.py (in this directory).
// The script uses the `cryptography` library to create a fresh P-256 key,
// self-signed cert, and valid PKCS7 SignedData with the unknown OID injected
// into digestAlgorithms.
static const uint8_t p7_signed_mixed_algs[] = {
    0x30, 0x82, 0x02, 0x10, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
    0x01, 0x07, 0x02, 0xA0, 0x82, 0x02, 0x01, 0x30, 0x82, 0x01, 0xFD, 0x02,
    0x01, 0x01, 0x31, 0x16, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x06, 0x01, 0x30,
    0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
    0x05, 0x00, 0x30, 0x13, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
    0x01, 0x07, 0x01, 0xA0, 0x06, 0x04, 0x04, 0x74, 0x65, 0x73, 0x74, 0xA0,
    0x82, 0x01, 0x2E, 0x30, 0x82, 0x01, 0x2A, 0x30, 0x81, 0xD0, 0xA0, 0x03,
    0x02, 0x01, 0x02, 0x02, 0x14, 0x18, 0xE7, 0x5C, 0x43, 0xA6, 0x74, 0x20,
    0x0F, 0x82, 0x72, 0x27, 0x14, 0x1B, 0xC8, 0xDC, 0x4B, 0x29, 0x9D, 0x8D,
    0x82, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03,
    0x02, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
    0x0C, 0x0A, 0x50, 0x4B, 0x43, 0x53, 0x37, 0x20, 0x54, 0x65, 0x73, 0x74,
    0x30, 0x1E, 0x17, 0x0D, 0x32, 0x35, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
    0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x31, 0x30,
    0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x15, 0x31, 0x13,
    0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0A, 0x50, 0x4B, 0x43,
    0x53, 0x37, 0x20, 0x54, 0x65, 0x73, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06,
    0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86,
    0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xED, 0xC5,
    0xFB, 0x1A, 0xC1, 0x6F, 0x2F, 0xA8, 0x90, 0xD1, 0xBA, 0x46, 0x6C, 0xDD,
    0xA0, 0xB0, 0x97, 0xA5, 0x86, 0xD5, 0xBE, 0x9B, 0x2B, 0xC4, 0x9C, 0x8F,
    0x1A, 0x16, 0x8A, 0x05, 0xA6, 0xB8, 0x8E, 0x99, 0xCD, 0x59, 0xCD, 0x4D,
    0x72, 0x45, 0x11, 0x42, 0xAA, 0x4F, 0xF2, 0x03, 0xED, 0xC9, 0x6C, 0x27,
    0xA5, 0xB5, 0x95, 0x5E, 0x11, 0xFD, 0x1B, 0x27, 0x3A, 0x17, 0x31, 0xDB,
    0xBD, 0x95, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04,
    0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0x8D, 0xFE,
    0x8F, 0x1A, 0x46, 0x36, 0x9E, 0x58, 0x2A, 0x22, 0x81, 0x3B, 0x0F, 0xEC,
    0xAD, 0x38, 0x7C, 0xC5, 0xB1, 0xC8, 0xFF, 0x28, 0xD0, 0x23, 0xB9, 0x10,
    0xF9, 0xFE, 0x41, 0x8B, 0x63, 0x85, 0x02, 0x21, 0x00, 0xFC, 0x29, 0x07,
    0x9A, 0x62, 0xA5, 0x6E, 0x8F, 0xEB, 0xC9, 0x4B, 0x80, 0xD7, 0xD9, 0x80,
    0xDD, 0xE0, 0xB4, 0x6D, 0x98, 0x53, 0x5E, 0x9D, 0x57, 0x64, 0xFA, 0x51,
    0xEE, 0xF9, 0xC8, 0x9C, 0xC4, 0x31, 0x81, 0x98, 0x30, 0x81, 0x95, 0x02,
    0x01, 0x01, 0x30, 0x2D, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
    0x55, 0x04, 0x03, 0x0C, 0x0A, 0x50, 0x4B, 0x43, 0x53, 0x37, 0x20, 0x54,
    0x65, 0x73, 0x74, 0x02, 0x14, 0x18, 0xE7, 0x5C, 0x43, 0xA6, 0x74, 0x20,
    0x0F, 0x82, 0x72, 0x27, 0x14, 0x1B, 0xC8, 0xDC, 0x4B, 0x29, 0x9D, 0x8D,
    0x82, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
    0x02, 0x01, 0x05, 0x00, 0x30, 0x09, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE,
    0x3D, 0x02, 0x01, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x5A, 0x2B, 0x0E,
    0xD2, 0x2F, 0x24, 0x75, 0xB8, 0x18, 0xF5, 0x8D, 0x1D, 0x5E, 0x7E, 0x81,
    0x48, 0x55, 0x47, 0x35, 0xFF, 0xB0, 0xFA, 0x6E, 0x8C, 0x0F, 0xE5, 0xC7,
    0x1A, 0x2B, 0xCF, 0x5B, 0xE0, 0x02, 0x21, 0x00, 0xA0, 0x13, 0x3F, 0xF7,
    0xF3, 0x98, 0x86, 0xD5, 0x17, 0xE9, 0x23, 0x5B, 0xD2, 0x41, 0xC7, 0xD2,
    0x20, 0xD5, 0x91, 0xDC, 0x7E, 0xC8, 0x6E, 0x43, 0xBA, 0xC4, 0x5F, 0x9A,
    0xFA, 0xE9, 0xC5, 0x0A};

// Certificate DER extracted from p7_signed_mixed_algs (CN=PKCS7 Test,
// self-signed P-256).  Used to trust the cert before signature verification.
static const uint8_t p7_test_cert_der[] = {
    0x30, 0x82, 0x01, 0x2A, 0x30, 0x81, 0xD0, 0xA0, 0x03, 0x02, 0x01, 0x02,
    0x02, 0x14, 0x18, 0xE7, 0x5C, 0x43, 0xA6, 0x74, 0x20, 0x0F, 0x82, 0x72,
    0x27, 0x14, 0x1B, 0xC8, 0xDC, 0x4B, 0x29, 0x9D, 0x8D, 0x82, 0x30, 0x0A,
    0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x15,
    0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0A, 0x50,
    0x4B, 0x43, 0x53, 0x37, 0x20, 0x54, 0x65, 0x73, 0x74, 0x30, 0x1E, 0x17,
    0x0D, 0x32, 0x35, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
    0x30, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
    0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
    0x03, 0x55, 0x04, 0x03, 0x0C, 0x0A, 0x50, 0x4B, 0x43, 0x53, 0x37, 0x20,
    0x54, 0x65, 0x73, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
    0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
    0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xED, 0xC5, 0xFB, 0x1A, 0xC1,
    0x6F, 0x2F, 0xA8, 0x90, 0xD1, 0xBA, 0x46, 0x6C, 0xDD, 0xA0, 0xB0, 0x97,
    0xA5, 0x86, 0xD5, 0xBE, 0x9B, 0x2B, 0xC4, 0x9C, 0x8F, 0x1A, 0x16, 0x8A,
    0x05, 0xA6, 0xB8, 0x8E, 0x99, 0xCD, 0x59, 0xCD, 0x4D, 0x72, 0x45, 0x11,
    0x42, 0xAA, 0x4F, 0xF2, 0x03, 0xED, 0xC9, 0x6C, 0x27, 0xA5, 0xB5, 0x95,
    0x5E, 0x11, 0xFD, 0x1B, 0x27, 0x3A, 0x17, 0x31, 0xDB, 0xBD, 0x95, 0x30,
    0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03,
    0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0x8D, 0xFE, 0x8F, 0x1A, 0x46,
    0x36, 0x9E, 0x58, 0x2A, 0x22, 0x81, 0x3B, 0x0F, 0xEC, 0xAD, 0x38, 0x7C,
    0xC5, 0xB1, 0xC8, 0xFF, 0x28, 0xD0, 0x23, 0xB9, 0x10, 0xF9, 0xFE, 0x41,
    0x8B, 0x63, 0x85, 0x02, 0x21, 0x00, 0xFC, 0x29, 0x07, 0x9A, 0x62, 0xA5,
    0x6E, 0x8F, 0xEB, 0xC9, 0x4B, 0x80, 0xD7, 0xD9, 0x80, 0xDD, 0xE0, 0xB4,
    0x6D, 0x98, 0x53, 0x5E, 0x9D, 0x57, 0x64, 0xFA, 0x51, 0xEE, 0xF9, 0xC8,
    0x9C, 0xC4};

class P7ImportTest : public ::testing::Test {};

TEST_F(P7ImportTest, DigestsAlignWithDigestAlgorithms) {
  ScopedSEC_PKCS7DecoderContext dcx(SEC_PKCS7DecoderStart(
      nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
  ASSERT_TRUE(dcx);
  SECStatus rv = SEC_PKCS7DecoderUpdate(
      dcx.get(), reinterpret_cast<const char *>(p7_mixed_digest_algs),
      sizeof(p7_mixed_digest_algs));
  ASSERT_EQ(SECSuccess, rv);
  SEC_PKCS7ContentInfo *cinfo = SEC_PKCS7DecoderFinish(dcx.release());
  ASSERT_TRUE(cinfo);
  ASSERT_EQ(SEC_OID_PKCS7_SIGNED_DATA, SEC_PKCS7ContentType(cinfo));

  SEC_PKCS7SignedData *sigd = cinfo->content.signedData;
  ASSERT_TRUE(sigd);
  ASSERT_TRUE(sigd->digestAlgorithms);
  ASSERT_TRUE(sigd->digestAlgorithms[0]);
  ASSERT_TRUE(sigd->digestAlgorithms[1]);

  ASSERT_TRUE(sigd->digests);
  // digests[0] corresponds to the unknown algorithm — should be NULL.
  EXPECT_EQ(nullptr, sigd->digests[0]);
  // digests[1] corresponds to SHA-256 — should be non-NULL.
  EXPECT_NE(nullptr, sigd->digests[1]);

  SEC_PKCS7DestroyContentInfo(cinfo);
}

// Verify that the digest for a recognized algorithm can be found by index
// even when an unrecognized algorithm occupies an earlier slot.  This
// replicates the lookup logic in sec_pkcs7_verify_signature.
TEST_F(P7ImportTest, DigestLookupSkipsUnrecognizedAlgorithm) {
  ScopedSEC_PKCS7DecoderContext dcx(SEC_PKCS7DecoderStart(
      nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
  ASSERT_TRUE(dcx);
  SECStatus rv = SEC_PKCS7DecoderUpdate(
      dcx.get(), reinterpret_cast<const char *>(p7_mixed_digest_algs),
      sizeof(p7_mixed_digest_algs));
  ASSERT_EQ(SECSuccess, rv);
  SEC_PKCS7ContentInfo *cinfo = SEC_PKCS7DecoderFinish(dcx.release());
  ASSERT_TRUE(cinfo);

  SEC_PKCS7SignedData *sigd = cinfo->content.signedData;
  ASSERT_TRUE(sigd);
  SECAlgorithmID **digestalgs = sigd->digestAlgorithms;
  SECItem **digests = sigd->digests;
  ASSERT_TRUE(digestalgs);
  ASSERT_TRUE(digests);

  // digests[0] is NULL (unknown algorithm), but digests is non-NULL.
  // The early-out in sec_pkcs7_verify_signature must not treat this as
  // "no digests available".
  EXPECT_EQ(nullptr, digests[0]);

  // Replicate the verification lookup: find SHA-256 in digestAlgorithms,
  // then access digests at the same index.
  int i;
  for (i = 0; digestalgs[i] != NULL; i++) {
    if (SECOID_FindOIDTag(&digestalgs[i]->algorithm) == SEC_OID_SHA256) break;
  }
  ASSERT_NE(nullptr, digestalgs[i]) << "SHA-256 not found in digestAlgorithms";
  EXPECT_NE(nullptr, digests[i])
      << "digests[" << i << "] is NULL despite SHA-256 being recognized";

  SEC_PKCS7DestroyContentInfo(cinfo);
}

// End-to-end verification of a signed PKCS7 message whose digestAlgorithms
// contains an unrecognized OID before the signer's SHA-256.  This exercises
// sec_pkcs7_verify_signature including the index-based digest lookup.
TEST_F(P7ImportTest, VerifySignatureWithMixedDigestAlgorithms) {
  CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
  ASSERT_TRUE(certdb);

  // Import the test cert and trust it for object signing so that
  // CERT_VerifyCert succeeds inside sec_pkcs7_verify_signature.
  SECItem certDER = {siBuffer, const_cast<uint8_t *>(p7_test_cert_der),
                     sizeof(p7_test_cert_der)};
  ScopedCERTCertificate cert(
      CERT_NewTempCertificate(certdb, &certDER, nullptr, PR_TRUE, PR_TRUE));
  ASSERT_TRUE(cert);

  CERTCertTrust trust;
  memset(&trust, 0sizeof(trust));
  trust.emailFlags = CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED | CERTDB_VALID_CA |
                     CERTDB_TRUSTED_CA;
  ASSERT_EQ(SECSuccess, CERT_ChangeCertTrust(certdb, cert.get(), &trust));

  // Decode the PKCS7 message.
  ScopedSEC_PKCS7DecoderContext dcx(SEC_PKCS7DecoderStart(
      nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
  ASSERT_TRUE(dcx);
  SECStatus rv = SEC_PKCS7DecoderUpdate(
      dcx.get(), reinterpret_cast<const char *>(p7_signed_mixed_algs),
      sizeof(p7_signed_mixed_algs));
  ASSERT_EQ(SECSuccess, rv);
  SEC_PKCS7ContentInfo *cinfo = SEC_PKCS7DecoderFinish(dcx.release());
  ASSERT_TRUE(cinfo);
  ASSERT_EQ(SEC_OID_PKCS7_SIGNED_DATA, SEC_PKCS7ContentType(cinfo));

  // Verify the signature.  This reaches sec_pkcs7_verify_signature and
  // exercises the digest lookup at the index matching the signer's algorithm.
  PRBool valid =
      SEC_PKCS7VerifySignature(cinfo, certUsageEmailSigner, PR_FALSE);
  EXPECT_TRUE(valid) << "Signature verification failed; error="
                     << PORT_GetError();

  SEC_PKCS7DestroyContentInfo(cinfo);
}

TEST_F(P7ImportTest, FailSafeWithUnknownHashes) {
  ScopedSEC_PKCS7DecoderContext dcx(SEC_PKCS7DecoderStart(
      nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
  ASSERT_TRUE(dcx);
  SECStatus rv = SEC_PKCS7DecoderUpdate(
      dcx.get(), reinterpret_cast<const char *>(p7_with_unknown_hashes),
      sizeof(p7_with_unknown_hashes));
  ASSERT_EQ(SECFailure, rv);
}

TEST_F(P7ImportTest, NoLeakWithMultipleHashes) {
  ScopedSEC_PKCS7DecoderContext dcx(SEC_PKCS7DecoderStart(
      nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
  ASSERT_TRUE(dcx);
  SECStatus rv = SEC_PKCS7DecoderUpdate(
      dcx.get(), reinterpret_cast<const char *>(p7_with_multiple_hashes),
      sizeof(p7_with_multiple_hashes));
  ASSERT_EQ(SECFailure, rv);
}

// RSA-2048 private key (PKCS #8, unencrypted DER) that matches kTestCert.
static const uint8_t kTestRsaKey[] = {
    0x30, 0x82, 0x04, 0xbe, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
    0x04, 0xa8, 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
    0x01, 0x00, 0xc5, 0x2a, 0xdb, 0x86, 0xb0, 0x2a, 0x4d, 0xe0, 0x52, 0xb0,
    0x4a, 0x29, 0xe2, 0xe0, 0xb4, 0xcc, 0xf8, 0x0c, 0x00, 0xcd, 0x0d, 0x7e,
    0xcc, 0xb1, 0xd3, 0xc8, 0xa2, 0x0d, 0x43, 0x6d, 0x06, 0x07, 0x22, 0x49,
    0xec, 0x86, 0x21, 0x85, 0x68, 0xf7, 0x6e, 0x48, 0xa3, 0xe8, 0x5b, 0x54,
    0x4d, 0x0c, 0x5b, 0xfb, 0x80, 0x07, 0x10, 0xab, 0xe4, 0xda, 0x3e, 0xd6,
    0xec, 0x08, 0x3e, 0x25, 0x2c, 0x08, 0x07, 0x78, 0xbf, 0x1d, 0x84, 0xeb,
    0x46, 0x58, 0xb1, 0x29, 0x9c, 0x38, 0xdd, 0x5f, 0x48, 0x78, 0x5f, 0x02,
    0xaa, 0x8f, 0x4b, 0x93, 0xd3, 0x03, 0x83, 0xb6, 0x68, 0xa3, 0xfe, 0x07,
    0xfc, 0x67, 0x8c, 0xdd, 0x4f, 0x86, 0x88, 0x80, 0xfe, 0xa3, 0xbf, 0xc6,
    0x79, 0x20, 0xed, 0xcf, 0x5f, 0x2a, 0x65, 0xcd, 0x3c, 0xf8, 0x2d, 0x97,
    0x1b, 0x63, 0x0e, 0xad, 0x79, 0xc6, 0x74, 0x1d, 0x66, 0xcd, 0x11, 0xdc,
    0x15, 0xd0, 0x46, 0x0f, 0xf0, 0x3b, 0x70, 0xca, 0x69, 0x74, 0x70, 0x87,
    0x8f, 0xd1, 0xfe, 0x3c, 0xdd, 0xbc, 0x34, 0xb2, 0xee, 0x74, 0xd7, 0xfe,
    0x10, 0xbe, 0x40, 0xf4, 0x52, 0x8f, 0x77, 0xbf, 0xbf, 0x03, 0xa7, 0x36,
    0x62, 0x96, 0x10, 0x4e, 0x4e, 0x6a, 0x1a, 0x5a, 0xea, 0x89, 0x04, 0x5b,
    0x3e, 0x37, 0x4f, 0x61, 0x65, 0x33, 0xbe, 0xa5, 0x4f, 0x19, 0x20, 0x51,
    0x02, 0x0b, 0x59, 0x12, 0xcf, 0x48, 0xc3, 0x79, 0x09, 0xe8, 0xc2, 0x0e,
    0x5d, 0xec, 0xbe, 0x8e, 0xc9, 0xf7, 0xf2, 0xf5, 0x4a, 0xae, 0x16, 0xb0,
    0xee, 0xc8, 0x5b, 0x20, 0x37, 0xe5, 0x29, 0x4f, 0x15, 0x40, 0x5f, 0x1f,
    0x14, 0x05, 0x5c, 0xb6, 0x8a, 0x5d, 0x44, 0x45, 0xb4, 0x96, 0x51, 0xeb,
    0x2b, 0xa6, 0xac, 0xc9, 0xa1, 0xbe, 0xa1, 0xcf, 0x53, 0x9e, 0x21, 0xdd,
    0x01, 0x08, 0xfc, 0x05, 0xfc, 0x0d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
    0x82, 0x01, 0x00, 0x10, 0xc9, 0x4f, 0xa6, 0xb8, 0x49, 0x91, 0xc1, 0xc9,
    0xd3, 0x1f, 0xd7, 0xfb, 0x17, 0x48, 0x82, 0xb4, 0x3c, 0xf4, 0x0b, 0x2b,
    0xdd, 0x4c, 0xce, 0x23, 0x0a, 0xcf, 0x89, 0x33, 0x8c, 0x0d, 0x04, 0x54,
    0x78, 0xae, 0x13, 0x7e, 0xb7, 0xc8, 0xb2, 0x5a, 0xdd, 0xad, 0x09, 0x73,
    0xa5, 0x1f, 0x68, 0xda, 0xf7, 0xf4, 0x49, 0x7b, 0x08, 0xe2, 0x28, 0xc1,
    0x4a, 0xde, 0x63, 0x96, 0x99, 0x91, 0x95, 0xc9, 0x6a, 0x65, 0x53, 0x12,
    0x65, 0xa4, 0x37, 0xee, 0xe0, 0x17, 0xb5, 0xdb, 0xb0, 0x68, 0xba, 0x1e,
    0xd4, 0xaf, 0x9d, 0x6d, 0x96, 0x28, 0xa9, 0x56, 0xf0, 0x69, 0x18, 0xf5,
    0x35, 0x76, 0xd9, 0x80, 0xc1, 0x0d, 0x81, 0x40, 0x63, 0xed, 0xca, 0x16,
    0x8c, 0xc3, 0x9e, 0xa3, 0x15, 0xe7, 0x08, 0x9e, 0xb6, 0xdf, 0x91, 0xa8,
    0x48, 0x02, 0x2e, 0x92, 0x7f, 0x00, 0x81, 0x7d, 0xe7, 0x4c, 0x40, 0xd3,
    0xad, 0xa8, 0x50, 0xa0, 0x88, 0x4f, 0x01, 0x20, 0x8e, 0x97, 0xe3, 0x82,
    0x42, 0xa5, 0x41, 0x11, 0xbe, 0x94, 0x3e, 0x8b, 0x37, 0x36, 0xfa, 0x62,
    0x0c, 0x7a, 0x28, 0x05, 0x0f, 0x8e, 0x6f, 0x93, 0x60, 0xea, 0x03, 0x63,
    0x6e, 0xb0, 0xfb, 0xf2, 0x4d, 0x1a, 0x4a, 0x56, 0xd8, 0x51, 0x8e, 0xc5,
    0x3a, 0x42, 0x26, 0x35, 0x0b, 0x05, 0x70, 0xe8, 0x4e, 0x2c, 0xe6, 0x4e,
    0x42, 0x5c, 0x9e, 0x82, 0x19, 0x71, 0x8d, 0xc5, 0xba, 0xe1, 0x86, 0x1b,
    0x5a, 0x6b, 0xfe, 0x4a, 0x79, 0xa9, 0x84, 0x47, 0x8f, 0xe4, 0x03, 0xfd,
    0x41, 0x6c, 0x51, 0x60, 0x9a, 0xd8, 0x43, 0x33, 0xf4, 0xbb, 0xb1, 0x51,
    0xc6, 0xdd, 0x45, 0x26, 0x46, 0x86, 0x0f, 0xde, 0x2e, 0x2c, 0x6a, 0xd2,
    0x2b, 0x5e, 0x3f, 0x5e, 0xe8, 0x76, 0xc8, 0x70, 0xc8, 0x19, 0x85, 0xd2,
    0x3e, 0x78, 0x4b, 0xa7, 0x8a, 0x1e, 0x9d, 0x02, 0x81, 0x81, 0x00, 0xf0,
    0xd5, 0xab, 0x7f, 0x10, 0x62, 0xcc, 0x0b, 0xcb, 0x01, 0xd8, 0xfd, 0x73,
    0x30, 0xe6, 0xb5, 0xe2, 0x8d, 0x30, 0xdf, 0x31, 0x6d, 0x80, 0x7e, 0x4b,
    0x01, 0xa9, 0x08, 0x00, 0x4f, 0xfc, 0x1c, 0x40, 0x33, 0x4d, 0x8a, 0x6b,
    0xc5, 0x4a, 0x7a, 0x72, 0x43, 0x1b, 0x99, 0x4d, 0x8f, 0xc7, 0xb6, 0x5d,
    0xb5, 0x45, 0x6f, 0xe2, 0x56, 0x25, 0x91, 0xdf, 0x25, 0x04, 0x9a, 0x97,
    0x95, 0xab, 0x95, 0x2e, 0x63, 0x0b, 0x9d, 0x95, 0xe4, 0xb2, 0x94, 0xf8,
    0xd4, 0xe7, 0xbe, 0x71, 0x1f, 0xae, 0xb6, 0xe3, 0x57, 0xe0, 0x20, 0x40,
    0xd7, 0xa8, 0x3f, 0x53, 0x80, 0x93, 0x6c, 0xca, 0x7c, 0xfc, 0x46, 0x7e,
    0x91, 0x2d, 0x82, 0x52, 0xfd, 0x99, 0xd8, 0x6a, 0x8a, 0x6b, 0x5e, 0x6a,
    0x94, 0xd5, 0xa9, 0xca, 0x55, 0x6f, 0x37, 0xae, 0xaf, 0x9d, 0x36, 0x8d,
    0x8b, 0xda, 0x2f, 0x7c, 0x60, 0x6f, 0xb3, 0x02, 0x81, 0x81, 0x00, 0xd1,
    0x95, 0x42, 0x11, 0x0f, 0x56, 0x91, 0xf1, 0x9b, 0x2e, 0xb8, 0x77, 0xde,
    0xaa, 0xef, 0x79, 0x3b, 0x29, 0x4e, 0x53, 0xea, 0x37, 0x4d, 0xfc, 0xbe,
    0x50, 0x76, 0xfb, 0x95, 0x76, 0xec, 0x65, 0xe3, 0xb3, 0xa7, 0x47, 0x27,
    0xdc, 0xbd, 0xff, 0xc9, 0x00, 0x54, 0x03, 0x5a, 0xbf, 0xd4, 0xb2, 0xed,
    0x32, 0x4d, 0xd9, 0xf3, 0xf8, 0x18, 0x12, 0x2b, 0xa4, 0xf0, 0xbe, 0x97,
    0x81, 0x61, 0x67, 0x09, 0xf9, 0xc9, 0x3d, 0xad, 0x8e, 0x9f, 0xfc, 0xe4,
    0xae, 0xcf, 0x1c, 0x76, 0xc2, 0x71, 0x19, 0x95, 0xa3, 0xf3, 0x60, 0x56,
    0xf4, 0x32, 0x53, 0x85, 0x5b, 0x8b, 0xc8, 0xba, 0x76, 0x89, 0x13, 0x71,
    0x1d, 0xd3, 0x9b, 0xba, 0x39, 0xd1, 0x97, 0xb2, 0x49, 0x94, 0xc0, 0xfb,
    0xed, 0xd8, 0x93, 0xa8, 0x44, 0xec, 0x74, 0xc5, 0x30, 0x08, 0x3a, 0xa8,
    0x4a, 0xdb, 0x4b, 0x1b, 0x74, 0x05, 0x3f, 0x02, 0x81, 0x80, 0x6b, 0x52,
    0x7c, 0x93, 0x2a, 0x25, 0x2c, 0xd2, 0xd0, 0x8b, 0xa9, 0x3c, 0x00, 0xda,
    0x38, 0xe5, 0xb2, 0xe8, 0xc2, 0x6f, 0xa3, 0xe2, 0x2d, 0x51, 0x9a, 0x71,
    0x49, 0xf7, 0x23, 0xd4, 0x80, 0xff, 0xc1, 0xe8, 0x5a, 0xd4, 0xa5, 0x84,
    0x0c, 0xd5, 0x96, 0x17, 0xab, 0xb3, 0xdc, 0x69, 0x87, 0x51, 0x10, 0x5f,
    0x58, 0x6b, 0x2c, 0x8c, 0xc1, 0x3f, 0x49, 0x16, 0x80, 0xff, 0xb7, 0x2f,
    0x5e, 0x80, 0x23, 0x64, 0xc5, 0xe7, 0x5a, 0xc5, 0xc8, 0x83, 0x34, 0x84,
    0x04, 0x25, 0xcc, 0xd9, 0x96, 0x8d, 0x2f, 0xb0, 0x98, 0x53, 0x27, 0x32,
    0x33, 0x6a, 0xcc, 0xf6, 0x4e, 0x3c, 0x3b, 0xdc, 0x08, 0xbc, 0x0d, 0x68,
    0xfa, 0xc3, 0xc9, 0xe1, 0xf3, 0x6e, 0x0a, 0xc4, 0x56, 0x66, 0x83, 0xce,
    0x81, 0x8c, 0xa1, 0x7b, 0x03, 0x0d, 0xe8, 0x4d, 0xa0, 0x1c, 0x90, 0x65,
    0x53, 0x3c, 0xb8, 0x0b, 0x6d, 0x9b, 0x02, 0x81, 0x81, 0x00, 0xa5, 0xc0,
    0x8c, 0xc2, 0x9f, 0x45, 0xd1, 0x20, 0xaa, 0xa1, 0x55, 0xa4, 0xff, 0xc6,
    0x62, 0xa4, 0x97, 0x64, 0x80, 0x9d, 0x1f, 0x34, 0x64, 0x0a, 0x4a, 0x9d,
    0xaa, 0xac, 0x28, 0x36, 0x28, 0x9a, 0x20, 0x6e, 0x7a, 0x12, 0x6d, 0x75,
    0x48, 0x12, 0xde, 0x6d, 0xd3, 0x03, 0xe0, 0x26, 0xac, 0xda, 0x61, 0x7b,
    0x92, 0x54, 0x98, 0x7d, 0x92, 0xd3, 0xf4, 0x0e, 0x7b, 0x93, 0xd0, 0x90,
    0xb3, 0x6e, 0xe1, 0x55, 0xda, 0x91, 0x5c, 0x0c, 0xdb, 0x7d, 0x0f, 0x83,
    0x2d, 0x2b, 0x8e, 0xc5, 0x12, 0xdb, 0xb0, 0x1c, 0x3d, 0x23, 0xe9, 0x41,
    0x31, 0xf8, 0x1a, 0x15, 0x1f, 0xc5, 0x3d, 0xaa, 0xf7, 0x98, 0x17, 0xb3,
    0x06, 0x23, 0x38, 0x31, 0xf8, 0x10, 0x28, 0x21, 0xc7, 0x72, 0xa5, 0x0c,
    0x23, 0x68, 0x0c, 0x01, 0x8e, 0x9c, 0x7f, 0x43, 0x10, 0x8f, 0x0b, 0x80,
    0x40, 0x54, 0xf3, 0x3e, 0x5b, 0xd3, 0x02, 0x81, 0x81, 0x00, 0x80, 0x1f,
    0x1f, 0x58, 0x4f, 0xe0, 0xc0, 0x88, 0xe4, 0x06, 0x4a, 0x0a, 0x65, 0x87,
    0xb0, 0xd2, 0x30, 0x96, 0x8d, 0xaf, 0x88, 0x65, 0x37, 0x72, 0x5b, 0x75,
    0xd8, 0xeb, 0x1a, 0x20, 0x96, 0x61, 0xa7, 0x40, 0xcc, 0xdb, 0xe3, 0xe3,
    0x58, 0x9c, 0xcb, 0x37, 0x78, 0xd4, 0x36, 0x01, 0xaa, 0xeb, 0x2f, 0x53,
    0xc1, 0x16, 0x80, 0xf2, 0x36, 0x17, 0x4e, 0x5c, 0xa9, 0x3c, 0xd7, 0x14,
    0x1f, 0x6d, 0xa3, 0xbf, 0x81, 0x3d, 0x69, 0xbd, 0xc7, 0xa9, 0xc6, 0x22,
    0x21, 0x58, 0x67, 0x01, 0x76, 0xec, 0x7b, 0x82, 0x14, 0xb2, 0xff, 0xae,
    0x04, 0x7b, 0x18, 0x6c, 0x78, 0xd0, 0x1f, 0x15, 0x13, 0x7b, 0x76, 0x89,
    0x9f, 0xec, 0xd0, 0x43, 0x3f, 0x59, 0x33, 0x8b, 0x68, 0x55, 0xdd, 0xb2,
    0x36, 0x20, 0x67, 0x20, 0x4b, 0x3b, 0x30, 0x42, 0xdd, 0x7d, 0xbc, 0x8c,
    0x58, 0x8f, 0x17, 0x46, 0xa0, 0x85,
};

// Self-signed RSA-2048 certificate, CN=PKCS7 Test, serial 5e0a3d...
static const uint8_t kTestCert[] = {
    0x30, 0x82, 0x03, 0x0a, 0x30, 0x82, 0x01, 0xf2, 0xa0, 0x03, 0x02, 0x01,
    0x02, 0x02, 0x13, 0x5e, 0x0a, 0x3d, 0x63, 0xe7, 0xc3, 0xfe, 0x17, 0x6c,
    0x21, 0x8d, 0x2e, 0x9e, 0xc7, 0xbf, 0xa3, 0xa0, 0xa0, 0x88, 0x30, 0x0d,
    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
    0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
    0x0c, 0x0a, 0x50, 0x4b, 0x43, 0x53, 0x37, 0x20, 0x54, 0x65, 0x73, 0x74,
    0x30, 0x1e, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x34, 0x30, 0x38, 0x31, 0x37,
    0x31, 0x39, 0x33, 0x35, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x34, 0x30,
    0x35, 0x31, 0x37, 0x31, 0x39, 0x33, 0x35, 0x5a, 0x30, 0x15, 0x31, 0x13,
    0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x50, 0x4b, 0x43,
    0x53, 0x37, 0x20, 0x54, 0x65, 0x73, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30,
    0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
    0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02,
    0x82, 0x01, 0x01, 0x00, 0xc5, 0x2a, 0xdb, 0x86, 0xb0, 0x2a, 0x4d, 0xe0,
    0x52, 0xb0, 0x4a, 0x29, 0xe2, 0xe0, 0xb4, 0xcc, 0xf8, 0x0c, 0x00, 0xcd,
    0x0d, 0x7e, 0xcc, 0xb1, 0xd3, 0xc8, 0xa2, 0x0d, 0x43, 0x6d, 0x06, 0x07,
    0x22, 0x49, 0xec, 0x86, 0x21, 0x85, 0x68, 0xf7, 0x6e, 0x48, 0xa3, 0xe8,
    0x5b, 0x54, 0x4d, 0x0c, 0x5b, 0xfb, 0x80, 0x07, 0x10, 0xab, 0xe4, 0xda,
    0x3e, 0xd6, 0xec, 0x08, 0x3e, 0x25, 0x2c, 0x08, 0x07, 0x78, 0xbf, 0x1d,
    0x84, 0xeb, 0x46, 0x58, 0xb1, 0x29, 0x9c, 0x38, 0xdd, 0x5f, 0x48, 0x78,
    0x5f, 0x02, 0xaa, 0x8f, 0x4b, 0x93, 0xd3, 0x03, 0x83, 0xb6, 0x68, 0xa3,
    0xfe, 0x07, 0xfc, 0x67, 0x8c, 0xdd, 0x4f, 0x86, 0x88, 0x80, 0xfe, 0xa3,
    0xbf, 0xc6, 0x79, 0x20, 0xed, 0xcf, 0x5f, 0x2a, 0x65, 0xcd, 0x3c, 0xf8,
    0x2d, 0x97, 0x1b, 0x63, 0x0e, 0xad, 0x79, 0xc6, 0x74, 0x1d, 0x66, 0xcd,
    0x11, 0xdc, 0x15, 0xd0, 0x46, 0x0f, 0xf0, 0x3b, 0x70, 0xca, 0x69, 0x74,
    0x70, 0x87, 0x8f, 0xd1, 0xfe, 0x3c, 0xdd, 0xbc, 0x34, 0xb2, 0xee, 0x74,
    0xd7, 0xfe, 0x10, 0xbe, 0x40, 0xf4, 0x52, 0x8f, 0x77, 0xbf, 0xbf, 0x03,
    0xa7, 0x36, 0x62, 0x96, 0x10, 0x4e, 0x4e, 0x6a, 0x1a, 0x5a, 0xea, 0x89,
    0x04, 0x5b, 0x3e, 0x37, 0x4f, 0x61, 0x65, 0x33, 0xbe, 0xa5, 0x4f, 0x19,
    0x20, 0x51, 0x02, 0x0b, 0x59, 0x12, 0xcf, 0x48, 0xc3, 0x79, 0x09, 0xe8,
    0xc2, 0x0e, 0x5d, 0xec, 0xbe, 0x8e, 0xc9, 0xf7, 0xf2, 0xf5, 0x4a, 0xae,
    0x16, 0xb0, 0xee, 0xc8, 0x5b, 0x20, 0x37, 0xe5, 0x29, 0x4f, 0x15, 0x40,
    0x5f, 0x1f, 0x14, 0x05, 0x5c, 0xb6, 0x8a, 0x5d, 0x44, 0x45, 0xb4, 0x96,
    0x51, 0xeb, 0x2b, 0xa6, 0xac, 0xc9, 0xa1, 0xbe, 0xa1, 0xcf, 0x53, 0x9e,
    0x21, 0xdd, 0x01, 0x08, 0xfc, 0x05, 0xfc, 0x0d, 0x02, 0x03, 0x01, 0x00,
    0x01, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
    0x04, 0x16, 0x04, 0x14, 0xad, 0x27, 0x48, 0x83, 0xbb, 0xa1, 0x29, 0x5c,
    0x0d, 0xf6, 0xaf, 0x20, 0x06, 0x72, 0x27, 0xe8, 0x75, 0x41, 0x4e, 0x7c,
    0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
    0x14, 0xad, 0x27, 0x48, 0x83, 0xbb, 0xa1, 0x29, 0x5c, 0x0d, 0xf6, 0xaf,
    0x20, 0x06, 0x72, 0x27, 0xe8, 0x75, 0x41, 0x4e, 0x7c, 0x30, 0x0f, 0x06,
    0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01,
    0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
    0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7a, 0xbd,
    0x2f, 0x03, 0x1a, 0xfb, 0x56, 0x6b, 0x1b, 0x20, 0x37, 0x15, 0x31, 0x1b,
    0xd9, 0x25, 0xb9, 0x22, 0x2e, 0xc7, 0x98, 0x8a, 0x30, 0x5c, 0x9f, 0xe2,
    0x28, 0x63, 0x1b, 0xc9, 0x42, 0x42, 0xfe, 0xd0, 0x2e, 0x97, 0xef, 0xb6,
    0x0b, 0x83, 0x9d, 0x14, 0x60, 0xa4, 0xf1, 0x1c, 0x3e, 0x76, 0x3f, 0x20,
    0xf6, 0x03, 0x8c, 0x4e, 0x8f, 0x8d, 0xa7, 0xca, 0xc2, 0x43, 0x71, 0xbd,
    0xc7, 0x35, 0x28, 0x9d, 0x32, 0xec, 0x09, 0x8e, 0x9d, 0x10, 0xa0, 0xf3,
    0x78, 0x61, 0x57, 0x2c, 0xc6, 0x49, 0x82, 0x98, 0x97, 0x67, 0xed, 0x36,
    0xbe, 0x5e, 0xa2, 0x50, 0xb8, 0xc9, 0x83, 0x2b, 0xe0, 0xe6, 0xfb, 0xb7,
    0xf9, 0x30, 0x6b, 0xa7, 0x18, 0xdf, 0x6d, 0xf7, 0x00, 0x30, 0x13, 0x12,
    0x25, 0xe5, 0xcd, 0x14, 0x5c, 0xd3, 0xbe, 0x4f, 0x96, 0x19, 0x28, 0xc0,
    0xa6, 0xe8, 0x1f, 0xe6, 0x00, 0x87, 0x92, 0xff, 0x57, 0xb9, 0x51, 0x0e,
    0x2c, 0xfd, 0x64, 0x80, 0xf7, 0xd0, 0x94, 0xc3, 0x26, 0x66, 0x74, 0xe3,
    0xdc, 0xba, 0x09, 0x8e, 0x84, 0x48, 0x43, 0x68, 0x46, 0x74, 0x6f, 0xcf,
    0x17, 0x2e, 0xca, 0x49, 0x54, 0xb9, 0xa3, 0xce, 0x4f, 0x77, 0xfc, 0x1f,
    0x81, 0x04, 0x6c, 0xdb, 0x33, 0x6d, 0xab, 0xb9, 0xf7, 0x8a, 0x83, 0x67,
    0x73, 0x35, 0x13, 0x8f, 0x6f, 0xa9, 0xa8, 0xb7, 0x97, 0x31, 0xcb, 0x7a,
    0xda, 0x8c, 0xd0, 0xf6, 0x5a, 0xd1, 0x4b, 0x4f, 0x23, 0x69, 0x88, 0xef,
    0x49, 0xe2, 0xcc, 0x81, 0xef, 0x1c, 0xdf, 0x73, 0x73, 0xa4, 0xcb, 0x5b,
    0x60, 0x28, 0x43, 0xb0, 0x4d, 0x8c, 0x4a, 0xfd, 0x2f, 0xaa, 0xb9, 0x41,
    0xa8, 0xc4, 0x70, 0xd2, 0x25, 0x49, 0x16, 0xfe, 0xeb, 0x9c, 0x21, 0x32,
    0x7a, 0x2c, 0x7b, 0x76, 0x1e, 0x72, 0xb6, 0xca, 0xf4, 0xdb, 0x82, 0x68,
    0x5a, 0x2e,
};

static PRBool DecryptionAllowed(SECAlgorithmID * /*alg*/,
                                PK11SymKey * /*key*/) {
  return PR_TRUE;
}

// Test fixture that imports kTestRsaKey + kTestCert into the internal NSS slot.
class P7EnvelopedDataTest : public ::testing::Test {
 protected:
  void SetUp() override {
    ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
    ASSERT_NE(nullptr, slot.get());

    SECItem key_item = {siBuffer, const_cast<uint8_t *>(kTestRsaKey),
                        sizeof(kTestRsaKey)};
    ASSERT_EQ(SECSuccess, PK11_ImportDERPrivateKeyInfo(
                              slot.get(), &key_item, nullptr, nullptr, PR_TRUE,
                              PR_FALSE, KU_ALL, nullptr));

    // Decode the certificate DER into a CERTCertificate, then import it
    // permanently into the slot so the PKCS7 decoder can find the key.
    SECItem cert_item = {siBuffer, const_cast<uint8_t *>(kTestCert),
                         sizeof(kTestCert)};
    ScopedCERTCertificate cert(CERT_NewTempCertificate(
        CERT_GetDefaultCertDB(), &cert_item, nullptr, PR_FALSE, PR_TRUE));
    ASSERT_NE(nullptr, cert.get());
    char cert_nick[] = "p7-test-cert";
    ASSERT_EQ(SECSuccess,
              PK11_ImportCert(slot.get(), cert.get(), CK_INVALID_HANDLE,
                              cert_nick, PR_FALSE));

    // Mark as an email-user cert so pk11_FindCertObjectByRecipient's
    // CERTDB_USER trust check passes.
    CERTCertTrust trust = {0, CERTDB_USER, 0};
    ASSERT_EQ(SECSuccess, CERT_ChangeCertTrust(nullptr, cert.get(), &trust));
  }
};

// bug 2029783: when no content callback is provided,
// sec_pkcs7_decoder_work_data accumulates decrypted output in
// envelopedData->encContentInfo.plainContent. Test that reallocation of the
// internal buffer is handled correctly across multiple calls to
// SEC_PKCS7DecoderUpdate.
TEST_F(P7EnvelopedDataTest, MultiChunkDecryptPlaintextCorrect) {
  // Split the 451-byte DER so that the first call delivers 25 bytes of
  // ciphertext and the second delivers the remaining 31.
  const unsigned int splitOffset = 420;

  // EnvelopedData (DES-EDE3-CBC, RSA-v1.5 key wrap) for kTestCert.
  // Plaintext: "plaintext: hello world from pkcs7 enveloped data test\n" (54 B)
  // The [0 PRIMITIVE] ciphertext element begins at byte 395, length 56.
  const uint8_t envelopedData[] = {
      0x30, 0x82, 0x01, 0xbf, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
      0x01, 0x07, 0x03, 0xa0, 0x82, 0x01, 0xb0, 0x30, 0x82, 0x01, 0xac, 0x02,
      0x01, 0x00, 0x31, 0x82, 0x01, 0x48, 0x30, 0x82, 0x01, 0x44, 0x02, 0x01,
      0x00, 0x30, 0x2c, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
      0x04, 0x03, 0x0c, 0x0a, 0x50, 0x4b, 0x43, 0x53, 0x37, 0x20, 0x54, 0x65,
      0x73, 0x74, 0x02, 0x13, 0x5e, 0x0a, 0x3d, 0x63, 0xe7, 0xc3, 0xfe, 0x17,
      0x6c, 0x21, 0x8d, 0x2e, 0x9e, 0xc7, 0xbf, 0xa3, 0xa0, 0xa0, 0x88, 0x30,
      0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
      0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xbb, 0x9c, 0xd7, 0xb3, 0x8e, 0x15,
      0x03, 0x60, 0x25, 0xfb, 0x15, 0x62, 0x88, 0x9b, 0xdd, 0xa6, 0x1a, 0xc6,
      0xf8, 0x36, 0x9e, 0x65, 0xd7, 0x25, 0xcf, 0x38, 0xe4, 0xe0, 0x14, 0x8c,
      0x25, 0x12, 0x41, 0xf9, 0xad, 0x9a, 0x5a, 0x07, 0xb8, 0x56, 0xfe, 0xf2,
      0x5f, 0x53, 0x78, 0x64, 0xe7, 0xc1, 0x23, 0x42, 0x7b, 0x1c, 0x8f, 0x42,
      0x0b, 0xa6, 0x33, 0x9a, 0x26, 0xb6, 0x41, 0xbc, 0xd6, 0x30, 0x66, 0x2e,
      0x93, 0x17, 0xb1, 0x1c, 0x9d, 0x44, 0xf7, 0x33, 0xab, 0xa5, 0x5c, 0xf1,
      0xf6, 0x5c, 0x79, 0x44, 0x17, 0x80, 0xf1, 0xa9, 0x79, 0x4f, 0x22, 0x83,
      0x29, 0x7a, 0xd6, 0x5f, 0x8b, 0x3f, 0xfa, 0xb3, 0xce, 0xae, 0xa9, 0xdf,
      0xa1, 0xd9, 0xbd, 0x1c, 0xab, 0xde, 0x87, 0x8d, 0x00, 0xb5, 0x97, 0x5e,
      0xe5, 0xd9, 0xc1, 0xc2, 0x28, 0xbb, 0x16, 0x70, 0x01, 0xea, 0x73, 0x68,
      0x86, 0x66, 0x4a, 0x10, 0x65, 0x27, 0x57, 0xec, 0x16, 0xdc, 0x0d, 0xfa,
      0x19, 0x96, 0x3f, 0x01, 0x27, 0x54, 0x75, 0x3f, 0xfa, 0xf6, 0x76, 0x0d,
      0x18, 0x03, 0x5b, 0x2c, 0xd4, 0xcb, 0x41, 0xdc, 0x34, 0xb7, 0xed, 0x2a,
      0x16, 0x85, 0xa3, 0xfb, 0x0b, 0xd2, 0x22, 0x2e, 0x8d, 0xf4, 0xf9, 0x21,
      0x52, 0xa6, 0x68, 0xeb, 0xdb, 0xb2, 0xc2, 0x94, 0xfe, 0xb9, 0xbf, 0xcf,
      0x04, 0x26, 0x73, 0x29, 0xbf, 0x06, 0xf9, 0xd9, 0xfb, 0x3d, 0x0d, 0x03,
      0x49, 0x39, 0xc6, 0x63, 0x70, 0x58, 0x30, 0x79, 0x54, 0x01, 0x85, 0x3b,
      0x72, 0xb9, 0xc2, 0x28, 0x4d, 0x86, 0xe1, 0x02, 0x92, 0xb3, 0x65, 0x56,
      0xb2, 0x24, 0xf3, 0xda, 0x90, 0x9a, 0xf3, 0x28, 0xcb, 0x8e, 0x1c, 0x4d,
      0x96, 0x08, 0x81, 0x2c, 0xbd, 0x8b, 0x8e, 0xca, 0xa0, 0x10, 0x4f, 0x1a,
      0xdf, 0xe7, 0xf4, 0x2d, 0xf8, 0x53, 0x24, 0xd9, 0x0e, 0x2e, 0x30, 0x5b,
      0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30,
      0x14, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04,
      0x08, 0xed, 0x29, 0x04, 0x3e, 0x0f, 0xbb, 0x12, 0x7c, 0x80, 0x38, 0xc5,
      0xd0, 0x1a, 0x1e, 0xbe, 0xaa, 0x15, 0xb8, 0xe7, 0xb7, 0xe6, 0xac, 0x29,
      0xfe, 0x50, 0x34, 0xa4, 0x47, 0x93, 0xe3, 0xa5, 0x96, 0x78, 0x50, 0xf9,
      0xa5, 0x8c, 0xed, 0x0e, 0xa9, 0xe3, 0x6b, 0x61, 0xf2, 0x7d, 0x1a, 0x07,
      0x4d, 0xf6, 0x12, 0xaf, 0x9b, 0xde, 0xfd, 0xb9, 0xaf, 0xac, 0xb6, 0x8d,
      0xfc, 0x0e, 0x01, 0x63, 0x64, 0xf5, 0x57,
  };

  // Expected decrypted content (55 bytes, CRLF line ending, no NUL terminator).
  // DES-EDE3-CBC pads to a multiple of 8: 55 bytes + 1 pad byte = 56 bytes
  // ciphertext, so the PKCS#7 pad value is 0x01.
  const uint8_t kExpectedPlaintext[] = {
      'p''l''a''i''n''t''e''x''t'':'' ''h',  'e',  'l',
      'l''o'' ''w''o''r''l''d'' ''f''r''o',  'm',  ' ',
      'p''k''c''s''7'' ''e''n''v''e''l''o',  'p',  'e',
      'd'' ''d''a''t''a'' ''t''e''s''t''\r''\n',
  };

  ScopedSEC_PKCS7DecoderContext dcx(
      SEC_PKCS7DecoderStart(nullptr, nullptr,  // no content callback
                            nullptr, nullptr,  // no password callback
                            nullptr, nullptr,  // no key callback
                            DecryptionAllowed));
  ASSERT_TRUE(dcx);

  ASSERT_EQ(SECSuccess,
            SEC_PKCS7DecoderUpdate(
                dcx.get(), reinterpret_cast<const char *>(envelopedData),
                splitOffset));
  ASSERT_EQ(SECSuccess,
            SEC_PKCS7DecoderUpdate(
                dcx.get(),
                reinterpret_cast<const char *>(envelopedData) + splitOffset,
                sizeof(envelopedData) - splitOffset));

  // SEC_PKCS7DecoderFinish takes ownership of dcx; release() prevents the
  // ScopedSEC_PKCS7DecoderContext destructor from calling Finish a second time.
  ScopedSEC_PKCS7ContentInfo cinfo(SEC_PKCS7DecoderFinish(dcx.release()));
  ASSERT_NE(nullptr, cinfo);
  ASSERT_EQ(SEC_OID_PKCS7_ENVELOPED_DATA, SEC_PKCS7ContentType(cinfo.get()));

  const SECItem *plain =
      &cinfo.get()->content.envelopedData->encContentInfo.plainContent;
  ASSERT_EQ(sizeof(kExpectedPlaintext), plain->len);
  EXPECT_EQ(
      0, memcmp(plain->data, kExpectedPlaintext, sizeof(kExpectedPlaintext)));
}

}  // namespace nss_test

Messung V0.5 in Prozent
C=93 H=98 G=95

¤ Dauer der Verarbeitung: 0.20 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.