1 // Copyright 2023 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 // https://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 #include "anonymous_tokens/cpp/crypto/crypto_utils.h"
16
17 #include <stddef.h>
18 #include <stdint.h>
19
20 #include <cstdint>
21 #include <iterator>
22 #include <memory>
23 #include <string>
24 #include <utility>
25 #include <vector>
26
27 #include "absl/status/status.h"
28 #include "absl/status/statusor.h"
29 #include "absl/strings/str_cat.h"
30 #include "absl/strings/string_view.h"
31 #include "anonymous_tokens/cpp/crypto/constants.h"
32 #include "anonymous_tokens/cpp/shared/status_utils.h"
33 #include <openssl/bytestring.h>
34 #include <openssl/err.h>
35 #include <openssl/hkdf.h>
36 #include <openssl/mem.h>
37 #include <openssl/rand.h>
38 #include <openssl/rsa.h>
39
40 namespace anonymous_tokens {
41
42 namespace internal {
43
44 // Approximation of sqrt(2) taken from
45 // //depot/google3/third_party/openssl/boringssl/src/crypto/fipsmodule/rsa/rsa_impl.c;l=997
46 constexpr uint32_t kBoringSSLRSASqrtTwo[] = {
47 0x4d7c60a5, 0xe633e3e1, 0x5fcf8f7b, 0xca3ea33b, 0xc246785e, 0x92957023,
48 0xf9acce41, 0x797f2805, 0xfdfe170f, 0xd3b1f780, 0xd24f4a76, 0x3facb882,
49 0x18838a2e, 0xaff5f3b2, 0xc1fcbdde, 0xa2f7dc33, 0xdea06241, 0xf7aa81c2,
50 0xf6a1be3f, 0xca221307, 0x332a5e9f, 0x7bda1ebf, 0x0104dc01, 0xfe32352f,
51 0xb8cf341b, 0x6f8236c7, 0x4264dabc, 0xd528b651, 0xf4d3a02c, 0xebc93e0c,
52 0x81394ab6, 0xd8fd0efd, 0xeaa4a089, 0x9040ca4a, 0xf52f120f, 0x836e582e,
53 0xcb2a6343, 0x31f3c84d, 0xc6d5a8a3, 0x8bb7e9dc, 0x460abc72, 0x2f7c4e33,
54 0xcab1bc91, 0x1688458a, 0x53059c60, 0x11bc337b, 0xd2202e87, 0x42af1f4e,
55 0x78048736, 0x3dfa2768, 0x0f74a85e, 0x439c7b4a, 0xa8b1fe6f, 0xdc83db39,
56 0x4afc8304, 0x3ab8a2c3, 0xed17ac85, 0x83339915, 0x1d6f60ba, 0x893ba84c,
57 0x597d89b3, 0x754abe9f, 0xb504f333, 0xf9de6484,
58 };
59
PublicMetadataHashWithHKDF(absl::string_view public_metadata,absl::string_view rsa_modulus_str,size_t out_len_bytes)60 absl::StatusOr<bssl::UniquePtr<BIGNUM>> PublicMetadataHashWithHKDF(
61 absl::string_view public_metadata, absl::string_view rsa_modulus_str,
62 size_t out_len_bytes) {
63 const EVP_MD* evp_md_sha_384 = EVP_sha384();
64 // Prepend "key" to input.
65 std::string modified_input = absl::StrCat("key", public_metadata);
66 std::vector<uint8_t> input_buffer(modified_input.begin(),
67 modified_input.end());
68 // Append 0x00 to input.
69 input_buffer.push_back(0x00);
70 std::string out_e;
71 // We set the out_e size beyond out_len_bytes so that out_e bytes are
72 // indifferentiable from truly random bytes even after truncations.
73 //
74 // Expanding to 16 more bytes is sufficient.
75 // https://cfrg.github.io/draft-irtf-cfrg-hash-to-curve/draft-irtf-cfrg-hash-to-curve.html#name-hashing-to-a-finite-field
76 const size_t hkdf_output_size = out_len_bytes + 16;
77 out_e.resize(hkdf_output_size);
78 // The modulus is used as salt to ensure different outputs for same metadata
79 // and different modulus.
80 if (HKDF(reinterpret_cast<uint8_t*>(out_e.data()), hkdf_output_size,
81 evp_md_sha_384, input_buffer.data(), input_buffer.size(),
82 reinterpret_cast<const uint8_t*>(rsa_modulus_str.data()),
83 rsa_modulus_str.size(),
84 reinterpret_cast<const uint8_t*>(kHkdfPublicMetadataInfo.data()),
85 kHkdfPublicMetadataInfoSizeInBytes) != kBsslSuccess) {
86 return absl::InternalError("HKDF failed in public_metadata_crypto_utils");
87 }
88 // Truncate out_e to out_len_bytes
89 out_e.resize(out_len_bytes);
90 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> out,
91 StringToBignum(out_e));
92 return out;
93 }
94
95 } // namespace internal
96
97 namespace {
98
99 // Marshals an RSA public key in the DER format.
MarshalRsaPublicKey(const RSA * rsa)100 absl::StatusOr<std::string> MarshalRsaPublicKey(const RSA* rsa) {
101 uint8_t* rsa_public_key_bytes;
102 size_t rsa_public_key_bytes_len = 0;
103 if (!RSA_public_key_to_bytes(&rsa_public_key_bytes, &rsa_public_key_bytes_len,
104 rsa)) {
105 return absl::InvalidArgumentError(absl::StrCat(
106 "Failed to marshall rsa public key to a DER encoded RSAPublicKey "
107 "structure (RFC 8017): ",
108 GetSslErrors()));
109 }
110 std::string rsa_public_key_str(reinterpret_cast<char*>(rsa_public_key_bytes),
111 rsa_public_key_bytes_len);
112 OPENSSL_free(rsa_public_key_bytes);
113 return rsa_public_key_str;
114 }
115
116 } // namespace
117
GetAndStartBigNumCtx()118 absl::StatusOr<BnCtxPtr> GetAndStartBigNumCtx() {
119 // Create context to be used in intermediate computation.
120 BnCtxPtr bn_ctx = BnCtxPtr(BN_CTX_new());
121 if (!bn_ctx.get()) {
122 return absl::InternalError("Error generating bignum context.");
123 }
124 BN_CTX_start(bn_ctx.get());
125
126 return bn_ctx;
127 }
128
NewBigNum()129 absl::StatusOr<bssl::UniquePtr<BIGNUM>> NewBigNum() {
130 bssl::UniquePtr<BIGNUM> bn(BN_new());
131 if (!bn.get()) {
132 return absl::InternalError("Error generating bignum.");
133 }
134 return bn;
135 }
136
BignumToString(const BIGNUM & big_num,const size_t output_len)137 absl::StatusOr<std::string> BignumToString(const BIGNUM& big_num,
138 const size_t output_len) {
139 std::vector<uint8_t> serialization(output_len);
140 if (BN_bn2bin_padded(serialization.data(), serialization.size(), &big_num) !=
141 kBsslSuccess) {
142 return absl::InternalError(
143 absl::StrCat("Function BN_bn2bin_padded failed: ", GetSslErrors()));
144 }
145 return std::string(std::make_move_iterator(serialization.begin()),
146 std::make_move_iterator(serialization.end()));
147 }
148
StringToBignum(const absl::string_view input_str)149 absl::StatusOr<bssl::UniquePtr<BIGNUM>> StringToBignum(
150 const absl::string_view input_str) {
151 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> output, NewBigNum());
152 if (!BN_bin2bn(reinterpret_cast<const uint8_t*>(input_str.data()),
153 input_str.size(), output.get())) {
154 return absl::InternalError(
155 absl::StrCat("Function BN_bin2bn failed: ", GetSslErrors()));
156 }
157 if (!output.get()) {
158 return absl::InternalError("Function BN_bin2bn failed.");
159 }
160 return output;
161 }
162
GetSslErrors()163 std::string GetSslErrors() {
164 std::string ret;
165 ERR_print_errors_cb(
166 [](const char* str, size_t len, void* ctx) -> int {
167 static_cast<std::string*>(ctx)->append(str, len);
168 return 1;
169 },
170 &ret);
171 return ret;
172 }
173
MaskMessageConcat(absl::string_view mask,absl::string_view message)174 std::string MaskMessageConcat(absl::string_view mask,
175 absl::string_view message) {
176 return absl::StrCat(mask, message);
177 }
178
EncodeMessagePublicMetadata(absl::string_view message,absl::string_view public_metadata)179 std::string EncodeMessagePublicMetadata(absl::string_view message,
180 absl::string_view public_metadata) {
181 // Prepend encoding of "msg" followed by 4 bytes representing public metadata
182 // length.
183 std::string tag = "msg";
184 std::vector<uint8_t> buffer(tag.begin(), tag.end());
185 buffer.push_back((public_metadata.size() >> 24) & 0xFF);
186 buffer.push_back((public_metadata.size() >> 16) & 0xFF);
187 buffer.push_back((public_metadata.size() >> 8) & 0xFF);
188 buffer.push_back((public_metadata.size() >> 0) & 0xFF);
189
190 // Finally append public metadata and then the message to the output.
191 std::string encoding(buffer.begin(), buffer.end());
192 return absl::StrCat(encoding, public_metadata, message);
193 }
194
GetRsaSqrtTwo(int x)195 absl::StatusOr<bssl::UniquePtr<BIGNUM>> GetRsaSqrtTwo(int x) {
196 // Compute hard-coded sqrt(2).
197 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> sqrt2, NewBigNum());
198 const int sqrt2_size = sizeof(internal::kBoringSSLRSASqrtTwo) /
199 sizeof(*internal::kBoringSSLRSASqrtTwo);
200 for (int i = sqrt2_size - 2; i >= 0; i = i - 2) {
201 // Add the uint32_t values as words directly and shift.
202 // 'i' is the "hi" value of a uint64_t, and 'i+1' is the "lo" value.
203 if (BN_add_word(sqrt2.get(), internal::kBoringSSLRSASqrtTwo[i]) != 1) {
204 return absl::InternalError(absl::StrCat(
205 "Cannot add word to compute RSA sqrt(2): ", GetSslErrors()));
206 }
207 if (BN_lshift(sqrt2.get(), sqrt2.get(), 32) != 1) {
208 return absl::InternalError(absl::StrCat(
209 "Cannot shift to compute RSA sqrt(2): ", GetSslErrors()));
210 }
211 if (BN_add_word(sqrt2.get(), internal::kBoringSSLRSASqrtTwo[i + 1]) != 1) {
212 return absl::InternalError(absl::StrCat(
213 "Cannot add word to compute RSA sqrt(2): ", GetSslErrors()));
214 }
215 if (i > 0) {
216 if (BN_lshift(sqrt2.get(), sqrt2.get(), 32) != 1) {
217 return absl::InternalError(absl::StrCat(
218 "Cannot shift to compute RSA sqrt(2): ", GetSslErrors()));
219 }
220 }
221 }
222
223 // Check that hard-coded result is correct length.
224 int sqrt2_bits = 32 * sqrt2_size;
225 if (BN_num_bits(sqrt2.get()) != static_cast<unsigned int>(sqrt2_bits)) {
226 return absl::InternalError("RSA sqrt(2) is not correct length.");
227 }
228
229 // Either shift left or right depending on value x.
230 if (sqrt2_bits > x) {
231 if (BN_rshift(sqrt2.get(), sqrt2.get(), sqrt2_bits - x) != 1) {
232 return absl::InternalError(
233 absl::StrCat("Cannot rshift to compute 2^(x-1/2): ", GetSslErrors()));
234 }
235 } else {
236 // Round up and be pessimistic about minimium factors.
237 if (BN_add_word(sqrt2.get(), 1) != 1 ||
238 BN_lshift(sqrt2.get(), sqrt2.get(), x - sqrt2_bits) != 1) {
239 return absl::InternalError(absl::StrCat(
240 "Cannot add/lshift to compute 2^(x-1/2): ", GetSslErrors()));
241 }
242 }
243
244 // Check that 2^(x - 1/2) is correct length.
245 if (BN_num_bits(sqrt2.get()) != static_cast<unsigned int>(x)) {
246 return absl::InternalError(
247 "2^(x-1/2) is not correct length after shifting.");
248 }
249
250 return std::move(sqrt2);
251 }
252
ComputePowerOfTwo(int x)253 absl::StatusOr<bssl::UniquePtr<BIGNUM>> ComputePowerOfTwo(int x) {
254 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> ret, NewBigNum());
255 if (BN_set_bit(ret.get(), x) != 1) {
256 return absl::InternalError(
257 absl::StrCat("Unable to set bit to compute 2^x: ", GetSslErrors()));
258 }
259 if (!BN_is_pow2(ret.get()) || !BN_is_bit_set(ret.get(), x)) {
260 return absl::InternalError(absl::StrCat("Unable to compute 2^", x, "."));
261 }
262 return ret;
263 }
264
ComputeHash(absl::string_view input,const EVP_MD & hasher)265 absl::StatusOr<std::string> ComputeHash(absl::string_view input,
266 const EVP_MD& hasher) {
267 std::string digest;
268 digest.resize(EVP_MAX_MD_SIZE);
269
270 uint32_t digest_length = 0;
271 if (EVP_Digest(input.data(), input.length(),
272 reinterpret_cast<uint8_t*>(&digest[0]), &digest_length,
273 &hasher, /*impl=*/nullptr) != 1) {
274 return absl::InternalError(absl::StrCat(
275 "Openssl internal error computing hash: ", GetSslErrors()));
276 }
277 digest.resize(digest_length);
278 return digest;
279 }
280
CreatePrivateKeyRSA(const absl::string_view rsa_modulus,const absl::string_view public_exponent,const absl::string_view private_exponent,const absl::string_view p,const absl::string_view q,const absl::string_view dp,const absl::string_view dq,const absl::string_view crt)281 absl::StatusOr<bssl::UniquePtr<RSA>> CreatePrivateKeyRSA(
282 const absl::string_view rsa_modulus,
283 const absl::string_view public_exponent,
284 const absl::string_view private_exponent, const absl::string_view p,
285 const absl::string_view q, const absl::string_view dp,
286 const absl::string_view dq, const absl::string_view crt) {
287 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> n_bn,
288 StringToBignum(rsa_modulus));
289 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> e_bn,
290 StringToBignum(public_exponent));
291 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> d_bn,
292 StringToBignum(private_exponent));
293 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> p_bn, StringToBignum(p));
294 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> q_bn, StringToBignum(q));
295 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> dp_bn,
296 StringToBignum(dp));
297 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> dq_bn,
298 StringToBignum(dq));
299 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> crt_bn,
300 StringToBignum(crt));
301
302 bssl::UniquePtr<RSA> rsa_private_key(
303 RSA_new_private_key(n_bn.get(), e_bn.get(), d_bn.get(), p_bn.get(),
304 q_bn.get(), dp_bn.get(), dq_bn.get(), crt_bn.get()));
305 if (!rsa_private_key.get()) {
306 return absl::InternalError(
307 absl::StrCat("RSA_new_private_key failed: ", GetSslErrors()));
308 }
309 return rsa_private_key;
310 }
311
CreatePublicKeyRSA(const absl::string_view rsa_modulus,const absl::string_view public_exponent)312 absl::StatusOr<bssl::UniquePtr<RSA>> CreatePublicKeyRSA(
313 const absl::string_view rsa_modulus,
314 const absl::string_view public_exponent) {
315 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> n_bn,
316 StringToBignum(rsa_modulus));
317 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> e_bn,
318 StringToBignum(public_exponent));
319 // Convert to OpenSSL RSA.
320 bssl::UniquePtr<RSA> rsa_public_key(
321 RSA_new_public_key(n_bn.get(), e_bn.get()));
322 if (!rsa_public_key.get()) {
323 return absl::InternalError(
324 absl::StrCat("RSA_new_public_key failed: ", GetSslErrors()));
325 }
326 return rsa_public_key;
327 }
328
CreatePublicKeyRSAWithPublicMetadata(const BIGNUM & rsa_modulus,const BIGNUM & public_exponent,absl::string_view public_metadata,const bool use_rsa_public_exponent)329 absl::StatusOr<bssl::UniquePtr<RSA>> CreatePublicKeyRSAWithPublicMetadata(
330 const BIGNUM& rsa_modulus, const BIGNUM& public_exponent,
331 absl::string_view public_metadata, const bool use_rsa_public_exponent) {
332 bssl::UniquePtr<BIGNUM> derived_rsa_e;
333 if (use_rsa_public_exponent) {
334 ANON_TOKENS_ASSIGN_OR_RETURN(
335 derived_rsa_e, ComputeExponentWithPublicMetadataAndPublicExponent(
336 rsa_modulus, public_exponent, public_metadata));
337 } else {
338 ANON_TOKENS_ASSIGN_OR_RETURN(
339 derived_rsa_e,
340 ComputeExponentWithPublicMetadata(rsa_modulus, public_metadata));
341 }
342 bssl::UniquePtr<RSA> rsa_public_key = bssl::UniquePtr<RSA>(
343 RSA_new_public_key_large_e(&rsa_modulus, derived_rsa_e.get()));
344 if (!rsa_public_key.get()) {
345 return absl::InternalError(
346 absl::StrCat("RSA_new_public_key_large_e failed: ", GetSslErrors()));
347 }
348 return rsa_public_key;
349 }
350
CreatePublicKeyRSAWithPublicMetadata(const absl::string_view rsa_modulus,const absl::string_view public_exponent,const absl::string_view public_metadata,const bool use_rsa_public_exponent)351 absl::StatusOr<bssl::UniquePtr<RSA>> CreatePublicKeyRSAWithPublicMetadata(
352 const absl::string_view rsa_modulus,
353 const absl::string_view public_exponent,
354 const absl::string_view public_metadata,
355 const bool use_rsa_public_exponent) {
356 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> rsa_n,
357 StringToBignum(rsa_modulus));
358 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> rsa_e,
359 StringToBignum(public_exponent));
360 return CreatePublicKeyRSAWithPublicMetadata(
361 *rsa_n.get(), *rsa_e.get(), public_metadata, use_rsa_public_exponent);
362 }
363
ComputeCarmichaelLcm(const BIGNUM & phi_p,const BIGNUM & phi_q,BN_CTX & bn_ctx)364 absl::StatusOr<bssl::UniquePtr<BIGNUM>> ComputeCarmichaelLcm(
365 const BIGNUM& phi_p, const BIGNUM& phi_q, BN_CTX& bn_ctx) {
366 // To compute lcm(phi(p), phi(q)), we first compute phi(n) =
367 // (p-1)(q-1). As n is assumed to be a safe RSA modulus (signing_key is
368 // assumed to be part of a strong rsa key pair), phi(n) = (p-1)(q-1) =
369 // (2 phi(p))(2 phi(q)) = 4 * phi(p) * phi(q) where phi(p) and phi(q) are also
370 // primes. So we get the lcm by outputting phi(n) >> 1 = 2 * phi(p) * phi(q).
371 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> phi_n, NewBigNum());
372 if (BN_mul(phi_n.get(), &phi_p, &phi_q, &bn_ctx) != 1) {
373 return absl::InternalError(
374 absl::StrCat("Unable to compute phi(n): ", GetSslErrors()));
375 }
376 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> lcm, NewBigNum());
377 if (BN_rshift1(lcm.get(), phi_n.get()) != 1) {
378 return absl::InternalError(absl::StrCat(
379 "Could not compute LCM(phi(p), phi(q)): ", GetSslErrors()));
380 }
381 return lcm;
382 }
383
ComputeExponentWithPublicMetadata(const BIGNUM & n,absl::string_view public_metadata)384 absl::StatusOr<bssl::UniquePtr<BIGNUM>> ComputeExponentWithPublicMetadata(
385 const BIGNUM& n, absl::string_view public_metadata) {
386 // Check modulus length.
387 if (BN_num_bits(&n) % 2 == 1) {
388 return absl::InvalidArgumentError(
389 "Strong RSA modulus should be even length.");
390 }
391 int modulus_bytes = BN_num_bytes(&n);
392 // The integer modulus_bytes is expected to be a power of 2.
393 unsigned int prime_bytes = modulus_bytes / 2;
394
395 ANON_TOKENS_ASSIGN_OR_RETURN(std::string rsa_modulus_str,
396 BignumToString(n, modulus_bytes));
397
398 // Get HKDF output of length prime_bytes.
399 ANON_TOKENS_ASSIGN_OR_RETURN(
400 bssl::UniquePtr<BIGNUM> exponent,
401 internal::PublicMetadataHashWithHKDF(public_metadata, rsa_modulus_str,
402 prime_bytes));
403
404 // We need to generate random odd exponents < 2^(primes_bits - 2) where
405 // prime_bits = prime_bytes * 8. This will guarantee that the resulting
406 // exponent is coprime to phi(N) = 4p'q' as 2^(prime_bits - 2) < p', q' <
407 // 2^(prime_bits - 1).
408 //
409 // To do this, we can truncate the HKDF output (exponent) which is prime_bits
410 // long, to prime_bits - 2, by clearing its top two bits. We then set the
411 // least significant bit to 1. This way the final exponent will be less than
412 // 2^(primes_bits - 2) and will always be odd.
413 if (BN_clear_bit(exponent.get(), (prime_bytes * 8) - 1) != kBsslSuccess ||
414 BN_clear_bit(exponent.get(), (prime_bytes * 8) - 2) != kBsslSuccess ||
415 BN_set_bit(exponent.get(), 0) != kBsslSuccess) {
416 return absl::InvalidArgumentError(absl::StrCat(
417 "Could not clear the two most significant bits and set the least "
418 "significant bit to zero: ",
419 GetSslErrors()));
420 }
421 // Check that exponent is small enough to ensure it is coprime to phi(n).
422 if (BN_num_bits(exponent.get()) >= (8 * prime_bytes - 1)) {
423 return absl::InternalError("Generated exponent is too large.");
424 }
425
426 return exponent;
427 }
428
429 absl::StatusOr<bssl::UniquePtr<BIGNUM>>
ComputeExponentWithPublicMetadataAndPublicExponent(const BIGNUM & n,const BIGNUM & e,absl::string_view public_metadata)430 ComputeExponentWithPublicMetadataAndPublicExponent(
431 const BIGNUM& n, const BIGNUM& e, absl::string_view public_metadata) {
432 ANON_TOKENS_ASSIGN_OR_RETURN(
433 bssl::UniquePtr<BIGNUM> md_exp,
434 ComputeExponentWithPublicMetadata(n, public_metadata));
435 ANON_TOKENS_ASSIGN_OR_RETURN(BnCtxPtr bn_ctx, GetAndStartBigNumCtx());
436 // new_e=e*md_exp
437 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> new_e, NewBigNum());
438 if (BN_mul(new_e.get(), md_exp.get(), &e, bn_ctx.get()) != kBsslSuccess) {
439 return absl::InternalError(
440 absl::StrCat("Unable to multiply e with md_exp: ", GetSslErrors()));
441 }
442 return new_e;
443 }
444
RsaBlindSignatureVerify(const int salt_length,const EVP_MD * sig_hash,const EVP_MD * mgf1_hash,const absl::string_view signature,const absl::string_view message,RSA * rsa_public_key)445 absl::Status RsaBlindSignatureVerify(const int salt_length,
446 const EVP_MD* sig_hash,
447 const EVP_MD* mgf1_hash,
448 const absl::string_view signature,
449 const absl::string_view message,
450 RSA* rsa_public_key) {
451 ANON_TOKENS_ASSIGN_OR_RETURN(std::string message_digest,
452 ComputeHash(message, *sig_hash));
453 const size_t hash_size = EVP_MD_size(sig_hash);
454 // Make sure the size of the digest is correct.
455 if (message_digest.size() != hash_size) {
456 return absl::InvalidArgumentError(
457 absl::StrCat("Size of the digest doesn't match the one "
458 "of the hashing algorithm; expected ",
459 hash_size, " got ", message_digest.size()));
460 }
461 // Make sure the size of the signature is correct.
462 const unsigned int rsa_modulus_size =
463 BN_num_bytes(RSA_get0_n(rsa_public_key));
464 if (signature.size() != rsa_modulus_size) {
465 return absl::InvalidArgumentError(
466 "Signature size not equal to modulus size.");
467 }
468
469 std::string recovered_message_digest(rsa_modulus_size, 0);
470 int recovered_message_digest_size = RSA_public_decrypt(
471 /*flen=*/signature.size(),
472 /*from=*/reinterpret_cast<const uint8_t*>(signature.data()),
473 /*to=*/
474 reinterpret_cast<uint8_t*>(recovered_message_digest.data()),
475 /*rsa=*/rsa_public_key,
476 /*padding=*/RSA_NO_PADDING);
477 if (recovered_message_digest_size == -1 ||
478 static_cast<unsigned int>(recovered_message_digest_size) !=
479 rsa_modulus_size) {
480 return absl::InvalidArgumentError(
481 absl::StrCat("Invalid signature size (likely an incorrect key is "
482 "used); expected ",
483 rsa_modulus_size, " got ", recovered_message_digest_size,
484 ": ", GetSslErrors()));
485 }
486 if (RSA_verify_PKCS1_PSS_mgf1(
487 rsa_public_key, reinterpret_cast<const uint8_t*>(&message_digest[0]),
488 sig_hash, mgf1_hash,
489 reinterpret_cast<const uint8_t*>(recovered_message_digest.data()),
490 salt_length) != kBsslSuccess) {
491 return absl::InvalidArgumentError(
492 absl::StrCat("PSS padding verification failed: ", GetSslErrors()));
493 }
494 return absl::OkStatus();
495 }
496
RsaSsaPssPublicKeyToDerEncoding(const RSA * rsa)497 absl::StatusOr<std::string> RsaSsaPssPublicKeyToDerEncoding(const RSA* rsa) {
498 if (rsa == NULL) {
499 return absl::InvalidArgumentError("Public Key rsa is null.");
500 }
501 // Create DER encoded RSA public key string.
502 ANON_TOKENS_ASSIGN_OR_RETURN(std::string rsa_public_key_str,
503 MarshalRsaPublicKey(rsa));
504 // Main CRYPTO ByteBuilder object cbb which will be passed to CBB_finish to
505 // finalize and output the DER encoding of the RsaSsaPssPublicKey.
506 bssl::ScopedCBB cbb;
507 // initial_capacity only serves as a hint.
508 if (!CBB_init(cbb.get(), /*initial_capacity=*/2 * RSA_size(rsa))) {
509 return absl::InternalError("CBB_init() failed.");
510 }
511
512 // Temporary CBB objects to write ASN1 sequences and object identifiers into.
513 CBB outer_seq, inner_seq, param_seq, sha384_seq, mgf1_seq, mgf1_sha384_seq;
514 CBB param0_tag, param1_tag, param2_tag;
515 CBB rsassa_pss_oid, sha384_oid, mgf1_oid, mgf1_sha384_oid;
516 CBB public_key_bit_str_cbb;
517 // RsaSsaPssPublicKey ASN.1 structure example:
518 //
519 // SEQUENCE { # outer_seq
520 // SEQUENCE { # inner_seq
521 // OBJECT_IDENTIFIER{1.2.840.113549.1.1.10} # rsassa_pss_oid
522 // SEQUENCE { # param_seq
523 // [0] { # param0_tag
524 // { # sha384_seq
525 // OBJECT_IDENTIFIER{2.16.840.1.101.3.4.2.2} # sha384_oid
526 // }
527 // }
528 // [1] { # param1_tag
529 // { # mgf1_seq
530 // OBJECT_IDENTIFIER{1.2.840.113549.1.1.8} # mgf1_oid
531 // { # mgf1_sha384_seq
532 // OBJECT_IDENTIFIER{2.16.840.1.101.3.4.2.2}# mgf1_sha384_oid
533 // }
534 // }
535 // }
536 // [2] { # param2_tag
537 // INTEGER { 48 } # salt length
538 // }
539 // }
540 // }
541 // BIT STRING { # public_key_bit_str_cbb
542 // 0 # unused bits
543 // der_encoded_rsa_public_key_structure
544 // }
545 // }
546 //
547 // Start with the outer sequence.
548 if (!CBB_add_asn1(cbb.get(), &outer_seq, CBS_ASN1_SEQUENCE) ||
549 // The outer sequence consists of two parts; the inner sequence and the
550 // encoded rsa public key.
551 //
552 // Add the inner sequence to the outer sequence.
553 !CBB_add_asn1(&outer_seq, &inner_seq, CBS_ASN1_SEQUENCE) ||
554 // Add object identifier for RSASSA-PSS algorithm to the inner sequence.
555 !CBB_add_asn1(&inner_seq, &rsassa_pss_oid, CBS_ASN1_OBJECT) ||
556 !CBB_add_asn1_oid_from_text(&rsassa_pss_oid, kRsaSsaPssOid,
557 strlen(kRsaSsaPssOid)) ||
558 // Add a parameter sequence to the inner sequence.
559 !CBB_add_asn1(&inner_seq, ¶m_seq, CBS_ASN1_SEQUENCE) ||
560 // SHA384 hash function algorithm identifier will be parameter 0 in the
561 // parameter sequence.
562 !CBB_add_asn1(¶m_seq, ¶m0_tag,
563 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
564 !CBB_add_asn1(¶m0_tag, &sha384_seq, CBS_ASN1_SEQUENCE) ||
565 // Add SHA384 object identifier to finish the SHA384 algorithm identifier
566 // and parameter 0.
567 !CBB_add_asn1(&sha384_seq, &sha384_oid, CBS_ASN1_OBJECT) ||
568 !CBB_add_asn1_oid_from_text(&sha384_oid, kSha384Oid,
569 strlen(kSha384Oid)) ||
570 // mgf1-SHA384 algorithm identifier as parameter 1 to the parameter
571 // sequence.
572 !CBB_add_asn1(¶m_seq, ¶m1_tag,
573 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1) ||
574 !CBB_add_asn1(¶m1_tag, &mgf1_seq, CBS_ASN1_SEQUENCE) ||
575 // Add mgf1 object identifier to the mgf1-SHA384 algorithm identifier.
576 !CBB_add_asn1(&mgf1_seq, &mgf1_oid, CBS_ASN1_OBJECT) ||
577 !CBB_add_asn1_oid_from_text(&mgf1_oid, kRsaSsaPssMgf1Oid,
578 strlen(kRsaSsaPssMgf1Oid)) ||
579 // Add SHA384 algorithm identifier to the mgf1-SHA384 algorithm
580 // identifier.
581 !CBB_add_asn1(&mgf1_seq, &mgf1_sha384_seq, CBS_ASN1_SEQUENCE) ||
582 // Add SHA384 object identifier to finish SHA384 algorithm identifier,
583 // mgf1-SHA384 algorithm identifier and parameter 1.
584 !CBB_add_asn1(&mgf1_sha384_seq, &mgf1_sha384_oid, CBS_ASN1_OBJECT) ||
585 !CBB_add_asn1_oid_from_text(&mgf1_sha384_oid, kSha384Oid,
586 strlen(kSha384Oid)) ||
587 // Add salt length as parameter 2 to the parameter sequence to finish the
588 // parameter sequence and the inner sequence.
589 !CBB_add_asn1(¶m_seq, ¶m2_tag,
590 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2) ||
591 !CBB_add_asn1_int64(¶m2_tag, kSaltLengthInBytes48) ||
592 // Add public key to the outer sequence as an ASN1 bitstring.
593 !CBB_add_asn1(&outer_seq, &public_key_bit_str_cbb, CBS_ASN1_BITSTRING) ||
594 !CBB_add_u8(&public_key_bit_str_cbb, 0 /* no unused bits */) ||
595 !CBB_add_bytes(
596 &public_key_bit_str_cbb,
597 reinterpret_cast<const uint8_t*>(rsa_public_key_str.data()),
598 rsa_public_key_str.size())) {
599 return absl::InvalidArgumentError(
600 "Failed to set the crypto byte builder object.");
601 }
602 // Finish creating the DER-encoding of RsaSsaPssPublicKey.
603 uint8_t* rsa_ssa_pss_public_key_der;
604 size_t rsa_ssa_pss_public_key_der_len;
605 if (!CBB_finish(cbb.get(), &rsa_ssa_pss_public_key_der,
606 &rsa_ssa_pss_public_key_der_len)) {
607 return absl::InternalError("CBB_finish() failed.");
608 }
609 std::string rsa_ssa_pss_public_key_der_str(
610 reinterpret_cast<const char*>(rsa_ssa_pss_public_key_der),
611 rsa_ssa_pss_public_key_der_len);
612 // Free memory.
613 OPENSSL_free(rsa_ssa_pss_public_key_der);
614 // Return the DER encoding as string.
615 return rsa_ssa_pss_public_key_der_str;
616 }
617
618 } // namespace anonymous_tokens
619