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/rsa_blind_signer.h"
16
17 #include <cstddef>
18 #include <cstdint>
19 #include <memory>
20 #include <string>
21 #include <utility>
22
23 #include "absl/memory/memory.h"
24 #include "absl/status/status.h"
25 #include "absl/status/statusor.h"
26 #include "absl/strings/str_cat.h"
27 #include "absl/strings/string_view.h"
28 #include "anonymous_tokens/cpp/crypto/anonymous_tokens_pb_openssl_converters.h"
29 #include "anonymous_tokens/cpp/crypto/constants.h"
30 #include "anonymous_tokens/cpp/crypto/crypto_utils.h"
31 #include "anonymous_tokens/cpp/shared/status_utils.h"
32 #include "anonymous_tokens/proto/anonymous_tokens.pb.h"
33 #include <openssl/rsa.h>
34
35 namespace anonymous_tokens {
36 namespace {
37
CreatePrivateKeyWithPublicMetadata(const absl::string_view rsa_modulus_str,const absl::string_view rsa_public_exponent_str,const absl::string_view rsa_p_str,const absl::string_view rsa_q_str,const absl::string_view rsa_crt_str,const absl::string_view public_metadata,const bool use_rsa_public_exponent)38 absl::StatusOr<bssl::UniquePtr<RSA>> CreatePrivateKeyWithPublicMetadata(
39 const absl::string_view rsa_modulus_str,
40 const absl::string_view rsa_public_exponent_str,
41 const absl::string_view rsa_p_str, const absl::string_view rsa_q_str,
42 const absl::string_view rsa_crt_str,
43 const absl::string_view public_metadata,
44 const bool use_rsa_public_exponent) {
45 // Convert RSA modulus n (=p*q) to BIGNUM.
46 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> rsa_modulus,
47 StringToBignum(rsa_modulus_str));
48 // Convert public exponent e to BIGNUM.
49 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> old_e,
50 StringToBignum(rsa_public_exponent_str));
51
52 // Compute new public exponent based on public metadata.
53 bssl::UniquePtr<BIGNUM> derived_rsa_e;
54 if (use_rsa_public_exponent) {
55 ANON_TOKENS_ASSIGN_OR_RETURN(
56 derived_rsa_e, ComputeExponentWithPublicMetadataAndPublicExponent(
57 *rsa_modulus, *old_e, public_metadata));
58 } else {
59 ANON_TOKENS_ASSIGN_OR_RETURN(
60 derived_rsa_e,
61 ComputeExponentWithPublicMetadata(*rsa_modulus, public_metadata));
62 }
63
64 // Convert p & q to BIGNUM.
65 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> rsa_p,
66 StringToBignum(rsa_p_str));
67 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> rsa_q,
68 StringToBignum(rsa_q_str));
69
70 // Compute phi(p) = p-1 and phi(q) = q-1.
71 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> phi_p, NewBigNum());
72 if (BN_sub(phi_p.get(), rsa_p.get(), BN_value_one()) != 1) {
73 return absl::InternalError(
74 absl::StrCat("Unable to compute phi(p): ", GetSslErrors()));
75 }
76 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> phi_q, NewBigNum());
77 if (BN_sub(phi_q.get(), rsa_q.get(), BN_value_one()) != 1) {
78 return absl::InternalError(
79 absl::StrCat("Unable to compute phi(q): ", GetSslErrors()));
80 }
81
82 bssl::UniquePtr<BN_CTX> bn_ctx(BN_CTX_new());
83 if (!bn_ctx) {
84 return absl::InternalError("BN_CTX_new failed.");
85 }
86 // Compute lcm(phi(p), phi(q)).
87 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> lcm,
88 ComputeCarmichaelLcm(*phi_p, *phi_q, *bn_ctx));
89
90 // Compute the new private exponent derived_rsa_d.
91 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> derived_rsa_d,
92 NewBigNum());
93 if (!BN_mod_inverse(derived_rsa_d.get(), derived_rsa_e.get(), lcm.get(),
94 bn_ctx.get())) {
95 return absl::InternalError(
96 absl::StrCat("Could not compute private exponent d: ", GetSslErrors()));
97 }
98
99 // Compute new_dpm1 = derived_rsa_d mod p-1.
100 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> new_dpm1, NewBigNum());
101 BN_mod(new_dpm1.get(), derived_rsa_d.get(), phi_p.get(), bn_ctx.get());
102 // Compute new_dqm1 = derived_rsa_d mod q-1.
103 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> new_dqm1, NewBigNum());
104 BN_mod(new_dqm1.get(), derived_rsa_d.get(), phi_q.get(), bn_ctx.get());
105 // Convert crt to BIGNUM.
106 ANON_TOKENS_ASSIGN_OR_RETURN(bssl::UniquePtr<BIGNUM> rsa_crt,
107 StringToBignum(rsa_crt_str));
108
109 // Create private key derived from given key and public metadata.
110 bssl::UniquePtr<RSA> derived_private_key(RSA_new_private_key_large_e(
111 rsa_modulus.get(), derived_rsa_e.get(), derived_rsa_d.get(), rsa_p.get(),
112 rsa_q.get(), new_dpm1.get(), new_dqm1.get(), rsa_crt.get()));
113 if (!derived_private_key.get()) {
114 return absl::InternalError(
115 absl::StrCat("RSA_new_private_key_large_e failed: ", GetSslErrors()));
116 }
117
118 return derived_private_key;
119 }
120
121 } // namespace
122
RsaBlindSigner(std::optional<absl::string_view> public_metadata,bssl::UniquePtr<RSA> rsa_private_key)123 RsaBlindSigner::RsaBlindSigner(std::optional<absl::string_view> public_metadata,
124 bssl::UniquePtr<RSA> rsa_private_key)
125 : public_metadata_(public_metadata),
126 rsa_private_key_(std::move(rsa_private_key)) {}
127
New(const RSAPrivateKey & signing_key,const bool use_rsa_public_exponent,std::optional<absl::string_view> public_metadata)128 absl::StatusOr<std::unique_ptr<RsaBlindSigner>> RsaBlindSigner::New(
129 const RSAPrivateKey& signing_key, const bool use_rsa_public_exponent,
130 std::optional<absl::string_view> public_metadata) {
131 bssl::UniquePtr<RSA> rsa_private_key;
132 if (!public_metadata.has_value()) {
133 // The RSA modulus and exponent are checked as part of the conversion to
134 // bssl::UniquePtr<RSA>.
135 ANON_TOKENS_ASSIGN_OR_RETURN(
136 rsa_private_key, AnonymousTokensRSAPrivateKeyToRSA(signing_key));
137 } else {
138 // If public metadata is passed, RsaBlindSigner will compute a new private
139 // exponent using the public metadata.
140 //
141 // Empty string is a valid public metadata value.
142 ANON_TOKENS_ASSIGN_OR_RETURN(
143 rsa_private_key,
144 CreatePrivateKeyWithPublicMetadata(
145 signing_key.n(), signing_key.e(), signing_key.p(), signing_key.q(),
146 signing_key.crt(), *public_metadata, use_rsa_public_exponent));
147 }
148 return absl::WrapUnique(
149 new RsaBlindSigner(public_metadata, std::move(rsa_private_key)));
150 }
151
Sign(const absl::string_view blinded_data) const152 absl::StatusOr<std::string> RsaBlindSigner::Sign(
153 const absl::string_view blinded_data) const {
154 if (blinded_data.empty() || blinded_data.data() == nullptr) {
155 return absl::InvalidArgumentError("blinded_data string is empty.");
156 }
157
158 unsigned int mod_size = RSA_size(rsa_private_key_.get());
159 if (blinded_data.size() != mod_size) {
160 return absl::InternalError(absl::StrCat(
161 "Expected blind data size = ", mod_size,
162 " actual blind data size = ", blinded_data.size(), " bytes."));
163 }
164
165 std::string signature(mod_size, 0);
166 // Compute a raw RSA signature.
167 size_t out_len;
168 if (RSA_sign_raw(
169 /*rsa=*/rsa_private_key_.get(), /*out_len=*/&out_len,
170 /*out=*/reinterpret_cast<uint8_t*>(&signature[0]),
171 /*max_out=*/mod_size,
172 /*in=*/reinterpret_cast<const uint8_t*>(&blinded_data[0]),
173 /*in_len=*/mod_size,
174 /*padding=*/RSA_NO_PADDING) != kBsslSuccess) {
175 return absl::InternalError(
176 "RSA_sign_raw failed when called from RsaBlindSigner::Sign");
177 }
178 if (out_len != mod_size || out_len != signature.size()) {
179 return absl::InternalError(absl::StrCat(
180 "Expected value of out_len and signature.size() = ", mod_size,
181 " bytes, actual value of out_len and signature.size() = ", out_len,
182 " and ", signature.size(), " bytes."));
183 }
184 return signature;
185 }
186
187 } // namespace anonymous_tokens
188