1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
|
/* -*- indent-tabs-mode: nil -*- */
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <memory>
#include <string>
#include "log/cert.h"
#include "log/cms_verifier.h"
#include "log/ct_extensions.h"
#include "util/status_test_util.h"
#include "util/testing.h"
#include "util/util.h"
using cert_trans::Cert;
using cert_trans::CmsVerifier;
using cert_trans::ScopedBIO;
using std::string;
using std::unique_ptr;
using std::vector;
using util::testing::StatusIs;
// Self-signed
static const char kCaCert[] = "ca-cert.pem";
// Issued by ca-cert.pem
static const char kLeafCert[] = "test-cert.pem";
// Issued by ca-cert.pem
static const char kIntermediateCert[] = "intermediate-cert.pem";
// A DER file containing a CMS signed message wrapping data that is not
// valid DER
static const char kCmsSignedDataTest2[] = "cms_test2.der";
// A DER file containing a CMS signed message wrapping a DER encoded
// certificate for test case 3 (valid signature, same signer as cert)
static const char kCmsSignedDataTest3[] = "cms_test3.der";
// A DER file with a CMS signed message but not signed by the same
// key as the certificate it contains in the payload
static const char kCmsSignedDataTest4[] = "cms_test4.der";
// A DER file with a CMS signed message with intermediate as signer and
// issuer of the embedded cert
static const char kCmsSignedDataTest5[] = "cms_test5.der";
// Subject name we expect in our embedded certificate CMS tests
static const char kCmsTestSubject[] =
"CN=?.example.com, C=GB, ST=Wales, "
"L=Erw Wen, O=Certificate Transparency";
namespace {
unique_ptr<Cert> ReadCertFromFile(const string& filename) {
string content;
CHECK(util::ReadTextFile(filename, &content))
<< "Could not read test data from " << filename
<< ". Wrong --test_srcdir?";
unique_ptr<Cert> cert(Cert::FromPemString(content));
CHECK(cert.get());
return cert;
}
class CmsVerifierTest : public ::testing::Test {
protected:
CmsVerifierTest()
: cert_dir_(FLAGS_test_srcdir + "/test/testdata"),
cert_dir_v2_(FLAGS_test_srcdir + "/test/testdata/v2/"),
ca_cert_(ReadCertFromFile(cert_dir_ + "/" + kCaCert)),
intermediate_cert_(
ReadCertFromFile(cert_dir_ + "/" + kIntermediateCert)),
leaf_cert_(ReadCertFromFile(cert_dir_ + "/" + kLeafCert)) {
}
const string cert_dir_;
const string cert_dir_v2_;
const unique_ptr<Cert> ca_cert_;
const unique_ptr<Cert> intermediate_cert_;
const unique_ptr<Cert> leaf_cert_;
CmsVerifier verifier_;
};
BIO* OpenTestFileBio(const string& filename) {
BIO* der_bio = BIO_new_file(filename.c_str(), "r");
CHECK_NOTNULL(der_bio);
return der_bio;
}
TEST_F(CmsVerifierTest, CmsSignTestCase2) {
// In this test the embedded data is not a certificate in DER format
// but it doesn't get unpacked and the signature is valid.
ScopedBIO bio(OpenTestFileBio(cert_dir_v2_ + kCmsSignedDataTest2));
ASSERT_NE(bio.get(), nullptr);
EXPECT_TRUE(verifier_.IsCmsSignedByCert(bio.get(), *ca_cert_).ValueOrDie());
}
TEST_F(CmsVerifierTest, CmsSignTestCase3) {
// The CMS should be signed by the CA that signed the cert
ScopedBIO bio(OpenTestFileBio(cert_dir_v2_ + kCmsSignedDataTest3));
ASSERT_NE(bio.get(), nullptr);
EXPECT_TRUE(verifier_.IsCmsSignedByCert(bio.get(), *ca_cert_).ValueOrDie());
}
TEST_F(CmsVerifierTest, CmsSignTestCase4) {
// The CMS is not signed by the CA that signed the cert it contains
ScopedBIO bio(OpenTestFileBio(cert_dir_v2_ + kCmsSignedDataTest4));
ASSERT_NE(bio.get(), nullptr);
EXPECT_FALSE(verifier_.IsCmsSignedByCert(bio.get(), *ca_cert_).ValueOrDie());
}
TEST_F(CmsVerifierTest, CmsVerifyTestCase2) {
ScopedBIO bio(OpenTestFileBio(cert_dir_v2_ + kCmsSignedDataTest2));
unique_ptr<Cert> unpacked_cert(
verifier_.UnpackCmsSignedCertificate(bio.get(), *ca_cert_));
ASSERT_FALSE(unpacked_cert.get());
}
TEST_F(CmsVerifierTest, CmsVerifyTestCase3) {
// For this test the embedded cert is signed by the CA
ScopedBIO bio(OpenTestFileBio(cert_dir_v2_ + kCmsSignedDataTest3));
unique_ptr<Cert> unpacked_cert(
verifier_.UnpackCmsSignedCertificate(bio.get(), *ca_cert_));
ASSERT_FALSE(unpacked_cert->HasBasicConstraintCATrue().ValueOrDie());
ASSERT_TRUE(
unpacked_cert->HasExtension(NID_authority_key_identifier).ValueOrDie());
// We built the embedded cert with redaction so this helps to prove
// that it was correctly unpacked
ASSERT_OK(unpacked_cert->IsValidWildcardRedaction());
ASSERT_EQ(kCmsTestSubject, unpacked_cert->PrintSubjectName());
}
TEST_F(CmsVerifierTest, CmsVerifyTestCase4) {
// For this test the embedded cert is signed by the intermediate CA
ScopedBIO bio(OpenTestFileBio(cert_dir_v2_ + kCmsSignedDataTest4));
unique_ptr<Cert> unpacked_cert(
verifier_.UnpackCmsSignedCertificate(bio.get(), *ca_cert_));
ASSERT_FALSE(unpacked_cert.get());
}
TEST_F(CmsVerifierTest, CmsVerifyTestCase5) {
// For this test the embedded cert is signed by the intermediate
ScopedBIO bio(OpenTestFileBio(cert_dir_v2_ + kCmsSignedDataTest5));
unique_ptr<Cert> unpacked_cert(
verifier_.UnpackCmsSignedCertificate(bio.get(), *intermediate_cert_));
ASSERT_TRUE(unpacked_cert.get());
ASSERT_FALSE(unpacked_cert->HasBasicConstraintCATrue().ValueOrDie());
ASSERT_TRUE(
unpacked_cert->HasExtension(NID_authority_key_identifier).ValueOrDie());
// We built the embedded cert with redaction so this helps to prove
// that it was correctly unpacked
ASSERT_OK(unpacked_cert->IsValidWildcardRedaction());
ASSERT_EQ(kCmsTestSubject, unpacked_cert->PrintSubjectName());
}
TEST_F(CmsVerifierTest, CmsVerifyTestCase7) {
// For this test the embedded cert is signed by the intermediate
ScopedBIO bio(OpenTestFileBio(cert_dir_v2_ + kCmsSignedDataTest5));
unique_ptr<Cert> unpacked_cert(
verifier_.UnpackCmsSignedCertificate(bio.get(), *leaf_cert_));
ASSERT_FALSE(unpacked_cert.get());
}
TEST_F(CmsVerifierTest, CmsVerifyTestCase8) {
// For this test the embedded cert is signed by the intermediate
ScopedBIO bio(OpenTestFileBio(cert_dir_v2_ + kCmsSignedDataTest5));
unique_ptr<Cert> unpacked_cert(
verifier_.UnpackCmsSignedCertificate(bio.get(), *ca_cert_));
ASSERT_FALSE(unpacked_cert.get());
}
} // namespace
int main(int argc, char** argv) {
cert_trans::test::InitTesting(argv[0], &argc, &argv, true);
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
cert_trans::LoadCtExtensions();
return RUN_ALL_TESTS();
}
|