xref: /aosp_15_r20/external/tink/cc/subtle/ecies_hkdf_sender_kem_boringssl_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2017 Google Inc.
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/subtle/ecies_hkdf_sender_kem_boringssl.h"
18 
19 #include <iostream>
20 #include <ostream>
21 #include <string>
22 #include <utility>
23 #include <vector>
24 
25 #include "gtest/gtest.h"
26 #include "absl/status/status.h"
27 #include "absl/strings/escaping.h"
28 #include "tink/config/tink_fips.h"
29 #include "tink/internal/ec_util.h"
30 #include "tink/subtle/common_enums.h"
31 #include "tink/subtle/ecies_hkdf_recipient_kem_boringssl.h"
32 #include "tink/util/secret_data.h"
33 #include "tink/util/status.h"
34 #include "tink/util/statusor.h"
35 #include "tink/util/test_matchers.h"
36 
37 // TODO(quannguyen): Add extensive tests.
38 // It's important to test compatibility with Java.
39 namespace crypto {
40 namespace tink {
41 namespace subtle {
42 namespace {
43 
44 using ::crypto::tink::test::StatusIs;
45 
46 class EciesHkdfSenderKemBoringSslTest : public ::testing::Test {};
47 
48 struct TestVector {
49   EllipticCurveType curve;
50   HashType hash;
51   EcPointFormat point_format;
52   std::string salt_hex;
53   std::string info_hex;
54   int out_len;
55 };
56 
57 static const std::vector<TestVector> test_vector(
58     {{
59          EllipticCurveType::NIST_P256,
60          HashType::SHA256,
61          EcPointFormat::UNCOMPRESSED,
62          "0b0b0b0b",
63          "0b0b0b0b0b0b0b0b",
64          32,
65      },
66      {
67          EllipticCurveType::NIST_P256,
68          HashType::SHA256,
69          EcPointFormat::COMPRESSED,
70          "0b0b0b0b",
71          "0b0b0b0b0b0b0b0b",
72          32,
73      },
74      {
75          EllipticCurveType::CURVE25519,
76          HashType::SHA256,
77          EcPointFormat::COMPRESSED,
78          "0b0b0b0b",
79          "0b0b0b0b0b0b0b0b",
80          32,
81      }});
82 
TEST_F(EciesHkdfSenderKemBoringSslTest,TestSenderRecipientBasic)83 TEST_F(EciesHkdfSenderKemBoringSslTest, TestSenderRecipientBasic) {
84   if (IsFipsModeEnabled()) {
85     GTEST_SKIP() << "Not supported in FIPS-only mode";
86   }
87   for (const TestVector& test : test_vector) {
88     auto status_or_test_key = internal::NewEcKey(test.curve);
89     ASSERT_TRUE(status_or_test_key.ok());
90     auto test_key = status_or_test_key.value();
91     auto status_or_sender_kem = EciesHkdfSenderKemBoringSsl::New(
92         test.curve, test_key.pub_x, test_key.pub_y);
93     ASSERT_TRUE(status_or_sender_kem.ok());
94     auto sender_kem = std::move(status_or_sender_kem.value());
95     auto status_or_kem_key = sender_kem->GenerateKey(
96         test.hash, absl::HexStringToBytes(test.salt_hex),
97         absl::HexStringToBytes(test.info_hex), test.out_len, test.point_format);
98     ASSERT_TRUE(status_or_kem_key.ok());
99     auto kem_key = std::move(status_or_kem_key.value());
100     auto ecies_recipient(
101         std::move(EciesHkdfRecipientKemBoringSsl::New(test.curve, test_key.priv)
102                       .value()));
103     auto status_or_shared_secret = ecies_recipient->GenerateKey(
104         kem_key->get_kem_bytes(), test.hash,
105         absl::HexStringToBytes(test.salt_hex),
106         absl::HexStringToBytes(test.info_hex),
107         test.out_len, test.point_format);
108     std::cout << absl::BytesToHexString(kem_key->get_kem_bytes()) << std::endl;
109     EXPECT_EQ(absl::BytesToHexString(
110                   util::SecretDataAsStringView(kem_key->get_symmetric_key())),
111               absl::BytesToHexString(util::SecretDataAsStringView(
112                   status_or_shared_secret.value())));
113   }
114 }
115 
TEST_F(EciesHkdfSenderKemBoringSslTest,TestNewUnknownCurve)116 TEST_F(EciesHkdfSenderKemBoringSslTest, TestNewUnknownCurve) {
117   if (IsFipsModeEnabled()) {
118     GTEST_SKIP() << "Not supported in FIPS-only mode";
119   }
120   auto status_or_sender_kem = EciesHkdfSenderKemBoringSsl::New(
121       EllipticCurveType::UNKNOWN_CURVE, "", "");
122   EXPECT_EQ(absl::StatusCode::kUnimplemented,
123             status_or_sender_kem.status().code());
124 }
125 
126 class EciesHkdfNistPCurveSendKemBoringSslTest : public ::testing::Test {};
127 
TEST_F(EciesHkdfNistPCurveSendKemBoringSslTest,TestNew)128 TEST_F(EciesHkdfNistPCurveSendKemBoringSslTest, TestNew) {
129   if (IsFipsModeEnabled()) {
130     GTEST_SKIP() << "Not supported in FIPS-only mode";
131   }
132   EllipticCurveType curve = EllipticCurveType::NIST_P256;
133   auto status_or_test_key = internal::NewEcKey(curve);
134   ASSERT_TRUE(status_or_test_key.ok());
135   auto test_key = status_or_test_key.value();
136   auto status_or_sender_kem = EciesHkdfNistPCurveSendKemBoringSsl::New(
137       curve, test_key.pub_x, test_key.pub_y);
138   ASSERT_TRUE(status_or_sender_kem.ok());
139 }
140 
TEST_F(EciesHkdfNistPCurveSendKemBoringSslTest,TestNewInvalidCurve)141 TEST_F(EciesHkdfNistPCurveSendKemBoringSslTest, TestNewInvalidCurve) {
142   if (IsFipsModeEnabled()) {
143     GTEST_SKIP() << "Not supported in FIPS-only mode";
144   }
145   EllipticCurveType curve = EllipticCurveType::NIST_P256;
146   auto status_or_test_key = internal::NewEcKey(curve);
147   ASSERT_TRUE(status_or_test_key.ok());
148   auto test_key = status_or_test_key.value();
149   auto status_or_sender_kem = EciesHkdfNistPCurveSendKemBoringSsl::New(
150       EllipticCurveType::CURVE25519, test_key.pub_x, test_key.pub_y);
151   EXPECT_EQ(status_or_sender_kem.status().code(),
152             absl::StatusCode::kUnimplemented);
153 }
154 
TEST_F(EciesHkdfNistPCurveSendKemBoringSslTest,TestGenerateKey)155 TEST_F(EciesHkdfNistPCurveSendKemBoringSslTest, TestGenerateKey) {
156   if (IsFipsModeEnabled()) {
157     GTEST_SKIP() << "Not supported in FIPS-only mode";
158   }
159   EllipticCurveType curve = EllipticCurveType::NIST_P256;
160   auto status_or_test_key = internal::NewEcKey(curve);
161   ASSERT_TRUE(status_or_test_key.ok());
162   auto test_key = status_or_test_key.value();
163   auto status_or_sender_kem = EciesHkdfNistPCurveSendKemBoringSsl::New(
164       curve, test_key.pub_x, test_key.pub_y);
165   ASSERT_TRUE(status_or_sender_kem.ok());
166   auto sender_kem = std::move(status_or_sender_kem.value());
167 
168   uint32_t key_size_in_bytes = 128;
169   auto status_or_kem_key =
170       sender_kem->GenerateKey(HashType::SHA256, "hkdf_salt", "hkdf_info",
171                               key_size_in_bytes, EcPointFormat::COMPRESSED);
172   ASSERT_TRUE(status_or_kem_key.ok());
173   auto kem_key = std::move(status_or_kem_key.value());
174   EXPECT_FALSE(kem_key->get_kem_bytes().empty());
175   EXPECT_EQ(kem_key->get_symmetric_key().size(), key_size_in_bytes);
176 }
177 
178 class EciesHkdfX25519SendKemBoringSslTest : public ::testing::Test {};
179 
TEST_F(EciesHkdfX25519SendKemBoringSslTest,TestNew)180 TEST_F(EciesHkdfX25519SendKemBoringSslTest, TestNew) {
181   if (IsFipsModeEnabled()) {
182     GTEST_SKIP() << "Not supported in FIPS-only mode";
183   }
184   EllipticCurveType curve = EllipticCurveType::CURVE25519;
185   auto status_or_test_key = internal::NewEcKey(curve);
186   ASSERT_TRUE(status_or_test_key.ok());
187   auto test_key = status_or_test_key.value();
188   auto status_or_sender_kem = EciesHkdfX25519SendKemBoringSsl::New(
189       curve, test_key.pub_x, test_key.pub_y);
190   ASSERT_TRUE(status_or_sender_kem.ok());
191 }
192 
TEST_F(EciesHkdfX25519SendKemBoringSslTest,TestNewInvalidCurve)193 TEST_F(EciesHkdfX25519SendKemBoringSslTest, TestNewInvalidCurve) {
194   if (IsFipsModeEnabled()) {
195     GTEST_SKIP() << "Not supported in FIPS-only mode";
196   }
197   EllipticCurveType curve = EllipticCurveType::CURVE25519;
198   auto status_or_test_key = internal::NewEcKey(curve);
199   ASSERT_TRUE(status_or_test_key.ok());
200   auto test_key = status_or_test_key.value();
201   auto status_or_sender_kem = EciesHkdfX25519SendKemBoringSsl::New(
202       EllipticCurveType::NIST_P256, test_key.pub_x, test_key.pub_y);
203   EXPECT_EQ(status_or_sender_kem.status().code(),
204             absl::StatusCode::kInvalidArgument);
205 }
206 
TEST_F(EciesHkdfX25519SendKemBoringSslTest,TestNewPubxTooLong)207 TEST_F(EciesHkdfX25519SendKemBoringSslTest, TestNewPubxTooLong) {
208   if (IsFipsModeEnabled()) {
209     GTEST_SKIP() << "Not supported in FIPS-only mode";
210   }
211   EllipticCurveType curve = EllipticCurveType::CURVE25519;
212   auto status_or_test_key = internal::NewEcKey(curve);
213   ASSERT_TRUE(status_or_test_key.ok());
214   auto test_key = status_or_test_key.value();
215   test_key.pub_x.resize(test_key.pub_x.size() / 2);
216   auto status_or_sender_kem = EciesHkdfX25519SendKemBoringSsl::New(
217       curve, test_key.pub_x, test_key.pub_y);
218   EXPECT_EQ(status_or_sender_kem.status().code(),
219             absl::StatusCode::kInvalidArgument);
220 }
221 
TEST_F(EciesHkdfX25519SendKemBoringSslTest,TestNewPubyNotEmpty)222 TEST_F(EciesHkdfX25519SendKemBoringSslTest, TestNewPubyNotEmpty) {
223   if (IsFipsModeEnabled()) {
224     GTEST_SKIP() << "Not supported in FIPS-only mode";
225   }
226   EllipticCurveType curve = EllipticCurveType::CURVE25519;
227   auto status_or_test_key = internal::NewEcKey(curve);
228   ASSERT_TRUE(status_or_test_key.ok());
229   auto test_key = status_or_test_key.value();
230   test_key.pub_y = test_key.pub_x;
231   auto status_or_sender_kem = EciesHkdfX25519SendKemBoringSsl::New(
232       curve, test_key.pub_x, test_key.pub_y);
233   EXPECT_EQ(status_or_sender_kem.status().code(),
234             absl::StatusCode::kInvalidArgument);
235 }
236 
TEST_F(EciesHkdfX25519SendKemBoringSslTest,TestGenerateKey)237 TEST_F(EciesHkdfX25519SendKemBoringSslTest, TestGenerateKey) {
238   if (IsFipsModeEnabled()) {
239     GTEST_SKIP() << "Not supported in FIPS-only mode";
240   }
241   EllipticCurveType curve = EllipticCurveType::CURVE25519;
242   auto status_or_test_key = internal::NewEcKey(curve);
243   ASSERT_TRUE(status_or_test_key.ok());
244   auto test_key = status_or_test_key.value();
245   auto status_or_sender_kem = EciesHkdfX25519SendKemBoringSsl::New(
246       curve, test_key.pub_x, test_key.pub_y);
247   ASSERT_TRUE(status_or_sender_kem.ok());
248   auto sender_kem = std::move(status_or_sender_kem.value());
249 
250   uint32_t key_size_in_bytes = 128;
251   auto status_or_kem_key =
252       sender_kem->GenerateKey(HashType::SHA256, "hkdf_salt", "hkdf_info",
253                               key_size_in_bytes, EcPointFormat::COMPRESSED);
254   ASSERT_TRUE(status_or_kem_key.ok());
255   auto kem_key = std::move(status_or_kem_key.value());
256   EXPECT_EQ(kem_key->get_kem_bytes().size(), internal::Ed25519KeyPubKeySize());
257   EXPECT_EQ(kem_key->get_symmetric_key().size(), key_size_in_bytes);
258 }
259 
TEST_F(EciesHkdfX25519SendKemBoringSslTest,TestGenerateKeyUncompressed)260 TEST_F(EciesHkdfX25519SendKemBoringSslTest, TestGenerateKeyUncompressed) {
261   if (IsFipsModeEnabled()) {
262     GTEST_SKIP() << "Not supported in FIPS-only mode";
263   }
264   EllipticCurveType curve = EllipticCurveType::CURVE25519;
265   auto status_or_test_key = internal::NewEcKey(curve);
266   ASSERT_TRUE(status_or_test_key.ok());
267   auto test_key = status_or_test_key.value();
268   auto status_or_sender_kem = EciesHkdfX25519SendKemBoringSsl::New(
269       curve, test_key.pub_x, test_key.pub_y);
270   ASSERT_TRUE(status_or_sender_kem.ok());
271   auto sender_kem = std::move(status_or_sender_kem.value());
272 
273   auto status_or_kem_key =
274       sender_kem->GenerateKey(HashType::SHA256, "hkdf_salt", "hkdf_info", 32,
275                               EcPointFormat::UNCOMPRESSED);
276   EXPECT_EQ(status_or_kem_key.status().code(),
277             absl::StatusCode::kInvalidArgument);
278 }
279 
280 // Tests for FIPS only mode
TEST_F(EciesHkdfNistPCurveSendKemBoringSslTest,TestFipsOnly)281 TEST_F(EciesHkdfNistPCurveSendKemBoringSslTest, TestFipsOnly) {
282   if (!IsFipsModeEnabled()) {
283     GTEST_SKIP() << "Only supported in FIPS-only mode";
284   }
285   EllipticCurveType curve = EllipticCurveType::NIST_P256;
286   auto status_or_test_key = internal::NewEcKey(curve);
287   auto test_key = status_or_test_key.value();
288 
289   EXPECT_THAT(EciesHkdfNistPCurveSendKemBoringSsl::New(curve, test_key.pub_x,
290                                                        test_key.pub_y)
291                   .status(),
292               StatusIs(absl::StatusCode::kInternal));
293 }
294 
TEST_F(EciesHkdfX25519SendKemBoringSslTest,TestFipsOnly)295 TEST_F(EciesHkdfX25519SendKemBoringSslTest, TestFipsOnly) {
296   if (!IsFipsModeEnabled()) {
297     GTEST_SKIP() << "Only supported in FIPS-only mode";
298   }
299   EllipticCurveType curve = EllipticCurveType::NIST_P256;
300   auto status_or_test_key = internal::NewEcKey(curve);
301   auto test_key = status_or_test_key.value();
302 
303   EXPECT_THAT(EciesHkdfX25519SendKemBoringSsl::New(curve, test_key.pub_x,
304                                                    test_key.pub_y)
305                   .status(),
306               StatusIs(absl::StatusCode::kInternal));
307 }
308 
309 }  // namespace
310 }  // namespace subtle
311 }  // namespace tink
312 }  // namespace crypto
313