xref: /aosp_15_r20/external/tink/cc/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_encrypt_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2021 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 
17 #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_aead_hkdf_hybrid_encrypt.h"
18 
19 #include <memory>
20 #include <string>
21 #include <utility>
22 
23 #include "gtest/gtest.h"
24 #include "absl/memory/memory.h"
25 #include "absl/status/status.h"
26 #include "openssl/curve25519.h"
27 #include "openssl/hrss.h"
28 #include "tink/aead/aes_gcm_key_manager.h"
29 #include "tink/experimental/pqcrypto/kem/subtle/cecpq2_subtle_boringssl_util.h"
30 #include "tink/experimental/pqcrypto/kem/util/test_util.h"
31 #include "tink/hybrid_encrypt.h"
32 #include "tink/registry.h"
33 #include "tink/subtle/random.h"
34 #include "tink/subtle/subtle_util.h"
35 #include "tink/util/enums.h"
36 #include "tink/util/statusor.h"
37 #include "tink/util/test_matchers.h"
38 #include "tink/util/test_util.h"
39 
40 using ::crypto::tink::test::IsOk;
41 using ::crypto::tink::test::StatusIs;
42 using ::testing::HasSubstr;
43 
44 namespace crypto {
45 namespace tink {
46 namespace {
47 
CreateValidKey()48 google::crypto::tink::Cecpq2AeadHkdfPublicKey CreateValidKey() {
49   auto cecp2_key_pair = crypto::tink::pqc::GenerateCecpq2Keypair(
50                             subtle::EllipticCurveType::CURVE25519)
51                             .value();
52   google::crypto::tink::Cecpq2AeadHkdfPublicKey sender_key;
53   sender_key.set_hrss_public_key_marshalled(
54       cecp2_key_pair.hrss_key_pair.hrss_public_key_marshaled);
55   sender_key.set_x25519_public_key_x(cecp2_key_pair.x25519_key_pair.pub_x);
56   sender_key.mutable_params()->mutable_kem_params()->set_curve_type(
57       google::crypto::tink::EllipticCurveType::CURVE25519);
58   sender_key.mutable_params()->mutable_kem_params()->set_hkdf_hash_type(
59       google::crypto::tink::HashType::SHA256);
60   sender_key.mutable_params()
61       ->mutable_dem_params()
62       ->mutable_aead_dem()
63       ->set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey");
64   return sender_key;
65 }
66 
TEST(Cecpq2AeadHkdfHybridEncryptTest,ValidKey)67 TEST(Cecpq2AeadHkdfHybridEncryptTest, ValidKey) {
68   google::crypto::tink::Cecpq2AeadHkdfPublicKey sender_key = CreateValidKey();
69   auto result = Cecpq2AeadHkdfHybridEncrypt::New(sender_key);
70   EXPECT_THAT(result, IsOk());
71 }
72 
TEST(Cecpq2AeadHkdfHybridEncryptTest,InvalidKeyNoFieldSet)73 TEST(Cecpq2AeadHkdfHybridEncryptTest, InvalidKeyNoFieldSet) {
74   auto result = Cecpq2AeadHkdfHybridEncrypt::New(
75       google::crypto::tink::Cecpq2AeadHkdfPublicKey());
76   EXPECT_THAT(result.status(),
77               StatusIs(absl::StatusCode::kInvalidArgument,
78                        HasSubstr("missing KEM required fields")));
79 }
80 
TEST(Cecpq2AeadHkdfHybridEncryptTest,InvalidKeySomeFieldsSet)81 TEST(Cecpq2AeadHkdfHybridEncryptTest, InvalidKeySomeFieldsSet) {
82   google::crypto::tink::Cecpq2AeadHkdfPublicKey sender_key = CreateValidKey();
83   sender_key.set_x25519_public_key_x("");
84   auto result(Cecpq2AeadHkdfHybridEncrypt::New(sender_key));
85   EXPECT_THAT(result.status(),
86               StatusIs(absl::StatusCode::kInvalidArgument,
87                        HasSubstr("missing KEM required fields")));
88 }
89 
TEST(Cecpq2AeadHkdfHybridEncryptTest,InvalidKeyUnsupportedEcType)90 TEST(Cecpq2AeadHkdfHybridEncryptTest, InvalidKeyUnsupportedEcType) {
91   google::crypto::tink::Cecpq2AeadHkdfPublicKey sender_key = CreateValidKey();
92   sender_key.mutable_params()->mutable_kem_params()->set_curve_type(
93       google::crypto::tink::EllipticCurveType::NIST_P256);
94   auto result = Cecpq2AeadHkdfHybridEncrypt::New(sender_key);
95   EXPECT_THAT(result.status(),
96               StatusIs(absl::StatusCode::kUnimplemented,
97                        HasSubstr("Unsupported elliptic curve")));
98 }
99 
TEST(Cecpq2AeadHkdfHybridEncryptTest,InvalidKeyUnsupportedDemKeyType)100 TEST(Cecpq2AeadHkdfHybridEncryptTest, InvalidKeyUnsupportedDemKeyType) {
101   auto status_or_cecpq2_key =
102       pqc::GenerateCecpq2Keypair(subtle::EllipticCurveType::CURVE25519);
103   ASSERT_THAT(status_or_cecpq2_key, IsOk());
104   auto cecpq2_key_pair = std::move(status_or_cecpq2_key).value();
105 
106   google::crypto::tink::Cecpq2AeadHkdfPublicKey sender_key = CreateValidKey();
107   sender_key.mutable_params()
108       ->mutable_dem_params()
109       ->mutable_aead_dem()
110       ->set_type_url("some.type.url/that.is.not.supported");
111   auto result(Cecpq2AeadHkdfHybridEncrypt::New(sender_key));
112   EXPECT_THAT(result.status(), StatusIs(absl::StatusCode::kInvalidArgument,
113                                         HasSubstr("Unsupported DEM key type")));
114 }
115 
TEST(Cecpq2AeadHkdfHybridEncryptTest,Basic)116 TEST(Cecpq2AeadHkdfHybridEncryptTest, Basic) {
117   // Prepare an Cecpq2 key
118   auto cecpq2_key = CreateValidKey();
119 
120   // Register DEM key manager
121   ASSERT_THAT(Registry::RegisterKeyTypeManager(
122                   absl::make_unique<AesGcmKeyManager>(), true),
123               IsOk());
124   std::string dem_key_type = AesGcmKeyManager().get_key_type();
125 
126   // Generate and test many keys with various parameters
127   std::string plaintext = "some plaintext";
128   std::string context_info = "some context info";
129   for (auto curve : {google::crypto::tink::EllipticCurveType::CURVE25519}) {
130     for (auto ec_point_format :
131          {google::crypto::tink::EcPointFormat::COMPRESSED}) {
132       for (auto hash_type : {google::crypto::tink::HashType::SHA256,
133                              google::crypto::tink::HashType::SHA512}) {
134         for (uint32_t aes_gcm_key_size : {16, 32}) {
135           SCOPED_TRACE(absl::StrCat(curve, ":", ec_point_format, ":", hash_type,
136                                     ":", aes_gcm_key_size));
137           cecpq2_key.mutable_params()->mutable_kem_params()->set_curve_type(
138               curve);
139           cecpq2_key.mutable_params()
140               ->mutable_kem_params()
141               ->set_ec_point_format(ec_point_format);
142           cecpq2_key.mutable_params()->mutable_kem_params()->set_hkdf_hash_type(
143               hash_type);
144 
145           google::crypto::tink::AesGcmKeyFormat format;
146           format.set_key_size(aes_gcm_key_size);
147           cecpq2_key.mutable_params()
148               ->mutable_dem_params()
149               ->mutable_aead_dem()
150               ->set_value(format.SerializeAsString());
151           cecpq2_key.mutable_params()
152               ->mutable_dem_params()
153               ->mutable_aead_dem()
154               ->set_type_url(
155                   "type.googleapis.com/google.crypto.tink.AesGcmKey");
156           auto key_or = Cecpq2AeadHkdfHybridEncrypt::New(cecpq2_key);
157           ASSERT_THAT(key_or, IsOk());
158           std::unique_ptr<HybridEncrypt> hybrid_encrypt(
159               std::move(key_or.value()));
160           // Use the primitive
161           auto encrypt_result =
162               hybrid_encrypt->Encrypt(plaintext, context_info);
163           EXPECT_THAT(encrypt_result, IsOk());
164         }
165       }
166     }
167   }
168 }
169 
170 }  // namespace
171 }  // namespace tink
172 }  // namespace crypto
173