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_recipient_kem_boringssl.h"
18
19 #include <string>
20 #include <utility>
21 #include <vector>
22
23 #include "gtest/gtest.h"
24 #include "absl/status/status.h"
25 #include "absl/strings/escaping.h"
26 #include "tink/config/tink_fips.h"
27 #include "tink/subtle/common_enums.h"
28 #include "tink/util/secret_data.h"
29 #include "tink/util/status.h"
30 #include "tink/util/statusor.h"
31 #include "tink/util/test_matchers.h"
32
33 namespace crypto {
34 namespace tink {
35 namespace subtle {
36 namespace {
37
38 using ::crypto::tink::test::StatusIs;
39
40 class EciesHkdfRecipientKemBoringSslTest : public ::testing::Test {};
41
42 struct TestVector {
43 EllipticCurveType curve;
44 HashType hash;
45 EcPointFormat point_format;
46 std::string pub_encoded_hex;
47 std::string priv_hex;
48 std::string salt_hex;
49 std::string info_hex;
50 int out_len;
51 std::string out_key_hex;
52 };
53
54 static const char kSaltHex[] = "0b0b0b0b";
55 static const char kInfoHex[] = "0b0b0b0b0b0b0b0b";
56
57 static const char kNistP256PublicValueHex[] =
58 "04700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287db71e509"
59 "e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac";
60 static const char kNistP256PrivateKeyHex[] =
61 "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534";
62 static const char kNistP256SharedKeyHex[] =
63 "0f19c0f322fc0a4b73b32bac6a66baa274de261db38a57f11ee4896ede24dbba";
64
65 static const char kX25519PublicValueHex[] =
66 "bef00c1a15e0601678ef4899a8506f751cd0c1f4d210a2852ac9d42151d0e160";
67 static const char kX25519PrivateKeyHex[] =
68 "df4320cecfd87a5a928355241c9d0e491be499cedf7b2b70687193124039eb92";
69 static const char kX25519SharedKeyHex[] =
70 "4c77c4d086e2d267052bad906f8c00092f8ea944fc1dc69eb2fe8bb29df400cc";
71
72 static const std::vector<TestVector> test_vector(
73 {{EllipticCurveType::NIST_P256, HashType::SHA256,
74 EcPointFormat::UNCOMPRESSED, kNistP256PublicValueHex,
75 kNistP256PrivateKeyHex, kSaltHex, kInfoHex, 32, kNistP256SharedKeyHex},
76 {EllipticCurveType::CURVE25519, HashType::SHA256,
77 EcPointFormat::COMPRESSED, kX25519PublicValueHex, kX25519PrivateKeyHex,
78 kSaltHex, kInfoHex, 32, kX25519SharedKeyHex}});
79
TEST_F(EciesHkdfRecipientKemBoringSslTest,TestBasic)80 TEST_F(EciesHkdfRecipientKemBoringSslTest, TestBasic) {
81 if (IsFipsModeEnabled()) {
82 GTEST_SKIP() << "Not supported in FIPS-only mode";
83 }
84 for (const TestVector& test : test_vector) {
85 auto ecies_kem_or = EciesHkdfRecipientKemBoringSsl::New(
86 test.curve,
87 util::SecretDataFromStringView(absl::HexStringToBytes(test.priv_hex)));
88 ASSERT_TRUE(ecies_kem_or.ok());
89 auto ecies_kem = std::move(ecies_kem_or).value();
90 auto kem_key_or = ecies_kem->GenerateKey(
91 absl::HexStringToBytes(test.pub_encoded_hex), test.hash,
92 absl::HexStringToBytes(test.salt_hex),
93 absl::HexStringToBytes(test.info_hex), test.out_len, test.point_format);
94 ASSERT_TRUE(kem_key_or.ok());
95 EXPECT_EQ(test.out_key_hex,
96 absl::BytesToHexString(
97 util::SecretDataAsStringView(kem_key_or.value())));
98 }
99 }
100
TEST_F(EciesHkdfRecipientKemBoringSslTest,TestNewUnimplementedCurve)101 TEST_F(EciesHkdfRecipientKemBoringSslTest, TestNewUnimplementedCurve) {
102 if (IsFipsModeEnabled()) {
103 GTEST_SKIP() << "Not supported in FIPS-only mode";
104 }
105 auto status_or_recipient_kem =
106 EciesHkdfRecipientKemBoringSsl::New(EllipticCurveType::UNKNOWN_CURVE, {});
107 EXPECT_EQ(status_or_recipient_kem.status().code(),
108 absl::StatusCode::kUnimplemented);
109 }
110
111 class EciesHkdfNistPCurveRecipientKemBoringSslTest : public ::testing::Test {};
112
TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest,TestNew)113 TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest, TestNew) {
114 if (IsFipsModeEnabled()) {
115 GTEST_SKIP() << "Not supported in FIPS-only mode";
116 }
117 auto status_or_recipient_kem = EciesHkdfNistPCurveRecipientKemBoringSsl::New(
118 EllipticCurveType::NIST_P256,
119 util::SecretDataFromStringView(
120 absl::HexStringToBytes(kNistP256PrivateKeyHex)));
121 ASSERT_TRUE(status_or_recipient_kem.ok());
122 }
123
TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest,TestNewInvalidCurve)124 TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest, TestNewInvalidCurve) {
125 if (IsFipsModeEnabled()) {
126 GTEST_SKIP() << "Not supported in FIPS-only mode";
127 }
128 auto status_or_recipient_kem = EciesHkdfNistPCurveRecipientKemBoringSsl::New(
129 EllipticCurveType::CURVE25519,
130 util::SecretDataFromStringView(
131 absl::HexStringToBytes(kNistP256PrivateKeyHex)));
132 EXPECT_EQ(status_or_recipient_kem.status().code(),
133 absl::StatusCode::kUnimplemented);
134 }
135
TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest,TestNewEmptyPrivateKey)136 TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest, TestNewEmptyPrivateKey) {
137 if (IsFipsModeEnabled()) {
138 GTEST_SKIP() << "Not supported in FIPS-only mode";
139 }
140 auto status_or_recipient_kem = EciesHkdfNistPCurveRecipientKemBoringSsl::New(
141 EllipticCurveType::CURVE25519, {});
142 EXPECT_EQ(status_or_recipient_kem.status().code(),
143 absl::StatusCode::kInvalidArgument);
144 }
145
TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest,TestGenerateKey)146 TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest, TestGenerateKey) {
147 if (IsFipsModeEnabled()) {
148 GTEST_SKIP() << "Not supported in FIPS-only mode";
149 }
150 auto status_or_recipient_kem = EciesHkdfNistPCurveRecipientKemBoringSsl::New(
151 EllipticCurveType::NIST_P256,
152 util::SecretDataFromStringView(
153 absl::HexStringToBytes(kNistP256PrivateKeyHex)));
154 ASSERT_TRUE(status_or_recipient_kem.ok());
155 auto recipient_kem = std::move(status_or_recipient_kem.value());
156
157 auto status_or_shared_key = recipient_kem->GenerateKey(
158 absl::HexStringToBytes(kNistP256PublicValueHex), HashType::SHA256,
159 absl::HexStringToBytes(kSaltHex), absl::HexStringToBytes(kInfoHex), 32,
160 EcPointFormat::UNCOMPRESSED);
161 ASSERT_TRUE(status_or_shared_key.ok());
162
163 EXPECT_EQ(absl::BytesToHexString(
164 util::SecretDataAsStringView(status_or_shared_key.value())),
165 kNistP256SharedKeyHex);
166 }
167
168 class EciesHkdfX25519RecipientKemBoringSslTest : public ::testing::Test {};
169
TEST_F(EciesHkdfX25519RecipientKemBoringSslTest,TestNew)170 TEST_F(EciesHkdfX25519RecipientKemBoringSslTest, TestNew) {
171 if (IsFipsModeEnabled()) {
172 GTEST_SKIP() << "Not supported in FIPS-only mode";
173 }
174 auto status_or_recipient_kem = EciesHkdfX25519RecipientKemBoringSsl::New(
175 EllipticCurveType::CURVE25519,
176 util::SecretDataFromStringView(
177 absl::HexStringToBytes(kX25519PrivateKeyHex)));
178 ASSERT_TRUE(status_or_recipient_kem.ok());
179 }
180
TEST_F(EciesHkdfX25519RecipientKemBoringSslTest,TestNewInvalidCurve)181 TEST_F(EciesHkdfX25519RecipientKemBoringSslTest, TestNewInvalidCurve) {
182 if (IsFipsModeEnabled()) {
183 GTEST_SKIP() << "Not supported in FIPS-only mode";
184 }
185 auto status_or_recipient_kem = EciesHkdfX25519RecipientKemBoringSsl::New(
186 EllipticCurveType::NIST_P256,
187 util::SecretDataFromStringView(
188 absl::HexStringToBytes(kX25519PrivateKeyHex)));
189 EXPECT_EQ(status_or_recipient_kem.status().code(),
190 absl::StatusCode::kInvalidArgument);
191 }
192
TEST_F(EciesHkdfX25519RecipientKemBoringSslTest,TestNewShortKey)193 TEST_F(EciesHkdfX25519RecipientKemBoringSslTest, TestNewShortKey) {
194 if (IsFipsModeEnabled()) {
195 GTEST_SKIP() << "Not supported in FIPS-only mode";
196 }
197 util::SecretData private_key = util::SecretDataFromStringView(
198 absl::HexStringToBytes(kX25519PrivateKeyHex));
199 private_key.resize(private_key.size() / 2);
200 auto status_or_recipient_kem = EciesHkdfX25519RecipientKemBoringSsl::New(
201 EllipticCurveType::CURVE25519, private_key);
202 EXPECT_EQ(status_or_recipient_kem.status().code(),
203 absl::StatusCode::kInvalidArgument);
204 }
205
206 // Tests for FIPS only mode
TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest,TestFipsOnly)207 TEST_F(EciesHkdfNistPCurveRecipientKemBoringSslTest, TestFipsOnly) {
208 if (!IsFipsModeEnabled()) {
209 GTEST_SKIP() << "Only supported in FIPS-only mode";
210 }
211 util::SecretData private_key = util::SecretDataFromStringView(
212 absl::HexStringToBytes(kNistP256PrivateKeyHex));
213 EXPECT_THAT(EciesHkdfRecipientKemBoringSsl::New(EllipticCurveType::NIST_P256,
214 private_key)
215 .status(),
216 StatusIs(absl::StatusCode::kInternal));
217 }
218
TEST_F(EciesHkdfX25519RecipientKemBoringSslTest,TestFipsOnly)219 TEST_F(EciesHkdfX25519RecipientKemBoringSslTest, TestFipsOnly) {
220 if (!IsFipsModeEnabled()) {
221 GTEST_SKIP() << "Only supported in FIPS-only mode";
222 }
223 util::SecretData private_key = util::SecretDataFromStringView(
224 absl::HexStringToBytes(kX25519PrivateKeyHex));
225 EXPECT_THAT(EciesHkdfX25519RecipientKemBoringSsl::New(
226 EllipticCurveType::CURVE25519, private_key)
227 .status(),
228 StatusIs(absl::StatusCode::kInternal));
229 }
230
231 } // namespace
232 } // namespace subtle
233 } // namespace tink
234 } // namespace crypto
235