Files
cli/vendor/aws-lc-sys/aws-lc/crypto/pkcs7/pkcs7_test.cc

2607 lines
134 KiB
C++

// Copyright (c) 2014, Google Inc.
// SPDX-License-Identifier: ISC
#include <gtest/gtest.h>
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/mem.h>
#include <openssl/pem.h>
#include <openssl/pkcs7.h>
#include <openssl/stack.h>
#include <openssl/x509.h>
#include "../bytestring/internal.h"
#include "../internal.h"
#include "../test/test_util.h"
#include "internal.h"
std::string GetTestData(const char *path);
// kPKCS7NSS contains the certificate chain of mail.google.com, as saved by NSS
// using the Chrome UI.
static const uint8_t kPKCS7NSS[] = {
0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, 0x31, 0x00, 0x30, 0x80,
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x00,
0x00, 0xa0, 0x82, 0x0b, 0x1e, 0x30, 0x82, 0x03, 0x54, 0x30, 0x82, 0x02,
0x3c, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x02, 0x34, 0x56, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
0x05, 0x00, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55,
0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74,
0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74,
0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x1e,
0x17, 0x0d, 0x30, 0x32, 0x30, 0x35, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30,
0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x35, 0x32, 0x31, 0x30,
0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09,
0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30,
0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54,
0x72, 0x75, 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30,
0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54,
0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20,
0x43, 0x41, 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, 0xda,
0xcc, 0x18, 0x63, 0x30, 0xfd, 0xf4, 0x17, 0x23, 0x1a, 0x56, 0x7e, 0x5b,
0xdf, 0x3c, 0x6c, 0x38, 0xe4, 0x71, 0xb7, 0x78, 0x91, 0xd4, 0xbc, 0xa1,
0xd8, 0x4c, 0xf8, 0xa8, 0x43, 0xb6, 0x03, 0xe9, 0x4d, 0x21, 0x07, 0x08,
0x88, 0xda, 0x58, 0x2f, 0x66, 0x39, 0x29, 0xbd, 0x05, 0x78, 0x8b, 0x9d,
0x38, 0xe8, 0x05, 0xb7, 0x6a, 0x7e, 0x71, 0xa4, 0xe6, 0xc4, 0x60, 0xa6,
0xb0, 0xef, 0x80, 0xe4, 0x89, 0x28, 0x0f, 0x9e, 0x25, 0xd6, 0xed, 0x83,
0xf3, 0xad, 0xa6, 0x91, 0xc7, 0x98, 0xc9, 0x42, 0x18, 0x35, 0x14, 0x9d,
0xad, 0x98, 0x46, 0x92, 0x2e, 0x4f, 0xca, 0xf1, 0x87, 0x43, 0xc1, 0x16,
0x95, 0x57, 0x2d, 0x50, 0xef, 0x89, 0x2d, 0x80, 0x7a, 0x57, 0xad, 0xf2,
0xee, 0x5f, 0x6b, 0xd2, 0x00, 0x8d, 0xb9, 0x14, 0xf8, 0x14, 0x15, 0x35,
0xd9, 0xc0, 0x46, 0xa3, 0x7b, 0x72, 0xc8, 0x91, 0xbf, 0xc9, 0x55, 0x2b,
0xcd, 0xd0, 0x97, 0x3e, 0x9c, 0x26, 0x64, 0xcc, 0xdf, 0xce, 0x83, 0x19,
0x71, 0xca, 0x4e, 0xe6, 0xd4, 0xd5, 0x7b, 0xa9, 0x19, 0xcd, 0x55, 0xde,
0xc8, 0xec, 0xd2, 0x5e, 0x38, 0x53, 0xe5, 0x5c, 0x4f, 0x8c, 0x2d, 0xfe,
0x50, 0x23, 0x36, 0xfc, 0x66, 0xe6, 0xcb, 0x8e, 0xa4, 0x39, 0x19, 0x00,
0xb7, 0x95, 0x02, 0x39, 0x91, 0x0b, 0x0e, 0xfe, 0x38, 0x2e, 0xd1, 0x1d,
0x05, 0x9a, 0xf6, 0x4d, 0x3e, 0x6f, 0x0f, 0x07, 0x1d, 0xaf, 0x2c, 0x1e,
0x8f, 0x60, 0x39, 0xe2, 0xfa, 0x36, 0x53, 0x13, 0x39, 0xd4, 0x5e, 0x26,
0x2b, 0xdb, 0x3d, 0xa8, 0x14, 0xbd, 0x32, 0xeb, 0x18, 0x03, 0x28, 0x52,
0x04, 0x71, 0xe5, 0xab, 0x33, 0x3d, 0xe1, 0x38, 0xbb, 0x07, 0x36, 0x84,
0x62, 0x9c, 0x79, 0xea, 0x16, 0x30, 0xf4, 0x5f, 0xc0, 0x2b, 0xe8, 0x71,
0x6b, 0xe4, 0xf9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, 0x51,
0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05,
0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
0x04, 0x16, 0x04, 0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab,
0x05, 0x64, 0x0c, 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e,
0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c,
0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x0d, 0x06,
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
0x03, 0x82, 0x01, 0x01, 0x00, 0x35, 0xe3, 0x29, 0x6a, 0xe5, 0x2f, 0x5d,
0x54, 0x8e, 0x29, 0x50, 0x94, 0x9f, 0x99, 0x1a, 0x14, 0xe4, 0x8f, 0x78,
0x2a, 0x62, 0x94, 0xa2, 0x27, 0x67, 0x9e, 0xd0, 0xcf, 0x1a, 0x5e, 0x47,
0xe9, 0xc1, 0xb2, 0xa4, 0xcf, 0xdd, 0x41, 0x1a, 0x05, 0x4e, 0x9b, 0x4b,
0xee, 0x4a, 0x6f, 0x55, 0x52, 0xb3, 0x24, 0xa1, 0x37, 0x0a, 0xeb, 0x64,
0x76, 0x2a, 0x2e, 0x2c, 0xf3, 0xfd, 0x3b, 0x75, 0x90, 0xbf, 0xfa, 0x71,
0xd8, 0xc7, 0x3d, 0x37, 0xd2, 0xb5, 0x05, 0x95, 0x62, 0xb9, 0xa6, 0xde,
0x89, 0x3d, 0x36, 0x7b, 0x38, 0x77, 0x48, 0x97, 0xac, 0xa6, 0x20, 0x8f,
0x2e, 0xa6, 0xc9, 0x0c, 0xc2, 0xb2, 0x99, 0x45, 0x00, 0xc7, 0xce, 0x11,
0x51, 0x22, 0x22, 0xe0, 0xa5, 0xea, 0xb6, 0x15, 0x48, 0x09, 0x64, 0xea,
0x5e, 0x4f, 0x74, 0xf7, 0x05, 0x3e, 0xc7, 0x8a, 0x52, 0x0c, 0xdb, 0x15,
0xb4, 0xbd, 0x6d, 0x9b, 0xe5, 0xc6, 0xb1, 0x54, 0x68, 0xa9, 0xe3, 0x69,
0x90, 0xb6, 0x9a, 0xa5, 0x0f, 0xb8, 0xb9, 0x3f, 0x20, 0x7d, 0xae, 0x4a,
0xb5, 0xb8, 0x9c, 0xe4, 0x1d, 0xb6, 0xab, 0xe6, 0x94, 0xa5, 0xc1, 0xc7,
0x83, 0xad, 0xdb, 0xf5, 0x27, 0x87, 0x0e, 0x04, 0x6c, 0xd5, 0xff, 0xdd,
0xa0, 0x5d, 0xed, 0x87, 0x52, 0xb7, 0x2b, 0x15, 0x02, 0xae, 0x39, 0xa6,
0x6a, 0x74, 0xe9, 0xda, 0xc4, 0xe7, 0xbc, 0x4d, 0x34, 0x1e, 0xa9, 0x5c,
0x4d, 0x33, 0x5f, 0x92, 0x09, 0x2f, 0x88, 0x66, 0x5d, 0x77, 0x97, 0xc7,
0x1d, 0x76, 0x13, 0xa9, 0xd5, 0xe5, 0xf1, 0x16, 0x09, 0x11, 0x35, 0xd5,
0xac, 0xdb, 0x24, 0x71, 0x70, 0x2c, 0x98, 0x56, 0x0b, 0xd9, 0x17, 0xb4,
0xd1, 0xe3, 0x51, 0x2b, 0x5e, 0x75, 0xe8, 0xd5, 0xd0, 0xdc, 0x4f, 0x34,
0xed, 0xc2, 0x05, 0x66, 0x80, 0xa1, 0xcb, 0xe6, 0x33, 0x30, 0x82, 0x03,
0xba, 0x30, 0x82, 0x02, 0xa2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08,
0x3e, 0xa3, 0xe4, 0x78, 0x99, 0x38, 0x13, 0x9d, 0x30, 0x0d, 0x06, 0x09,
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
0x49, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
0x0a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31,
0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20,
0x47, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x37, 0x31, 0x36,
0x31, 0x32, 0x32, 0x31, 0x34, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x31,
0x30, 0x31, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x69,
0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a,
0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16,
0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d, 0x6f, 0x75,
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, 0x31, 0x13,
0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x18, 0x30, 0x16, 0x06,
0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 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,
0xb2, 0x68, 0x6e, 0x3f, 0x03, 0x9e, 0x43, 0x85, 0x16, 0xb7, 0x89, 0x0b,
0x16, 0x2a, 0xbe, 0x26, 0x36, 0xdd, 0x68, 0x0a, 0x53, 0x4e, 0x20, 0x40,
0xf8, 0xd1, 0xdd, 0x63, 0xcb, 0x46, 0x73, 0x09, 0x96, 0x36, 0xde, 0x2c,
0x45, 0x71, 0x2e, 0x8a, 0x79, 0xeb, 0x40, 0x2f, 0x65, 0x83, 0x81, 0xdb,
0x37, 0x03, 0x84, 0xa1, 0x9a, 0xd0, 0x22, 0x3b, 0x73, 0x38, 0x45, 0xd3,
0xd5, 0x91, 0xb2, 0x52, 0xa3, 0x82, 0x01, 0x4f, 0x30, 0x82, 0x01, 0x4b,
0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06,
0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b,
0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x1a, 0x06, 0x03, 0x55,
0x1d, 0x11, 0x04, 0x13, 0x30, 0x11, 0x82, 0x0f, 0x6d, 0x61, 0x69, 0x6c,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30,
0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80,
0x30, 0x68, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01,
0x04, 0x5c, 0x30, 0x5a, 0x30, 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
0x05, 0x07, 0x30, 0x02, 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
0x2f, 0x70, 0x6b, 0x69, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32, 0x2e, 0x63, 0x72,
0x74, 0x30, 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30,
0x01, 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x6c,
0x69, 0x65, 0x6e, 0x74, 0x73, 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x1d,
0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x75, 0xc6, 0xb0,
0x4a, 0x46, 0x61, 0x83, 0xff, 0x91, 0x46, 0x45, 0x35, 0xa7, 0x0f, 0xd0,
0x5b, 0xe9, 0xdd, 0x94, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55,
0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4a, 0xdd, 0x06, 0x16,
0x1b, 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a,
0xba, 0x5a, 0x81, 0x2f, 0x30, 0x17, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04,
0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01,
0xd6, 0x79, 0x02, 0x05, 0x01, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d, 0x1f,
0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0xa0, 0x23, 0xa0, 0x21, 0x86, 0x1f,
0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x47, 0x49,
0x41, 0x47, 0x32, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82,
0x01, 0x01, 0x00, 0x7f, 0x41, 0xf5, 0x57, 0x18, 0x3c, 0x75, 0xf5, 0x23,
0x66, 0xc3, 0xf0, 0xf2, 0x3e, 0x70, 0x34, 0x56, 0xca, 0x78, 0xec, 0xc7,
0x81, 0x58, 0x0d, 0xdf, 0xf0, 0xfd, 0x86, 0xe6, 0xe6, 0x50, 0x3d, 0xf6,
0x09, 0x9a, 0x4d, 0xca, 0x60, 0x37, 0x9a, 0xd4, 0xca, 0x51, 0x7c, 0xf0,
0x66, 0x23, 0xea, 0x5e, 0x6a, 0x6f, 0x7b, 0xa6, 0x7a, 0x38, 0x97, 0x42,
0x58, 0x1a, 0x1b, 0x42, 0xae, 0x28, 0xde, 0x18, 0x7f, 0xcc, 0x76, 0x18,
0x58, 0x05, 0xbf, 0xea, 0xef, 0x14, 0xad, 0x34, 0xe5, 0x5f, 0x25, 0xab,
0xa1, 0x5f, 0x78, 0x5b, 0x6f, 0xe6, 0x69, 0xd8, 0x74, 0x8c, 0x19, 0x59,
0xb0, 0x1a, 0xfb, 0x8e, 0xdf, 0x61, 0xac, 0xeb, 0x2b, 0x0a, 0x1c, 0xab,
0x30, 0x0d, 0x64, 0x25, 0x78, 0xdf, 0x81, 0x71, 0xe3, 0xbd, 0xde, 0x9c,
0x3f, 0xdd, 0xe9, 0xf8, 0xb6, 0x98, 0x2d, 0x13, 0xa3, 0x7b, 0x14, 0x6f,
0xe3, 0x8b, 0xfc, 0x4e, 0x31, 0x26, 0xba, 0x10, 0xb4, 0x12, 0xe9, 0xc9,
0x49, 0x60, 0xf0, 0xaa, 0x1f, 0x44, 0x68, 0x19, 0xd2, 0xb3, 0xc8, 0x46,
0x22, 0x6b, 0xe1, 0x21, 0x77, 0xfd, 0x72, 0x33, 0x13, 0x21, 0x27, 0x81,
0xe4, 0x7a, 0xc9, 0xe4, 0x1c, 0x05, 0x04, 0x73, 0x13, 0xda, 0x47, 0xfe,
0x59, 0x41, 0x9c, 0x11, 0xc5, 0xf6, 0xb5, 0xd0, 0x01, 0xcb, 0x40, 0x19,
0xf5, 0xfe, 0xb3, 0x3c, 0x1f, 0x61, 0x8f, 0x4d, 0xdb, 0x81, 0x2a, 0x8a,
0xed, 0xb8, 0x53, 0xc7, 0x19, 0x6b, 0xfa, 0x8b, 0xfc, 0xe3, 0x2e, 0x12,
0x4e, 0xbd, 0xc5, 0x44, 0x9d, 0x1c, 0x7f, 0x3b, 0x09, 0x51, 0xd7, 0x0a,
0x0f, 0x22, 0x0a, 0xfd, 0x8c, 0x90, 0x14, 0xed, 0x10, 0xcb, 0x50, 0xcf,
0xa5, 0x45, 0xce, 0xb0, 0x21, 0x28, 0xcb, 0xd6, 0xf5, 0x6e, 0xb2, 0x3e,
0xfa, 0x35, 0x0c, 0x3d, 0x09, 0x0d, 0x81, 0x30, 0x82, 0x04, 0x04, 0x30,
0x82, 0x02, 0xec, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x02, 0x3a,
0x69, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
0x01, 0x05, 0x05, 0x00, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06,
0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75,
0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75,
0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41,
0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x34, 0x30, 0x35, 0x31, 0x35,
0x31, 0x35, 0x35, 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x34, 0x30,
0x34, 0x31, 0x35, 0x31, 0x35, 0x35, 0x35, 0x5a, 0x30, 0x49, 0x31, 0x0b,
0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x25, 0x30, 0x23,
0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x41,
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32, 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, 0x9c, 0x2a, 0x04, 0x77,
0x5c, 0xd8, 0x50, 0x91, 0x3a, 0x06, 0xa3, 0x82, 0xe0, 0xd8, 0x50, 0x48,
0xbc, 0x89, 0x3f, 0xf1, 0x19, 0x70, 0x1a, 0x88, 0x46, 0x7e, 0xe0, 0x8f,
0xc5, 0xf1, 0x89, 0xce, 0x21, 0xee, 0x5a, 0xfe, 0x61, 0x0d, 0xb7, 0x32,
0x44, 0x89, 0xa0, 0x74, 0x0b, 0x53, 0x4f, 0x55, 0xa4, 0xce, 0x82, 0x62,
0x95, 0xee, 0xeb, 0x59, 0x5f, 0xc6, 0xe1, 0x05, 0x80, 0x12, 0xc4, 0x5e,
0x94, 0x3f, 0xbc, 0x5b, 0x48, 0x38, 0xf4, 0x53, 0xf7, 0x24, 0xe6, 0xfb,
0x91, 0xe9, 0x15, 0xc4, 0xcf, 0xf4, 0x53, 0x0d, 0xf4, 0x4a, 0xfc, 0x9f,
0x54, 0xde, 0x7d, 0xbe, 0xa0, 0x6b, 0x6f, 0x87, 0xc0, 0xd0, 0x50, 0x1f,
0x28, 0x30, 0x03, 0x40, 0xda, 0x08, 0x73, 0x51, 0x6c, 0x7f, 0xff, 0x3a,
0x3c, 0xa7, 0x37, 0x06, 0x8e, 0xbd, 0x4b, 0x11, 0x04, 0xeb, 0x7d, 0x24,
0xde, 0xe6, 0xf9, 0xfc, 0x31, 0x71, 0xfb, 0x94, 0xd5, 0x60, 0xf3, 0x2e,
0x4a, 0xaf, 0x42, 0xd2, 0xcb, 0xea, 0xc4, 0x6a, 0x1a, 0xb2, 0xcc, 0x53,
0xdd, 0x15, 0x4b, 0x8b, 0x1f, 0xc8, 0x19, 0x61, 0x1f, 0xcd, 0x9d, 0xa8,
0x3e, 0x63, 0x2b, 0x84, 0x35, 0x69, 0x65, 0x84, 0xc8, 0x19, 0xc5, 0x46,
0x22, 0xf8, 0x53, 0x95, 0xbe, 0xe3, 0x80, 0x4a, 0x10, 0xc6, 0x2a, 0xec,
0xba, 0x97, 0x20, 0x11, 0xc7, 0x39, 0x99, 0x10, 0x04, 0xa0, 0xf0, 0x61,
0x7a, 0x95, 0x25, 0x8c, 0x4e, 0x52, 0x75, 0xe2, 0xb6, 0xed, 0x08, 0xca,
0x14, 0xfc, 0xce, 0x22, 0x6a, 0xb3, 0x4e, 0xcf, 0x46, 0x03, 0x97, 0x97,
0x03, 0x7e, 0xc0, 0xb1, 0xde, 0x7b, 0xaf, 0x45, 0x33, 0xcf, 0xba, 0x3e,
0x71, 0xb7, 0xde, 0xf4, 0x25, 0x25, 0xc2, 0x0d, 0x35, 0x89, 0x9d, 0x9d,
0xfb, 0x0e, 0x11, 0x79, 0x89, 0x1e, 0x37, 0xc5, 0xaf, 0x8e, 0x72, 0x69,
0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfb, 0x30, 0x81, 0xf8, 0x30,
0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c, 0x11,
0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x1d, 0x06, 0x03,
0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b,
0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a, 0xba,
0x5a, 0x81, 0x2f, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01,
0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30,
0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03,
0x02, 0x01, 0x06, 0x30, 0x3a, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x33,
0x30, 0x31, 0x30, 0x2f, 0xa0, 0x2d, 0xa0, 0x2b, 0x86, 0x29, 0x68, 0x74,
0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x67, 0x65, 0x6f,
0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72,
0x6c, 0x73, 0x2f, 0x67, 0x74, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x2e,
0x63, 0x72, 0x6c, 0x30, 0x3d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
0x07, 0x01, 0x01, 0x04, 0x31, 0x30, 0x2f, 0x30, 0x2d, 0x06, 0x08, 0x2b,
0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x21, 0x68, 0x74, 0x74,
0x70, 0x3a, 0x2f, 0x2f, 0x67, 0x74, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c,
0x2d, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75,
0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x17, 0x06, 0x03, 0x55, 0x1d,
0x20, 0x04, 0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01,
0x04, 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82,
0x01, 0x01, 0x00, 0x36, 0xd7, 0x06, 0x80, 0x11, 0x27, 0xad, 0x2a, 0x14,
0x9b, 0x38, 0x77, 0xb3, 0x23, 0xa0, 0x75, 0x58, 0xbb, 0xb1, 0x7e, 0x83,
0x42, 0xba, 0x72, 0xda, 0x1e, 0xd8, 0x8e, 0x36, 0x06, 0x97, 0xe0, 0xf0,
0x95, 0x3b, 0x37, 0xfd, 0x1b, 0x42, 0x58, 0xfe, 0x22, 0xc8, 0x6b, 0xbd,
0x38, 0x5e, 0xd1, 0x3b, 0x25, 0x6e, 0x12, 0xeb, 0x5e, 0x67, 0x76, 0x46,
0x40, 0x90, 0xda, 0x14, 0xc8, 0x78, 0x0d, 0xed, 0x95, 0x66, 0xda, 0x8e,
0x86, 0x6f, 0x80, 0xa1, 0xba, 0x56, 0x32, 0x95, 0x86, 0xdc, 0xdc, 0x6a,
0xca, 0x04, 0x8c, 0x5b, 0x7f, 0xf6, 0xbf, 0xcc, 0x6f, 0x85, 0x03, 0x58,
0xc3, 0x68, 0x51, 0x13, 0xcd, 0xfd, 0xc8, 0xf7, 0x79, 0x3d, 0x99, 0x35,
0xf0, 0x56, 0xa3, 0xbd, 0xe0, 0x59, 0xed, 0x4f, 0x44, 0x09, 0xa3, 0x9e,
0x38, 0x7a, 0xf6, 0x46, 0xd1, 0x1d, 0x12, 0x9d, 0x4f, 0xbe, 0xd0, 0x40,
0xfc, 0x55, 0xfe, 0x06, 0x5e, 0x3c, 0xda, 0x1c, 0x56, 0xbd, 0x96, 0x51,
0x7b, 0x6f, 0x57, 0x2a, 0xdb, 0xa2, 0xaa, 0x96, 0xdc, 0x8c, 0x74, 0xc2,
0x95, 0xbe, 0xf0, 0x6e, 0x95, 0x13, 0xff, 0x17, 0xf0, 0x3c, 0xac, 0xb2,
0x10, 0x8d, 0xcc, 0x73, 0xfb, 0xe8, 0x8f, 0x02, 0xc6, 0xf0, 0xfb, 0x33,
0xb3, 0x95, 0x3b, 0xe3, 0xc2, 0xcb, 0x68, 0x58, 0x73, 0xdb, 0xa8, 0x24,
0x62, 0x3b, 0x06, 0x35, 0x9d, 0x0d, 0xa9, 0x33, 0xbd, 0x78, 0x03, 0x90,
0x2e, 0x4c, 0x78, 0x5d, 0x50, 0x3a, 0x81, 0xd4, 0xee, 0xa0, 0xc8, 0x70,
0x38, 0xdc, 0xb2, 0xf9, 0x67, 0xfa, 0x87, 0x40, 0x5d, 0x61, 0xc0, 0x51,
0x8f, 0x6b, 0x83, 0x6b, 0xcd, 0x05, 0x3a, 0xca, 0xe1, 0xa7, 0x05, 0x78,
0xfc, 0xca, 0xda, 0x94, 0xd0, 0x2c, 0x08, 0x3d, 0x7e, 0x16, 0x79, 0xc8,
0xa0, 0x50, 0x20, 0x24, 0x54, 0x33, 0x71, 0x31, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
};
// Cribbed from
// https://github.com/bcgit/bc-java/blob/main/pkix/src/test/resources/org/bouncycastle/openssl/test/pkcs7.pem
static const uint8_t kPKCS7EnvelopedData[] = {
0x30, 0x82, 0x09, 0xA2, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
0x01, 0x07, 0x03, 0xA0, 0x82, 0x09, 0x93, 0x30, 0x82, 0x09, 0x8F, 0x02,
0x01, 0x00, 0x31, 0x81, 0xF8, 0x30, 0x81, 0xF5, 0x02, 0x01, 0x00, 0x30,
0x5E, 0x30, 0x59, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x47, 0x42, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
0x08, 0x13, 0x09, 0x42, 0x65, 0x72, 0x6B, 0x73, 0x68, 0x69, 0x72, 0x65,
0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x4E,
0x65, 0x77, 0x62, 0x75, 0x72, 0x79, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03,
0x55, 0x04, 0x0A, 0x13, 0x0E, 0x4D, 0x79, 0x20, 0x43, 0x6F, 0x6D, 0x70,
0x61, 0x6E, 0x79, 0x20, 0x4C, 0x74, 0x64, 0x31, 0x0B, 0x30, 0x09, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x02, 0x58, 0x58, 0x02, 0x01, 0x00, 0x30,
0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
0x05, 0x00, 0x04, 0x81, 0x80, 0x22, 0x91, 0xBF, 0x5C, 0x0F, 0x7F, 0x68,
0x0D, 0x8A, 0x4C, 0x1F, 0x32, 0xEE, 0xA8, 0x0E, 0x01, 0xA2, 0x73, 0x69,
0x3F, 0x1F, 0xA3, 0x62, 0xDA, 0xA5, 0x50, 0x86, 0x89, 0xBF, 0x7D, 0x15,
0xD3, 0x79, 0xD4, 0xCF, 0x53, 0x0B, 0x9B, 0xB2, 0x07, 0xED, 0x31, 0x6D,
0x66, 0x12, 0xFA, 0x05, 0x70, 0x1B, 0x74, 0x2D, 0xA2, 0xC2, 0x4E, 0xB6,
0x29, 0x54, 0xBA, 0xE9, 0x90, 0x8B, 0x04, 0xA7, 0x6C, 0xAA, 0xD0, 0xF7,
0xC3, 0xD3, 0x76, 0x1E, 0xDC, 0x53, 0x11, 0x6E, 0x80, 0x75, 0xA3, 0x47,
0x28, 0xD5, 0x1B, 0xEB, 0x3F, 0x37, 0xC9, 0xAA, 0xCD, 0x40, 0x6C, 0xC1,
0xEB, 0xB9, 0x65, 0x66, 0x37, 0x82, 0x2D, 0xE8, 0xA9, 0x3F, 0xB4, 0x56,
0x22, 0xF0, 0x59, 0x71, 0x5D, 0x0E, 0xA2, 0xA0, 0xA0, 0x2D, 0xCA, 0x59,
0x92, 0x96, 0x6A, 0xCE, 0xB9, 0xB3, 0xE4, 0xC8, 0xF1, 0x4C, 0x29, 0x81,
0xFC, 0x30, 0x82, 0x08, 0x8D, 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, 0x8D, 0xAF, 0x67, 0x1A, 0x1B, 0x90,
0x13, 0x51, 0x80, 0x82, 0x08, 0x68, 0x72, 0xCC, 0x21, 0x7B, 0x93, 0x19,
0x46, 0x8B, 0xFD, 0x66, 0x8D, 0x60, 0x9C, 0x1D, 0xB9, 0x4B, 0x43, 0xFC,
0x33, 0x0D, 0xF8, 0xEB, 0x75, 0x5A, 0x39, 0xC6, 0xFE, 0x96, 0x35, 0xF5,
0x99, 0x79, 0x13, 0xDD, 0xF8, 0xAF, 0x90, 0x1B, 0xF4, 0xA6, 0x52, 0xE5,
0x99, 0x54, 0xFE, 0x9B, 0xE0, 0x91, 0x81, 0xCC, 0xEE, 0xA7, 0xDA, 0x76,
0xD7, 0xEB, 0x75, 0x3A, 0xAB, 0x1D, 0x68, 0x84, 0xCD, 0x23, 0x2A, 0xC6,
0x85, 0x84, 0x95, 0x11, 0x35, 0xB2, 0x14, 0x0F, 0xD8, 0x9F, 0xB7, 0x50,
0xBA, 0x92, 0xBE, 0x71, 0xD0, 0x9A, 0x54, 0xB2, 0x82, 0xDE, 0x54, 0xFC,
0x7F, 0x5D, 0xE2, 0x3E, 0xB5, 0x38, 0xD3, 0x09, 0xDB, 0x7A, 0x8E, 0x19,
0x2A, 0x2D, 0xAF, 0x6E, 0xFF, 0xD7, 0xDE, 0xE5, 0x38, 0x7D, 0x13, 0x19,
0xC1, 0x29, 0x72, 0x73, 0x31, 0x68, 0xCD, 0xCB, 0xE2, 0x51, 0x85, 0x11,
0xB4, 0x0E, 0x4C, 0x65, 0xA4, 0xB6, 0x7B, 0xAF, 0xF6, 0xAF, 0x57, 0x8B,
0x65, 0xC5, 0x25, 0x71, 0x9D, 0x01, 0x0D, 0xCB, 0x83, 0xF8, 0x53, 0x5D,
0xAF, 0x21, 0x9B, 0x2B, 0x3B, 0x52, 0x59, 0xAD, 0xB2, 0x7B, 0x46, 0x26,
0x52, 0x29, 0x6E, 0xF8, 0x60, 0x19, 0xAF, 0x90, 0x90, 0x8B, 0x72, 0x31,
0xA5, 0x1C, 0x43, 0xAA, 0xB4, 0xBE, 0x45, 0x44, 0x19, 0x36, 0x59, 0x5C,
0x83, 0xC9, 0xC6, 0x67, 0x65, 0x0F, 0xE5, 0x6F, 0x05, 0x8C, 0x7F, 0x99,
0xE7, 0xAF, 0x0D, 0x27, 0xB7, 0x63, 0xA3, 0x38, 0x82, 0x5F, 0x41, 0x07,
0xC9, 0xDE, 0x2F, 0xA7, 0xE8, 0x34, 0x2D, 0x11, 0xB6, 0x76, 0x48, 0x46,
0x5C, 0x87, 0xDF, 0xE2, 0xE7, 0xCE, 0xD9, 0x4D, 0xD0, 0x38, 0x08, 0x02,
0x20, 0xEB, 0x99, 0x98, 0x6E, 0x58, 0x4A, 0x94, 0x4D, 0xD9, 0x4E, 0xC5,
0xE9, 0x3F, 0x16, 0xFC, 0x5C, 0x12, 0x84, 0x53, 0xB5, 0xBB, 0xE4, 0x07,
0x61, 0xDB, 0x80, 0xDE, 0x90, 0x3F, 0xE4, 0xAF, 0x88, 0x0D, 0xF0, 0x9B,
0x11, 0x90, 0xCC, 0x5B, 0x39, 0xDD, 0xD7, 0x79, 0x53, 0x11, 0x94, 0x25,
0x2D, 0x25, 0xD5, 0xED, 0xD2, 0xCD, 0x0A, 0xAA, 0x51, 0xDF, 0x42, 0x56,
0xA4, 0x68, 0x3D, 0xE7, 0xAA, 0xC9, 0x47, 0x49, 0x36, 0x6D, 0x3E, 0xC6,
0x28, 0x54, 0xD7, 0x85, 0x25, 0x0A, 0xFC, 0xFB, 0x9A, 0x73, 0x9C, 0xBA,
0x21, 0x59, 0x89, 0xC0, 0xFC, 0x6A, 0x02, 0x48, 0xC7, 0xFB, 0x18, 0xD7,
0xA4, 0x4D, 0xF6, 0xFC, 0x07, 0x11, 0x1E, 0x2E, 0xFB, 0x2D, 0xAD, 0xE7,
0x2A, 0x9D, 0x5A, 0x40, 0x42, 0xA8, 0xE6, 0xE1, 0xE0, 0xEC, 0x71, 0x20,
0xC3, 0x5E, 0xB4, 0x4B, 0x52, 0xD4, 0x7A, 0x72, 0x52, 0xA9, 0xC9, 0x8E,
0xBA, 0x4E, 0x57, 0x5A, 0xF3, 0x35, 0xC1, 0xDB, 0x14, 0x26, 0x5E, 0x50,
0x93, 0x89, 0xBD, 0x6B, 0x45, 0x72, 0xA2, 0xF2, 0xCF, 0x9B, 0xF4, 0x6B,
0x9E, 0xE9, 0x4C, 0xB5, 0x48, 0xD1, 0xBA, 0x0C, 0x49, 0x2D, 0xF6, 0x4A,
0xDB, 0xB3, 0x62, 0xBC, 0xEA, 0xCB, 0x97, 0xD8, 0x7F, 0x5A, 0x6E, 0x81,
0x5D, 0x8A, 0xB8, 0x3E, 0x88, 0x4C, 0xE5, 0xDF, 0xB9, 0xCC, 0xF6, 0x2A,
0xBA, 0x99, 0xF9, 0x8A, 0x92, 0x87, 0xB0, 0x0E, 0xBC, 0x3E, 0xCE, 0xEB,
0x9C, 0x31, 0x06, 0x4B, 0x75, 0x73, 0x39, 0x0D, 0xF6, 0x86, 0xAB, 0xB8,
0x91, 0xD9, 0xBA, 0xC4, 0x8D, 0xB3, 0x2D, 0x62, 0xB4, 0xFB, 0xA9, 0x90,
0x9E, 0xEB, 0x01, 0x3C, 0xED, 0x08, 0x03, 0x1B, 0x63, 0x6B, 0xA0, 0x4F,
0xCF, 0xCB, 0xD3, 0x32, 0x55, 0xA3, 0x66, 0xD5, 0x99, 0x80, 0x42, 0x0C,
0xA6, 0x94, 0x0C, 0x85, 0x02, 0x4A, 0x04, 0x44, 0x06, 0xE8, 0x74, 0xD5,
0xCF, 0xEF, 0xE0, 0x90, 0x57, 0x6C, 0xDA, 0x91, 0x4E, 0xD2, 0xFF, 0x29,
0x2D, 0xC3, 0x01, 0xCB, 0xDF, 0xBC, 0x9E, 0xA8, 0x73, 0xC0, 0x66, 0x9C,
0xCA, 0x69, 0xEE, 0xA5, 0x72, 0x73, 0x07, 0xA9, 0x77, 0x82, 0x89, 0xF6,
0xB7, 0xF7, 0xB6, 0xCC, 0x98, 0xC0, 0x3C, 0xA5, 0x12, 0x09, 0xB1, 0xC8,
0x42, 0x10, 0xA3, 0x5B, 0x62, 0x4A, 0xF6, 0xD1, 0x8A, 0x4D, 0xB1, 0x78,
0xD2, 0xE6, 0x0C, 0x50, 0x63, 0x08, 0x3E, 0x1C, 0x6B, 0xEE, 0x3D, 0x6E,
0xE0, 0xB2, 0x8D, 0x12, 0x12, 0x82, 0x36, 0x19, 0x54, 0xCF, 0xCD, 0x8D,
0x4A, 0xC7, 0x49, 0xD3, 0x46, 0x0D, 0x41, 0xDC, 0x2E, 0x0C, 0xC5, 0x8D,
0x09, 0x30, 0x04, 0xF7, 0xF4, 0x93, 0x99, 0x11, 0x85, 0xDD, 0x91, 0xD3,
0xF4, 0xA5, 0xA6, 0xCF, 0x93, 0x10, 0x10, 0x2A, 0x7F, 0xA4, 0x63, 0x91,
0x0F, 0xB2, 0xED, 0x39, 0x0B, 0x25, 0x6D, 0x46, 0x22, 0x30, 0x7E, 0x68,
0x09, 0x83, 0xF5, 0x8C, 0x3F, 0x1E, 0x33, 0xE2, 0xB1, 0x0A, 0x58, 0xEF,
0xD6, 0x91, 0x4F, 0x7F, 0xEB, 0x19, 0x76, 0x96, 0xE8, 0x02, 0x47, 0x5A,
0x5C, 0xA7, 0x19, 0x56, 0x72, 0xAA, 0x3A, 0xE3, 0xC1, 0x3F, 0x76, 0x35,
0x8C, 0x19, 0x0B, 0x09, 0x9C, 0xA4, 0x82, 0x75, 0xE4, 0x55, 0xB1, 0x18,
0x33, 0xB8, 0x12, 0x76, 0xFB, 0x02, 0x18, 0xAE, 0x76, 0x19, 0xCC, 0x47,
0xCA, 0x2F, 0xE0, 0x3A, 0x17, 0xCE, 0x22, 0x0C, 0xB0, 0x98, 0x50, 0x77,
0x07, 0x86, 0x24, 0xE2, 0x60, 0xED, 0x53, 0xCE, 0x16, 0xA4, 0xAE, 0x6C,
0x56, 0x5A, 0xD9, 0xDA, 0xF6, 0x6E, 0x4D, 0xA0, 0x26, 0x38, 0x76, 0x93,
0x22, 0x45, 0x4C, 0xBE, 0x4A, 0xB7, 0xD0, 0x5F, 0xE3, 0xA5, 0x5C, 0xB7,
0x38, 0x5E, 0x2F, 0xF7, 0xF1, 0x1B, 0x10, 0x02, 0x46, 0xBF, 0xAA, 0xEA,
0x1C, 0xC8, 0x4A, 0x9A, 0xE2, 0x07, 0x3F, 0x9D, 0xF4, 0x08, 0xAB, 0x56,
0x91, 0x45, 0x1F, 0x1A, 0xFE, 0xEA, 0x42, 0x29, 0x59, 0xD5, 0x08, 0xBA,
0x37, 0x21, 0x49, 0x25, 0x37, 0xDB, 0xD5, 0xB8, 0x72, 0x10, 0xD2, 0x6D,
0x8F, 0xC0, 0x35, 0x41, 0x01, 0x48, 0x60, 0x70, 0xF3, 0x32, 0x89, 0x66,
0x52, 0x84, 0x20, 0xA8, 0xE5, 0xC9, 0xFF, 0xAC, 0x5C, 0xF4, 0x0B, 0x42,
0xBF, 0x47, 0xD4, 0xD8, 0xB8, 0xA3, 0x2D, 0x43, 0x45, 0x8C, 0x1E, 0x2B,
0x6A, 0x92, 0x60, 0x82, 0x8E, 0x54, 0x9D, 0x91, 0x3D, 0xF3, 0xE2, 0x2A,
0x50, 0x04, 0xFB, 0xB5, 0x66, 0xA5, 0xA5, 0xB1, 0x62, 0xB0, 0xE7, 0x57,
0xE4, 0x3C, 0xB9, 0xF3, 0x68, 0x61, 0xBD, 0xC1, 0x67, 0xFF, 0x50, 0xC3,
0xA4, 0x84, 0x97, 0xA4, 0x5D, 0x24, 0x80, 0x4F, 0x13, 0x57, 0xFB, 0x30,
0x90, 0x9E, 0xF3, 0xBA, 0xEF, 0xA1, 0x3B, 0xF6, 0x23, 0xD4, 0x73, 0x5D,
0x73, 0x01, 0xBA, 0x34, 0x2F, 0x7E, 0xC1, 0x40, 0xA3, 0x69, 0x1A, 0x80,
0xA1, 0xB0, 0x6D, 0xBC, 0xF4, 0x32, 0x2B, 0xAE, 0xBA, 0x23, 0xC0, 0xB5,
0xDA, 0x99, 0xD6, 0xD0, 0x07, 0xAE, 0xAA, 0xDC, 0xE7, 0x9D, 0x9B, 0xDE,
0xD8, 0x1D, 0x3F, 0x6B, 0xCD, 0xC4, 0x09, 0x2D, 0x2D, 0x52, 0x6C, 0x42,
0x3C, 0xEF, 0x73, 0xBF, 0xD4, 0x4D, 0xC1, 0xC6, 0xA4, 0xCA, 0x79, 0x25,
0xAE, 0xEA, 0x70, 0xEC, 0x1E, 0x0F, 0x71, 0x71, 0x1A, 0x11, 0xBC, 0x69,
0xBC, 0x71, 0x3E, 0xFF, 0x33, 0x4B, 0x81, 0xFA, 0xCF, 0x46, 0x08, 0x28,
0x15, 0xDA, 0x92, 0x21, 0x11, 0x52, 0xF7, 0x14, 0x11, 0x3C, 0x4F, 0x53,
0xB8, 0xEE, 0xE3, 0x12, 0x1F, 0xAD, 0xCA, 0x1E, 0xF4, 0x78, 0xBA, 0x9C,
0x7B, 0x68, 0xEA, 0x2A, 0x94, 0x70, 0xC4, 0x8B, 0x59, 0xB2, 0xDD, 0xC0,
0x05, 0x3E, 0x57, 0x6A, 0xB2, 0x7A, 0xBD, 0xF1, 0xB1, 0xC5, 0xCB, 0x39,
0xE6, 0xC2, 0x46, 0xEF, 0x18, 0xEF, 0xE7, 0x6C, 0x6E, 0x32, 0x29, 0x18,
0x80, 0xE6, 0xA0, 0x48, 0xAA, 0x44, 0x4D, 0x17, 0x64, 0x78, 0x4D, 0x5A,
0x02, 0x62, 0xB0, 0xA5, 0xAF, 0xEF, 0x10, 0x5B, 0xB6, 0x27, 0x83, 0xAA,
0xD4, 0x08, 0xAF, 0xF8, 0x3D, 0x86, 0x73, 0xB1, 0xB4, 0xE1, 0xC3, 0xAC,
0x75, 0xCF, 0xBA, 0x3F, 0xE3, 0x7D, 0x10, 0x4B, 0xFB, 0xD2, 0xFD, 0x11,
0xDC, 0xD0, 0x38, 0xBE, 0x0D, 0xE0, 0x4C, 0x17, 0x0E, 0xDF, 0x0C, 0x70,
0x9C, 0x96, 0x40, 0x4B, 0xB1, 0xB0, 0x50, 0x93, 0x9C, 0xAE, 0xA0, 0xB5,
0x70, 0x06, 0x90, 0x91, 0xCE, 0x4D, 0x47, 0x49, 0x54, 0xC7, 0x49, 0x4C,
0xCE, 0x05, 0x96, 0x0C, 0x34, 0xB9, 0xA8, 0xA5, 0xFE, 0x63, 0x02, 0x14,
0xEC, 0xA1, 0x10, 0x8B, 0x28, 0x6A, 0x43, 0xBE, 0x2B, 0x91, 0xFE, 0xA1,
0xC5, 0x0C, 0x9F, 0x7A, 0xC6, 0x81, 0xC6, 0xAC, 0x42, 0x65, 0x99, 0x22,
0x91, 0xBC, 0x01, 0x1E, 0x50, 0xD9, 0xC2, 0x83, 0xDF, 0xC2, 0x77, 0xEB,
0x57, 0x85, 0xF8, 0xFF, 0x1C, 0xA8, 0xDD, 0xCA, 0x82, 0xA9, 0xB8, 0x5F,
0x14, 0x59, 0x47, 0x38, 0x05, 0xE2, 0xB2, 0xCC, 0xF5, 0xE3, 0x0B, 0x13,
0x3E, 0x1E, 0x17, 0x42, 0xE9, 0xA3, 0xE5, 0x16, 0x52, 0x9F, 0x08, 0xFC,
0x80, 0x62, 0xB6, 0xC6, 0x8B, 0xBD, 0x1F, 0xDC, 0x0C, 0xAF, 0x0B, 0x99,
0xD9, 0xE0, 0x13, 0xFF, 0x72, 0xF7, 0x3A, 0xD6, 0xC8, 0xAF, 0xF4, 0xB3,
0x09, 0xBA, 0x7C, 0x63, 0xDE, 0x53, 0xCF, 0xC1, 0x60, 0x9A, 0xB2, 0x57,
0xBF, 0x28, 0x0C, 0x54, 0xED, 0x71, 0xBF, 0xBE, 0xCF, 0x03, 0x50, 0xF3,
0x13, 0xD4, 0x8B, 0x88, 0xBC, 0x81, 0xE9, 0x32, 0xFC, 0x96, 0xCC, 0x45,
0x43, 0x56, 0x45, 0xD8, 0x3F, 0x09, 0x86, 0x90, 0xDE, 0x20, 0xFA, 0x63,
0x2F, 0x49, 0x36, 0xBD, 0x3A, 0xE6, 0x0A, 0x01, 0x0D, 0x27, 0xEB, 0x42,
0x73, 0x49, 0xE0, 0x64, 0xEE, 0x79, 0x66, 0x04, 0x5B, 0xA3, 0x57, 0xDB,
0x07, 0xF4, 0x54, 0x7E, 0x44, 0xD1, 0x80, 0x42, 0x85, 0xF5, 0x69, 0x89,
0x62, 0x79, 0x57, 0x51, 0x5A, 0x21, 0xEF, 0xB9, 0x19, 0xD1, 0xC7, 0x3D,
0x63, 0xE2, 0xAC, 0xB9, 0xE1, 0x19, 0xA7, 0x5C, 0x28, 0x49, 0x3C, 0xB0,
0x25, 0xBD, 0xED, 0x73, 0xF8, 0xD7, 0x79, 0x11, 0x92, 0x99, 0xC6, 0x96,
0x7B, 0xAA, 0x5A, 0xD0, 0x37, 0x1F, 0x33, 0x9D, 0x1C, 0xA1, 0x5D, 0x32,
0xE2, 0x5C, 0x35, 0x79, 0xD9, 0xC4, 0x57, 0x7C, 0xE4, 0x03, 0x5A, 0xF8,
0xCD, 0x5B, 0x54, 0x07, 0x0F, 0x17, 0xBE, 0xBF, 0x46, 0x29, 0xC3, 0x5F,
0x59, 0xD9, 0xAA, 0x80, 0x82, 0x4A, 0xB1, 0x0A, 0xDA, 0xAB, 0xA5, 0x82,
0x78, 0x8C, 0x42, 0x3C, 0xF2, 0x70, 0xEF, 0x4F, 0x3E, 0xFD, 0x11, 0x11,
0x40, 0x1A, 0x14, 0xA1, 0xB5, 0xC8, 0xE3, 0xE2, 0x5A, 0xB7, 0x0F, 0xF3,
0x5E, 0x25, 0x7D, 0x4A, 0x3A, 0xE3, 0x2B, 0xD9, 0xC9, 0xE0, 0x7D, 0x58,
0x2B, 0x23, 0xA3, 0xCB, 0x3D, 0xD2, 0x01, 0xB7, 0x98, 0xAE, 0x07, 0x60,
0xAD, 0x31, 0xAF, 0x90, 0x44, 0xC2, 0x3C, 0x00, 0x0B, 0x6F, 0xEE, 0x11,
0x83, 0x51, 0x47, 0xCA, 0x64, 0x8C, 0x7C, 0x3A, 0xAE, 0xC0, 0xEB, 0x01,
0xEB, 0x73, 0x1D, 0x97, 0xAD, 0xC3, 0x22, 0x42, 0x69, 0x89, 0xC0, 0x3A,
0x09, 0x8E, 0xB2, 0x93, 0xF2, 0xE0, 0x38, 0x00, 0xD0, 0xCC, 0x48, 0xA9,
0x8D, 0xC7, 0x4A, 0xAB, 0x34, 0x0E, 0x8E, 0x56, 0xF8, 0x86, 0xC4, 0x19,
0xC4, 0xDF, 0x37, 0x93, 0x31, 0x89, 0x89, 0x60, 0x74, 0xA9, 0x93, 0x8B,
0x5D, 0x52, 0xEB, 0x19, 0x73, 0xF8, 0xC5, 0x16, 0x12, 0xD9, 0xB5, 0x05,
0x07, 0x44, 0xFC, 0xA6, 0x89, 0xF4, 0x2B, 0x9A, 0xAC, 0x67, 0xDA, 0x0A,
0x29, 0xFF, 0x87, 0x65, 0xA1, 0xCC, 0x62, 0x49, 0xE2, 0xE3, 0x71, 0x1F,
0xF4, 0x84, 0x40, 0xD2, 0xA7, 0x83, 0x97, 0x81, 0x5F, 0x02, 0xEA, 0x40,
0x90, 0xBD, 0x25, 0x2E, 0x70, 0x63, 0x80, 0x64, 0x47, 0x73, 0xAA, 0xCC,
0x07, 0x2E, 0x2A, 0x2F, 0x5F, 0x31, 0x46, 0x34, 0xED, 0x47, 0xD8, 0x6C,
0x9F, 0x86, 0x7F, 0xA5, 0x88, 0x48, 0x82, 0xA3, 0x26, 0xDD, 0x01, 0x15,
0x90, 0xAF, 0xDA, 0x3A, 0x04, 0xCE, 0x97, 0x05, 0xC7, 0x74, 0x8C, 0x2E,
0xF8, 0x7B, 0xF3, 0xC7, 0x46, 0x3F, 0x06, 0x03, 0x1D, 0x09, 0x94, 0xA5,
0xAE, 0xCA, 0x4F, 0x6D, 0x00, 0x43, 0x82, 0xB9, 0x56, 0xCE, 0xBF, 0x8F,
0x8D, 0xC8, 0xC4, 0xBC, 0x37, 0xF7, 0x2D, 0x88, 0xFD, 0xC2, 0x1B, 0x51,
0x24, 0xFE, 0x5C, 0x5D, 0x5C, 0x62, 0x62, 0xA8, 0xBF, 0x4A, 0x90, 0xA4,
0x1A, 0x1C, 0xB8, 0xED, 0x17, 0xCD, 0x61, 0xF9, 0x24, 0x26, 0xCF, 0xE0,
0x6E, 0x88, 0xE5, 0x3B, 0xF9, 0x43, 0xBC, 0xCF, 0x28, 0xA3, 0xE5, 0xCF,
0x8B, 0x6D, 0xB3, 0x00, 0xDE, 0xB2, 0x14, 0xBB, 0xB1, 0xAF, 0xAE, 0x65,
0x25, 0x92, 0xBB, 0x40, 0x8B, 0xDA, 0x6C, 0x7B, 0xD3, 0x90, 0x42, 0x0D,
0xC2, 0x6A, 0x67, 0x59, 0xC4, 0x47, 0xF8, 0xCC, 0x1C, 0x15, 0x93, 0xB7,
0xC8, 0xAB, 0x7A, 0x97, 0x16, 0x3B, 0x9C, 0x95, 0xAE, 0x5B, 0x98, 0x61,
0xF0, 0xEE, 0xE4, 0xE3, 0xFA, 0x0D, 0xD2, 0x93, 0x5D, 0x1A, 0xDB, 0xF5,
0xFF, 0x65, 0xE0, 0x5C, 0x53, 0x82, 0x44, 0x44, 0x38, 0x09, 0xC3, 0xE7,
0x66, 0x6F, 0xEF, 0x5D, 0x42, 0xCB, 0x08, 0x28, 0x7B, 0xA0, 0xFF, 0x91,
0xCA, 0x49, 0x67, 0xC3, 0x27, 0x9D, 0xBD, 0xF7, 0x92, 0x7D, 0x8E, 0x25,
0xA6, 0x57, 0x70, 0xC8, 0x70, 0x88, 0xB1, 0x8C, 0x98, 0x99, 0xF6, 0x47,
0x33, 0x0D, 0xF6, 0xCE, 0xA1, 0xF9, 0x8C, 0x29, 0xD2, 0xC5, 0x90, 0x38,
0x7C, 0x70, 0x6B, 0x6E, 0x5A, 0xF8, 0x32, 0x3F, 0xF9, 0x8F, 0x21, 0xCB,
0x50, 0x5E, 0x71, 0x1A, 0xC2, 0x5D, 0x9B, 0x94, 0x6D, 0x0D, 0xFC, 0x09,
0x59, 0xEE, 0x8D, 0x7A, 0x53, 0xBF, 0x90, 0x93, 0x2C, 0xDF, 0x95, 0x23,
0x03, 0xA7, 0x61, 0x48, 0xE7, 0xC7, 0x12, 0x4C, 0x3B, 0xDC, 0xCE, 0x4F,
0x8D, 0xC4, 0x68, 0xD4, 0xEB, 0x58, 0x64, 0x6B, 0xB5, 0xF7, 0x1D, 0x90,
0x82, 0xE8, 0x48, 0x2E, 0x96, 0x71, 0xB8, 0x0B, 0xCD, 0xB4, 0xBA, 0x4E,
0xB7, 0xCF, 0x33, 0xDC, 0xFB, 0x6C, 0xC4, 0x0E, 0x85, 0x73, 0x40, 0x46,
0xA5, 0x05, 0xCF, 0x25, 0x36, 0x30, 0xB5, 0x78, 0x8F, 0x7F, 0x59, 0x63,
0x7D, 0x47, 0x79, 0x28, 0x5B, 0x0F, 0xA2, 0x13, 0xC9, 0x38, 0x81, 0x09,
0x01, 0xA1, 0x47, 0x2F, 0x71, 0x93, 0xC2, 0x65, 0x85, 0xB4, 0xAD, 0x5D,
0x1E, 0x87, 0xCF, 0x42, 0xE9, 0x22, 0x39, 0x36, 0xFA, 0xA4, 0x2E, 0xB2,
0x2A, 0x53, 0x3F, 0xCC, 0x65, 0x8B, 0x3B, 0x2C, 0xD3, 0x33, 0x8A, 0x8F,
0x52, 0xFB, 0x94, 0x4B, 0x08, 0x35, 0x51, 0x8F, 0x06, 0xA6, 0x50, 0x9E,
0xAA, 0x10, 0x89, 0x35, 0x38, 0x9E, 0x36, 0x6C, 0x98, 0xEF, 0x4B, 0xF3,
0x1B, 0x60, 0x96, 0x72, 0x8B, 0x40, 0xC1, 0x13, 0xDE, 0x55, 0xBA, 0x5A,
0xE0, 0xC1, 0x16, 0x45, 0x71, 0xDF, 0xF5, 0xFB, 0x78, 0x31, 0xAC, 0x1B,
0xAA, 0x7D, 0x89, 0xE3, 0xC8, 0x96, 0xE1, 0x98, 0x21, 0xF3, 0x6B, 0xC5,
0x1C, 0xD6, 0x1C, 0x19, 0x18, 0xCA, 0x44, 0x9A, 0x8B, 0xCE, 0x9E, 0x15,
0x06, 0x7F, 0xEA, 0xA5, 0x16, 0x97, 0xF9, 0xA5, 0x84, 0xB1, 0xD5, 0xEA,
0xE2, 0xC8, 0x51, 0x80, 0x53, 0x80, 0x38, 0xAC, 0x90, 0x34, 0xC7, 0xB1,
0x19, 0x9C, 0x9D, 0xF5, 0xA9, 0xA4, 0x6E, 0x5A, 0xA3, 0x10, 0xE3, 0x84,
0xCF, 0x3C, 0x4F, 0x51, 0xD9, 0xAD, 0xF2, 0x4F, 0x90, 0x12, 0x6F, 0x89,
0x0B, 0xCD, 0x0D, 0x47, 0x6B, 0x2F, 0xD6, 0x6C, 0x3C, 0xD0, 0xFA, 0x94,
0xFE, 0x18, 0xAC, 0xE7, 0x35, 0x09, 0xD4, 0x08, 0xF8, 0xB7, 0x39, 0x05,
0x7E, 0x2E, 0x23, 0xCB, 0x69, 0xCF, 0x36, 0xF5, 0x52, 0xA6, 0x35, 0xA2,
0x00, 0x8E, 0x9C, 0xA5, 0x9B, 0x1B, 0x76, 0x17, 0x61, 0xF6, 0x26, 0xB2,
0x8A, 0x3E, 0x18, 0x75, 0x08, 0x37, 0x1C, 0x1D, 0xB4, 0xFB, 0x52, 0xBD,
0x55, 0xC1, 0x67, 0x4E, 0x60, 0x6A, 0x2C, 0xA8, 0x81, 0x6C, 0x6D, 0xA8,
0xE2, 0x85, 0xF6, 0xA0, 0xD3, 0xC4, 0xF5, 0x5A, 0xF7, 0x1F, 0xD6, 0x3C,
0x61, 0xA5, 0x68, 0x79, 0x45, 0x3E, 0x2A, 0x2A, 0xA8, 0xE6,
};
// kPKCS7Windows is the Equifax root certificate, as exported by Windows 7.
static const uint8_t kPKCS7Windows[] = {
0x30, 0x82, 0x02, 0xb1, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0xa2, 0x30, 0x82, 0x02, 0x9e, 0x02,
0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x02, 0x86, 0x30, 0x82, 0x02,
0x82, 0x30, 0x82, 0x01, 0xeb, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01,
0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
0x01, 0x04, 0x05, 0x00, 0x30, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06,
0x03, 0x55, 0x04, 0x0a, 0x13, 0x13, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61,
0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x49, 0x6e, 0x63,
0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1d,
0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65, 0x63, 0x75,
0x72, 0x65, 0x20, 0x65, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73,
0x20, 0x43, 0x41, 0x2d, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x39, 0x39, 0x30,
0x36, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d,
0x32, 0x30, 0x30, 0x36, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30,
0x5a, 0x30, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04,
0x0a, 0x13, 0x13, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53,
0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26,
0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1d, 0x45, 0x71, 0x75,
0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20,
0x65, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x43, 0x41,
0x2d, 0x31, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xce, 0x2f, 0x19, 0xbc, 0x17,
0xb7, 0x77, 0xde, 0x93, 0xa9, 0x5f, 0x5a, 0x0d, 0x17, 0x4f, 0x34, 0x1a,
0x0c, 0x98, 0xf4, 0x22, 0xd9, 0x59, 0xd4, 0xc4, 0x68, 0x46, 0xf0, 0xb4,
0x35, 0xc5, 0x85, 0x03, 0x20, 0xc6, 0xaf, 0x45, 0xa5, 0x21, 0x51, 0x45,
0x41, 0xeb, 0x16, 0x58, 0x36, 0x32, 0x6f, 0xe2, 0x50, 0x62, 0x64, 0xf9,
0xfd, 0x51, 0x9c, 0xaa, 0x24, 0xd9, 0xf4, 0x9d, 0x83, 0x2a, 0x87, 0x0a,
0x21, 0xd3, 0x12, 0x38, 0x34, 0x6c, 0x8d, 0x00, 0x6e, 0x5a, 0xa0, 0xd9,
0x42, 0xee, 0x1a, 0x21, 0x95, 0xf9, 0x52, 0x4c, 0x55, 0x5a, 0xc5, 0x0f,
0x38, 0x4f, 0x46, 0xfa, 0x6d, 0xf8, 0x2e, 0x35, 0xd6, 0x1d, 0x7c, 0xeb,
0xe2, 0xf0, 0xb0, 0x75, 0x80, 0xc8, 0xa9, 0x13, 0xac, 0xbe, 0x88, 0xef,
0x3a, 0x6e, 0xab, 0x5f, 0x2a, 0x38, 0x62, 0x02, 0xb0, 0x12, 0x7b, 0xfe,
0x8f, 0xa6, 0x03, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x66, 0x30, 0x64,
0x30, 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01,
0x01, 0x04, 0x04, 0x03, 0x02, 0x00, 0x07, 0x30, 0x0f, 0x06, 0x03, 0x55,
0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff,
0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
0x14, 0x4a, 0x78, 0x32, 0x52, 0x11, 0xdb, 0x59, 0x16, 0x36, 0x5e, 0xdf,
0xc1, 0x14, 0x36, 0x40, 0x6a, 0x47, 0x7c, 0x4c, 0xa1, 0x30, 0x1d, 0x06,
0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x4a, 0x78, 0x32, 0x52,
0x11, 0xdb, 0x59, 0x16, 0x36, 0x5e, 0xdf, 0xc1, 0x14, 0x36, 0x40, 0x6a,
0x47, 0x7c, 0x4c, 0xa1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x75,
0x5b, 0xa8, 0x9b, 0x03, 0x11, 0xe6, 0xe9, 0x56, 0x4c, 0xcd, 0xf9, 0xa9,
0x4c, 0xc0, 0x0d, 0x9a, 0xf3, 0xcc, 0x65, 0x69, 0xe6, 0x25, 0x76, 0xcc,
0x59, 0xb7, 0xd6, 0x54, 0xc3, 0x1d, 0xcd, 0x99, 0xac, 0x19, 0xdd, 0xb4,
0x85, 0xd5, 0xe0, 0x3d, 0xfc, 0x62, 0x20, 0xa7, 0x84, 0x4b, 0x58, 0x65,
0xf1, 0xe2, 0xf9, 0x95, 0x21, 0x3f, 0xf5, 0xd4, 0x7e, 0x58, 0x1e, 0x47,
0x87, 0x54, 0x3e, 0x58, 0xa1, 0xb5, 0xb5, 0xf8, 0x2a, 0xef, 0x71, 0xe7,
0xbc, 0xc3, 0xf6, 0xb1, 0x49, 0x46, 0xe2, 0xd7, 0xa0, 0x6b, 0xe5, 0x56,
0x7a, 0x9a, 0x27, 0x98, 0x7c, 0x46, 0x62, 0x14, 0xe7, 0xc9, 0xfc, 0x6e,
0x03, 0x12, 0x79, 0x80, 0x38, 0x1d, 0x48, 0x82, 0x8d, 0xfc, 0x17, 0xfe,
0x2a, 0x96, 0x2b, 0xb5, 0x62, 0xa6, 0xa6, 0x3d, 0xbd, 0x7f, 0x92, 0x59,
0xcd, 0x5a, 0x2a, 0x82, 0xb2, 0x37, 0x79, 0x31, 0x00,
};
// kPKCS7SignedWithSignerInfo has content SignedData, but unlike other test
// objects, it contains SignerInfos as well.
static const uint8_t kPKCS7SignedWithSignerInfo[]{
0x30, 0x82, 0x03, 0x54, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
0x01, 0x07, 0x02, 0xa0, 0x82, 0x03, 0x45, 0x30, 0x82, 0x03, 0x41, 0x02,
0x01, 0x01, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x82, 0x00, 0x25, 0x06,
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82,
0x00, 0x16, 0x04, 0x82, 0x00, 0x12, 0x49, 0x6e, 0x69, 0x7a, 0x69, 0x6f,
0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x75, 0x74, 0x6f, 0x2e, 0x0a,
0xa0, 0x82, 0x01, 0x72, 0x30, 0x82, 0x01, 0x6e, 0x30, 0x82, 0x01, 0x14,
0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x60, 0x5c, 0xd2, 0xd5, 0x26,
0x75, 0xb3, 0x92, 0xa5, 0xaa, 0x9b, 0x02, 0xb2, 0x6a, 0x55, 0x66, 0x30,
0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30,
0x0f, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x04,
0x54, 0x65, 0x73, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x37,
0x31, 0x36, 0x31, 0x34, 0x35, 0x36, 0x33, 0x35, 0x5a, 0x17, 0x0d, 0x31,
0x39, 0x30, 0x37, 0x31, 0x36, 0x31, 0x34, 0x35, 0x36, 0x33, 0x35, 0x5a,
0x30, 0x0f, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
0x04, 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, 0x24, 0x4c, 0xb6, 0xcc,
0x1c, 0x69, 0x21, 0xff, 0x49, 0xd8, 0xbe, 0x26, 0x3e, 0x0b, 0x7c, 0xd0,
0x5a, 0x28, 0x65, 0x5a, 0x84, 0x6c, 0x82, 0x5e, 0xca, 0xe6, 0xec, 0xe6,
0x9a, 0x6a, 0x21, 0xc4, 0xe4, 0xf2, 0x20, 0x24, 0xc0, 0xe9, 0xf4, 0xe4,
0x74, 0x9c, 0x98, 0xa1, 0xad, 0xf2, 0x5f, 0x90, 0xde, 0x6e, 0xf9, 0x48,
0x2b, 0x67, 0x18, 0x83, 0xa7, 0x0e, 0xb4, 0xb7, 0xab, 0x9f, 0x06, 0x43,
0xa3, 0x52, 0x30, 0x50, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01,
0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x04, 0xf0, 0x30, 0x1d, 0x06, 0x03,
0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc3, 0xc0, 0x84, 0xdf, 0x7b,
0x04, 0x0d, 0xb0, 0x38, 0xaf, 0x51, 0x8c, 0xe3, 0x97, 0xf6, 0xec, 0x20,
0xd6, 0x26, 0xe6, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
0x30, 0x16, 0x80, 0x14, 0xc3, 0xc0, 0x84, 0xdf, 0x7b, 0x04, 0x0d, 0xb0,
0x38, 0xaf, 0x51, 0x8c, 0xe3, 0x97, 0xf6, 0xec, 0x20, 0xd6, 0x26, 0xe6,
0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xde, 0x60, 0x1e, 0x57,
0x3d, 0xaf, 0xb5, 0x9b, 0xc5, 0x51, 0xd5, 0x8e, 0x3e, 0x7b, 0x9e, 0xda,
0x06, 0x12, 0xdd, 0x01, 0x12, 0x80, 0x5a, 0x22, 0x17, 0xb7, 0x34, 0x75,
0x9b, 0x88, 0x44, 0x17, 0x02, 0x20, 0x67, 0xc3, 0xfd, 0xe6, 0x07, 0x80,
0xd4, 0x1c, 0x1d, 0x7a, 0x3b, 0x90, 0x29, 0x1f, 0x3d, 0x39, 0xc4, 0xdc,
0x2f, 0x20, 0x6d, 0xcc, 0xba, 0x2f, 0x98, 0x2c, 0x06, 0xb6, 0x7c, 0x09,
0xb2, 0x32, 0x31, 0x82, 0x01, 0x8a, 0x30, 0x82, 0x01, 0x86, 0x02, 0x01,
0x01, 0x30, 0x23, 0x30, 0x0f, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x02, 0x10, 0x60, 0x5c,
0xd2, 0xd5, 0x26, 0x75, 0xb3, 0x92, 0xa5, 0xaa, 0x9b, 0x02, 0xb2, 0x6a,
0x55, 0x66, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
0x04, 0x02, 0x01, 0x05, 0x00, 0xa0, 0x81, 0xf7, 0x30, 0x18, 0x06, 0x09,
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x03, 0x31, 0x0b, 0x06,
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1c,
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x05, 0x31,
0x0f, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x37, 0x31, 0x36, 0x31, 0x34, 0x35,
0x36, 0x33, 0x35, 0x5a, 0x30, 0x2a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x09, 0x34, 0x31, 0x1d, 0x30, 0x1b, 0x30, 0x0d, 0x06,
0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
0xa1, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09,
0x04, 0x31, 0x22, 0x04, 0x20, 0x72, 0x4c, 0x51, 0xbb, 0xe7, 0x6d, 0xa0,
0x5a, 0xfb, 0x20, 0xcb, 0xe8, 0xeb, 0x03, 0x7c, 0xda, 0xe1, 0xaf, 0xd7,
0x13, 0x12, 0x5d, 0x2d, 0xc1, 0x3d, 0x55, 0x2d, 0xa9, 0xf4, 0x42, 0xd2,
0x4d, 0x30, 0x60, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
0x09, 0x10, 0x02, 0x2f, 0x31, 0x51, 0x30, 0x4f, 0x30, 0x4d, 0x30, 0x4b,
0x04, 0x20, 0xba, 0xbc, 0x08, 0x43, 0x4c, 0x58, 0x26, 0x73, 0x01, 0xe0,
0x06, 0x86, 0x1d, 0x27, 0xec, 0xa1, 0x25, 0x67, 0x0e, 0x79, 0x27, 0x97,
0x24, 0x8e, 0x76, 0xa5, 0x71, 0x7a, 0x5b, 0xf9, 0x93, 0xc2, 0x30, 0x27,
0x30, 0x13, 0xa4, 0x11, 0x30, 0x0f, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03,
0x55, 0x04, 0x03, 0x0c, 0x04, 0x54, 0x65, 0x73, 0x74, 0x02, 0x10, 0x60,
0x5c, 0xd2, 0xd5, 0x26, 0x75, 0xb3, 0x92, 0xa5, 0xaa, 0x9b, 0x02, 0xb2,
0x6a, 0x55, 0x66, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xf1, 0x04,
0x30, 0x2e, 0xab, 0xb4, 0x28, 0xec, 0xc8, 0xe7, 0x1c, 0xe2, 0xe3, 0x8f,
0x6c, 0xbe, 0xd8, 0x48, 0xa8, 0xe9, 0xa2, 0xb5, 0xd5, 0xda, 0x19, 0x93,
0x3e, 0x48, 0x5c, 0x83, 0xcc, 0x71, 0x02, 0x20, 0x0c, 0xbb, 0x40, 0xa0,
0xb7, 0xb9, 0xb2, 0xe0, 0x48, 0x92, 0x06, 0x22, 0xfb, 0x28, 0x6f, 0xd1,
0x46, 0x95, 0xf2, 0x4c, 0xf6, 0x50, 0xbd, 0xaa, 0x40, 0xb8, 0x85, 0xf8,
0x4c, 0x34, 0xbb, 0xb9,
};
// kOpenSSLCRL is the Equifax CRL, converted to PKCS#7 form by:
// openssl crl2pkcs7 -inform DER -in secureca.crl
static const uint8_t kOpenSSLCRL[] = {
0x30, 0x82, 0x03, 0x85, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
0x01, 0x07, 0x02, 0xa0, 0x82, 0x03, 0x76, 0x30, 0x82, 0x03, 0x72, 0x02,
0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x00, 0xa1, 0x82, 0x03, 0x58, 0x30,
0x82, 0x03, 0x54, 0x30, 0x82, 0x02, 0xbd, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4e,
0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07,
0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x31, 0x2d, 0x30, 0x2b, 0x06,
0x03, 0x55, 0x04, 0x0b, 0x13, 0x24, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61,
0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72,
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74,
0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x32,
0x32, 0x37, 0x30, 0x31, 0x32, 0x33, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31,
0x35, 0x30, 0x33, 0x30, 0x39, 0x30, 0x31, 0x32, 0x33, 0x30, 0x30, 0x5a,
0x30, 0x82, 0x02, 0x3c, 0x30, 0x14, 0x02, 0x03, 0x0f, 0x58, 0xe4, 0x17,
0x0d, 0x31, 0x34, 0x30, 0x34, 0x32, 0x37, 0x30, 0x38, 0x31, 0x39, 0x32,
0x32, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x14, 0x76, 0x19, 0x17, 0x0d, 0x31,
0x34, 0x30, 0x36, 0x31, 0x38, 0x31, 0x35, 0x30, 0x30, 0x30, 0x33, 0x5a,
0x30, 0x14, 0x02, 0x03, 0x0f, 0x9a, 0xfb, 0x17, 0x0d, 0x31, 0x34, 0x30,
0x34, 0x32, 0x39, 0x31, 0x38, 0x30, 0x39, 0x31, 0x37, 0x5a, 0x30, 0x14,
0x02, 0x03, 0x14, 0x8b, 0xc0, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x37, 0x30,
0x39, 0x31, 0x39, 0x34, 0x36, 0x33, 0x33, 0x5a, 0x30, 0x14, 0x02, 0x03,
0x14, 0xe4, 0x9c, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x34, 0x31, 0x36, 0x32,
0x33, 0x33, 0x39, 0x33, 0x35, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0f, 0x86,
0x07, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x35, 0x32, 0x31, 0x31, 0x35, 0x35,
0x30, 0x35, 0x33, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x12, 0xe2, 0x29, 0x17,
0x0d, 0x31, 0x34, 0x30, 0x36, 0x31, 0x37, 0x31, 0x38, 0x35, 0x35, 0x31,
0x35, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0d, 0x42, 0x66, 0x17, 0x0d, 0x31,
0x32, 0x30, 0x36, 0x32, 0x37, 0x31, 0x37, 0x31, 0x30, 0x35, 0x33, 0x5a,
0x30, 0x14, 0x02, 0x03, 0x03, 0x1e, 0x33, 0x17, 0x0d, 0x30, 0x32, 0x30,
0x35, 0x31, 0x35, 0x31, 0x33, 0x30, 0x36, 0x31, 0x31, 0x5a, 0x30, 0x14,
0x02, 0x03, 0x12, 0xe2, 0x23, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x30,
0x36, 0x32, 0x30, 0x34, 0x30, 0x32, 0x31, 0x5a, 0x30, 0x14, 0x02, 0x03,
0x13, 0x9c, 0xab, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x37, 0x32, 0x39, 0x31,
0x36, 0x34, 0x34, 0x33, 0x39, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x12, 0xc6,
0x0a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x30, 0x36, 0x32, 0x32, 0x32,
0x31, 0x33, 0x39, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x03, 0x25, 0x85, 0x17,
0x0d, 0x30, 0x32, 0x30, 0x35, 0x31, 0x34, 0x31, 0x38, 0x31, 0x31, 0x35,
0x37, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x14, 0x86, 0xe6, 0x17, 0x0d, 0x31,
0x34, 0x30, 0x37, 0x32, 0x35, 0x30, 0x32, 0x30, 0x30, 0x33, 0x38, 0x5a,
0x30, 0x14, 0x02, 0x03, 0x13, 0x9c, 0xa1, 0x17, 0x0d, 0x31, 0x30, 0x30,
0x37, 0x32, 0x39, 0x31, 0x36, 0x34, 0x37, 0x33, 0x32, 0x5a, 0x30, 0x14,
0x02, 0x03, 0x15, 0x4d, 0x5c, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x34, 0x33,
0x30, 0x30, 0x30, 0x30, 0x34, 0x34, 0x32, 0x5a, 0x30, 0x14, 0x02, 0x03,
0x0f, 0xfa, 0x2d, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x31, 0x37, 0x31,
0x38, 0x35, 0x30, 0x31, 0x31, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x13, 0x75,
0x55, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x31, 0x31, 0x38, 0x30, 0x32, 0x32,
0x31, 0x33, 0x33, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0f, 0x56, 0x96, 0x17,
0x0d, 0x31, 0x34, 0x30, 0x36, 0x32, 0x34, 0x31, 0x32, 0x33, 0x31, 0x30,
0x32, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0b, 0x80, 0x8a, 0x17, 0x0d, 0x31,
0x32, 0x30, 0x36, 0x32, 0x37, 0x31, 0x37, 0x31, 0x30, 0x32, 0x35, 0x5a,
0x30, 0x14, 0x02, 0x03, 0x0f, 0x94, 0x16, 0x17, 0x0d, 0x31, 0x30, 0x30,
0x33, 0x30, 0x31, 0x31, 0x33, 0x34, 0x35, 0x33, 0x31, 0x5a, 0x30, 0x14,
0x02, 0x03, 0x14, 0x16, 0xb3, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x31,
0x38, 0x31, 0x34, 0x33, 0x32, 0x35, 0x36, 0x5a, 0x30, 0x14, 0x02, 0x03,
0x0a, 0xe1, 0x85, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x36, 0x32, 0x37, 0x31,
0x37, 0x31, 0x30, 0x31, 0x37, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x14, 0xcc,
0x3e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x37, 0x31, 0x31, 0x31, 0x32, 0x35,
0x35, 0x33, 0x31, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x10, 0x5b, 0xcb, 0x17,
0x0d, 0x31, 0x30, 0x30, 0x37, 0x33, 0x30, 0x32, 0x31, 0x33, 0x31, 0x32,
0x30, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x15, 0x6a, 0x1f, 0x17, 0x0d, 0x31,
0x34, 0x30, 0x32, 0x32, 0x36, 0x31, 0x32, 0x33, 0x35, 0x31, 0x39, 0x5a,
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x1d, 0x5c, 0x27, 0x07, 0x11,
0x03, 0xf2, 0x00, 0xbd, 0xf4, 0x46, 0x3e, 0x71, 0xfd, 0x10, 0x84, 0x83,
0xd9, 0xd2, 0xd2, 0x19, 0xa0, 0x20, 0xf7, 0x1a, 0x43, 0x3d, 0xac, 0xda,
0x33, 0xfc, 0xb7, 0x42, 0x60, 0x1a, 0xa4, 0xa8, 0xb2, 0x07, 0x5c, 0x51,
0x16, 0xc0, 0x42, 0x80, 0x0a, 0x0f, 0xf0, 0x47, 0x5b, 0x4b, 0x78, 0x90,
0xaf, 0xc7, 0xac, 0x48, 0xf8, 0xca, 0x3c, 0x13, 0x5e, 0xf6, 0xd1, 0x88,
0xae, 0x55, 0xa3, 0x0c, 0x8a, 0x62, 0x47, 0x29, 0xf8, 0x72, 0xb8, 0x24,
0x17, 0xaf, 0xb2, 0x06, 0x1e, 0xa7, 0x72, 0x76, 0xab, 0x96, 0x1d, 0xe0,
0x7c, 0xd4, 0x0c, 0x42, 0x82, 0x3d, 0x4a, 0x8e, 0x15, 0x77, 0x2f, 0x3c,
0x2a, 0x8c, 0x3a, 0x04, 0x10, 0x55, 0xdc, 0xbb, 0xba, 0xb1, 0x91, 0xee,
0x7b, 0xe7, 0x23, 0xc5, 0x71, 0x13, 0xae, 0x6b, 0x21, 0x35, 0xd3, 0x64,
0xf0, 0x00, 0x54, 0x31, 0x00,
};
// kPEMCert is the result of exporting the mail.google.com certificate from
// Chrome and then running it through:
// openssl pkcs7 -inform DER -in mail.google.com -outform PEM
static const char kPEMCert[] =
"-----BEGIN PKCS7-----\n"
"MIID+wYJKoZIhvcNAQcCoIID7DCCA+gCAQExADALBgkqhkiG9w0BBwGgggPQMIID\n"
"zDCCArSgAwIBAgIIWesoywKxoNQwDQYJKoZIhvcNAQELBQAwSTELMAkGA1UEBhMC\n"
"VVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5l\n"
"dCBBdXRob3JpdHkgRzIwHhcNMTUwMjExMTQxNTA2WhcNMTUwNTEyMDAwMDAwWjBp\n"
"MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91\n"
"bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEYMBYGA1UEAwwPbWFpbC5n\n"
"b29nbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7MdALmCkcRRf/tzQ\n"
"a8eu3J7S5CTQa5ns0ReF9ktlbB1RL56BVGAu4p7BrT32D6gDpiggXq3gxN81A0TG\n"
"C2yICKOCAWEwggFdMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAsBgNV\n"
"HREEJTAjgg9tYWlsLmdvb2dsZS5jb22CEGluYm94Lmdvb2dsZS5jb20wCwYDVR0P\n"
"BAQDAgeAMGgGCCsGAQUFBwEBBFwwWjArBggrBgEFBQcwAoYfaHR0cDovL3BraS5n\n"
"b29nbGUuY29tL0dJQUcyLmNydDArBggrBgEFBQcwAYYfaHR0cDovL2NsaWVudHMx\n"
"Lmdvb2dsZS5jb20vb2NzcDAdBgNVHQ4EFgQUQqsYsRoWLiG6qmV2N1mpYaHawxAw\n"
"DAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBRK3QYWG7z2aLV29YG2u2IaulqBLzAX\n"
"BgNVHSAEEDAOMAwGCisGAQQB1nkCBQEwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDov\n"
"L3BraS5nb29nbGUuY29tL0dJQUcyLmNybDANBgkqhkiG9w0BAQsFAAOCAQEAKNh3\n"
"isNuGBisPKVlekOsZR6S8oP/fS/xt6Hqvg0EwFXvhxoJ40rxAB2LMykY17e+ln3P\n"
"MwBBlRkwY1btcDT15JwzgaZb38rq/r+Pkb5Qgmx/InA/pw0QHDtwHQp5uXZuvu6p\n"
"J/SlCwyq7EOvByWdVQcMU/dhGa3idXEkn/zwfqcG6YjdWKoDmXWZYv3RiP3wJcRB\n"
"9+3U1wOe3uebnZLRWO6/w0to1XY8TFHklyw5rwIE5sbxOx5N3Ne8+GgPrUDvGAz0\n"
"rAUKnh3b7GNXL1qlZh2qkhB6rUzvtPpg397Asg3xVtExCHOk4zPqzzicttoEbVVy\n"
"0T8rIMUNwC4Beh4JVjEA\n"
"-----END PKCS7-----\n";
// kPEMCRL is the result of downloading the Equifax CRL and running:
// openssl crl2pkcs7 -inform DER -in secureca.crl */
static const char kPEMCRL[] =
"-----BEGIN PKCS7-----\n"
"MIIDhQYJKoZIhvcNAQcCoIIDdjCCA3ICAQExADALBgkqhkiG9w0BBwGgAKGCA1gw\n"
"ggNUMIICvTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UEChMH\n"
"RXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0\n"
"aG9yaXR5Fw0xNTAyMjcwMTIzMDBaFw0xNTAzMDkwMTIzMDBaMIICPDAUAgMPWOQX\n"
"DTE0MDQyNzA4MTkyMlowFAIDFHYZFw0xNDA2MTgxNTAwMDNaMBQCAw+a+xcNMTQw\n"
"NDI5MTgwOTE3WjAUAgMUi8AXDTE0MDcwOTE5NDYzM1owFAIDFOScFw0xNDA0MTYy\n"
"MzM5MzVaMBQCAw+GBxcNMTQwNTIxMTU1MDUzWjAUAgMS4ikXDTE0MDYxNzE4NTUx\n"
"NVowFAIDDUJmFw0xMjA2MjcxNzEwNTNaMBQCAwMeMxcNMDIwNTE1MTMwNjExWjAU\n"
"AgMS4iMXDTE0MDYwNjIwNDAyMVowFAIDE5yrFw0xMDA3MjkxNjQ0MzlaMBQCAxLG\n"
"ChcNMTQwNjA2MjIyMTM5WjAUAgMDJYUXDTAyMDUxNDE4MTE1N1owFAIDFIbmFw0x\n"
"NDA3MjUwMjAwMzhaMBQCAxOcoRcNMTAwNzI5MTY0NzMyWjAUAgMVTVwXDTE0MDQz\n"
"MDAwMDQ0MlowFAIDD/otFw0xNDA2MTcxODUwMTFaMBQCAxN1VRcNMTUwMTE4MDIy\n"
"MTMzWjAUAgMPVpYXDTE0MDYyNDEyMzEwMlowFAIDC4CKFw0xMjA2MjcxNzEwMjVa\n"
"MBQCAw+UFhcNMTAwMzAxMTM0NTMxWjAUAgMUFrMXDTE0MDYxODE0MzI1NlowFAID\n"
"CuGFFw0xMjA2MjcxNzEwMTdaMBQCAxTMPhcNMTQwNzExMTI1NTMxWjAUAgMQW8sX\n"
"DTEwMDczMDIxMzEyMFowFAIDFWofFw0xNDAyMjYxMjM1MTlaMA0GCSqGSIb3DQEB\n"
"BQUAA4GBAB1cJwcRA/IAvfRGPnH9EISD2dLSGaAg9xpDPazaM/y3QmAapKiyB1xR\n"
"FsBCgAoP8EdbS3iQr8esSPjKPBNe9tGIrlWjDIpiRyn4crgkF6+yBh6ncnarlh3g\n"
"fNQMQoI9So4Vdy88Kow6BBBV3Lu6sZHue+cjxXETrmshNdNk8ABUMQA=\n"
"-----END PKCS7-----\n";
static void TestCertReparse(const uint8_t *der_bytes, size_t der_len) {
bssl::UniquePtr<STACK_OF(X509)> certs(sk_X509_new_null());
ASSERT_TRUE(certs);
bssl::UniquePtr<STACK_OF(X509)> certs2(sk_X509_new_null());
ASSERT_TRUE(certs2);
uint8_t *result_data, *result2_data;
size_t result_len, result2_len;
CBS pkcs7;
CBS_init(&pkcs7, der_bytes, der_len);
ASSERT_TRUE(PKCS7_get_certificates(certs.get(), &pkcs7));
EXPECT_EQ(0u, CBS_len(&pkcs7));
// Some test cases contain indefinite-length BER input
CBS der_conv_out;
uint8_t *der_conv = nullptr;
CBS_init(&pkcs7, der_bytes, der_len);
ASSERT_TRUE(CBS_asn1_ber_to_der(&pkcs7, &der_conv_out, &der_conv));
bool is_ber = der_conv != nullptr;
bssl::UniquePtr<uint8_t> free_der_conv(der_conv);
bssl::ScopedCBB cbb;
ASSERT_TRUE(CBB_init(cbb.get(), der_len));
ASSERT_TRUE(PKCS7_bundle_certificates(cbb.get(), certs.get()));
ASSERT_TRUE(CBB_finish(cbb.get(), &result_data, &result_len));
bssl::UniquePtr<uint8_t> free_result_data(result_data);
CBS_init(&pkcs7, result_data, result_len);
ASSERT_TRUE(PKCS7_get_certificates(certs2.get(), &pkcs7));
EXPECT_EQ(0u, CBS_len(&pkcs7));
// PKCS#7 stores certificates in a SET OF, so |PKCS7_bundle_certificates| may
// not preserve the original order. All of our test inputs are already sorted,
// but this check should be relaxed if we add others.
ASSERT_EQ(sk_X509_num(certs.get()), sk_X509_num(certs2.get()));
for (size_t i = 0; i < sk_X509_num(certs.get()); i++) {
X509 *a = sk_X509_value(certs.get(), i);
X509 *b = sk_X509_value(certs2.get(), i);
ASSERT_EQ(0, X509_cmp(a, b));
}
ASSERT_TRUE(CBB_init(cbb.get(), der_len));
ASSERT_TRUE(PKCS7_bundle_certificates(cbb.get(), certs2.get()));
ASSERT_TRUE(CBB_finish(cbb.get(), &result2_data, &result2_len));
bssl::UniquePtr<uint8_t> free_result2_data(result2_data);
EXPECT_EQ(Bytes(result_data, result_len), Bytes(result2_data, result2_len));
// Parse with the legacy API instead.
const uint8_t *ptr = der_bytes;
bssl::UniquePtr<PKCS7> pkcs7_obj(d2i_PKCS7(nullptr, &ptr, der_len));
ASSERT_TRUE(pkcs7_obj);
// |ASN1_item_d2i| natively handles BER, so the pointer always advances by
// the full input length regardless of whether the input is BER or DER.
EXPECT_EQ(ptr, der_bytes + der_len);
bssl::UniquePtr<PKCS7> pkcs7_dup(PKCS7_dup(pkcs7_obj.get()));
ASSERT_TRUE(pkcs7_dup);
EXPECT_EQ(OBJ_obj2nid(pkcs7_obj.get()->type),
OBJ_obj2nid(pkcs7_dup.get()->type));
ASSERT_TRUE(PKCS7_type_is_signed(pkcs7_obj.get()));
const STACK_OF(X509) *certs3 = pkcs7_obj->d.sign->cert;
ASSERT_EQ(sk_X509_num(certs.get()), sk_X509_num(certs3));
for (size_t i = 0; i < sk_X509_num(certs.get()); i++) {
X509 *a = sk_X509_value(certs.get(), i);
X509 *b = sk_X509_value(certs3, i);
ASSERT_EQ(0, X509_cmp(a, b));
}
// Serialize the original object. This should echo back the original saved
// bytes.
uint8_t *result3_data = nullptr;
int result3_len = i2d_PKCS7(pkcs7_obj.get(), &result3_data);
ASSERT_GT(result3_len, 0);
bssl::UniquePtr<uint8_t> free_result3_data(result3_data);
if (is_ber) {
EXPECT_EQ(Bytes(der_conv, CBS_len(&der_conv_out)),
Bytes(result3_data, result3_len));
} else {
EXPECT_EQ(Bytes(der_bytes, der_len), Bytes(result3_data, result3_len));
}
// Make a new object with the legacy API.
pkcs7_obj.reset(
PKCS7_sign(nullptr, nullptr, certs.get(), nullptr, PKCS7_DETACHED));
ASSERT_TRUE(pkcs7_obj);
ASSERT_TRUE(PKCS7_type_is_signed(pkcs7_obj.get()));
const STACK_OF(X509) *certs4 = pkcs7_obj->d.sign->cert;
ASSERT_EQ(sk_X509_num(certs.get()), sk_X509_num(certs4));
for (size_t i = 0; i < sk_X509_num(certs.get()); i++) {
X509 *a = sk_X509_value(certs.get(), i);
X509 *b = sk_X509_value(certs4, i);
ASSERT_EQ(0, X509_cmp(a, b));
}
// This new object should serialize canonically.
uint8_t *result4_data = nullptr;
int result4_len = i2d_PKCS7(pkcs7_obj.get(), &result4_data);
ASSERT_GT(result4_len, 0);
bssl::UniquePtr<uint8_t> free_result4_data(result4_data);
EXPECT_EQ(Bytes(result_data, result_len), Bytes(result4_data, result4_len));
}
static void TestCRLReparse(const uint8_t *der_bytes, size_t der_len) {
bssl::UniquePtr<STACK_OF(X509_CRL)> crls(sk_X509_CRL_new_null());
ASSERT_TRUE(crls);
bssl::UniquePtr<STACK_OF(X509_CRL)> crls2(sk_X509_CRL_new_null());
ASSERT_TRUE(crls2);
uint8_t *result_data, *result2_data;
size_t result_len, result2_len;
CBS pkcs7;
CBS_init(&pkcs7, der_bytes, der_len);
ASSERT_TRUE(PKCS7_get_CRLs(crls.get(), &pkcs7));
EXPECT_EQ(0u, CBS_len(&pkcs7));
bssl::ScopedCBB cbb;
ASSERT_TRUE(CBB_init(cbb.get(), der_len));
ASSERT_TRUE(PKCS7_bundle_CRLs(cbb.get(), crls.get()));
ASSERT_TRUE(CBB_finish(cbb.get(), &result_data, &result_len));
bssl::UniquePtr<uint8_t> free_result_data(result_data);
CBS_init(&pkcs7, result_data, result_len);
ASSERT_TRUE(PKCS7_get_CRLs(crls2.get(), &pkcs7));
EXPECT_EQ(0u, CBS_len(&pkcs7));
// PKCS#7 stores CRLs in a SET OF, so |PKCS7_bundle_CRLs| may not preserve the
// original order. All of our test inputs are already sorted, but this check
// should be relaxed if we add others.
ASSERT_EQ(sk_X509_CRL_num(crls.get()), sk_X509_CRL_num(crls.get()));
for (size_t i = 0; i < sk_X509_CRL_num(crls.get()); i++) {
X509_CRL *a = sk_X509_CRL_value(crls.get(), i);
X509_CRL *b = sk_X509_CRL_value(crls2.get(), i);
ASSERT_EQ(0, X509_CRL_cmp(a, b));
}
ASSERT_TRUE(CBB_init(cbb.get(), der_len));
ASSERT_TRUE(PKCS7_bundle_CRLs(cbb.get(), crls2.get()));
ASSERT_TRUE(CBB_finish(cbb.get(), &result2_data, &result2_len));
bssl::UniquePtr<uint8_t> free_result2_data(result2_data);
EXPECT_EQ(Bytes(result_data, result_len), Bytes(result2_data, result2_len));
// Parse with the legacy API instead.
const uint8_t *ptr = der_bytes;
bssl::UniquePtr<PKCS7> pkcs7_obj(d2i_PKCS7(nullptr, &ptr, der_len));
ASSERT_TRUE(pkcs7_obj);
EXPECT_EQ(ptr, der_bytes + der_len);
ASSERT_TRUE(PKCS7_type_is_signed(pkcs7_obj.get()));
const STACK_OF(X509_CRL) *crls3 = pkcs7_obj->d.sign->crl;
ASSERT_EQ(sk_X509_CRL_num(crls.get()), sk_X509_CRL_num(crls3));
for (size_t i = 0; i < sk_X509_CRL_num(crls.get()); i++) {
X509_CRL *a = sk_X509_CRL_value(crls.get(), i);
X509_CRL *b = sk_X509_CRL_value(crls3, i);
ASSERT_EQ(0, X509_CRL_cmp(a, b));
}
ptr = result_data;
pkcs7_obj.reset(d2i_PKCS7(nullptr, &ptr, result_len));
ASSERT_TRUE(pkcs7_obj);
EXPECT_EQ(ptr, result_data + result_len);
ASSERT_TRUE(PKCS7_type_is_signed(pkcs7_obj.get()));
const STACK_OF(X509_CRL) *crls4 = pkcs7_obj->d.sign->crl;
ASSERT_EQ(sk_X509_CRL_num(crls.get()), sk_X509_CRL_num(crls4));
for (size_t i = 0; i < sk_X509_CRL_num(crls.get()); i++) {
X509_CRL *a = sk_X509_CRL_value(crls.get(), i);
X509_CRL *b = sk_X509_CRL_value(crls4, i);
ASSERT_EQ(0, X509_CRL_cmp(a, b));
}
}
static void TestPEMCerts(const char *pem) {
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem, strlen(pem)));
ASSERT_TRUE(bio);
bssl::UniquePtr<STACK_OF(X509)> certs(sk_X509_new_null());
ASSERT_TRUE(certs);
ASSERT_TRUE(PKCS7_get_PEM_certificates(certs.get(), bio.get()));
ASSERT_EQ(1u, sk_X509_num(certs.get()));
}
static void TestPEMCRLs(const char *pem) {
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem, strlen(pem)));
ASSERT_TRUE(bio);
bssl::UniquePtr<STACK_OF(X509_CRL)> crls(sk_X509_CRL_new_null());
ASSERT_TRUE(crls);
ASSERT_TRUE(PKCS7_get_PEM_CRLs(crls.get(), bio.get()));
ASSERT_EQ(1u, sk_X509_CRL_num(crls.get()));
}
TEST(PKCS7Test, CertReparseNSS) {
TestCertReparse(kPKCS7NSS, sizeof(kPKCS7NSS));
}
TEST(PKCS7Test, CertReparseWindows) {
TestCertReparse(kPKCS7Windows, sizeof(kPKCS7Windows));
}
TEST(PKCS7Test, CertSignedWithSignerInfos) {
TestCertReparse(kPKCS7SignedWithSignerInfo,
sizeof(kPKCS7SignedWithSignerInfo));
}
TEST(PKCS7Test, CrlReparse) {
TestCRLReparse(kOpenSSLCRL, sizeof(kOpenSSLCRL));
}
TEST(PKCS7Test, PEMCerts) { TestPEMCerts(kPEMCert); }
TEST(PKCS7Test, PEMCRLs) { TestPEMCRLs(kPEMCRL); }
// Test that we output certificates in the canonical DER order.
TEST(PKCS7Test, SortCerts) {
// kPKCS7NSS contains three certificates in the canonical DER order.
CBS pkcs7;
CBS_init(&pkcs7, kPKCS7NSS, sizeof(kPKCS7NSS));
bssl::UniquePtr<STACK_OF(X509)> certs(sk_X509_new_null());
ASSERT_TRUE(certs);
ASSERT_TRUE(PKCS7_get_certificates(certs.get(), &pkcs7));
ASSERT_EQ(3u, sk_X509_num(certs.get()));
X509 *cert1 = sk_X509_value(certs.get(), 0);
X509 *cert2 = sk_X509_value(certs.get(), 1);
X509 *cert3 = sk_X509_value(certs.get(), 2);
auto check_order = [&](X509 *new_cert1, X509 *new_cert2, X509 *new_cert3) {
// Bundle the certificates in the new order.
bssl::UniquePtr<STACK_OF(X509)> new_certs(sk_X509_new_null());
ASSERT_TRUE(new_certs);
ASSERT_TRUE(bssl::PushToStack(new_certs.get(), bssl::UpRef(new_cert1)));
ASSERT_TRUE(bssl::PushToStack(new_certs.get(), bssl::UpRef(new_cert2)));
ASSERT_TRUE(bssl::PushToStack(new_certs.get(), bssl::UpRef(new_cert3)));
bssl::ScopedCBB cbb;
ASSERT_TRUE(CBB_init(cbb.get(), sizeof(kPKCS7NSS)));
ASSERT_TRUE(PKCS7_bundle_certificates(cbb.get(), new_certs.get()));
// The bundle should be sorted back to the original order.
CBS cbs;
CBS_init(&cbs, CBB_data(cbb.get()), CBB_len(cbb.get()));
bssl::UniquePtr<STACK_OF(X509)> result(sk_X509_new_null());
ASSERT_TRUE(result);
ASSERT_TRUE(PKCS7_get_certificates(result.get(), &cbs));
ASSERT_EQ(sk_X509_num(certs.get()), sk_X509_num(result.get()));
for (size_t i = 0; i < sk_X509_num(certs.get()); i++) {
X509 *a = sk_X509_value(certs.get(), i);
X509 *b = sk_X509_value(result.get(), i);
EXPECT_EQ(0, X509_cmp(a, b));
}
};
check_order(cert1, cert2, cert3);
check_order(cert3, cert2, cert1);
check_order(cert2, cert3, cert1);
}
// Test that we output certificates in the canonical DER order, using the
// CRYPTO_BUFFER version of the parse and bundle functions.
TEST(PKCS7Test, SortCertsRaw) {
// kPKCS7NSS contains three certificates in the canonical DER order.
CBS pkcs7;
CBS_init(&pkcs7, kPKCS7NSS, sizeof(kPKCS7NSS));
bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> certs(sk_CRYPTO_BUFFER_new_null());
ASSERT_TRUE(certs);
ASSERT_TRUE(PKCS7_get_raw_certificates(certs.get(), &pkcs7, nullptr));
ASSERT_EQ(3u, sk_CRYPTO_BUFFER_num(certs.get()));
CRYPTO_BUFFER *cert1 = sk_CRYPTO_BUFFER_value(certs.get(), 0);
CRYPTO_BUFFER *cert2 = sk_CRYPTO_BUFFER_value(certs.get(), 1);
CRYPTO_BUFFER *cert3 = sk_CRYPTO_BUFFER_value(certs.get(), 2);
auto check_order = [&](CRYPTO_BUFFER *new_cert1, CRYPTO_BUFFER *new_cert2,
CRYPTO_BUFFER *new_cert3) {
// Bundle the certificates in the new order.
bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> new_certs(
sk_CRYPTO_BUFFER_new_null());
ASSERT_TRUE(new_certs);
ASSERT_TRUE(bssl::PushToStack(new_certs.get(), bssl::UpRef(new_cert1)));
ASSERT_TRUE(bssl::PushToStack(new_certs.get(), bssl::UpRef(new_cert2)));
ASSERT_TRUE(bssl::PushToStack(new_certs.get(), bssl::UpRef(new_cert3)));
bssl::ScopedCBB cbb;
ASSERT_TRUE(CBB_init(cbb.get(), sizeof(kPKCS7NSS)));
ASSERT_TRUE(PKCS7_bundle_raw_certificates(cbb.get(), new_certs.get()));
// The bundle should be sorted back to the original order.
CBS cbs;
CBS_init(&cbs, CBB_data(cbb.get()), CBB_len(cbb.get()));
bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> result(
sk_CRYPTO_BUFFER_new_null());
ASSERT_TRUE(result);
ASSERT_TRUE(PKCS7_get_raw_certificates(result.get(), &cbs, nullptr));
ASSERT_EQ(sk_CRYPTO_BUFFER_num(certs.get()),
sk_CRYPTO_BUFFER_num(result.get()));
for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(certs.get()); i++) {
CRYPTO_BUFFER *a = sk_CRYPTO_BUFFER_value(certs.get(), i);
CRYPTO_BUFFER *b = sk_CRYPTO_BUFFER_value(result.get(), i);
EXPECT_EQ(Bytes(CRYPTO_BUFFER_data(a), CRYPTO_BUFFER_len(a)),
Bytes(CRYPTO_BUFFER_data(b), CRYPTO_BUFFER_len(b)));
}
};
check_order(cert1, cert2, cert3);
check_order(cert3, cert2, cert1);
check_order(cert2, cert3, cert1);
}
// Test that we output CRLs in the canonical DER order.
TEST(PKCS7Test, SortCRLs) {
static const char kCRL1[] = R"(
-----BEGIN X509 CRL-----
MIIBpzCBkAIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE
CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ
Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoA4wDDAKBgNV
HRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAnrBKKgvd9x9zwK9rtUvVeFeJ7+LN
ZEAc+a5oxpPNEsJx6hXoApYEbzXMxuWBQoCs5iEBycSGudct21L+MVf27M38KrWo
eOkq0a2siqViQZO2Fb/SUFR0k9zb8xl86Zf65lgPplALun0bV/HT7MJcl04Tc4os
dsAReBs5nqTGNEd5AlC1iKHvQZkM//MD51DspKnDpsDiUVi54h9C1SpfZmX8H2Vv
diyu0fZ/bPAM3VAGawatf/SyWfBMyKpoPXEG39oAzmjjOj8en82psn7m474IGaho
/vBbhl1ms5qQiLYPjm4YELtnXQoFyC72tBjbdFd/ZE9k4CNKDbxFUXFbkw==
-----END X509 CRL-----
)";
static const char kCRL2[] = R"(
-----BEGIN X509 CRL-----
MIIBvjCBpwIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE
CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ
Qm9yaW5nU1NMFw0xNjA5MjYxNTEyNDRaFw0xNjEwMjYxNTEyNDRaMBUwEwICEAAX
DTE2MDkyNjE1MTIyNlqgDjAMMAoGA1UdFAQDAgECMA0GCSqGSIb3DQEBCwUAA4IB
AQCUGaM4DcWzlQKrcZvI8TMeR8BpsvQeo5BoI/XZu2a8h//PyRyMwYeaOM+3zl0d
sjgCT8b3C1FPgT+P2Lkowv7rJ+FHJRNQkogr+RuqCSPTq65ha4WKlRGWkMFybzVH
NloxC+aU3lgp/NlX9yUtfqYmJek1CDrOOGPrAEAwj1l/BUeYKNGqfBWYJQtPJu+5
OaSvIYGpETCZJscUWODmLEb/O3DM438vLvxonwGqXqS0KX37+CHpUlyhnSovxXxp
Pz4aF+L7OtczxL0GYtD2fR9B7TDMqsNmHXgQrixvvOY7MUdLGbd4RfJL3yA53hyO
xzfKY2TzxLiOmctG0hXFkH5J
-----END X509 CRL-----
)";
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(kCRL1, strlen(kCRL1)));
ASSERT_TRUE(bio);
bssl::UniquePtr<X509_CRL> crl1(
PEM_read_bio_X509_CRL(bio.get(), nullptr, nullptr, nullptr));
ASSERT_TRUE(crl1);
bio.reset(BIO_new_mem_buf(kCRL2, strlen(kCRL2)));
ASSERT_TRUE(bio);
bssl::UniquePtr<X509_CRL> crl2(
PEM_read_bio_X509_CRL(bio.get(), nullptr, nullptr, nullptr));
ASSERT_TRUE(crl2);
// DER's SET OF ordering sorts by tag, then length, so |crl1| comes before
// |crl2|.
auto check_order = [&](X509_CRL *new_crl1, X509_CRL *new_crl2) {
// Bundle the CRLs in the new order.
bssl::UniquePtr<STACK_OF(X509_CRL)> new_crls(sk_X509_CRL_new_null());
ASSERT_TRUE(new_crls);
ASSERT_TRUE(bssl::PushToStack(new_crls.get(), bssl::UpRef(new_crl1)));
ASSERT_TRUE(bssl::PushToStack(new_crls.get(), bssl::UpRef(new_crl2)));
bssl::ScopedCBB cbb;
ASSERT_TRUE(CBB_init(cbb.get(), 64));
ASSERT_TRUE(PKCS7_bundle_CRLs(cbb.get(), new_crls.get()));
// The bundle should be sorted back to the original order.
CBS cbs;
CBS_init(&cbs, CBB_data(cbb.get()), CBB_len(cbb.get()));
bssl::UniquePtr<STACK_OF(X509_CRL)> result(sk_X509_CRL_new_null());
ASSERT_TRUE(result);
ASSERT_TRUE(PKCS7_get_CRLs(result.get(), &cbs));
ASSERT_EQ(2u, sk_X509_CRL_num(result.get()));
EXPECT_EQ(0, X509_CRL_cmp(crl1.get(), sk_X509_CRL_value(result.get(), 0)));
EXPECT_EQ(0, X509_CRL_cmp(crl2.get(), sk_X509_CRL_value(result.get(), 1)));
};
check_order(crl1.get(), crl2.get());
check_order(crl2.get(), crl1.get());
}
TEST(PKCS7Test, KernelModuleSigning) {
// Sign a message with the same call that the Linux kernel's sign-file.c
// makes.
static const char kCert[] = R"(
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIURVkPzF/4dwy7419Qk75uhIuyf0EwDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTA5MjExOTIyMTJaFw0yMjA5
MjExOTIyMTJaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQC1+MOn+BopcEVR4QMvjXdAxGkWFllXyQFDToL+qOiP
RU1yN7C8KCtkbOAFttJIO4O/i0iZ7KqYbnmB6YUA/ONAcakocnrdoESgRJcVMeAx
Dk/11OtMF5yIfeOOO/TUeVNmAUaT63gFbKy/adpqhzJtOv9BBl5VcYNGGSE+0wtb
mjpmNsxunEQR1KLDc97fGYHeRfKoSyrCIEE8IaAEpKGR2Sku3v9Jwh7RpjupgiUA
kH6pJk7VMZm5vl2wFjYvfysgjeN5ZtsxFDMaPYZStpxMxpNd5C9DsO2Ljp5NMpGf
NGmG4ZqiaQg8z2cIM6ESmN1zDJdUh5IXed1fOxBZD/poUFH0wDRFWnvzlaPmjJEF
rYLMK8svnE5nEQp9vu93ISFBx7cofs+niMaUXPEqaRSqruifN2M1it3kOf/8YZl1
vurs+VtHD6nOJo6bd11+37aBidIB/BaWnzLrDmSTcPFa1tkTHwoLqc9+jThTq9jZ
6w3lAMPpsoenyD19UmQB589+4kNp2SIO/TtzVQCGgQPXE2jDCl6G9aIPMkfvpPZK
4THVil3WQRCFYnYdDO4HQXo2ZuC4RiqgY5ygfeoL+fa9k383lgxxAHQLS7xsbaVB
40RmfdbdevgPYIwZNNO78ddRmMdSv6IknSW9gydGzY//btY+t1SWcBZWzn1Ewq8g
2QIDAQABo1MwUTAdBgNVHQ4EFgQUotZD9ajEvnQYVezIWzcW4pzvMcUwHwYDVR0j
BBgwFoAUotZD9ajEvnQYVezIWzcW4pzvMcUwDwYDVR0TAQH/BAUwAwEB/zANBgkq
hkiG9w0BAQsFAAOCAgEAqCe42PIWoyLDx9bR+5cSp99N5xo5lLiSLtWx2emDbZB2
AunqKYeEgIV+TWNF2w1SZ/ckFgV7SlL2Yl73N/veSNRfNAnpjLksGDFpdJb7YXrx
cUvxdy1mr8oau6J7PC9JGjBTBrnhqwCQX1FtcAxODKll2Lsfuj6+bdC3rCK7KBEo
ENamMJZIeo8lRP9qFF2xwCEzZjRv2zvB6O5o9045aTUcdCrwUfKE2sqY6EXRzFTC
waK0HRCd1FLv9omhz/Ug5PMHP4d6MZfnAbFm+AzAhnpkrk/9TJYSOoNTNLWsuqhp
dN0rKqiFWv1zIwfknXvTh1P1Ap+G5jffAca0zWUH1oKjE7ZZioSsaZ6gySnD8+WQ
TPbOYtG+n0mhCH1TrU8Dqi3rd8g5IbC8loYLRH94QtodOnevD4Qo9Orfrsr8hGOW
ABespanZArhoQ03DAtpNhtHm2NWJQF2uHNqcTrkq0omqZBTbMD1GKMBujoNooAUu
w51U9r+RycPJTFqEGHb0nd7EjoyXEXtuX1Ld5fTZjQ9SszmQKQ8w3lHqRGNlkSiO
e3IOOq2ruXmq1jykxpmi82IcTRUE8TZBfL/yz0nxpHKAYC1VwMezrkgZDGz4npxf
1z2+qd58xU6/jsf7/+3xdPFubeEJujdbCkWQsQC5Rzm48zDWGq/pyzFji44K3TA=
-----END CERTIFICATE-----
)";
static const char kKey[] = R"(
-----BEGIN PRIVATE KEY-----
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
hJTbHtjEDJ7BHLC/CNUhXbpyyu1y
-----END PRIVATE KEY-----
)";
bssl::UniquePtr<BIO> cert_bio(
BIO_new_mem_buf(const_cast<char *>(kCert), sizeof(kCert) - 1));
bssl::UniquePtr<X509> cert(
PEM_read_bio_X509(cert_bio.get(), nullptr, nullptr, nullptr));
bssl::UniquePtr<BIO> key_bio(
BIO_new_mem_buf(const_cast<char *>(kKey), sizeof(kKey) - 1));
bssl::UniquePtr<EVP_PKEY> key(
PEM_read_bio_PrivateKey(key_bio.get(), nullptr, nullptr, nullptr));
static const char kSignedData[] = "signed data";
bssl::UniquePtr<BIO> data_bio(BIO_new_mem_buf(const_cast<char *>(kSignedData),
sizeof(kSignedData) - 1));
bssl::UniquePtr<PKCS7> pkcs7(
PKCS7_sign(cert.get(), key.get(), /*certs=*/nullptr, data_bio.get(),
PKCS7_NOATTR | PKCS7_BINARY | PKCS7_NOCERTS | PKCS7_DETACHED));
ASSERT_TRUE(pkcs7);
uint8_t *pkcs7_bytes = nullptr;
const int pkcs7_len = i2d_PKCS7(pkcs7.get(), &pkcs7_bytes);
ASSERT_GE(pkcs7_len, 0);
bssl::UniquePtr<uint8_t> pkcs7_storage(pkcs7_bytes);
// RSA signatures are deterministic so the output should not change.
static const uint8_t kExpectedOutput[] = {
0x30, 0x82, 0x02, 0xbc, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0xad, 0x30, 0x82, 0x02, 0xa9, 0x02,
0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48,
0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x02, 0x86, 0x30, 0x82,
0x02, 0x82, 0x02, 0x01, 0x01, 0x30, 0x5d, 0x30, 0x45, 0x31, 0x0b, 0x30,
0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d,
0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x02, 0x14, 0x45, 0x59, 0x0f, 0xcc,
0x5f, 0xf8, 0x77, 0x0c, 0xbb, 0xe3, 0x5f, 0x50, 0x93, 0xbe, 0x6e, 0x84,
0x8b, 0xb2, 0x7f, 0x41, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00,
0x54, 0xd4, 0x7c, 0xdc, 0x19, 0x86, 0xa1, 0xb2, 0xbe, 0xe3, 0xa4, 0x5e,
0xad, 0x16, 0x6f, 0x7c, 0xf9, 0xa6, 0x40, 0x90, 0xb8, 0x78, 0x85, 0xf1,
0x02, 0x59, 0xe5, 0x9f, 0x83, 0xfb, 0x20, 0xcf, 0x29, 0x52, 0xb6, 0x35,
0x5c, 0xf9, 0xef, 0x4e, 0xc5, 0xd3, 0xa6, 0x45, 0x6e, 0xfa, 0x0a, 0xa7,
0x53, 0xc8, 0xf4, 0xf9, 0xd6, 0xc5, 0xd8, 0xd8, 0x04, 0x3d, 0xb4, 0x15,
0xa7, 0x7a, 0x53, 0xdd, 0x27, 0xfa, 0x58, 0x2e, 0x5e, 0xc4, 0xcd, 0x45,
0xaa, 0xc2, 0x7b, 0xf9, 0x3d, 0xd7, 0x22, 0x20, 0x90, 0xbb, 0xa5, 0x62,
0xd5, 0xaa, 0x39, 0x8f, 0xc1, 0x00, 0xef, 0x4b, 0x03, 0x2c, 0x32, 0xc0,
0xad, 0x27, 0xb6, 0xfe, 0x86, 0xe5, 0x9d, 0xf0, 0xbe, 0xb1, 0x0d, 0xa4,
0xa3, 0x40, 0xe0, 0xaa, 0x0a, 0x13, 0x6e, 0x61, 0x9a, 0x3b, 0xae, 0x78,
0xd4, 0x6f, 0x2d, 0x1d, 0x40, 0x4b, 0xe3, 0x5f, 0xf8, 0xe8, 0x21, 0x89,
0x35, 0x73, 0x6d, 0x7e, 0x41, 0xc6, 0x0f, 0x0c, 0x01, 0x64, 0x61, 0xa8,
0x37, 0xef, 0x2b, 0x95, 0xb7, 0x34, 0xac, 0xc7, 0xdb, 0x66, 0x87, 0x45,
0xb4, 0x0f, 0x60, 0x01, 0x07, 0x29, 0x74, 0x32, 0x0b, 0xae, 0xbc, 0x08,
0x88, 0x15, 0xc3, 0x79, 0x4a, 0x1c, 0x5a, 0x9c, 0xc2, 0xfb, 0x4f, 0xd3,
0x17, 0xc2, 0x40, 0x71, 0x37, 0xea, 0xa6, 0x1e, 0xf0, 0x5b, 0xa5, 0xd7,
0x9b, 0x9e, 0x57, 0x44, 0x74, 0xc5, 0xd5, 0x5f, 0xba, 0xbc, 0xd7, 0xe1,
0xae, 0xd0, 0xd3, 0xb5, 0x10, 0xc6, 0x8b, 0xb1, 0x83, 0x7c, 0xaa, 0x3a,
0xbb, 0xe8, 0x7f, 0x56, 0xc4, 0x3b, 0x9d, 0x45, 0x09, 0x9b, 0x34, 0xc9,
0xfb, 0x5a, 0xa1, 0xab, 0xd0, 0x07, 0x79, 0x43, 0x58, 0x44, 0xd7, 0x40,
0xc4, 0xa7, 0xd3, 0xe9, 0x18, 0xb9, 0x78, 0x1d, 0x93, 0x0b, 0xc1, 0xdb,
0xc3, 0xae, 0xc9, 0xe8, 0x2c, 0xa7, 0x8c, 0x7e, 0x31, 0x1e, 0xec, 0x1c,
0xab, 0x83, 0xa0, 0x5d, 0x0e, 0xc3, 0x6a, 0x7c, 0x97, 0x09, 0xcf, 0x00,
0xa9, 0x66, 0xda, 0x21, 0x85, 0xaa, 0x47, 0xd8, 0xea, 0x8f, 0x72, 0x54,
0x03, 0x6c, 0xbc, 0x4b, 0xf9, 0x92, 0xae, 0x82, 0x75, 0x33, 0x10, 0x4d,
0x65, 0x4d, 0x0e, 0x73, 0x5d, 0x6f, 0x09, 0xee, 0x56, 0x78, 0x87, 0x0b,
0xa3, 0xaa, 0xc2, 0x5f, 0x49, 0x73, 0x0d, 0x78, 0xfa, 0x40, 0xc1, 0x25,
0x2f, 0x5d, 0x8a, 0xe1, 0xbf, 0x38, 0x2c, 0xd0, 0x26, 0xbd, 0xf5, 0x6e,
0x02, 0x01, 0x2e, 0x9e, 0x27, 0x64, 0x4b, 0x61, 0x8c, 0x68, 0x6e, 0x09,
0xfe, 0x0b, 0xf8, 0x36, 0x4e, 0x84, 0xb7, 0x76, 0xcb, 0x41, 0xf0, 0x40,
0x72, 0xc9, 0x74, 0x64, 0x5f, 0xbe, 0x9e, 0xfe, 0x9e, 0xce, 0x89, 0x84,
0x68, 0x81, 0x57, 0x2a, 0xdb, 0xd6, 0x01, 0xa8, 0x1b, 0x6e, 0x5d, 0xc4,
0x65, 0xbd, 0x0d, 0x98, 0x54, 0xa3, 0x18, 0x23, 0x09, 0x4a, 0x8d, 0x6c,
0xc6, 0x2e, 0xfe, 0x7a, 0xa9, 0x11, 0x92, 0x8b, 0xd0, 0xc1, 0xe7, 0x76,
0x71, 0xec, 0x34, 0xfc, 0xc8, 0x2a, 0x5e, 0x38, 0x52, 0xe6, 0xc8, 0xa5,
0x1d, 0x0b, 0xce, 0xf5, 0xc0, 0xe5, 0x0b, 0x88, 0xa9, 0x55, 0x88, 0x6c,
0xfa, 0xea, 0xaa, 0x39, 0x66, 0xdd, 0x80, 0x52, 0xe0, 0x7e, 0x45, 0x8e,
0x51, 0x2c, 0x36, 0x07, 0xd7, 0x2b, 0xf1, 0x46, 0x00, 0x66, 0xb2, 0x5a,
0x39, 0xbe, 0xf7, 0x26, 0x15, 0xbc, 0x55, 0xdb, 0xe9, 0x01, 0xdd, 0x54,
0x27, 0x2b, 0xfe, 0x86, 0x52, 0xef, 0xc6, 0x27, 0xa3, 0xf7, 0x55, 0x55,
0xb8, 0xe2, 0x1f, 0xcb, 0x32, 0xd8, 0xba, 0xd6, 0x69, 0xde, 0x8d, 0xa7,
0xfa, 0xad, 0xf6, 0x2a, 0xc0, 0x6f, 0x86, 0x50, 0x27, 0x5a, 0xe2, 0xe3,
0xf6, 0xb9, 0x01, 0xec, 0x01, 0x37, 0x84, 0x01,
};
EXPECT_EQ(Bytes(pkcs7_bytes, pkcs7_len),
Bytes(kExpectedOutput, sizeof(kExpectedOutput)));
ERR_clear_error();
}
TEST(PKCS7Test, GettersSetters) {
bssl::UniquePtr<PKCS7> p7;
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
EXPECT_FALSE(PKCS7_set_type(p7.get(), NID_undef));
EXPECT_FALSE(PKCS7_content_new(p7.get(), NID_undef));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
EXPECT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signed));
// set type redundantly to ensure we're properly freeing up existing
// resources on subsequent set.
EXPECT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signed));
EXPECT_TRUE(PKCS7_type_is_signed(p7.get()));
EXPECT_TRUE(PKCS7_content_new(p7.get(), NID_pkcs7_signed));
EXPECT_FALSE(PKCS7_set_cipher(p7.get(), EVP_aes_128_gcm()));
EXPECT_FALSE(PKCS7_add_recipient_info(p7.get(), nullptr));
EXPECT_FALSE(PKCS7_get_signer_info(nullptr));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
EXPECT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_digest));
// set type redundantly to ensure we're properly freeing up existing
// resources on subsequent set.
EXPECT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_digest));
EXPECT_TRUE(PKCS7_type_is_digest(p7.get()));
EXPECT_TRUE(PKCS7_content_new(p7.get(), NID_pkcs7_digest));
EXPECT_FALSE(PKCS7_add_certificate(p7.get(), nullptr));
EXPECT_FALSE(PKCS7_add_crl(p7.get(), nullptr));
EXPECT_FALSE(PKCS7_add_signer(p7.get(), nullptr));
EXPECT_FALSE(PKCS7_get_signer_info(p7.get()));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7.get());
EXPECT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_data));
// set type redundantly to ensure we're properly freeing up existing
// resources on subsequent set.
EXPECT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_data));
EXPECT_TRUE(PKCS7_type_is_data(p7.get()));
EXPECT_FALSE(PKCS7_set_content(p7.get(), p7.get()));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7.get());
EXPECT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signedAndEnveloped));
// set type redundantly to ensure we're properly freeing up existing
// resources on subsequent set.
EXPECT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signedAndEnveloped));
EXPECT_TRUE(PKCS7_type_is_signedAndEnveloped(p7.get()));
EXPECT_TRUE(PKCS7_set_cipher(p7.get(), EVP_aes_128_gcm()));
EXPECT_FALSE(PKCS7_set_content(p7.get(), p7.get()));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7.get());
EXPECT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_enveloped));
// set type redundantly to ensure we're properly freeing up existing
// resources on subsequent set.
EXPECT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_enveloped));
EXPECT_TRUE(PKCS7_type_is_enveloped(p7.get()));
EXPECT_TRUE(PKCS7_set_cipher(p7.get(), EVP_aes_128_gcm()));
EXPECT_FALSE(PKCS7_set_content(p7.get(), p7.get()));
// Ruby requires that we can set type NID_pkcs7_encrypted even though we don't
// really support it for most functions.
p7.reset(PKCS7_new());
ASSERT_TRUE(p7.get());
EXPECT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_encrypted));
// set type redundantly to ensure we're properly freeing up existing
// resources on subsequent set.
EXPECT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_encrypted));
EXPECT_TRUE(PKCS7_type_is_encrypted(p7.get()));
EXPECT_FALSE(PKCS7_set_content(p7.get(), p7.get()));
// |d2i_*| functions advance the input reference by number of bytes parsed,
// so save off a local reference and reset it for each test case.
const uint8_t *p7_der = kPKCS7SignedWithSignerInfo;
const size_t p7_der_len = sizeof(kPKCS7SignedWithSignerInfo);
p7.reset(d2i_PKCS7(nullptr, &p7_der, p7_der_len));
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_type_is_signed(p7.get()));
STACK_OF(PKCS7_SIGNER_INFO) *sk_p7si_signed = PKCS7_get_signer_info(p7.get());
ASSERT_TRUE(sk_p7si_signed);
ASSERT_GT(sk_PKCS7_SIGNER_INFO_num(sk_p7si_signed), 0UL);
PKCS7_SIGNER_INFO *p7si = sk_PKCS7_SIGNER_INFO_value(sk_p7si_signed, 0);
ASSERT_TRUE(p7si);
EXPECT_FALSE(PKCS7_get_signed_attribute(
p7si, NID_md5)); // hash nid not valid x509 attr
ASN1_TYPE *signing_time =
PKCS7_get_signed_attribute(p7si, NID_pkcs9_signingTime);
ASSERT_TRUE(signing_time);
EVP_PKEY *pkey;
X509_ALGOR *pdig;
X509_ALGOR *psig;
PKCS7_SIGNER_INFO_get0_algs(p7si, &pkey, &pdig, &psig);
ASSERT_FALSE(pkey); // no attached pkey
ASSERT_TRUE(psig);
ASSERT_TRUE(pdig);
// Negative lengths not valid
EXPECT_FALSE(d2i_PKCS7(nullptr, &p7_der, -1));
bssl::UniquePtr<PKCS7> p7_dup(PKCS7_dup(p7.get()));
ASSERT_TRUE(p7_dup);
EXPECT_TRUE(PKCS7_type_is_signed(p7_dup.get()));
p7_der = kPKCS7SignedWithSignerInfo;
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(p7_der, p7_der_len));
p7.reset(d2i_PKCS7_bio(bio.get(), nullptr));
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_type_is_signed(p7.get()));
bio.reset(BIO_new(BIO_s_mem()));
ASSERT_TRUE(i2d_PKCS7_bio(bio.get(), p7.get()));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signed));
bio.reset(BIO_new_mem_buf(kPEMCert, strlen(kPEMCert)));
ASSERT_TRUE(bio);
bssl::UniquePtr<STACK_OF(X509)> certs(sk_X509_new_null());
ASSERT_TRUE(certs);
ASSERT_TRUE(PKCS7_get_PEM_certificates(certs.get(), bio.get()));
ASSERT_EQ(1U, sk_X509_num(certs.get()));
EXPECT_TRUE(PKCS7_add_certificate(p7.get(), sk_X509_value(certs.get(), 0U)));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signed));
bio.reset(BIO_new_mem_buf(kPEMCRL, strlen(kPEMCRL)));
ASSERT_TRUE(bio);
bssl::UniquePtr<STACK_OF(X509_CRL)> crls(sk_X509_CRL_new_null());
ASSERT_TRUE(crls);
ASSERT_TRUE(PKCS7_get_PEM_CRLs(crls.get(), bio.get()));
ASSERT_EQ(1U, sk_X509_CRL_num(crls.get()));
EXPECT_TRUE(PKCS7_add_crl(p7.get(), sk_X509_CRL_value(crls.get(), 0U)));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signedAndEnveloped));
bio.reset(BIO_new_mem_buf(kPEMCert, strlen(kPEMCert)));
ASSERT_TRUE(bio);
certs.reset(sk_X509_new_null());
ASSERT_TRUE(certs);
ASSERT_TRUE(PKCS7_get_PEM_certificates(certs.get(), bio.get()));
ASSERT_EQ(1U, sk_X509_num(certs.get()));
EXPECT_TRUE(PKCS7_add_certificate(p7.get(), sk_X509_value(certs.get(), 0U)));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signedAndEnveloped));
bio.reset(BIO_new_mem_buf(kPEMCRL, strlen(kPEMCRL)));
ASSERT_TRUE(bio);
crls.reset(sk_X509_CRL_new_null());
ASSERT_TRUE(crls);
ASSERT_TRUE(PKCS7_get_PEM_CRLs(crls.get(), bio.get()));
ASSERT_EQ(1U, sk_X509_CRL_num(crls.get()));
EXPECT_TRUE(PKCS7_add_crl(p7.get(), sk_X509_CRL_value(crls.get(), 0U)));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signed));
bssl::UniquePtr<RSA> rsa(RSA_new());
ASSERT_TRUE(rsa);
ASSERT_TRUE(RSA_generate_key_fips(rsa.get(), 2048, nullptr));
bssl::UniquePtr<EVP_PKEY> rsa_pkey(EVP_PKEY_new());
ASSERT_TRUE(rsa_pkey);
ASSERT_TRUE(EVP_PKEY_set1_RSA(rsa_pkey.get(), rsa.get()));
bssl::UniquePtr<X509> rsa_x509(sk_X509_pop(certs.get()));
ASSERT_EQ(0U, sk_X509_num(certs.get()));
ASSERT_TRUE(rsa_x509);
p7si = PKCS7_SIGNER_INFO_new();
ASSERT_TRUE(p7si);
EXPECT_TRUE(PKCS7_SIGNER_INFO_set(p7si, rsa_x509.get(), rsa_pkey.get(),
EVP_sha256()));
EXPECT_FALSE(PKCS7_SIGNER_INFO_set(p7si, nullptr, nullptr, nullptr));
EXPECT_TRUE(PKCS7_add_signer(p7.get(), p7si));
EXPECT_TRUE(PKCS7_get_signer_info(p7.get()));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7.get());
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signedAndEnveloped));
p7si = PKCS7_SIGNER_INFO_new();
ASSERT_TRUE(p7si);
bssl::UniquePtr<X509> ecdsa_x509(X509_new());
ASSERT_TRUE(ecdsa_x509);
bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr));
ASSERT_TRUE(ctx);
ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));
ASSERT_TRUE(
EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(), NID_X9_62_prime256v1));
bssl::UniquePtr<EVP_PKEY> ecdsa_pkey(EVP_PKEY_new());
EVP_PKEY *ecdsa_pkey_ptr = ecdsa_pkey.get();
ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &ecdsa_pkey_ptr));
EXPECT_TRUE(PKCS7_SIGNER_INFO_set(p7si, ecdsa_x509.get(), ecdsa_pkey.get(),
EVP_sha256()));
EXPECT_TRUE(PKCS7_add_signer(p7.get(), p7si));
EXPECT_TRUE(PKCS7_get_signer_info(p7.get()));
// Cover overlap between |p7| and signer info message digest algorithms
p7.reset(PKCS7_new());
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signed));
X509_ALGOR *md_alg1 = X509_ALGOR_new();
X509_ALGOR_set_md(md_alg1, EVP_sha384());
sk_X509_ALGOR_push(p7->d.sign->md_algs, md_alg1);
X509_ALGOR *md_alg2 = X509_ALGOR_new();
X509_ALGOR_set_md(md_alg2, EVP_sha256());
sk_X509_ALGOR_push(p7->d.sign->md_algs, md_alg2);
p7si = PKCS7_SIGNER_INFO_new();
ASSERT_TRUE(p7si);
EXPECT_TRUE(PKCS7_SIGNER_INFO_set(p7si, ecdsa_x509.get(), ecdsa_pkey.get(),
EVP_sha256()));
EXPECT_TRUE(PKCS7_add_signer(p7.get(), p7si));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7.get());
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signed));
p7si = PKCS7_SIGNER_INFO_new();
ASSERT_TRUE(p7si);
ecdsa_x509.reset(X509_new());
ASSERT_TRUE(ecdsa_x509);
ctx.reset(EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, nullptr));
ASSERT_TRUE(ctx);
ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));
ecdsa_pkey.reset(EVP_PKEY_new());
ecdsa_pkey_ptr = ecdsa_pkey.get();
ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &ecdsa_pkey_ptr));
EXPECT_FALSE(PKCS7_SIGNER_INFO_set(p7si, ecdsa_x509.get(), ecdsa_pkey.get(),
EVP_sha256()));
PKCS7_SIGNER_INFO_free(p7si);
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signedAndEnveloped));
ASSERT_TRUE(X509_set_pubkey(rsa_x509.get(), rsa_pkey.get()));
PKCS7_RECIP_INFO *p7ri = PKCS7_RECIP_INFO_new();
EXPECT_TRUE(PKCS7_RECIP_INFO_set(p7ri, rsa_x509.get()));
EXPECT_FALSE(PKCS7_RECIP_INFO_set(p7ri, nullptr));
X509_ALGOR *penc = NULL;
PKCS7_RECIP_INFO_get0_alg(p7ri, &penc);
ASSERT_TRUE(penc);
EXPECT_TRUE(PKCS7_add_recipient_info(p7.get(), p7ri));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_enveloped));
ASSERT_TRUE(X509_set_pubkey(rsa_x509.get(), rsa_pkey.get()));
p7ri = PKCS7_RECIP_INFO_new();
EXPECT_TRUE(PKCS7_RECIP_INFO_set(p7ri, rsa_x509.get()));
PKCS7_RECIP_INFO_get0_alg(p7ri, &penc);
ASSERT_TRUE(penc);
EXPECT_TRUE(PKCS7_add_recipient_info(p7.get(), p7ri));
}
TEST(PKCS7Test, DataInitFinal) {
bssl::UniquePtr<PKCS7> p7;
bssl::UniquePtr<BIO> bio, bio_in;
bssl::UniquePtr<STACK_OF(X509)> certs;
bssl::UniquePtr<X509> rsa_x509;
bssl::UniquePtr<uint8_t> p7_der;
size_t p7_der_len;
const uint8_t *p7_ptr;
p7_ptr = kPKCS7SignedWithSignerInfo;
p7_der_len = sizeof(kPKCS7SignedWithSignerInfo);
p7.reset(d2i_PKCS7(nullptr, &p7_ptr, p7_der_len));
ASSERT_TRUE(p7);
EXPECT_TRUE(PKCS7_type_is_signed(p7.get()));
bio.reset(PKCS7_dataInit(p7.get(), nullptr));
ASSERT_TRUE(bio);
EXPECT_TRUE(PKCS7_dataFinal(p7.get(), bio.get()));
// parse a cert for use with recipient infos
bssl::UniquePtr<RSA> rsa(RSA_new());
ASSERT_TRUE(rsa);
ASSERT_TRUE(RSA_generate_key_fips(rsa.get(), 2048, nullptr));
bssl::UniquePtr<EVP_PKEY> rsa_pkey(EVP_PKEY_new());
ASSERT_TRUE(rsa_pkey);
ASSERT_TRUE(EVP_PKEY_set1_RSA(rsa_pkey.get(), rsa.get()));
bio.reset(BIO_new_mem_buf(kPEMCert, strlen(kPEMCert)));
ASSERT_TRUE(bio);
certs.reset(sk_X509_new_null());
ASSERT_TRUE(certs);
ASSERT_TRUE(PKCS7_get_PEM_certificates(certs.get(), bio.get()));
ASSERT_EQ(1U, sk_X509_num(certs.get()));
rsa_x509.reset(sk_X509_pop(certs.get()));
ASSERT_TRUE(X509_set_pubkey(rsa_x509.get(), rsa_pkey.get()));
p7_ptr = kPKCS7EnvelopedData;
p7_der_len = sizeof(kPKCS7EnvelopedData);
p7.reset(d2i_PKCS7(nullptr, &p7_ptr, p7_der_len));
ASSERT_TRUE(p7);
EXPECT_TRUE(PKCS7_type_is_enveloped(p7.get()));
// need to initialize cipher for enveloped data
EXPECT_TRUE(PKCS7_set_cipher(p7.get(), EVP_aes_128_ctr()));
// attach a (non-serialized, unrelated) cert to |p7ri_sk|
STACK_OF(PKCS7_RECIP_INFO) *p7ri_sk = PKCS7_get_recipient_info(p7.get());
PKCS7_RECIP_INFO *p7ri = sk_PKCS7_RECIP_INFO_value(p7ri_sk, 0);
ASSERT_TRUE(p7ri);
EXPECT_TRUE(PKCS7_RECIP_INFO_set(p7ri, rsa_x509.get()));
bio.reset(PKCS7_dataInit(p7.get(), nullptr));
ASSERT_TRUE(bio);
EXPECT_TRUE(PKCS7_dataFinal(p7.get(), bio.get()));
bio.reset(nullptr);
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signedAndEnveloped));
ASSERT_TRUE(PKCS7_set_cipher(p7.get(), EVP_aes_128_ctr()));
bio.reset(PKCS7_dataInit(p7.get(), nullptr));
EXPECT_TRUE(bio);
EXPECT_TRUE(PKCS7_dataFinal(p7.get(), bio.get()));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_digest));
ASSERT_TRUE(PKCS7_set_digest(p7.get(), EVP_sha256()));
ASSERT_TRUE(PKCS7_content_new(p7.get(), NID_pkcs7_data));
bio.reset(PKCS7_dataInit(p7.get(), nullptr));
EXPECT_TRUE(bio);
EXPECT_TRUE(PKCS7_dataFinal(p7.get(), bio.get()));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_data));
bio.reset(PKCS7_dataInit(p7.get(), nullptr));
EXPECT_TRUE(bio);
EXPECT_TRUE(PKCS7_dataFinal(p7.get(), bio.get()));
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_enveloped));
ASSERT_TRUE(PKCS7_set_cipher(p7.get(), EVP_aes_128_ctr()));
bio.reset(PKCS7_dataInit(p7.get(), nullptr));
EXPECT_TRUE(bio);
EXPECT_TRUE(PKCS7_dataFinal(p7.get(), bio.get()));
// pre-existing BIO?
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_enveloped));
ASSERT_TRUE(PKCS7_set_cipher(p7.get(), EVP_aes_128_ctr()));
bio.reset(PKCS7_dataInit(p7.get(), nullptr));
EXPECT_TRUE(bio);
EXPECT_TRUE(PKCS7_dataFinal(p7.get(), bio.get()));
// Error cases
// type NID_pkcs7_encrypted is not supported by the BIO functions
p7.reset(PKCS7_new());
bio_in.reset(BIO_new(BIO_s_mem()));
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_encrypted));
bio.reset(PKCS7_dataInit(p7.get(), bio_in.get()));
EXPECT_FALSE(bio);
EXPECT_FALSE(PKCS7_dataFinal(p7.get(), bio.get()));
// NID_pkcs7_enveloped and NID_pkcs7_signedAndEnveloped require a cipher
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_enveloped));
bio.reset(PKCS7_dataInit(p7.get(), nullptr));
EXPECT_FALSE(bio);
EXPECT_FALSE(PKCS7_dataFinal(p7.get(), bio.get()));
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_enveloped));
bio.reset(PKCS7_dataInit(p7.get(), nullptr));
EXPECT_FALSE(bio);
EXPECT_FALSE(PKCS7_dataFinal(p7.get(), bio.get()));
}
TEST(PKCS7Test, TestEnveloped) {
bssl::UniquePtr<PKCS7> p7;
bssl::UniquePtr<BIO> bio;
bssl::UniquePtr<STACK_OF(X509)> certs;
bssl::UniquePtr<X509> rsa_x509;
const size_t pt_len = 64;
// NOTE: we make |buf| larger than |pt_len| in case padding gets added.
// without the extra room, we sometimes overflow into the next variable on the
// stack.
uint8_t buf[pt_len + EVP_MAX_BLOCK_LENGTH];
uint8_t decrypted[pt_len + EVP_MAX_BLOCK_LENGTH];
OPENSSL_cleanse(buf, sizeof(buf));
OPENSSL_memset(buf, 'A', pt_len);
// parse a cert for use with recipient infos
bssl::UniquePtr<RSA> rsa(RSA_new());
ASSERT_TRUE(rsa);
ASSERT_TRUE(RSA_generate_key_fips(rsa.get(), 2048, nullptr));
bssl::UniquePtr<EVP_PKEY> rsa_pkey(EVP_PKEY_new());
ASSERT_TRUE(rsa_pkey);
ASSERT_TRUE(EVP_PKEY_set1_RSA(rsa_pkey.get(), rsa.get()));
certs.reset(sk_X509_new_null());
bio.reset(BIO_new_mem_buf(kPEMCert, strlen(kPEMCert)));
ASSERT_TRUE(bio);
certs.reset(sk_X509_new_null());
ASSERT_TRUE(certs);
ASSERT_TRUE(PKCS7_get_PEM_certificates(certs.get(), bio.get()));
ASSERT_EQ(1U, sk_X509_num(certs.get()));
rsa_x509.reset(sk_X509_value(certs.get(), 0));
ASSERT_TRUE(X509_set_pubkey(rsa_x509.get(), rsa_pkey.get()));
X509_up_ref(rsa_x509.get());
// standard success case
bio.reset(BIO_new_mem_buf(buf, pt_len));
p7.reset(
PKCS7_encrypt(certs.get(), bio.get(), EVP_aes_128_cbc(), /*flags*/ 0));
EXPECT_TRUE(p7);
EXPECT_TRUE(PKCS7_type_is_enveloped(p7.get()));
bio.reset(BIO_new(BIO_s_mem()));
EXPECT_TRUE(PKCS7_decrypt(p7.get(), rsa_pkey.get(), rsa_x509.get(), bio.get(),
/*flags*/ 0));
EXPECT_EQ(pt_len, BIO_pending(bio.get()));
OPENSSL_cleanse(decrypted, sizeof(decrypted));
ASSERT_EQ(pt_len, (size_t)BIO_read(bio.get(), decrypted, sizeof(decrypted)));
EXPECT_EQ(Bytes(buf, pt_len), Bytes(decrypted, pt_len));
// no certs provided for decryption
bio.reset(BIO_new_mem_buf(buf, pt_len));
p7.reset(
PKCS7_encrypt(certs.get(), bio.get(), EVP_aes_128_cbc(), /*flags*/ 0));
EXPECT_TRUE(p7);
EXPECT_TRUE(PKCS7_type_is_enveloped(p7.get()));
bio.reset(BIO_new(BIO_s_mem()));
EXPECT_TRUE(PKCS7_decrypt(p7.get(), rsa_pkey.get(), /*certs*/ nullptr,
bio.get(),
/*flags*/ 0));
EXPECT_EQ(pt_len, BIO_pending(bio.get()));
OPENSSL_cleanse(decrypted, sizeof(decrypted));
ASSERT_EQ(pt_len, (size_t)BIO_read(bio.get(), decrypted, sizeof(decrypted)));
EXPECT_EQ(Bytes(buf, pt_len), Bytes(decrypted, pt_len));
// empty plaintext
bio.reset(BIO_new(BIO_s_mem()));
ASSERT_TRUE(BIO_set_mem_eof_return(bio.get(), 0));
p7.reset(
PKCS7_encrypt(certs.get(), bio.get(), EVP_aes_128_cbc(), /*flags*/ 0));
EXPECT_TRUE(p7);
EXPECT_TRUE(PKCS7_type_is_enveloped(p7.get()));
bio.reset(BIO_new(BIO_s_mem()));
ASSERT_TRUE(BIO_set_mem_eof_return(bio.get(), 0));
EXPECT_TRUE(PKCS7_decrypt(p7.get(), rsa_pkey.get(), rsa_x509.get(), bio.get(),
/*flags*/ 0));
EXPECT_EQ(0UL, BIO_pending(bio.get()));
EXPECT_EQ(0, BIO_read(bio.get(), decrypted, sizeof(decrypted)));
EXPECT_FALSE(BIO_should_retry(bio.get()));
// unsupported content type, with and without content
p7.reset(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signed));
EXPECT_FALSE(PKCS7_decrypt(p7.get(), rsa_pkey.get(), nullptr, bio.get(), 0));
ASSERT_TRUE(PKCS7_content_new(p7.get(), NID_pkcs7_data));
EXPECT_FALSE(PKCS7_decrypt(p7.get(), rsa_pkey.get(), nullptr, bio.get(), 0));
// test multiple recipients using the same recipient twice. elide |cert| to
// exercise iterative decryption attempt behavior with multiple (2) successful
// decryptions.
sk_X509_push(certs.get(), rsa_x509.get());
bio.reset(BIO_new_mem_buf(buf, pt_len));
p7.reset(
PKCS7_encrypt(certs.get(), bio.get(), EVP_aes_128_cbc(), /*flags*/ 0));
ASSERT_TRUE(p7);
bio.reset(BIO_new(BIO_s_mem()));
// set |rsa_pkey| back to original RSA key
ASSERT_TRUE(EVP_PKEY_set1_RSA(rsa_pkey.get(), rsa.get()));
EXPECT_TRUE(PKCS7_decrypt(p7.get(), rsa_pkey.get(), /*cert*/ nullptr,
bio.get(),
/*flags*/ 0));
ASSERT_TRUE(sk_X509_pop(certs.get()));
ASSERT_EQ(1LU, sk_X509_num(certs.get()));
// test "MMA" decrypt with mismatched cert pub key/pkey private key and block
// cipher used for content encryption
bio.reset(BIO_new_mem_buf(buf, pt_len));
p7.reset(
PKCS7_encrypt(certs.get(), bio.get(), EVP_aes_128_cbc(), /*flags*/ 0));
EXPECT_TRUE(p7);
EXPECT_TRUE(PKCS7_type_is_enveloped(p7.get()));
bio.reset(BIO_new(BIO_s_mem()));
// set new RSA key, cert pub key and PKEY private key now mismatch
rsa.reset(RSA_new());
ASSERT_TRUE(RSA_generate_key_fips(rsa.get(), 2048, nullptr));
ASSERT_TRUE(EVP_PKEY_set1_RSA(rsa_pkey.get(), rsa.get()));
// attempt decryption with the new, mismatched keypair. content key decryption
// should "succeed" and produce random, useless content decryption key.
// The content is "decrypted" with the useless key, so nonsense gets written
// to the output |bio|. The cipher ends up in an unhealthy state due to bad
// padding (what should be the final pad block is now just random bytes), so
// the overall |PKCS7_decrypt| operation fails.
int decrypt_ok =
PKCS7_decrypt(p7.get(), rsa_pkey.get(), /*certs*/ nullptr, bio.get(),
/*flags*/ 0);
EXPECT_LE(pt_len, BIO_pending(bio.get()));
OPENSSL_cleanse(decrypted, sizeof(decrypted));
// There's a fun edge case here for block ciphers using conventional PKCS#7
// padding. In this padding scheme, the last byte of the padded plaintext
// determines how many bytes of padding have been appended and must be
// stripped, A random MMA-defense-garbled padded plaintext with last byte of
// 0x01 will trick the EVP API into thinking that byte is a valid padding
// byte, so it (and only it) will be stripped. This leaves the other
// block_size-1 bytes of the padding block in place, resulting in a larger
// "decrypted plaintext" than anticipated. However, this doesn't only apply to
// one byte of padding. With probability 16^-2, it applies to pad 0x02 0x02
// and so on with increasingly small probabilities. So, we give slack up to
// 16^-4 which means this test will erroneously fail 0.001526% of the time in
// expectation. Ideally we'd find a way to access the padded plaintext and
// account for this deterministically by checking the random "padding" and
// adusting accordingly.
const size_t max_decrypt = pt_len + EVP_CIPHER_block_size(EVP_aes_128_cbc());
const size_t decrypted_len =
(size_t)BIO_read(bio.get(), decrypted, sizeof(decrypted));
ASSERT_LE(decrypted_len, sizeof(decrypted));
if (decrypted_len > pt_len) {
EXPECT_LT(max_decrypt - 4, decrypted_len);
EXPECT_TRUE(decrypt_ok);
EXPECT_FALSE(ERR_GET_REASON(ERR_peek_error()));
} else {
EXPECT_EQ(pt_len, decrypted_len);
EXPECT_FALSE(decrypt_ok);
EXPECT_EQ(CIPHER_R_BAD_DECRYPT, ERR_GET_REASON(ERR_peek_error()));
}
// Of course, plaintext shouldn't equal decrypted in any case here
EXPECT_NE(Bytes(buf, pt_len), Bytes(decrypted, sizeof(decrypted)));
// test "MMA" decrypt as above, but with stream cipher. stream cipher has no
// padding, so content encryption should "succeed" but return nonsense because
// the content decryption key is just randomly generated bytes.
bio.reset(BIO_new_mem_buf(buf, pt_len));
p7.reset(
PKCS7_encrypt(certs.get(), bio.get(), EVP_aes_128_ctr(), /*flags*/ 0));
EXPECT_TRUE(p7);
EXPECT_TRUE(PKCS7_type_is_enveloped(p7.get()));
bio.reset(BIO_new(BIO_s_mem()));
// content decryption "succeeds"...
EXPECT_TRUE(PKCS7_decrypt(p7.get(), rsa_pkey.get(), /*certs*/ nullptr,
bio.get(),
/*flags*/ 0));
EXPECT_EQ(pt_len, BIO_pending(bio.get()));
OPENSSL_cleanse(decrypted, sizeof(decrypted));
ASSERT_EQ(pt_len, (size_t)BIO_read(bio.get(), decrypted, sizeof(decrypted)));
// ...but it produces pseudo-random nonsense
EXPECT_NE(Bytes(buf, pt_len), Bytes(decrypted, sizeof(decrypted)));
EXPECT_FALSE(ERR_GET_REASON(ERR_peek_error()));
// mismatched cert + pkey on decrypt
bio.reset(BIO_new_mem_buf(buf, pt_len));
p7.reset(
PKCS7_encrypt(certs.get(), bio.get(), EVP_aes_128_cbc(), /*flags*/ 0));
bio.reset(BIO_new(BIO_s_mem()));
bssl::UniquePtr<RSA> rsa2(RSA_new());
ASSERT_TRUE(RSA_generate_key_fips(rsa2.get(), 2048, nullptr));
ASSERT_TRUE(EVP_PKEY_set1_RSA(rsa_pkey.get(), rsa2.get()));
EXPECT_FALSE(PKCS7_decrypt(p7.get(), rsa_pkey.get(), rsa_x509.get(),
bio.get(),
/*flags*/ 0));
EXPECT_EQ(X509_R_KEY_VALUES_MISMATCH, ERR_GET_REASON(ERR_peek_error()));
}
TEST(PKCS7Test, TestSigned) {
bssl::UniquePtr<PKCS7> p7;
bssl::UniquePtr<BIO> bio_in, bio_out;
bssl::UniquePtr<STACK_OF(X509)> certs;
bssl::UniquePtr<X509_STORE> store;
bssl::UniquePtr<X509_STORE_CTX> store_ctx;
bssl::UniquePtr<ASN1_TIME> not_before, not_after;
bssl::UniquePtr<RSA> root_rsa, leaf_rsa;
bssl::UniquePtr<EVP_PKEY> root_pkey, leaf_pkey;
uint8_t buf[64], out_buf[sizeof(buf)];
OPENSSL_memset(buf, 'A', sizeof(buf));
OPENSSL_memset(out_buf, '\0', sizeof(out_buf));
root_rsa.reset(RSA_new());
ASSERT_TRUE(RSA_generate_key_fips(root_rsa.get(), 2048, nullptr));
root_pkey.reset(EVP_PKEY_new());
ASSERT_TRUE(EVP_PKEY_set1_RSA(root_pkey.get(), root_rsa.get()));
leaf_rsa.reset(RSA_new());
ASSERT_TRUE(RSA_generate_key_fips(leaf_rsa.get(), 2048, nullptr));
leaf_pkey.reset(EVP_PKEY_new());
ASSERT_TRUE(EVP_PKEY_set1_RSA(leaf_pkey.get(), leaf_rsa.get()));
// |PKCS7_verify| creates its own X509_STORE_CTX internally, so we can't set
// relative validity time on the store it uses from here (by default
// X509_STORE_CTX uses std's |time|). So, we set a wide validity gap here.
// |not_after| won't need to be updated until December 9999 and |not_before|
// would only need to be reconsidered in the advent of a time machine.
not_before.reset(ASN1_TIME_set_posix(nullptr, 0L));
not_after.reset(ASN1_TIME_set_posix(nullptr, INT64_C(253402300799)));
bssl::UniquePtr<X509> root =
MakeTestCert("Root", "Root", root_pkey.get(), /*is_ca=*/true);
ASSERT_TRUE(root);
ASSERT_TRUE(X509_set_notBefore(root.get(), not_before.get()));
ASSERT_TRUE(X509_set_notAfter(root.get(), not_after.get()));
// Root signs itself
ASSERT_TRUE(X509_sign(root.get(), root_pkey.get(), EVP_sha256()));
bssl::UniquePtr<X509> leaf =
MakeTestCert("Root", "Leaf", leaf_pkey.get(), /*is_ca=*/false);
ASSERT_TRUE(leaf);
ASSERT_TRUE(X509_set_notBefore(leaf.get(), not_before.get()));
ASSERT_TRUE(X509_set_notAfter(leaf.get(), not_after.get()));
// Root signs leaf
ASSERT_TRUE(X509_sign(leaf.get(), root_pkey.get(), EVP_sha256()));
X509_up_ref(leaf.get());
X509_up_ref(leaf.get());
store.reset(X509_STORE_new());
ASSERT_TRUE(X509_STORE_add_cert(store.get(), root.get()));
certs.reset(sk_X509_new_null());
ASSERT_TRUE(sk_X509_push(certs.get(), leaf.get()));
bio_in.reset(BIO_new_mem_buf(buf, sizeof(buf)));
p7.reset(PKCS7_sign(leaf.get(), leaf_pkey.get(), nullptr, bio_in.get(),
/*flags*/ 0));
ASSERT_TRUE(p7);
EXPECT_TRUE(PKCS7_type_is_signed(p7.get()));
STACK_OF(X509) *signers = PKCS7_get0_signers(p7.get(), certs.get(), 0);
EXPECT_TRUE(signers);
sk_X509_free(signers);
EXPECT_FALSE(PKCS7_is_detached(p7.get()));
// attached, check |outdata|
bio_out.reset(BIO_new(BIO_s_mem()));
// passing non-null |indata| with attached content should fail
EXPECT_FALSE(PKCS7_verify(p7.get(), certs.get(), store.get(), bio_in.get(),
bio_out.get(), /*flags*/ 0));
// but otherwise, it should succeed
EXPECT_TRUE(PKCS7_verify(p7.get(), certs.get(), store.get(), nullptr,
bio_out.get(), /*flags*/ 0));
ASSERT_EQ((int)sizeof(out_buf),
BIO_read(bio_out.get(), out_buf, sizeof(out_buf)));
EXPECT_EQ(Bytes(buf, sizeof(buf)), Bytes(out_buf, sizeof(out_buf)));
// attached, but no |outdata|
bio_in.reset(BIO_new_mem_buf(buf, sizeof(buf)));
p7.reset(PKCS7_sign(leaf.get(), leaf_pkey.get(), nullptr, bio_in.get(),
/*flags*/ 0));
EXPECT_TRUE(PKCS7_verify(p7.get(), certs.get(), store.get(),
/*indata*/ nullptr,
/*outdata*/ nullptr, /*flags*/ 0));
// attached, but specify |PKCS7_NOINTERN| to ignore bundled certs. this should
// fail when we elide the |certs| parameter to verify and succeed when we
// provide it.
bio_in.reset(BIO_new_mem_buf(buf, sizeof(buf)));
p7.reset(PKCS7_sign(leaf.get(), leaf_pkey.get(), nullptr, bio_in.get(),
/*flags*/ 0));
EXPECT_FALSE(PKCS7_verify(p7.get(), /*certs*/ nullptr, store.get(),
/*indata*/ nullptr,
/*outdata*/ nullptr, /*flags*/ PKCS7_NOINTERN));
EXPECT_TRUE(PKCS7_verify(p7.get(), certs.get(), store.get(),
/*indata*/ nullptr,
/*outdata*/ nullptr, /*flags*/ PKCS7_NOINTERN));
// detached
bio_in.reset(BIO_new_mem_buf(buf, sizeof(buf)));
// PKCS7_NOCERTS isn't supported
ASSERT_FALSE(PKCS7_sign(leaf.get(), leaf_pkey.get(), nullptr, bio_in.get(),
(PKCS7_DETACHED | PKCS7_NOCERTS)));
// but this should work fine without it
p7.reset(PKCS7_sign(leaf.get(), leaf_pkey.get(), nullptr, bio_in.get(),
PKCS7_DETACHED));
EXPECT_TRUE(PKCS7_is_detached(p7.get()));
certs.reset(sk_X509_new_null());
ASSERT_TRUE(sk_X509_push(certs.get(), leaf.get()));
bio_in.reset(BIO_new_mem_buf(buf, sizeof(buf)));
bio_out.reset(BIO_new(BIO_s_mem()));
// detached mode requires data to be passed in via |indata
EXPECT_FALSE(PKCS7_verify(p7.get(), certs.get(), store.get(), nullptr,
bio_out.get(), /*flags*/ 0));
// but once we provide the |indata|, it should work
EXPECT_TRUE(PKCS7_verify(p7.get(), certs.get(), store.get(), bio_in.get(),
bio_out.get(), /*flags*/ 0));
OPENSSL_memset(out_buf, '\0', sizeof(out_buf));
ASSERT_EQ((int)sizeof(out_buf),
BIO_read(bio_out.get(), out_buf, sizeof(out_buf)));
EXPECT_EQ(Bytes(buf, sizeof(buf)), Bytes(out_buf, sizeof(out_buf)));
// Error cases
p7.reset(PKCS7_new());
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_enveloped));
BIO *bio_tmp = nullptr;
EXPECT_FALSE(SMIME_read_PKCS7(bio_in.get(), &bio_tmp));
ASSERT_FALSE(bio_tmp); // never gets allocated
EXPECT_FALSE(SMIME_write_PKCS7(bio_in.get(), p7.get(), bio_tmp, 0));
EXPECT_FALSE(PKCS7_verify(p7.get(), nullptr, store.get(), bio_in.get(),
bio_out.get(), 0)); // |p7| is wrong type
EXPECT_FALSE(PKCS7_get_signer_info(p7.get())); // |p7| is wrong type
// Misatched sign/verify keys
bssl::UniquePtr<RSA> other_rsa;
bssl::UniquePtr<EVP_PKEY> other_pkey;
other_rsa.reset(RSA_new());
ASSERT_TRUE(RSA_generate_key_fips(other_rsa.get(), 2048, nullptr));
other_pkey.reset(EVP_PKEY_new());
ASSERT_TRUE(EVP_PKEY_set1_RSA(other_pkey.get(), other_rsa.get()));
bio_in.reset(BIO_new_mem_buf(buf, sizeof(buf)));
p7.reset(PKCS7_sign(leaf.get(), other_pkey.get(), nullptr, bio_in.get(),
/*flags*/ 0));
EXPECT_FALSE(PKCS7_verify(p7.get(), nullptr, store.get(), nullptr,
bio_out.get(), /*flags*/ 0));
// Use different detached indata to induce signature mismatch
bio_in.reset(BIO_new_mem_buf(buf, sizeof(buf)));
p7.reset(PKCS7_sign(leaf.get(), leaf_pkey.get(), nullptr, bio_in.get(),
PKCS7_DETACHED));
uint8_t other_data[sizeof(buf)];
OPENSSL_memset(other_data, 'B', sizeof(other_data));
bio_in.reset(BIO_new_mem_buf(other_data, sizeof(other_data)));
bio_out.reset(BIO_new(BIO_s_mem()));
EXPECT_FALSE(PKCS7_verify(p7.get(), certs.get(), store.get(), bio_in.get(),
bio_out.get(), /*flags*/ 0));
}
// Regression test: PKCS7_verify with detached data and multiple digest
// algorithms must free all intermediate digest BIOs, not just the head.
TEST(PKCS7Test, VerifyDetachedMultiDigestNoLeak) {
// Generate two distinct ECDSA key-pairs and leaf certificates so that each
// signer can use a different digest algorithm.
bssl::UniquePtr<EC_KEY> root_ec(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
ASSERT_TRUE(root_ec);
ASSERT_TRUE(EC_KEY_generate_key(root_ec.get()));
bssl::UniquePtr<EVP_PKEY> root_pkey(EVP_PKEY_new());
ASSERT_TRUE(EVP_PKEY_set1_EC_KEY(root_pkey.get(), root_ec.get()));
bssl::UniquePtr<EC_KEY> leaf1_ec(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
ASSERT_TRUE(leaf1_ec);
ASSERT_TRUE(EC_KEY_generate_key(leaf1_ec.get()));
bssl::UniquePtr<EVP_PKEY> leaf1_pkey(EVP_PKEY_new());
ASSERT_TRUE(EVP_PKEY_set1_EC_KEY(leaf1_pkey.get(), leaf1_ec.get()));
bssl::UniquePtr<EC_KEY> leaf2_ec(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
ASSERT_TRUE(leaf2_ec);
ASSERT_TRUE(EC_KEY_generate_key(leaf2_ec.get()));
bssl::UniquePtr<EVP_PKEY> leaf2_pkey(EVP_PKEY_new());
ASSERT_TRUE(EVP_PKEY_set1_EC_KEY(leaf2_pkey.get(), leaf2_ec.get()));
bssl::UniquePtr<ASN1_TIME> not_before(ASN1_TIME_set_posix(nullptr, 0L));
bssl::UniquePtr<ASN1_TIME> not_after(
ASN1_TIME_set_posix(nullptr, INT64_C(253402300799)));
bssl::UniquePtr<X509> root =
MakeTestCert("Root", "Root", root_pkey.get(), /*is_ca=*/true);
ASSERT_TRUE(root);
ASSERT_TRUE(X509_set_notBefore(root.get(), not_before.get()));
ASSERT_TRUE(X509_set_notAfter(root.get(), not_after.get()));
ASSERT_TRUE(X509_sign(root.get(), root_pkey.get(), EVP_sha256()));
bssl::UniquePtr<X509> leaf1 =
MakeTestCert("Root", "Leaf1", leaf1_pkey.get(), /*is_ca=*/false);
ASSERT_TRUE(leaf1);
ASSERT_TRUE(X509_set_notBefore(leaf1.get(), not_before.get()));
ASSERT_TRUE(X509_set_notAfter(leaf1.get(), not_after.get()));
ASSERT_TRUE(X509_sign(leaf1.get(), root_pkey.get(), EVP_sha256()));
bssl::UniquePtr<X509> leaf2 =
MakeTestCert("Root", "Leaf2", leaf2_pkey.get(), /*is_ca=*/false);
ASSERT_TRUE(leaf2);
ASSERT_TRUE(X509_set_notBefore(leaf2.get(), not_before.get()));
ASSERT_TRUE(X509_set_notAfter(leaf2.get(), not_after.get()));
ASSERT_TRUE(X509_sign(leaf2.get(), root_pkey.get(), EVP_sha256()));
// Build a PKCS7 signed structure with two signers using *different* digest
// algorithms. This causes PKCS7_dataInit to create two digest BIOs.
bssl::UniquePtr<PKCS7> p7(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signed));
ASSERT_TRUE(PKCS7_content_new(p7.get(), NID_pkcs7_data));
// Signer 1: SHA-256
PKCS7_SIGNER_INFO *si1 = PKCS7_SIGNER_INFO_new();
ASSERT_TRUE(si1);
ASSERT_TRUE(
PKCS7_SIGNER_INFO_set(si1, leaf1.get(), leaf1_pkey.get(), EVP_sha256()));
ASSERT_TRUE(PKCS7_add_signer(p7.get(), si1));
ASSERT_TRUE(PKCS7_add_certificate(p7.get(), leaf1.get()));
// Signer 2: SHA-384 (different digest => second digest BIO in chain)
PKCS7_SIGNER_INFO *si2 = PKCS7_SIGNER_INFO_new();
ASSERT_TRUE(si2);
ASSERT_TRUE(
PKCS7_SIGNER_INFO_set(si2, leaf2.get(), leaf2_pkey.get(), EVP_sha384()));
ASSERT_TRUE(PKCS7_add_signer(p7.get(), si2));
ASSERT_TRUE(PKCS7_add_certificate(p7.get(), leaf2.get()));
// Make it a detached signature.
ASN1_OCTET_STRING_free(p7->d.sign->contents->d.data);
p7->d.sign->contents->d.data = NULL;
// The signatures don't need to be valid for this leak test -- the leak
// happens during teardown regardless of verification outcome. Just add dummy
// signer info entries so PKCS7_get_signer_info returns them and the code
// path that builds the BIO chain in PKCS7_dataInit is reached.
// Call PKCS7_verify with detached indata. The BIO chain teardown is where
// intermediate digest BIOs are leaked.
uint8_t buf[64];
OPENSSL_memset(buf, 'A', sizeof(buf));
bssl::UniquePtr<X509_STORE> store(X509_STORE_new());
ASSERT_TRUE(X509_STORE_add_cert(store.get(), root.get()));
bssl::UniquePtr<BIO> indata(BIO_new_mem_buf(buf, sizeof(buf)));
ASSERT_TRUE(indata);
bssl::UniquePtr<BIO> outdata(BIO_new(BIO_s_mem()));
ASSERT_TRUE(outdata);
// Verification will fail (signatures are not computed), but the BIO chain
// teardown still runs to exercise the leak.
PKCS7_verify(p7.get(), nullptr, store.get(), indata.get(), outdata.get(),
PKCS7_NOVERIFY);
}
TEST(PKCS7Test, PKCS7PrintNoop) {
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
bssl::UniquePtr<PKCS7> p7(PKCS7_new());
ASSERT_TRUE(PKCS7_print_ctx(bio.get(), p7.get(), 0, nullptr));
const uint8_t *contents;
size_t len;
ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
EXPECT_EQ(Bytes(contents, len), Bytes("PKCS7 printing is not supported"));
}
TEST(PKCS7Test, SetDetached) {
bssl::UniquePtr<PKCS7> p7(PKCS7_new());
// |PKCS7_set_detached| does not work on an uninitialized |PKCS7|.
EXPECT_FALSE(PKCS7_set_detached(p7.get(), 0));
EXPECT_FALSE(PKCS7_set_detached(p7.get(), 1));
EXPECT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signed));
EXPECT_TRUE(PKCS7_type_is_signed(p7.get()));
PKCS7 *p7_internal = PKCS7_new();
EXPECT_TRUE(PKCS7_set_type(p7_internal, NID_pkcs7_data));
EXPECT_TRUE(PKCS7_type_is_data(p7_internal));
EXPECT_TRUE(PKCS7_set_content(p7.get(), p7_internal));
// Access the |p7|'s internal contents to verify that |PKCS7_set_detached|
// has the right behavior.
EXPECT_TRUE(p7.get()->d.sign->contents->d.data);
EXPECT_TRUE(PKCS7_set_detached(p7.get(), 0));
EXPECT_TRUE(p7.get()->d.sign->contents->d.data);
EXPECT_FALSE(PKCS7_set_detached(p7.get(), 2));
EXPECT_TRUE(p7.get()->d.sign->contents->d.data);
// data is "detached" when |PKCS7_set_detached| is set with 1.
EXPECT_TRUE(PKCS7_set_detached(p7.get(), 1));
EXPECT_FALSE(p7.get()->d.sign->contents->d.data);
}
TEST(PKCS7Test, PKCS7SignedAttributes) {
// This file was generated with the following command:
// openssl smime -sign -in input.txt -signer crypto/ocsp/aws/ca_cert.pem
// -inkey crypto/ocsp/aws/ca_key.pem -out signed.p7s -outform PEM
// -nodetach -md sha512
//
// Files with signed attributes aren't generatable with AWS-LC for now, as
// |PKCS7_NOATTR| is always assumed with |PKCS7_sign|. See |PKCS7_sign|
// for more details.
static const char kPKCS7SignedAttributes[] = R"(
-----BEGIN PKCS7-----
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
-----END PKCS7-----
)";
// Timestamp for March 11, 2025.
static const int64_t kReferencePKCS7Time = 1741824000;
const bssl::UniquePtr<BIO> bio(
BIO_new_mem_buf(kPKCS7SignedAttributes, strlen(kPKCS7SignedAttributes)));
ASSERT_TRUE(bio);
bssl::UniquePtr<PKCS7> pkcs7(
PEM_read_bio_PKCS7(bio.get(), nullptr, nullptr, nullptr));
ASSERT_TRUE(pkcs7);
ASSERT_TRUE(PKCS7_type_is_signed(pkcs7.get()));
STACK_OF(X509) *signers = PKCS7_get0_signers(pkcs7.get(), nullptr, 0);
EXPECT_TRUE(signers);
sk_X509_free(signers);
// Set up trust store for verification.
bssl::UniquePtr<X509_STORE> store(X509_STORE_new());
bssl::UniquePtr<X509> ca_cert(CertFromPEM(
GetTestData(std::string("crypto/ocsp/test/aws/ca_cert.pem").c_str())
.c_str()));
ASSERT_TRUE(X509_STORE_add_cert(store.get(), ca_cert.get()));
// Set a valid time to avoid time bomb in tests.
X509_VERIFY_PARAM *param = X509_STORE_get0_param(store.get());
X509_VERIFY_PARAM_set_time_posix(param, kReferencePKCS7Time);
bssl::UniquePtr<BIO> out(BIO_new(BIO_s_mem()));
EXPECT_TRUE(PKCS7_verify(pkcs7.get(), nullptr, store.get(), nullptr,
out.get(), /*flags*/ 0));
// Run |PKCS7_verify| again to check that we're consuming a copy of the
// underlying |EVP_MD_CTX|.
EXPECT_TRUE(PKCS7_verify(pkcs7.get(), nullptr, store.get(), nullptr,
out.get(), /*flags*/ 0));
}
TEST(PKCS7Test, PKCS7SignedAttributesRuby) {
// The following test file was taken from ruby/openssl's pkcs7 tests.
static const char kPKCS7Ruby[] = R"(
-----BEGIN PKCS7-----
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
-----END PKCS7-----
)";
// The test has an expected output. Check that we output the same contents
// as OpenSSL.
static const char kPKCS7RubyOpenSSLOutput[] =
R"(-----BEGIN PKCS7-----
MIIDawYJKoZIhvcNAQcDoIIDXDCCA1gCAQAxggEQMIIBDAIBADB1MHAxEDAOBgNV
BAoMB2V4YW1wbGUxFzAVBgNVBAMMDlRBUk1BQyBST09UIENBMSIwIAYJKoZIhvcN
AQkBFhNzb21lb25lQGV4YW1wbGUub3JnMQswCQYDVQQGEwJVUzESMBAGA1UEBwwJ
VG93biBIYWxsAgFmMA0GCSqGSIb3DQEBAQUABIGAbKV17HvGYRtRRBNz1QLpW763
UedhVj5KXi70o4BJGM04lItAgt6aFC9SruZjpWr1gCYKCaRSAg273DeGTQwsDoZ8
6CPXzBpptYLz0MteQXYYWUaPZT+xmvx4NgDyk9P9MoT7JifsPrtXuzqCRFXhGdu8
d/ru+OWxhHLvKH+bYekwggI9BgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECBNs2U5m
Msd/gIICGFOnLq/EAc9Nv+HjKR3ZVPSJMq0TImjGf5Mvc3nDgI572Hdo2aku0YXM
6WjSWkpYtxpg7Cqxfl6hPSefLPUnBqlIoM2qbrE7MSKEVD6+2bW9GqYPFVg4qQLL
sOxnxJIMfOvLFfd7guL+iLH424XfiUUxaf8EdZE4u2IEl4REvkS1FoEGwyA4BEGM
SeVPedQCbZ0qY7Pc2tmZE3XfEUhIsyStG0Nb6i6AKcAFYGapbgE6kAB0gwsYcHlW
MOvsvdAfcTq6jwtHlO1s68qtvkWquTQ9lpX+fzddUUNxEHSqv5eU3oo6fT3Vj5ZF
IVlaA5ThZMrI5PgRPuwJM4GL8/VLwY5mbDLFqn/irGeEvP99J3S87ornLLunjpxS
y1/AymcVep2H32Tj82WS/IRQXBOzz4EnQRJGszKxAV6tY+Zje3sWyTTgObhlsiTQ
TDgnvtSW8RvVHqKrwgkxxEsRHg7u8UdzZ0jg+O5+3F8B6/NWMyts0OaFqT9wvI8y
O7VIy3dUtGdz7Hde6Ggp/iTn1LbgdJ3N8Hzxf1j6NMWUKHVsadvwpRJbUeqq9c3+
QuxsJi8wWemxxQCE+tPyc1dP+ej5/M7bERbSOHMGgX03758IvP7A/fy2DjGPv2+l
AwlEke0Uze1367QKgxM0nc3SZDlptY7zPIJC5saWXb8Rt2bw2JxEBOTavrp+ZwJ8
tcH961onq8Tme2ICaCzk
-----END PKCS7-----
)";
const bssl::UniquePtr<BIO> bio(
BIO_new_mem_buf(kPKCS7Ruby, strlen(kPKCS7Ruby)));
ASSERT_TRUE(bio);
bssl::UniquePtr<PKCS7> pkcs7(
PEM_read_bio_PKCS7(bio.get(), nullptr, nullptr, nullptr));
ASSERT_TRUE(pkcs7);
ASSERT_TRUE(PKCS7_type_is_signed(pkcs7.get()));
// Verify the file how Ruby's tests do it.
bssl::UniquePtr<X509_STORE> store(X509_STORE_new());
bssl::UniquePtr<BIO> out(BIO_new(BIO_s_mem()));
EXPECT_TRUE(PKCS7_verify(pkcs7.get(), nullptr, store.get(), nullptr,
out.get(), /*flags*/ PKCS7_NOVERIFY));
// The following is bit wonky with the pkcs7 bytes being read and rewritten,
// but that's how Ruby's underlying PKCS7 test gets the PEM output.
BUF_MEM *buf;
BIO_get_mem_ptr(out.get(), &buf);
bssl::UniquePtr<BIO> out2(BIO_new_mem_buf(buf->data, buf->length));
bssl::UniquePtr<PKCS7> new_pk7(d2i_PKCS7_bio(out2.get(), nullptr));
ASSERT_TRUE(new_pk7);
bssl::UniquePtr<BIO> out3(BIO_new(BIO_s_mem()));
ASSERT_TRUE(PEM_write_bio_PKCS7(out3.get(), new_pk7.get()));
BIO_get_mem_ptr(out3.get(), &buf);
EXPECT_EQ(Bytes(buf->data, buf->length), Bytes(kPKCS7RubyOpenSSLOutput));
}
static const unsigned char test_data[] = {0x30, 0x02, 0x01, 0x02};
static bssl::UniquePtr<PKCS7> pkcs7_with_other(const unsigned char *data,
int data_len) {
bssl::UniquePtr<PKCS7> p7(PKCS7_new());
if (!p7) {
return nullptr;
}
bssl::UniquePtr<ASN1_STRING> seq(ASN1_STRING_new());
if (!seq || !ASN1_STRING_set(seq.get(), data, data_len)) {
return nullptr;
}
// Set up the ASN.1 structure
p7->d.other = ASN1_TYPE_new();
if (!p7->d.other) {
return nullptr;
}
ASN1_TYPE_set(p7->d.other, V_ASN1_OCTET_STRING, seq.release());
return p7;
}
TEST(PKCS7Test, OtherFieldMemoryLeak) {
// Set up the ASN.1 structure
// |p7->type| is intentionally undefined. OpenSSL frees all contents whether
// it's defined or not.
bssl::UniquePtr<PKCS7> p7(pkcs7_with_other(test_data, sizeof(test_data)));
ASSERT_EQ(p7->d.other->type, V_ASN1_OCTET_STRING);
EXPECT_EQ(p7->d.other->value.sequence->length,
static_cast<int>(sizeof(test_data)));
EXPECT_EQ(OPENSSL_memcmp(p7->d.other->value.sequence->data, test_data,
sizeof(test_data)),
0);
}
TEST(PKCS7Test, SerdeOtherField) {
// Create PKCS7 and required ASN.1 structures. |p7->type | needs to be defined
// to be properly serialized.
bssl::UniquePtr<PKCS7> p7(pkcs7_with_other(test_data, sizeof(test_data)));
p7->type = OBJ_nid2obj(NID_pkcs7);
// Serialize the original object. This should echo back the original saved
// bytes.
uint8_t *bytes = nullptr;
int bytes_len = i2d_PKCS7(p7.get(), &bytes);
ASSERT_GT(bytes_len, 0);
bssl::UniquePtr<uint8_t> free_bytes(bytes);
const uint8_t *ptr = bytes;
bssl::UniquePtr<PKCS7> pkcs7_obj(d2i_PKCS7(nullptr, &ptr, bytes_len));
ASSERT_TRUE(pkcs7_obj);
ASSERT_EQ(p7->d.other->type, V_ASN1_OCTET_STRING);
EXPECT_EQ(p7->d.other->value.sequence->length,
static_cast<int>(sizeof(test_data)));
EXPECT_EQ(OPENSSL_memcmp(p7->d.other->value.sequence->data, test_data,
sizeof(test_data)),
0);
}
// Test for signature bypass when authenticated attributes contain a
// malformed attribute that causes ASN.1 re-encoding to fail.
TEST(PKCS7Test, SignatureBypassWithMalformedAuthAttr) {
const unsigned char original_data[] = "Original legitimate content";
const size_t original_len = sizeof(original_data) - 1;
const unsigned char malicious_data[] = "MALICIOUS MODIFIED CONTENT!";
const size_t malicious_len = sizeof(malicious_data) - 1;
// Generate RSA key pair
bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
ASSERT_TRUE(pkey);
bssl::UniquePtr<EVP_PKEY_CTX> pkey_ctx(
EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr));
ASSERT_TRUE(pkey_ctx);
ASSERT_TRUE(EVP_PKEY_keygen_init(pkey_ctx.get()));
ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_keygen_bits(pkey_ctx.get(), 2048));
EVP_PKEY *pkey_raw = nullptr;
ASSERT_TRUE(EVP_PKEY_keygen(pkey_ctx.get(), &pkey_raw));
pkey.reset(pkey_raw);
// Create self-signed certificate
bssl::UniquePtr<X509> cert(X509_new());
ASSERT_TRUE(cert);
ASSERT_TRUE(X509_set_version(cert.get(), 2));
ASSERT_TRUE(ASN1_INTEGER_set(X509_get_serialNumber(cert.get()), 1));
X509_gmtime_adj(X509_get_notBefore(cert.get()), 0);
X509_gmtime_adj(X509_get_notAfter(cert.get()), 31536000L);
ASSERT_TRUE(X509_set_pubkey(cert.get(), pkey.get()));
X509_NAME *name = X509_get_subject_name(cert.get());
ASSERT_TRUE(X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
(const unsigned char *)"Test",
-1, -1, 0));
ASSERT_TRUE(X509_set_issuer_name(cert.get(), name));
ASSERT_TRUE(X509_sign(cert.get(), pkey.get(), EVP_sha256()));
// Set up trust store
bssl::UniquePtr<X509_STORE> store(X509_STORE_new());
ASSERT_TRUE(store);
ASSERT_TRUE(X509_STORE_add_cert(store.get(), cert.get()));
// Compute SHA-256 digest of original data
unsigned char md[SHA256_DIGEST_LENGTH];
SHA256(original_data, original_len, md);
// Create the PKCS7 SignedData structure
bssl::UniquePtr<PKCS7> p7(PKCS7_new());
ASSERT_TRUE(p7);
ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_signed));
ASSERT_TRUE(PKCS7_content_new(p7.get(), NID_pkcs7_data));
// Set the content payload
ASSERT_TRUE(ASN1_OCTET_STRING_set(p7->d.sign->contents->d.data,
original_data, (int)original_len));
// Add SHA-256 to the digest algorithms set
X509_ALGOR *alg = X509_ALGOR_new();
ASSERT_TRUE(alg);
ASSERT_TRUE(
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_sha256), V_ASN1_NULL, nullptr));
ASSERT_TRUE(sk_X509_ALGOR_push(p7->d.sign->md_algs, alg));
// Create and configure SIGNER_INFO
PKCS7_SIGNER_INFO *sinfo = PKCS7_SIGNER_INFO_new();
ASSERT_TRUE(sinfo);
ASSERT_TRUE(
PKCS7_SIGNER_INFO_set(sinfo, cert.get(), pkey.get(), EVP_sha256()));
// Build authenticated attributes: contentType + messageDigest
sinfo->auth_attr = sk_X509_ATTRIBUTE_new_null();
ASSERT_TRUE(sinfo->auth_attr);
// Add contentType attribute (pkcs7-data)
ASN1_OBJECT *content_type_obj = OBJ_dup(OBJ_nid2obj(NID_pkcs7_data));
ASSERT_TRUE(content_type_obj);
X509_ATTRIBUTE *ct_attr = X509_ATTRIBUTE_create(
NID_pkcs9_contentType, V_ASN1_OBJECT, content_type_obj);
ASSERT_TRUE(ct_attr);
ASSERT_TRUE(sk_X509_ATTRIBUTE_push(sinfo->auth_attr, ct_attr));
// Add messageDigest attribute
ASN1_OCTET_STRING *digest_os = ASN1_OCTET_STRING_new();
ASSERT_TRUE(digest_os);
ASSERT_TRUE(ASN1_OCTET_STRING_set(digest_os, md, SHA256_DIGEST_LENGTH));
X509_ATTRIBUTE *md_attr = X509_ATTRIBUTE_create(
NID_pkcs9_messageDigest, V_ASN1_OCTET_STRING, digest_os);
ASSERT_TRUE(md_attr);
ASSERT_TRUE(sk_X509_ATTRIBUTE_push(sinfo->auth_attr, md_attr));
// DER-encode the authenticated attributes for signing
unsigned char *attr_der = nullptr;
int attr_der_len = ASN1_item_i2d((ASN1_VALUE *)sinfo->auth_attr, &attr_der,
ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY));
ASSERT_GT(attr_der_len, 0);
ASSERT_TRUE(attr_der);
// Sign the DER-encoded authenticated attributes
bssl::UniquePtr<EVP_MD_CTX> md_ctx(EVP_MD_CTX_new());
ASSERT_TRUE(md_ctx);
ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, EVP_sha256(), nullptr,
pkey.get()));
ASSERT_TRUE(EVP_DigestSignUpdate(md_ctx.get(), attr_der, attr_der_len));
size_t sig_len = 0;
ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), nullptr, &sig_len));
unsigned char *sig =
(unsigned char *)OPENSSL_malloc(sig_len);
ASSERT_TRUE(sig);
ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), sig, &sig_len));
// Set the signature on the signer info
ASSERT_TRUE(
ASN1_OCTET_STRING_set(sinfo->enc_digest, sig, (int)sig_len));
OPENSSL_free(sig);
OPENSSL_free(attr_der);
// Attach signer info and certificate to the PKCS7
ASSERT_TRUE(sk_PKCS7_SIGNER_INFO_push(p7->d.sign->signer_info, sinfo));
ASSERT_TRUE(PKCS7_add_certificate(p7.get(), cert.get()));
// Verify the original (unmodified) message succeeds
bssl::UniquePtr<BIO> out_bio(BIO_new(BIO_s_mem()));
ASSERT_TRUE(out_bio);
EXPECT_TRUE(PKCS7_verify(p7.get(), nullptr, store.get(), nullptr,
out_bio.get(), /*flags*/ 0));
// Now tamper with the message to attempt bypass
// Get the signer info back for modification
STACK_OF(PKCS7_SIGNER_INFO) *sinfos = PKCS7_get_signer_info(p7.get());
ASSERT_TRUE(sinfos);
ASSERT_GT(sk_PKCS7_SIGNER_INFO_num(sinfos), (size_t)0);
PKCS7_SIGNER_INFO *sinfo_ptr = sk_PKCS7_SIGNER_INFO_value(sinfos, 0);
ASSERT_TRUE(sinfo_ptr);
// Modify the content to malicious data
ASSERT_TRUE(PKCS7_type_is_signed(p7.get()));
ASSERT_TRUE(p7->d.sign && p7->d.sign->contents);
ASSERT_EQ(OBJ_obj2nid(p7->d.sign->contents->type), NID_pkcs7_data);
ASSERT_TRUE(ASN1_OCTET_STRING_set(p7->d.sign->contents->d.data,
malicious_data, (int)malicious_len));
// Update the messageDigest attribute to match the malicious content
unsigned char new_md[SHA256_DIGEST_LENGTH];
SHA256(malicious_data, malicious_len, new_md);
ASN1_TYPE *md_type =
PKCS7_get_signed_attribute(sinfo_ptr, NID_pkcs9_messageDigest);
ASSERT_TRUE(md_type);
ASSERT_EQ(md_type->type, V_ASN1_OCTET_STRING);
ASSERT_TRUE(ASN1_OCTET_STRING_set(md_type->value.octet_string, new_md,
SHA256_DIGEST_LENGTH));
// Add a malformed attribute whose ASN1_OBJECT has zero length.
// This causes ASN1_item_i2d() to fail with ASN1_R_ILLEGAL_OBJECT when
// pkcs7_signature_verify() tries to re-encode auth_attr for signature
// verification.
ASN1_OCTET_STRING *bad_os = ASN1_OCTET_STRING_new();
ASSERT_TRUE(bad_os);
ASSERT_TRUE(
ASN1_OCTET_STRING_set(bad_os, (const unsigned char *)"test", 4));
X509_ATTRIBUTE *bad_attr = X509_ATTRIBUTE_create(
NID_id_smime_aa_signingCertificate, V_ASN1_OCTET_STRING, bad_os);
ASSERT_TRUE(bad_attr);
// Create an ASN1_OBJECT with zero-length OID data. When ASN1_item_i2d
// tries to encode this, i2d_ASN1_OBJECT returns -1 because length <= 0,
// which makes the overall encoding fail safely.
bssl::UniquePtr<ASN1_OBJECT> empty_obj(
ASN1_OBJECT_create(NID_undef, nullptr, 0, nullptr, nullptr));
ASSERT_TRUE(empty_obj);
ASSERT_TRUE(X509_ATTRIBUTE_set1_object(bad_attr, empty_obj.get()));
ASSERT_TRUE(sk_X509_ATTRIBUTE_push(sinfo_ptr->auth_attr, bad_attr));
// Verify that the tampered message is correctly rejected
out_bio.reset(BIO_new(BIO_s_mem()));
ASSERT_TRUE(out_bio);
EXPECT_FALSE(PKCS7_verify(p7.get(), nullptr, store.get(), nullptr,
out_bio.get(), /*flags*/ 0));
}