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