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