• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2023, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14 
15 #include <string.h>
16 
17 #include <optional>
18 #include <vector>
19 
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 #include <openssl/pki/verify.h>
23 #include <openssl/pki/verify_error.h>
24 #include <openssl/sha.h>
25 
26 #include "test_helpers.h"
27 
28 BSSL_NAMESPACE_BEGIN
29 
MozillaRootStore()30 static std::unique_ptr<VerifyTrustStore> MozillaRootStore() {
31   std::string diagnostic;
32   return VerifyTrustStore::FromDER(
33              bssl::ReadTestFileToString(
34                  "testdata/verify_unittest/mozilla_roots.der"),
35              &diagnostic);
36 }
37 
38 using ::testing::UnorderedElementsAre;
39 
GetTestdata(std::string_view filename)40 static std::string GetTestdata(std::string_view filename) {
41   return bssl::ReadTestFileToString("testdata/verify_unittest/" +
42                                     std::string(filename));
43 }
44 
TEST(VerifyTest,GoogleChain)45 TEST(VerifyTest, GoogleChain) {
46   const std::string leaf = GetTestdata("google-leaf.der");
47   const std::string intermediate1 = GetTestdata("google-intermediate1.der");
48   const std::string intermediate2 = GetTestdata("google-intermediate2.der");
49   CertificateVerifyOptions opts;
50   opts.leaf_cert = leaf;
51   opts.intermediates = {intermediate1, intermediate2};
52   opts.time = 1499727444;
53   std::unique_ptr<VerifyTrustStore> roots = MozillaRootStore();
54   opts.trust_store = roots.get();
55 
56   VerifyError error;
57   ASSERT_TRUE(CertificateVerify(opts, &error)) << error.DiagnosticString();
58 
59   opts.intermediates = {};
60   EXPECT_FALSE(CertificateVerify(opts, &error));
61   ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_NOT_FOUND)
62       << error.DiagnosticString();
63 }
64 
65 
TEST(VerifyTest,ExtraIntermediates)66 TEST(VerifyTest, ExtraIntermediates) {
67   const std::string leaf = GetTestdata("google-leaf.der");
68   const std::string intermediate1 = GetTestdata("google-intermediate1.der");
69   const std::string intermediate2 = GetTestdata("google-intermediate2.der");
70 
71   CertificateVerifyOptions opts;
72   opts.leaf_cert = leaf;
73   std::string diagnostic;
74   const auto cert_pool_status = CertPool::FromCerts(
75       {
76           intermediate1,
77           intermediate2,
78       },
79       &diagnostic);
80   ASSERT_TRUE(cert_pool_status) << diagnostic;
81   opts.extra_intermediates = cert_pool_status.get();
82   opts.time = 1499727444;
83   std::unique_ptr<VerifyTrustStore> roots = MozillaRootStore();
84   opts.trust_store = roots.get();
85 
86   VerifyError error;
87   ASSERT_TRUE(CertificateVerify(opts, &error)) << error.DiagnosticString();
88 }
89 
TEST(VerifyTest,AllPaths)90 TEST(VerifyTest, AllPaths) {
91   const std::string leaf = GetTestdata("lencr-leaf.der");
92   const std::string intermediate1 = GetTestdata("lencr-intermediate-r3.der");
93   const std::string intermediate2 =
94       GetTestdata("lencr-root-x1-cross-signed.der");
95   const std::string root1 = GetTestdata("lencr-root-x1.der");
96   const std::string root2 = GetTestdata("lencr-root-dst-x3.der");
97 
98   std::vector<std::string> expected_path1 = {leaf, intermediate1, root1};
99   std::vector<std::string> expected_path2 = {leaf, intermediate1, intermediate2,
100                                              root2};
101 
102   CertificateVerifyOptions opts;
103   opts.leaf_cert = leaf;
104   opts.intermediates = {intermediate1, intermediate2};
105   opts.time = 1699404611;
106   std::unique_ptr<VerifyTrustStore> roots = MozillaRootStore();
107   opts.trust_store = roots.get();
108 
109   auto paths = CertificateVerifyAllPaths(opts);
110   ASSERT_TRUE(paths);
111   EXPECT_EQ(2U, paths.value().size());
112   EXPECT_THAT(paths.value(),
113               UnorderedElementsAre(expected_path1, expected_path2));
114 }
115 
TEST(VerifyTest,DepthLimit)116 TEST(VerifyTest, DepthLimit) {
117   const std::string leaf = GetTestdata("google-leaf.der");
118   const std::string intermediate1 = GetTestdata("google-intermediate1.der");
119   const std::string intermediate2 = GetTestdata("google-intermediate2.der");
120   CertificateVerifyOptions opts;
121   opts.leaf_cert = leaf;
122   opts.intermediates = {intermediate1, intermediate2};
123   opts.time = 1499727444;
124   // Set the |max_path_building_depth| explicitly to test the non-default case.
125   // Depth of 5 is enough to successfully find a path.
126   opts.max_path_building_depth = 5;
127   std::unique_ptr<VerifyTrustStore> roots = MozillaRootStore();
128   opts.trust_store = roots.get();
129 
130   VerifyError error;
131   ASSERT_TRUE(CertificateVerify(opts, &error)) << error.DiagnosticString();
132 
133   // Depth of 2 is not enough to find a path.
134   opts.max_path_building_depth = 2;
135   EXPECT_FALSE(CertificateVerify(opts, &error));
136   ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_DEPTH_LIMIT_REACHED)
137       << error.DiagnosticString();
138 }
139 
140 BSSL_NAMESPACE_END
141