• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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