1 // Copyright 2015 The Chromium Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "verify_signed_data.h"
16 
17 #include <memory>
18 #include <optional>
19 #include <set>
20 
21 #include <gtest/gtest.h>
22 
23 #include <openssl/span.h>
24 
25 #include "cert_errors.h"
26 #include "input.h"
27 #include "mock_signature_verify_cache.h"
28 #include "parse_values.h"
29 #include "parser.h"
30 #include "signature_algorithm.h"
31 #include "test_helpers.h"
32 
33 BSSL_NAMESPACE_BEGIN
34 
35 namespace {
36 
37 enum VerifyResult {
38   SUCCESS,
39   FAILURE,
40 };
41 
42 // Reads test data from |file_name| and runs VerifySignedData() over its
43 // inputs.
44 //
45 // If expected_result was SUCCESS then the test will only succeed if
46 // VerifySignedData() returns true.
47 //
48 // If expected_result was FAILURE then the test will only succeed if
49 // VerifySignedData() returns false.
RunTestCase(VerifyResult expected_result,const char * file_name,SignatureVerifyCache * cache)50 void RunTestCase(VerifyResult expected_result, const char *file_name,
51                  SignatureVerifyCache *cache) {
52   std::string path =
53       std::string("testdata/verify_signed_data_unittest/") + file_name;
54 
55   std::string public_key;
56   std::string algorithm;
57   std::string signed_data;
58   std::string signature_value;
59 
60   const PemBlockMapping mappings[] = {
61       {"PUBLIC KEY", &public_key},
62       {"ALGORITHM", &algorithm},
63       {"DATA", &signed_data},
64       {"SIGNATURE", &signature_value},
65   };
66 
67   ASSERT_TRUE(ReadTestDataFromPemFile(path, mappings));
68 
69   std::optional<SignatureAlgorithm> signature_algorithm =
70       ParseSignatureAlgorithm(StringAsBytes(algorithm));
71   ASSERT_TRUE(signature_algorithm);
72 
73   der::Parser signature_value_parser(StringAsBytes(signature_value));
74   std::optional<der::BitString> signature_value_bit_string =
75       signature_value_parser.ReadBitString();
76   ASSERT_TRUE(signature_value_bit_string.has_value())
77       << "The signature value is not a valid BIT STRING";
78 
79   bool expected_result_bool = expected_result == SUCCESS;
80 
81   bool result = VerifySignedData(
82       *signature_algorithm, StringAsBytes(signed_data),
83       signature_value_bit_string.value(), StringAsBytes(public_key), cache);
84 
85   EXPECT_EQ(expected_result_bool, result);
86 }
87 
RunTestCase(VerifyResult expected_result,const char * file_name)88 void RunTestCase(VerifyResult expected_result, const char *file_name) {
89   RunTestCase(expected_result, file_name, /*cache=*/nullptr);
90 }
91 
92 // Read the descriptions in the test files themselves for details on what is
93 // being tested.
94 
TEST(VerifySignedDataTest,RsaPkcs1Sha1)95 TEST(VerifySignedDataTest, RsaPkcs1Sha1) {
96   RunTestCase(SUCCESS, "rsa-pkcs1-sha1.pem");
97 }
98 
TEST(VerifySignedDataTest,RsaPkcs1Sha256)99 TEST(VerifySignedDataTest, RsaPkcs1Sha256) {
100   RunTestCase(SUCCESS, "rsa-pkcs1-sha256.pem");
101 }
102 
TEST(VerifySignedDataTest,Rsa2048Pkcs1Sha512)103 TEST(VerifySignedDataTest, Rsa2048Pkcs1Sha512) {
104   RunTestCase(SUCCESS, "rsa2048-pkcs1-sha512.pem");
105 }
106 
TEST(VerifySignedDataTest,RsaPkcs1Sha256KeyEncodedBer)107 TEST(VerifySignedDataTest, RsaPkcs1Sha256KeyEncodedBer) {
108   RunTestCase(FAILURE, "rsa-pkcs1-sha256-key-encoded-ber.pem");
109 }
110 
TEST(VerifySignedDataTest,EcdsaSecp384r1Sha256)111 TEST(VerifySignedDataTest, EcdsaSecp384r1Sha256) {
112   RunTestCase(SUCCESS, "ecdsa-secp384r1-sha256.pem");
113 }
114 
TEST(VerifySignedDataTest,EcdsaPrime256v1Sha512)115 TEST(VerifySignedDataTest, EcdsaPrime256v1Sha512) {
116   RunTestCase(SUCCESS, "ecdsa-prime256v1-sha512.pem");
117 }
118 
TEST(VerifySignedDataTest,RsaPssSha256)119 TEST(VerifySignedDataTest, RsaPssSha256) {
120   RunTestCase(SUCCESS, "rsa-pss-sha256.pem");
121 }
122 
TEST(VerifySignedDataTest,RsaPssSha256WrongSalt)123 TEST(VerifySignedDataTest, RsaPssSha256WrongSalt) {
124   RunTestCase(FAILURE, "rsa-pss-sha256-wrong-salt.pem");
125 }
126 
TEST(VerifySignedDataTest,EcdsaSecp384r1Sha256CorruptedData)127 TEST(VerifySignedDataTest, EcdsaSecp384r1Sha256CorruptedData) {
128   RunTestCase(FAILURE, "ecdsa-secp384r1-sha256-corrupted-data.pem");
129 }
130 
TEST(VerifySignedDataTest,RsaPkcs1Sha1WrongAlgorithm)131 TEST(VerifySignedDataTest, RsaPkcs1Sha1WrongAlgorithm) {
132   RunTestCase(FAILURE, "rsa-pkcs1-sha1-wrong-algorithm.pem");
133 }
134 
TEST(VerifySignedDataTest,EcdsaPrime256v1Sha512WrongSignatureFormat)135 TEST(VerifySignedDataTest, EcdsaPrime256v1Sha512WrongSignatureFormat) {
136   RunTestCase(FAILURE, "ecdsa-prime256v1-sha512-wrong-signature-format.pem");
137 }
138 
TEST(VerifySignedDataTest,EcdsaUsingRsaKey)139 TEST(VerifySignedDataTest, EcdsaUsingRsaKey) {
140   RunTestCase(FAILURE, "ecdsa-using-rsa-key.pem");
141 }
142 
TEST(VerifySignedDataTest,RsaUsingEcKey)143 TEST(VerifySignedDataTest, RsaUsingEcKey) {
144   RunTestCase(FAILURE, "rsa-using-ec-key.pem");
145 }
146 
TEST(VerifySignedDataTest,RsaPkcs1Sha1BadKeyDerNull)147 TEST(VerifySignedDataTest, RsaPkcs1Sha1BadKeyDerNull) {
148   RunTestCase(FAILURE, "rsa-pkcs1-sha1-bad-key-der-null.pem");
149 }
150 
TEST(VerifySignedDataTest,RsaPkcs1Sha1BadKeyDerLength)151 TEST(VerifySignedDataTest, RsaPkcs1Sha1BadKeyDerLength) {
152   RunTestCase(FAILURE, "rsa-pkcs1-sha1-bad-key-der-length.pem");
153 }
154 
TEST(VerifySignedDataTest,RsaPkcs1Sha256UsingEcdsaAlgorithm)155 TEST(VerifySignedDataTest, RsaPkcs1Sha256UsingEcdsaAlgorithm) {
156   RunTestCase(FAILURE, "rsa-pkcs1-sha256-using-ecdsa-algorithm.pem");
157 }
158 
TEST(VerifySignedDataTest,EcdsaPrime256v1Sha512UsingRsaAlgorithm)159 TEST(VerifySignedDataTest, EcdsaPrime256v1Sha512UsingRsaAlgorithm) {
160   RunTestCase(FAILURE, "ecdsa-prime256v1-sha512-using-rsa-algorithm.pem");
161 }
162 
TEST(VerifySignedDataTest,EcdsaPrime256v1Sha512UsingEcdhKey)163 TEST(VerifySignedDataTest, EcdsaPrime256v1Sha512UsingEcdhKey) {
164   RunTestCase(FAILURE, "ecdsa-prime256v1-sha512-using-ecdh-key.pem");
165 }
166 
TEST(VerifySignedDataTest,EcdsaPrime256v1Sha512UsingEcmqvKey)167 TEST(VerifySignedDataTest, EcdsaPrime256v1Sha512UsingEcmqvKey) {
168   RunTestCase(FAILURE, "ecdsa-prime256v1-sha512-using-ecmqv-key.pem");
169 }
170 
TEST(VerifySignedDataTest,RsaPkcs1Sha1KeyParamsAbsent)171 TEST(VerifySignedDataTest, RsaPkcs1Sha1KeyParamsAbsent) {
172   RunTestCase(FAILURE, "rsa-pkcs1-sha1-key-params-absent.pem");
173 }
174 
TEST(VerifySignedDataTest,RsaPkcs1Sha1UsingPssKeyNoParams)175 TEST(VerifySignedDataTest, RsaPkcs1Sha1UsingPssKeyNoParams) {
176   RunTestCase(FAILURE, "rsa-pkcs1-sha1-using-pss-key-no-params.pem");
177 }
178 
TEST(VerifySignedDataTest,RsaPssSha256UsingPssKeyWithParams)179 TEST(VerifySignedDataTest, RsaPssSha256UsingPssKeyWithParams) {
180   // We do not support RSA-PSS SPKIs.
181   RunTestCase(FAILURE, "rsa-pss-sha256-using-pss-key-with-params.pem");
182 }
183 
TEST(VerifySignedDataTest,EcdsaPrime256v1Sha512SpkiParamsNull)184 TEST(VerifySignedDataTest, EcdsaPrime256v1Sha512SpkiParamsNull) {
185   RunTestCase(FAILURE, "ecdsa-prime256v1-sha512-spki-params-null.pem");
186 }
187 
TEST(VerifySignedDataTest,RsaPkcs1Sha256UsingIdEaRsa)188 TEST(VerifySignedDataTest, RsaPkcs1Sha256UsingIdEaRsa) {
189   RunTestCase(FAILURE, "rsa-pkcs1-sha256-using-id-ea-rsa.pem");
190 }
191 
TEST(VerifySignedDataTest,RsaPkcs1Sha256SpkiNonNullParams)192 TEST(VerifySignedDataTest, RsaPkcs1Sha256SpkiNonNullParams) {
193   RunTestCase(FAILURE, "rsa-pkcs1-sha256-spki-non-null-params.pem");
194 }
195 
TEST(VerifySignedDataTest,EcdsaPrime256v1Sha512UnusedBitsSignature)196 TEST(VerifySignedDataTest, EcdsaPrime256v1Sha512UnusedBitsSignature) {
197   RunTestCase(FAILURE, "ecdsa-prime256v1-sha512-unused-bits-signature.pem");
198 }
199 
TEST(VerifySignedDataTest,Ecdsa384)200 TEST(VerifySignedDataTest, Ecdsa384) {
201   // Using the regular policy both secp384r1 and secp256r1 should be accepted.
202   RunTestCase(SUCCESS, "ecdsa-secp384r1-sha256.pem");
203   RunTestCase(SUCCESS, "ecdsa-prime256v1-sha512.pem");
204 }
205 
TEST(VerifySignedDataTestWithCache,TestVerifyCache)206 TEST(VerifySignedDataTestWithCache, TestVerifyCache) {
207   MockSignatureVerifyCache verify_cache;
208   // Trivially, with no cache, all stats should be 0.
209   RunTestCase(SUCCESS, "rsa-pss-sha256.pem", /*cache=*/nullptr);
210   EXPECT_EQ(verify_cache.CacheHits(), 0U);
211   EXPECT_EQ(verify_cache.CacheMisses(), 0U);
212   EXPECT_EQ(verify_cache.CacheStores(), 0U);
213   // Use the cache, with a successful verification should see a miss and a
214   // store.
215   RunTestCase(SUCCESS, "rsa-pss-sha256.pem", &verify_cache);
216   EXPECT_EQ(verify_cache.CacheHits(), 0U);
217   EXPECT_EQ(verify_cache.CacheMisses(), 1U);
218   EXPECT_EQ(verify_cache.CacheStores(), 1U);
219   // Repeating the previous successful verification should show cache hits.
220   RunTestCase(SUCCESS, "rsa-pss-sha256.pem", &verify_cache);
221   RunTestCase(SUCCESS, "rsa-pss-sha256.pem", &verify_cache);
222   RunTestCase(SUCCESS, "rsa-pss-sha256.pem", &verify_cache);
223   EXPECT_EQ(verify_cache.CacheHits(), 3U);
224   EXPECT_EQ(verify_cache.CacheMisses(), 1U);
225   EXPECT_EQ(verify_cache.CacheStores(), 1U);
226   // Failures which are not due to a failed signature check should have no
227   // effect as they must not be cached.
228   RunTestCase(FAILURE, "ecdsa-prime256v1-sha512-using-ecdh-key.pem",
229               &verify_cache);
230   EXPECT_EQ(verify_cache.CacheHits(), 3U);
231   EXPECT_EQ(verify_cache.CacheMisses(), 1U);
232   EXPECT_EQ(verify_cache.CacheStores(), 1U);
233   // Failures which are due to a failed signature check should see a miss and a
234   // store.
235   RunTestCase(FAILURE, "ecdsa-secp384r1-sha256-corrupted-data.pem",
236               &verify_cache);
237   EXPECT_EQ(verify_cache.CacheHits(), 3U);
238   EXPECT_EQ(verify_cache.CacheMisses(), 2U);
239   EXPECT_EQ(verify_cache.CacheStores(), 2U);
240   // Repeating the previous failed verification should show cache hits.
241   RunTestCase(FAILURE, "ecdsa-secp384r1-sha256-corrupted-data.pem",
242               &verify_cache);
243   RunTestCase(FAILURE, "ecdsa-secp384r1-sha256-corrupted-data.pem",
244               &verify_cache);
245   RunTestCase(FAILURE, "ecdsa-secp384r1-sha256-corrupted-data.pem",
246               &verify_cache);
247   EXPECT_EQ(verify_cache.CacheHits(), 6U);
248   EXPECT_EQ(verify_cache.CacheMisses(), 2U);
249   EXPECT_EQ(verify_cache.CacheStores(), 2U);
250 }
251 
252 }  // namespace
253 
254 BSSL_NAMESPACE_END
255