Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(154)

Unified Diff: net/cert/internal/verify_certificate_chain_unittest.cc

Issue 1414923007: Add initial code for verifying a certificate chain. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@test_driver
Patch Set: Start tackling Matt's comments Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/cert/internal/verify_certificate_chain_unittest.cc
diff --git a/net/cert/internal/verify_certificate_chain_unittest.cc b/net/cert/internal/verify_certificate_chain_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b4512fd4fca62bc6a59f8679793816a56adebcac
--- /dev/null
+++ b/net/cert/internal/verify_certificate_chain_unittest.cc
@@ -0,0 +1,203 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cert/internal/verify_certificate_chain.h"
+
+#include "base/base_paths.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "net/cert/internal/parse_certificate.h"
+#include "net/cert/internal/signature_policy.h"
+#include "net/cert/internal/test_helpers.h"
+#include "net/cert/pem_tokenizer.h"
+#include "net/der/input.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+// Reads a data file from the unit-test data.
+std::string ReadTestFileToString(const std::string& file_name) {
+ // Compute the full path, relative to the src/ directory.
+ base::FilePath src_root;
+ PathService::Get(base::DIR_SOURCE_ROOT, &src_root);
+ base::FilePath filepath = src_root.AppendASCII(
+ std::string("net/data/verify_certificate_chain_unittest/") + file_name);
+
+ // Read the full contents of the file.
+ std::string file_data;
+ if (!base::ReadFileToString(filepath, &file_data)) {
+ ADD_FAILURE() << "Couldn't read file: " << filepath.value();
+ return std::string();
+ }
+
+ return file_data;
+}
+
+// Adds the certificate |cert_der| as a trusted root in |trust_store|.
+void AddCertificateToTrustStore(const std::string& cert_der,
+ TrustStore* trust_store) {
+ ParsedCertificate cert;
+ ASSERT_TRUE(ParseCertificate(InputFromString(&cert_der), &cert));
+
+ ParsedTbsCertificate tbs;
+ ASSERT_TRUE(ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs));
+ TrustedRoot root = {tbs.spki_tlv.AsString(), tbs.subject_tlv.AsString()};
+ trust_store->roots.push_back(root);
+}
+
+// Reads a test case from |file_name|. Test cases are comprised of a
+// certificate chain, trust store, and timestamp to validate at.
+void ReadTestFromFile(const std::string& file_name,
+ std::vector<std::string>* chain,
+ TrustStore* trust_store,
+ der::GeneralizedTime* time,
+ bool* verify_result) {
+ chain->clear();
+ *trust_store = TrustStore();
+
+ std::string file_data = ReadTestFileToString(file_name);
+
+ std::vector<std::string> pem_headers;
+
+ const char kCertificateHeader[] = "CERTIFICATE";
+ const char kTrustedCertificateHeader[] = "TRUSTED_CERTIFICATE";
+ const char kTimeHeader[] = "TIME";
+ const char kResultHeader[] = "VERIFY_RESULT";
+
+ pem_headers.push_back(kCertificateHeader);
+ pem_headers.push_back(kTrustedCertificateHeader);
+ pem_headers.push_back(kTimeHeader);
+ pem_headers.push_back(kResultHeader);
davidben 2015/11/19 22:24:02 (We should try to get cxx@chromium.org to allow in
eroman 2015/12/03 04:45:12 Word.
+
+ bool has_time = false;
+ bool has_result = false;
+
+ PEMTokenizer pem_tokenizer(file_data, pem_headers);
+ while (pem_tokenizer.GetNext()) {
+ const std::string& block_type = pem_tokenizer.block_type();
+ const std::string& block_data = pem_tokenizer.data();
+
+ if (block_type == kCertificateHeader) {
+ chain->push_back(block_data);
+ } else if (block_type == kTrustedCertificateHeader) {
+ AddCertificateToTrustStore(block_data, trust_store);
+ } else if (block_type == kTimeHeader) {
+ ASSERT_FALSE(has_time) << "Duplicate " << kTimeHeader;
+ has_time = true;
+ ASSERT_TRUE(der::ParseUTCTime(InputFromString(&block_data), time));
+ } else if (block_type == kResultHeader) {
+ ASSERT_FALSE(has_result) << "Duplicate " << kResultHeader;
+ has_result = true;
+ *verify_result = block_data == "SUCCESS";
davidben 2015/11/19 22:24:03 Nit: Probably good to explode if block_data isn't
eroman 2015/12/03 04:45:12 Done.
+ }
+ }
+
+ ASSERT_TRUE(has_time);
+ ASSERT_TRUE(has_result);
+}
+
+void RunTest(const char* file_name) {
+ std::vector<std::string> chain;
+ TrustStore trust_store;
+ der::GeneralizedTime time;
+ bool expected_result;
+
+ ReadTestFromFile(file_name, &chain, &trust_store, &time, &expected_result);
+
+ std::vector<der::Input> input_chain;
+ for (const auto& cert_str : chain)
+ input_chain.push_back(InputFromString(&cert_str));
+
+ SimpleSignaturePolicy signature_policy(2048);
+
+ bool result =
+ VerifyCertificateChain(input_chain, trust_store, &signature_policy, time);
+
+ ASSERT_EQ(expected_result, result);
+}
+
+TEST(VerifyCertificateChainTest, TargetAndIntermediary) {
+ RunTest("target-and-intermediary.pem");
+}
+
+TEST(VerifyCertificateChainTest, UnknownRoot) {
+ RunTest("unknown-root.pem");
+}
+
+TEST(VerifyCertificateChainTest, IntermediaryLacksBasicConstraints) {
+ RunTest("intermediary-lacks-basic-constraints.pem");
+}
+
+TEST(VerifyCertificateChainTest, IntermediaryBasicConstraintsCaFalse) {
+ RunTest("intermediary-basic-constraints-ca-false.pem");
+}
+
+TEST(VerifyCertificateChainTest, IntermediaryBasicConstraintsNotCritical) {
+ RunTest("intermediary-basic-constraints-not-critical.pem");
+}
+
+TEST(VerifyCertificateChainTest, IntermediaryLacksSigningKeyUsage) {
+ RunTest("intermediary-lacks-signing-key-usage.pem");
+}
+
+TEST(VerifyCertificateChainTest, IntermediaryUnknownCriticalExtension) {
+ RunTest("intermediary-unknown-critical-extension.pem");
+}
+
+TEST(VerifyCertificateChainTest, IntermediaryUnknownNonCriticalExtension) {
+ RunTest("intermediary-unknown-non-critical-extension.pem");
+}
+
+TEST(VerifyCertificateChainTest, ViolatesBasicConstraintsPathlen0) {
+ RunTest("violates-basic-constraints-pathlen-0.pem");
+}
+
+TEST(VerifyCertificateChainTest, BasicConstraintsPathlen0SelfIssued) {
+ RunTest("basic-constraints-pathlen-0-self-issued.pem");
+}
+
+TEST(VerifyCertificateChainTest, TargetSignedWithMd5) {
+ RunTest("target-signed-with-md5.pem");
+}
+
+TEST(VerifyCertificateChainTest, IntermediarySignedWithMd5) {
+ RunTest("intermediary-signed-with-md5.pem");
+}
+
+TEST(VerifyCertificateChainTest, TargetWrongSignature) {
+ RunTest("target-wrong-signature.pem");
+}
+
+TEST(VerifyCertificateChainTest, TargetSignedBy512bitRsa) {
+ RunTest("target-signed-by-512bit-rsa.pem");
+}
+
+TEST(VerifyCertificateChainTest, TargetSignedUsingEcdsa) {
+ RunTest("target-signed-using-ecdsa.pem");
+}
+
+TEST(VerifyCertificateChainTest, ExpiredIntermediary) {
+ RunTest("expired-intermediary.pem");
+}
+
+TEST(VerifyCertificateChainTest, ExpiredTarget) {
+ RunTest("expired-target.pem");
+}
+
+TEST(VerifyCertificateChainTest, ExpiredTargetNotBefore) {
+ RunTest("expired-target-notBefore.pem");
+}
+
+TEST(VerifyCertificateChainTest, TargetNotEndEntity) {
+ RunTest("target-not-end-entity.pem");
+}
+
+} // namespace
+
+} // namespace net

Powered by Google App Engine
This is Rietveld 408576698