xref: /aosp_15_r20/external/tink/cc/core/private_key_manager_impl_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2019 Google LLC
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 //     http://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 ///////////////////////////////////////////////////////////////////////////////
16 #include "tink/core/private_key_manager_impl.h"
17 
18 #include <memory>
19 #include <string>
20 
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 #include "absl/status/status.h"
24 #include "tink/core/key_manager_impl.h"
25 #include "tink/core/private_key_type_manager.h"
26 #include "tink/registry.h"
27 #include "tink/subtle/aes_gcm_boringssl.h"
28 #include "tink/subtle/random.h"
29 #include "tink/util/status.h"
30 #include "tink/util/statusor.h"
31 #include "tink/util/test_matchers.h"
32 #include "tink/util/test_util.h"
33 #include "tink/util/validation.h"
34 #include "proto/ecdsa.pb.h"
35 
36 namespace crypto {
37 namespace tink {
38 namespace internal {
39 namespace {
40 
41 using ::crypto::tink::test::StatusIs;
42 using ::google::crypto::tink::EcdsaKeyFormat;
43 using ::google::crypto::tink::EcdsaPrivateKey;
44 using ::google::crypto::tink::EcdsaPublicKey;
45 using ::google::crypto::tink::EcdsaSignatureEncoding;
46 using ::testing::Eq;
47 using ::testing::HasSubstr;
48 using ::testing::Return;
49 
50 }  // namespace
51 
52 // Placeholders for the primitives. We don't really want to test anything with
53 // these except that things compile and List<PrivatePrimitive> is never confused
54 // with List<PublicPrimitive> in private_key_manager_impl.
55 // NOTE: These are outside of the anonymous namespace to allow compiling with
56 // MSVC.
57 class PrivatePrimitive {};
58 class PublicPrimitive {};
59 
60 namespace {
61 
62 class ExamplePrivateKeyTypeManager
63     : public PrivateKeyTypeManager<EcdsaPrivateKey, EcdsaKeyFormat,
64                                    EcdsaPublicKey, List<PrivatePrimitive>> {
65  public:
66   class PrivatePrimitiveFactory : public PrimitiveFactory<PrivatePrimitive> {
67    public:
Create(const EcdsaPrivateKey & key) const68     crypto::tink::util::StatusOr<std::unique_ptr<PrivatePrimitive>> Create(
69         const EcdsaPrivateKey& key) const override {
70       return util::Status(absl::StatusCode::kUnimplemented, "Not implemented");
71     }
72   };
73 
ExamplePrivateKeyTypeManager()74   ExamplePrivateKeyTypeManager()
75       : PrivateKeyTypeManager(absl::make_unique<PrivatePrimitiveFactory>()) {}
76 
key_material_type() const77   google::crypto::tink::KeyData::KeyMaterialType key_material_type()
78       const override {
79     return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE;
80   }
81 
82   MOCK_METHOD(uint32_t, get_version, (), (const, override));
83 
84   // We mock out ValidateKey and ValidateKeyFormat so that we can easily test
85   // proper behavior in case they return an error.
86   MOCK_METHOD(crypto::tink::util::Status, ValidateKey,
87               (const EcdsaPrivateKey& key), (const, override));
88   MOCK_METHOD(crypto::tink::util::Status, ValidateKeyFormat,
89               (const EcdsaKeyFormat& key), (const, override));
90 
get_key_type() const91   const std::string& get_key_type() const override { return kKeyType; }
92 
CreateKey(const EcdsaKeyFormat & key_format) const93   crypto::tink::util::StatusOr<EcdsaPrivateKey> CreateKey(
94       const EcdsaKeyFormat& key_format) const override {
95     EcdsaPublicKey public_key;
96     *public_key.mutable_params() = key_format.params();
97     EcdsaPrivateKey result;
98     *result.mutable_public_key() = public_key;
99     return result;
100   }
101 
GetPublicKey(const EcdsaPrivateKey & private_key) const102   crypto::tink::util::StatusOr<EcdsaPublicKey> GetPublicKey(
103       const EcdsaPrivateKey& private_key) const override {
104     return private_key.public_key();
105   }
106 
107  private:
108   const std::string kKeyType =
109       "type.googleapis.com/google.crypto.tink.EcdsaPublicKey";
110 };
111 
112 class TestPublicKeyTypeManager
113     : public KeyTypeManager<EcdsaPublicKey, void, List<PublicPrimitive>> {
114  public:
115   class PublicPrimitiveFactory : public PrimitiveFactory<PublicPrimitive> {
116    public:
Create(const EcdsaPublicKey & key) const117     crypto::tink::util::StatusOr<std::unique_ptr<PublicPrimitive>> Create(
118         const EcdsaPublicKey& key) const override {
119       return util::Status(absl::StatusCode::kUnimplemented, "Not implemented");
120     }
121   };
122 
TestPublicKeyTypeManager()123   TestPublicKeyTypeManager()
124       : KeyTypeManager(absl::make_unique<PublicPrimitiveFactory>()) {}
125 
key_material_type() const126   google::crypto::tink::KeyData::KeyMaterialType key_material_type()
127       const override {
128     return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE;
129   }
130 
131   MOCK_METHOD(uint32_t, get_version, (), (const, override));
132 
133   // We mock out ValidateKey and ValidateKeyFormat so that we can easily test
134   // proper behavior in case they return an error.
135   MOCK_METHOD(crypto::tink::util::Status, ValidateKey,
136               (const EcdsaPublicKey& key), (const, override));
137 
get_key_type() const138   const std::string& get_key_type() const override { return kKeyType; }
139 
140  private:
141   const std::string kKeyType =
142       "type.googleapis.com/google.crypto.tink.EcdsaPublicKey";
143 };
144 
TEST(PrivateKeyManagerImplTest,FactoryNewKeyFromMessage)145 TEST(PrivateKeyManagerImplTest, FactoryNewKeyFromMessage) {
146   ExamplePrivateKeyTypeManager private_km;
147   TestPublicKeyTypeManager public_km;
148   std::unique_ptr<KeyManager<PrivatePrimitive>> key_manager =
149       MakePrivateKeyManager<PrivatePrimitive>(&private_km, &public_km);
150 
151   EcdsaKeyFormat key_format;
152   key_format.mutable_params()->set_encoding(EcdsaSignatureEncoding::DER);
153   auto key = key_manager->get_key_factory().NewKey(key_format).value();
154   EXPECT_THAT(
155       dynamic_cast<EcdsaPrivateKey&>(*key).public_key().params().encoding(),
156       Eq(EcdsaSignatureEncoding::DER));
157 }
158 
TEST(PrivateKeyManagerImplTest,GetPublicKeyData)159 TEST(PrivateKeyManagerImplTest, GetPublicKeyData) {
160   ExamplePrivateKeyTypeManager private_km;
161   TestPublicKeyTypeManager public_km;
162   std::unique_ptr<KeyManager<PrivatePrimitive>> key_manager =
163       MakePrivateKeyManager<PrivatePrimitive>(&private_km, &public_km);
164 
165   EcdsaPrivateKey private_key;
166   private_key.mutable_public_key()->mutable_params()->set_encoding(
167       EcdsaSignatureEncoding::DER);
168 
169   auto key_data =
170       dynamic_cast<const PrivateKeyFactory&>(key_manager->get_key_factory())
171           .GetPublicKeyData(private_key.SerializeAsString())
172           .value();
173   ASSERT_THAT(key_data->type_url(), Eq(public_km.get_key_type()));
174   EcdsaPublicKey public_key;
175   public_key.ParseFromString(key_data->value());
176   EXPECT_THAT(public_key.params().encoding(), Eq(EcdsaSignatureEncoding::DER));
177 }
178 
TEST(PrivateKeyManagerImplTest,GetPublicKeyDataValidatePrivateKey)179 TEST(PrivateKeyManagerImplTest, GetPublicKeyDataValidatePrivateKey) {
180   ExamplePrivateKeyTypeManager private_km;
181   TestPublicKeyTypeManager public_km;
182   EXPECT_CALL(private_km, ValidateKey)
183       .WillOnce(Return(util::Status(absl::StatusCode::kOutOfRange,
184                                     "GetPublicKeyDataValidatePrivateKey")));
185 
186   std::unique_ptr<KeyManager<PrivatePrimitive>> key_manager =
187       MakePrivateKeyManager<PrivatePrimitive>(&private_km, &public_km);
188 
189   EXPECT_THAT(
190       dynamic_cast<const PrivateKeyFactory&>(key_manager->get_key_factory())
191           .GetPublicKeyData(EcdsaPrivateKey().SerializeAsString())
192           .status(),
193       StatusIs(absl::StatusCode::kOutOfRange,
194                HasSubstr("GetPublicKeyDataValidatePrivateKey")));
195 }
196 
TEST(PrivateKeyManagerImplTest,PublicKeyManagerCanHaveShortLifetime)197 TEST(PrivateKeyManagerImplTest, PublicKeyManagerCanHaveShortLifetime) {
198   ExamplePrivateKeyTypeManager private_km;
199   std::unique_ptr<KeyManager<PrivatePrimitive>> key_manager;
200   {
201     TestPublicKeyTypeManager public_km;
202     key_manager =
203         MakePrivateKeyManager<PrivatePrimitive>(&private_km, &public_km);
204     // Let the public_km go out of scope; the key_manager should still work.
205   }
206 
207   EcdsaKeyFormat key_format;
208   key_format.mutable_params()->set_encoding(EcdsaSignatureEncoding::DER);
209   auto key = key_manager->get_key_factory().NewKey(key_format).value();
210   EXPECT_THAT(
211       dynamic_cast<EcdsaPrivateKey&>(*key).public_key().params().encoding(),
212       Eq(EcdsaSignatureEncoding::DER));
213 }
214 
215 }  // namespace
216 
217 }  // namespace internal
218 }  // namespace tink
219 }  // namespace crypto
220