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/signature/subtle/sphincs_sign.h"
18
19 #include <memory>
20 #include <string>
21 #include <utility>
22
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "absl/status/status.h"
26 #include "absl/strings/str_cat.h"
27 #include "tink/config/tink_fips.h"
28 #include "tink/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h"
29 #include "tink/public_key_sign.h"
30 #include "tink/public_key_verify.h"
31 #include "tink/util/status.h"
32 #include "tink/util/statusor.h"
33 #include "tink/util/test_matchers.h"
34
35 extern "C" {
36 #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-robust/api.h"
37 #include "third_party/pqclean/crypto_sign/sphincs-haraka-128f-simple/api.h"
38 #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-robust/api.h"
39 #include "third_party/pqclean/crypto_sign/sphincs-haraka-128s-simple/api.h"
40 #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-robust/api.h"
41 #include "third_party/pqclean/crypto_sign/sphincs-haraka-192f-simple/api.h"
42 #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-robust/api.h"
43 #include "third_party/pqclean/crypto_sign/sphincs-haraka-192s-simple/api.h"
44 #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-robust/api.h"
45 #include "third_party/pqclean/crypto_sign/sphincs-haraka-256f-simple/api.h"
46 #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-robust/api.h"
47 #include "third_party/pqclean/crypto_sign/sphincs-haraka-256s-simple/api.h"
48 #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-robust/api.h"
49 #include "third_party/pqclean/crypto_sign/sphincs-sha256-128f-simple/api.h"
50 #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-robust/api.h"
51 #include "third_party/pqclean/crypto_sign/sphincs-sha256-128s-simple/api.h"
52 #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-robust/api.h"
53 #include "third_party/pqclean/crypto_sign/sphincs-sha256-192f-simple/api.h"
54 #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-robust/api.h"
55 #include "third_party/pqclean/crypto_sign/sphincs-sha256-192s-simple/api.h"
56 #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-robust/api.h"
57 #include "third_party/pqclean/crypto_sign/sphincs-sha256-256f-simple/api.h"
58 #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-robust/api.h"
59 #include "third_party/pqclean/crypto_sign/sphincs-sha256-256s-simple/api.h"
60 #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-robust/api.h"
61 #include "third_party/pqclean/crypto_sign/sphincs-shake256-128f-simple/api.h"
62 #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-robust/api.h"
63 #include "third_party/pqclean/crypto_sign/sphincs-shake256-128s-simple/api.h"
64 #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-robust/api.h"
65 #include "third_party/pqclean/crypto_sign/sphincs-shake256-192f-simple/api.h"
66 #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-robust/api.h"
67 #include "third_party/pqclean/crypto_sign/sphincs-shake256-192s-simple/api.h"
68 #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-robust/api.h"
69 #include "third_party/pqclean/crypto_sign/sphincs-shake256-256f-simple/api.h"
70 #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-robust/api.h"
71 #include "third_party/pqclean/crypto_sign/sphincs-shake256-256s-simple/api.h"
72 }
73
74 namespace crypto {
75 namespace tink {
76 namespace subtle {
77
78 namespace {
79
80 struct SphincsTestCase {
81 std::string test_name;
82 SphincsHashType hash_type;
83 SphincsVariant variant;
84 SphincsSignatureType sig_length_type;
85 int32_t private_key_size;
86 int32_t signature_length;
87 };
88
89 using ::crypto::tink::test::IsOk;
90 using ::crypto::tink::test::StatusIs;
91 using crypto::tink::util::Status;
92
93 using SphincsSignTest = testing::TestWithParam<SphincsTestCase>;
94
TEST_P(SphincsSignTest,SignatureLength)95 TEST_P(SphincsSignTest, SignatureLength) {
96 if (IsFipsModeEnabled()) {
97 GTEST_SKIP() << "Test assumes kOnlyUseFips is false.";
98 }
99
100 const SphincsTestCase& test_case = GetParam();
101
102 SphincsParamsPqclean params = {
103 .hash_type = test_case.hash_type,
104 .variant = test_case.variant,
105 .sig_length_type = test_case.sig_length_type,
106 .private_key_size = test_case.private_key_size,
107 };
108
109 // Generate sphincs key pair.
110 util::StatusOr<SphincsKeyPair> key_pair = GenerateSphincsKeyPair(params);
111 ASSERT_THAT(key_pair, IsOk());
112
113 // Create a new signer.
114 util::StatusOr<std::unique_ptr<PublicKeySign>> signer =
115 SphincsSign::New(key_pair->GetPrivateKey());
116 ASSERT_THAT(signer, IsOk());
117
118 // Sign a message.
119 std::string message = "message to be signed";
120 util::StatusOr<std::string> signature = (*signer)->Sign(message);
121 ASSERT_THAT(signature, IsOk());
122
123 // Check signature size.
124 EXPECT_NE(*signature, message);
125 EXPECT_EQ((*signature).size(), test_case.signature_length);
126 }
127
TEST_P(SphincsSignTest,NonDeterminism)128 TEST_P(SphincsSignTest, NonDeterminism) {
129 if (IsFipsModeEnabled()) {
130 GTEST_SKIP() << "Test assumes kOnlyUseFips is false.";
131 }
132
133 const SphincsTestCase& test_case = GetParam();
134
135 SphincsParamsPqclean params = {
136 .hash_type = test_case.hash_type,
137 .variant = test_case.variant,
138 .sig_length_type = test_case.sig_length_type,
139 .private_key_size = test_case.private_key_size,
140 };
141
142 // Generate sphincs key pair.
143 util::StatusOr<SphincsKeyPair> key_pair = GenerateSphincsKeyPair(params);
144 ASSERT_THAT(key_pair, IsOk());
145
146 // Create two signers based on same private key.
147 util::StatusOr<std::unique_ptr<PublicKeySign>> first_signer =
148 SphincsSign::New(key_pair->GetPrivateKey());
149 ASSERT_THAT(first_signer, IsOk());
150
151 util::StatusOr<std::unique_ptr<PublicKeySign>> second_signer =
152 SphincsSign::New(key_pair->GetPrivateKey());
153 ASSERT_THAT(second_signer, IsOk());
154
155 // Sign the same message twice, using the same private key.
156 std::string message = "message to be signed";
157 util::StatusOr<std::string> first_signature = (*first_signer)->Sign(message);
158 ASSERT_THAT(first_signature, IsOk());
159
160 util::StatusOr<std::string> second_signature =
161 (*second_signer)->Sign(message);
162 ASSERT_THAT(second_signature, IsOk());
163
164 // Check signatures size.
165 EXPECT_NE(*first_signature, message);
166 EXPECT_EQ((*first_signature).size(), test_case.signature_length);
167
168 EXPECT_NE(*second_signature, message);
169 EXPECT_EQ((*second_signature).size(), test_case.signature_length);
170
171 // Check if signatures are equal.
172 EXPECT_NE(*first_signature, *second_signature);
173 }
174
TEST_P(SphincsSignTest,FipsMode)175 TEST_P(SphincsSignTest, FipsMode) {
176 if (!IsFipsModeEnabled()) {
177 GTEST_SKIP() << "Test assumes kOnlyUseFips.";
178 }
179
180 const SphincsTestCase& test_case = GetParam();
181
182 SphincsParamsPqclean params = {
183 .hash_type = test_case.hash_type,
184 .variant = test_case.variant,
185 .sig_length_type = test_case.sig_length_type,
186 .private_key_size = test_case.private_key_size,
187 };
188
189 // Generate sphincs key pair.
190 util::StatusOr<SphincsKeyPair> key_pair = GenerateSphincsKeyPair(params);
191 ASSERT_THAT(key_pair, IsOk());
192
193 // Create a new signer.
194 EXPECT_THAT(SphincsSign::New(key_pair->GetPrivateKey()).status(),
195 StatusIs(absl::StatusCode::kInternal));
196 }
197
198 INSTANTIATE_TEST_SUITE_P(
199 SphincsSignTests, SphincsSignTest,
200 testing::ValuesIn<SphincsTestCase>(
201 {{"SPHINCSHARAKA128FROBUST", SphincsHashType::HARAKA,
202 SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING,
203 PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_SECRETKEYBYTES,
204 PQCLEAN_SPHINCSHARAKA128FROBUST_CRYPTO_BYTES},
205 {"SPHINCSHARAKA128SROBUST", SphincsHashType::HARAKA,
206 SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE,
207 PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_SECRETKEYBYTES,
208 PQCLEAN_SPHINCSHARAKA128SROBUST_CRYPTO_BYTES},
209 {"SPHINCSHARAKA128FSIMPLE", SphincsHashType::HARAKA,
210 SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING,
211 PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_SECRETKEYBYTES,
212 PQCLEAN_SPHINCSHARAKA128FSIMPLE_CRYPTO_BYTES},
213 {"SPHINCSHARAKA128SSIMPLE", SphincsHashType::HARAKA,
214 SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE,
215 PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_SECRETKEYBYTES,
216 PQCLEAN_SPHINCSHARAKA128SSIMPLE_CRYPTO_BYTES},
217
218 {"SPHINCSHARAKA192FROBUST", SphincsHashType::HARAKA,
219 SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING,
220 PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_SECRETKEYBYTES,
221 PQCLEAN_SPHINCSHARAKA192FROBUST_CRYPTO_BYTES},
222 {"SPHINCSHARAKA192SROBUST", SphincsHashType::HARAKA,
223 SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE,
224 PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_SECRETKEYBYTES,
225 PQCLEAN_SPHINCSHARAKA192SROBUST_CRYPTO_BYTES},
226 {"SPHINCSHARAKA192FSIMPLE", SphincsHashType::HARAKA,
227 SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING,
228 PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_SECRETKEYBYTES,
229 PQCLEAN_SPHINCSHARAKA192FSIMPLE_CRYPTO_BYTES},
230 {"SPHINCSHARAKA192SSIMPLE", SphincsHashType::HARAKA,
231 SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE,
232 PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_SECRETKEYBYTES,
233 PQCLEAN_SPHINCSHARAKA192SSIMPLE_CRYPTO_BYTES},
234
235 {"SPHINCSHARAKA256FROBUST", SphincsHashType::HARAKA,
236 SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING,
237 PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_SECRETKEYBYTES,
238 PQCLEAN_SPHINCSHARAKA256FROBUST_CRYPTO_BYTES},
239 {"SPHINCSHARAKA256SROBUST", SphincsHashType::HARAKA,
240 SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE,
241 PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_SECRETKEYBYTES,
242 PQCLEAN_SPHINCSHARAKA256SROBUST_CRYPTO_BYTES},
243 {"SPHINCSHARAKA256FSIMPLE", SphincsHashType::HARAKA,
244 SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING,
245 PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_SECRETKEYBYTES,
246 PQCLEAN_SPHINCSHARAKA256FSIMPLE_CRYPTO_BYTES},
247 {"SPHINCSHARAKA256SSIMPLE", SphincsHashType::HARAKA,
248 SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE,
249 PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_SECRETKEYBYTES,
250 PQCLEAN_SPHINCSHARAKA256SSIMPLE_CRYPTO_BYTES},
251
252 {"SPHINCSSHA256128FROBUST", SphincsHashType::SHA256,
253 SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING,
254 PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_SECRETKEYBYTES,
255 PQCLEAN_SPHINCSSHA256128FROBUST_CRYPTO_BYTES},
256 {"SPHINCSSHA256128SROBUST", SphincsHashType::SHA256,
257 SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE,
258 PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_SECRETKEYBYTES,
259 PQCLEAN_SPHINCSSHA256128SROBUST_CRYPTO_BYTES},
260 {"SPHINCSSHA256128FSIMPLE", SphincsHashType::SHA256,
261 SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING,
262 PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_SECRETKEYBYTES,
263 PQCLEAN_SPHINCSSHA256128FSIMPLE_CRYPTO_BYTES},
264 {"SPHINCSSHA256128SSIMPLE", SphincsHashType::SHA256,
265 SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE,
266 PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_SECRETKEYBYTES,
267 PQCLEAN_SPHINCSSHA256128SSIMPLE_CRYPTO_BYTES},
268
269 {"SPHINCSSHA256192FROBUST", SphincsHashType::SHA256,
270 SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING,
271 PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_SECRETKEYBYTES,
272 PQCLEAN_SPHINCSSHA256192FROBUST_CRYPTO_BYTES},
273 {"SPHINCSSHA256192SROBUST", SphincsHashType::SHA256,
274 SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE,
275 PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_SECRETKEYBYTES,
276 PQCLEAN_SPHINCSSHA256192SROBUST_CRYPTO_BYTES},
277 {"SPHINCSSHA256192FSIMPLE", SphincsHashType::SHA256,
278 SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING,
279 PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_SECRETKEYBYTES,
280 PQCLEAN_SPHINCSSHA256192FSIMPLE_CRYPTO_BYTES},
281 {"SPHINCSSHA256192SSIMPLE", SphincsHashType::SHA256,
282 SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE,
283 PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_SECRETKEYBYTES,
284 PQCLEAN_SPHINCSSHA256192SSIMPLE_CRYPTO_BYTES},
285
286 {"SPHINCSSHA256256FROBUST", SphincsHashType::SHA256,
287 SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING,
288 PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_SECRETKEYBYTES,
289 PQCLEAN_SPHINCSSHA256256FROBUST_CRYPTO_BYTES},
290 {"SPHINCSSHA256256SROBUST", SphincsHashType::SHA256,
291 SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE,
292 PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_SECRETKEYBYTES,
293 PQCLEAN_SPHINCSSHA256256SROBUST_CRYPTO_BYTES},
294 {"SPHINCSSHA256256FSIMPLE", SphincsHashType::SHA256,
295 SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING,
296 PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_SECRETKEYBYTES,
297 PQCLEAN_SPHINCSSHA256256FSIMPLE_CRYPTO_BYTES},
298 {"SPHINCSSHA256256SSIMPLE", SphincsHashType::SHA256,
299 SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE,
300 PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_SECRETKEYBYTES,
301 PQCLEAN_SPHINCSSHA256256SSIMPLE_CRYPTO_BYTES},
302
303 {"SPHINCSSHAKE256128FROBUST", SphincsHashType::SHAKE256,
304 SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING,
305 PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_SECRETKEYBYTES,
306 PQCLEAN_SPHINCSSHAKE256128FROBUST_CRYPTO_BYTES},
307 {"SPHINCSSHAKE256128SROBUST", SphincsHashType::SHAKE256,
308 SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE,
309 PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_SECRETKEYBYTES,
310 PQCLEAN_SPHINCSSHAKE256128SROBUST_CRYPTO_BYTES},
311 {"SPHINCSSHAKE256128FSIMPLE", SphincsHashType::SHAKE256,
312 SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING,
313 PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_SECRETKEYBYTES,
314 PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CRYPTO_BYTES},
315 {"SPHINCSSHAKE256128SSIMPLE", SphincsHashType::SHAKE256,
316 SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE,
317 PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_SECRETKEYBYTES,
318 PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CRYPTO_BYTES},
319
320 {"SPHINCSSHAKE256192FROBUST", SphincsHashType::SHAKE256,
321 SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING,
322 PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_SECRETKEYBYTES,
323 PQCLEAN_SPHINCSSHAKE256192FROBUST_CRYPTO_BYTES},
324 {"SPHINCSSHAKE256192SROBUST", SphincsHashType::SHAKE256,
325 SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE,
326 PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_SECRETKEYBYTES,
327 PQCLEAN_SPHINCSSHAKE256192SROBUST_CRYPTO_BYTES},
328 {"SPHINCSSHAKE256192FSIMPLE", SphincsHashType::SHAKE256,
329 SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING,
330 PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_SECRETKEYBYTES,
331 PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CRYPTO_BYTES},
332 {"SPHINCSSHAKE256192SSIMPLE", SphincsHashType::SHAKE256,
333 SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE,
334 PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_SECRETKEYBYTES,
335 PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CRYPTO_BYTES},
336
337 {"SPHINCSSHAKE256256FROBUST", SphincsHashType::SHAKE256,
338 SphincsVariant::ROBUST, SphincsSignatureType::FAST_SIGNING,
339 PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_SECRETKEYBYTES,
340 PQCLEAN_SPHINCSSHAKE256256FROBUST_CRYPTO_BYTES},
341 {"SPHINCSSHAKE256256SROBUST", SphincsHashType::SHAKE256,
342 SphincsVariant::ROBUST, SphincsSignatureType::SMALL_SIGNATURE,
343 PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_SECRETKEYBYTES,
344 PQCLEAN_SPHINCSSHAKE256256SROBUST_CRYPTO_BYTES},
345 {"SPHINCSSHAKE256256FSIMPLE", SphincsHashType::SHAKE256,
346 SphincsVariant::SIMPLE, SphincsSignatureType::FAST_SIGNING,
347 PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_SECRETKEYBYTES,
348 PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CRYPTO_BYTES},
349 {"SPHINCSSHAKE256256SSIMPLE", SphincsHashType::SHAKE256,
350 SphincsVariant::SIMPLE, SphincsSignatureType::SMALL_SIGNATURE,
351 PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_SECRETKEYBYTES,
352 PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CRYPTO_BYTES}}),
__anon8e7c5ca90202(const testing::TestParamInfo<SphincsSignTest::ParamType>& info) 353 [](const testing::TestParamInfo<SphincsSignTest::ParamType>& info) {
354 return info.param.test_name;
355 });
356
357 } // namespace
358
359 } // namespace subtle
360 } // namespace tink
361 } // namespace crypto
362