// Copyright (c) 2014, Google Inc. // SPDX-License-Identifier: ISC #include #include #include #include #include #include #include #include #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 certs(sk_X509_new_null()); ASSERT_TRUE(certs); bssl::UniquePtr 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 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 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 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_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_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 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 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 crls(sk_X509_CRL_new_null()); ASSERT_TRUE(crls); bssl::UniquePtr 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 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 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_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_new_mem_buf(pem, strlen(pem))); ASSERT_TRUE(bio); bssl::UniquePtr 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_new_mem_buf(pem, strlen(pem))); ASSERT_TRUE(bio); bssl::UniquePtr 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 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 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 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 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 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 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_new_mem_buf(kCRL1, strlen(kCRL1))); ASSERT_TRUE(bio); bssl::UniquePtr 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 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 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 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 cert_bio( BIO_new_mem_buf(const_cast(kCert), sizeof(kCert) - 1)); bssl::UniquePtr cert( PEM_read_bio_X509(cert_bio.get(), nullptr, nullptr, nullptr)); bssl::UniquePtr key_bio( BIO_new_mem_buf(const_cast(kKey), sizeof(kKey) - 1)); bssl::UniquePtr key( PEM_read_bio_PrivateKey(key_bio.get(), nullptr, nullptr, nullptr)); static const char kSignedData[] = "signed data"; bssl::UniquePtr data_bio(BIO_new_mem_buf(const_cast(kSignedData), sizeof(kSignedData) - 1)); bssl::UniquePtr 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 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 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 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_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 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 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_new()); ASSERT_TRUE(rsa); ASSERT_TRUE(RSA_generate_key_fips(rsa.get(), 2048, nullptr)); bssl::UniquePtr rsa_pkey(EVP_PKEY_new()); ASSERT_TRUE(rsa_pkey); ASSERT_TRUE(EVP_PKEY_set1_RSA(rsa_pkey.get(), rsa.get())); bssl::UniquePtr 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 ecdsa_x509(X509_new()); ASSERT_TRUE(ecdsa_x509); bssl::UniquePtr 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 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 p7; bssl::UniquePtr bio, bio_in; bssl::UniquePtr certs; bssl::UniquePtr rsa_x509; bssl::UniquePtr 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_new()); ASSERT_TRUE(rsa); ASSERT_TRUE(RSA_generate_key_fips(rsa.get(), 2048, nullptr)); bssl::UniquePtr 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 p7; bssl::UniquePtr bio; bssl::UniquePtr certs; bssl::UniquePtr 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_new()); ASSERT_TRUE(rsa); ASSERT_TRUE(RSA_generate_key_fips(rsa.get(), 2048, nullptr)); bssl::UniquePtr 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 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 p7; bssl::UniquePtr bio_in, bio_out; bssl::UniquePtr certs; bssl::UniquePtr store; bssl::UniquePtr store_ctx; bssl::UniquePtr not_before, not_after; bssl::UniquePtr root_rsa, leaf_rsa; bssl::UniquePtr 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 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 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 other_rsa; bssl::UniquePtr 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 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 root_pkey(EVP_PKEY_new()); ASSERT_TRUE(EVP_PKEY_set1_EC_KEY(root_pkey.get(), root_ec.get())); bssl::UniquePtr 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 leaf1_pkey(EVP_PKEY_new()); ASSERT_TRUE(EVP_PKEY_set1_EC_KEY(leaf1_pkey.get(), leaf1_ec.get())); bssl::UniquePtr 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 leaf2_pkey(EVP_PKEY_new()); ASSERT_TRUE(EVP_PKEY_set1_EC_KEY(leaf2_pkey.get(), leaf2_ec.get())); bssl::UniquePtr not_before(ASN1_TIME_set_posix(nullptr, 0L)); bssl::UniquePtr not_after( ASN1_TIME_set_posix(nullptr, INT64_C(253402300799))); bssl::UniquePtr 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 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 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 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 store(X509_STORE_new()); ASSERT_TRUE(X509_STORE_add_cert(store.get(), root.get())); bssl::UniquePtr indata(BIO_new_mem_buf(buf, sizeof(buf))); ASSERT_TRUE(indata); bssl::UniquePtr 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_new(BIO_s_mem())); bssl::UniquePtr 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 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_new_mem_buf(kPKCS7SignedAttributes, strlen(kPKCS7SignedAttributes))); ASSERT_TRUE(bio); bssl::UniquePtr 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 store(X509_STORE_new()); bssl::UniquePtr 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 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_new_mem_buf(kPKCS7Ruby, strlen(kPKCS7Ruby))); ASSERT_TRUE(bio); bssl::UniquePtr 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 store(X509_STORE_new()); bssl::UniquePtr 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 out2(BIO_new_mem_buf(buf->data, buf->length)); bssl::UniquePtr new_pk7(d2i_PKCS7_bio(out2.get(), nullptr)); ASSERT_TRUE(new_pk7); bssl::UniquePtr 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_with_other(const unsigned char *data, int data_len) { bssl::UniquePtr p7(PKCS7_new()); if (!p7) { return nullptr; } bssl::UniquePtr 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 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(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 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 free_bytes(bytes); const uint8_t *ptr = bytes; bssl::UniquePtr 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(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 pkey(EVP_PKEY_new()); ASSERT_TRUE(pkey); bssl::UniquePtr 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 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 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 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 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 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 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)); }