xref: /aosp_15_r20/external/tink/cc/internal/rsa_util.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang // Copyright 2021 Google LLC
2*e7b1675dSTing-Kang Chang //
3*e7b1675dSTing-Kang Chang // Licensed under the Apache License, Version 2.0 (the "License");
4*e7b1675dSTing-Kang Chang // you may not use this file except in compliance with the License.
5*e7b1675dSTing-Kang Chang // You may obtain a copy of the License at
6*e7b1675dSTing-Kang Chang //
7*e7b1675dSTing-Kang Chang //     http://www.apache.org/licenses/LICENSE-2.0
8*e7b1675dSTing-Kang Chang //
9*e7b1675dSTing-Kang Chang // Unless required by applicable law or agreed to in writing, software
10*e7b1675dSTing-Kang Chang // distributed under the License is distributed on an "AS IS" BASIS,
11*e7b1675dSTing-Kang Chang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e7b1675dSTing-Kang Chang // See the License for the specific language governing permissions and
13*e7b1675dSTing-Kang Chang // limitations under the License.
14*e7b1675dSTing-Kang Chang //
15*e7b1675dSTing-Kang Chang ///////////////////////////////////////////////////////////////////////////////
16*e7b1675dSTing-Kang Chang #include "tink/internal/rsa_util.h"
17*e7b1675dSTing-Kang Chang 
18*e7b1675dSTing-Kang Chang #include <stddef.h>
19*e7b1675dSTing-Kang Chang 
20*e7b1675dSTing-Kang Chang #include <memory>
21*e7b1675dSTing-Kang Chang #include <string>
22*e7b1675dSTing-Kang Chang #include <utility>
23*e7b1675dSTing-Kang Chang 
24*e7b1675dSTing-Kang Chang #include "absl/status/status.h"
25*e7b1675dSTing-Kang Chang #include "absl/status/statusor.h"
26*e7b1675dSTing-Kang Chang #include "absl/strings/str_cat.h"
27*e7b1675dSTing-Kang Chang #include "absl/strings/string_view.h"
28*e7b1675dSTing-Kang Chang #include "openssl/bn.h"
29*e7b1675dSTing-Kang Chang #include "openssl/rsa.h"
30*e7b1675dSTing-Kang Chang #include "tink/config/tink_fips.h"
31*e7b1675dSTing-Kang Chang #include "tink/internal/bn_util.h"
32*e7b1675dSTing-Kang Chang #include "tink/internal/err_util.h"
33*e7b1675dSTing-Kang Chang #include "tink/internal/fips_utils.h"
34*e7b1675dSTing-Kang Chang #include "tink/internal/ssl_unique_ptr.h"
35*e7b1675dSTing-Kang Chang #include "tink/internal/ssl_util.h"
36*e7b1675dSTing-Kang Chang #include "tink/util/errors.h"
37*e7b1675dSTing-Kang Chang #include "tink/util/secret_data.h"
38*e7b1675dSTing-Kang Chang #include "tink/util/status.h"
39*e7b1675dSTing-Kang Chang #include "tink/util/statusor.h"
40*e7b1675dSTing-Kang Chang 
41*e7b1675dSTing-Kang Chang namespace crypto {
42*e7b1675dSTing-Kang Chang namespace tink {
43*e7b1675dSTing-Kang Chang namespace internal {
44*e7b1675dSTing-Kang Chang 
45*e7b1675dSTing-Kang Chang constexpr int kMaxRsaModulusSizeBits = 16 * 1024;
46*e7b1675dSTing-Kang Chang // Mitigate DoS attacks by limiting the exponent size. 33 bits was chosen as
47*e7b1675dSTing-Kang Chang // the limit based on the recommendations in [1] and [2]. Windows CryptoAPI
48*e7b1675dSTing-Kang Chang // doesn't support values larger than 32 bits [3], so it is unlikely that
49*e7b1675dSTing-Kang Chang // exponents larger than 32 bits are being used for anything Windows commonly
50*e7b1675dSTing-Kang Chang // does.
51*e7b1675dSTing-Kang Chang //
52*e7b1675dSTing-Kang Chang // [1] https://www.imperialviolet.org/2012/03/16/rsae.html
53*e7b1675dSTing-Kang Chang // [2] https://www.imperialviolet.org/2012/03/17/rsados.html
54*e7b1675dSTing-Kang Chang // [3] https://msdn.microsoft.com/en-us/library/aa387685(VS.85).aspx
55*e7b1675dSTing-Kang Chang constexpr int kMaxRsaExponentBits = 33;
56*e7b1675dSTing-Kang Chang 
ValidateRsaModulusSize(size_t modulus_size)57*e7b1675dSTing-Kang Chang util::Status ValidateRsaModulusSize(size_t modulus_size) {
58*e7b1675dSTing-Kang Chang   if (modulus_size < 2048) {
59*e7b1675dSTing-Kang Chang     return util::Status(
60*e7b1675dSTing-Kang Chang         absl::StatusCode::kInvalidArgument,
61*e7b1675dSTing-Kang Chang         absl::StrCat("Modulus size is ", modulus_size,
62*e7b1675dSTing-Kang Chang                      " only modulus size >= 2048-bit is supported"));
63*e7b1675dSTing-Kang Chang   }
64*e7b1675dSTing-Kang Chang 
65*e7b1675dSTing-Kang Chang   // In FIPS only mode we check here if the modulus is 2048- or 3072-bit, as
66*e7b1675dSTing-Kang Chang   // these are the only size which is covered by the FIPS validation and
67*e7b1675dSTing-Kang Chang   // supported by Tink. See
68*e7b1675dSTing-Kang Chang   // https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3318
69*e7b1675dSTing-Kang Chang   if (IsFipsModeEnabled()) {
70*e7b1675dSTing-Kang Chang     if (modulus_size != 2048 && modulus_size != 3072) {
71*e7b1675dSTing-Kang Chang       return util::Status(
72*e7b1675dSTing-Kang Chang           absl::StatusCode::kInternal,
73*e7b1675dSTing-Kang Chang           absl::StrCat("Modulus size is ", modulus_size,
74*e7b1675dSTing-Kang Chang                        " only modulus size 2048 or 3072 is supported."));
75*e7b1675dSTing-Kang Chang     }
76*e7b1675dSTing-Kang Chang   }
77*e7b1675dSTing-Kang Chang 
78*e7b1675dSTing-Kang Chang   return util::OkStatus();
79*e7b1675dSTing-Kang Chang }
80*e7b1675dSTing-Kang Chang 
ValidateRsaPublicExponent(const BIGNUM * exponent)81*e7b1675dSTing-Kang Chang util::Status ValidateRsaPublicExponent(const BIGNUM *exponent) {
82*e7b1675dSTing-Kang Chang   if (exponent == nullptr) {
83*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
84*e7b1675dSTing-Kang Chang                         "Public exponent must not be NULL.");
85*e7b1675dSTing-Kang Chang   }
86*e7b1675dSTing-Kang Chang 
87*e7b1675dSTing-Kang Chang   if (BN_is_odd(exponent) == 0) {
88*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
89*e7b1675dSTing-Kang Chang                         "Public exponent must be odd.");
90*e7b1675dSTing-Kang Chang   }
91*e7b1675dSTing-Kang Chang 
92*e7b1675dSTing-Kang Chang   if (CompareBignumWithWord(exponent, /*word=*/65536) <= 0) {
93*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
94*e7b1675dSTing-Kang Chang                         "Public exponent must be greater than 65536.");
95*e7b1675dSTing-Kang Chang   }
96*e7b1675dSTing-Kang Chang 
97*e7b1675dSTing-Kang Chang   // OpenSSL doesn't pose a limit to the size of the exponent, so for
98*e7b1675dSTing-Kang Chang   // consistency w.r.t. BoringSSL, we enforce it here.
99*e7b1675dSTing-Kang Chang   if (BN_num_bits(exponent) > 32) {
100*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
101*e7b1675dSTing-Kang Chang                         "Exponent size must be smaller than 32 bits");
102*e7b1675dSTing-Kang Chang   }
103*e7b1675dSTing-Kang Chang   return util::OkStatus();
104*e7b1675dSTing-Kang Chang }
105*e7b1675dSTing-Kang Chang 
ValidateRsaPublicExponent(absl::string_view exponent)106*e7b1675dSTing-Kang Chang util::Status ValidateRsaPublicExponent(absl::string_view exponent) {
107*e7b1675dSTing-Kang Chang   util::StatusOr<internal::SslUniquePtr<BIGNUM>> e =
108*e7b1675dSTing-Kang Chang       internal::StringToBignum(exponent);
109*e7b1675dSTing-Kang Chang   if (!e.ok()) {
110*e7b1675dSTing-Kang Chang     return e.status();
111*e7b1675dSTing-Kang Chang   }
112*e7b1675dSTing-Kang Chang   return ValidateRsaPublicExponent(e->get());
113*e7b1675dSTing-Kang Chang }
114*e7b1675dSTing-Kang Chang 
NewRsaKeyPair(int modulus_size_in_bits,const BIGNUM * e,RsaPrivateKey * private_key,RsaPublicKey * public_key)115*e7b1675dSTing-Kang Chang util::Status NewRsaKeyPair(int modulus_size_in_bits, const BIGNUM *e,
116*e7b1675dSTing-Kang Chang                            RsaPrivateKey *private_key,
117*e7b1675dSTing-Kang Chang                            RsaPublicKey *public_key) {
118*e7b1675dSTing-Kang Chang   internal::SslUniquePtr<RSA> rsa(RSA_new());
119*e7b1675dSTing-Kang Chang   if (rsa == nullptr) {
120*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInternal,
121*e7b1675dSTing-Kang Chang                         "Could not initialize RSA.");
122*e7b1675dSTing-Kang Chang   }
123*e7b1675dSTing-Kang Chang 
124*e7b1675dSTing-Kang Chang   util::Status exponent_validation_res = ValidateRsaPublicExponent(e);
125*e7b1675dSTing-Kang Chang   if (!exponent_validation_res.ok()) {
126*e7b1675dSTing-Kang Chang     return exponent_validation_res;
127*e7b1675dSTing-Kang Chang   }
128*e7b1675dSTing-Kang Chang 
129*e7b1675dSTing-Kang Chang   internal::SslUniquePtr<BIGNUM> e_copy(BN_new());
130*e7b1675dSTing-Kang Chang   if (BN_copy(e_copy.get(), e) == nullptr) {
131*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInternal, internal::GetSslErrors());
132*e7b1675dSTing-Kang Chang   }
133*e7b1675dSTing-Kang Chang   if (RSA_generate_key_ex(rsa.get(), modulus_size_in_bits, e_copy.get(),
134*e7b1675dSTing-Kang Chang                           /*cb=*/nullptr) != 1) {
135*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInternal,
136*e7b1675dSTing-Kang Chang                         absl::StrCat("Error generating private key: ",
137*e7b1675dSTing-Kang Chang                                      internal::GetSslErrors()));
138*e7b1675dSTing-Kang Chang   }
139*e7b1675dSTing-Kang Chang 
140*e7b1675dSTing-Kang Chang   const BIGNUM *n_bn, *e_bn, *d_bn;
141*e7b1675dSTing-Kang Chang   RSA_get0_key(rsa.get(), &n_bn, &e_bn, &d_bn);
142*e7b1675dSTing-Kang Chang 
143*e7b1675dSTing-Kang Chang   // Save exponents.
144*e7b1675dSTing-Kang Chang   util::StatusOr<std::string> n_str =
145*e7b1675dSTing-Kang Chang       internal::BignumToString(n_bn, BN_num_bytes(n_bn));
146*e7b1675dSTing-Kang Chang   if (!n_str.ok()) {
147*e7b1675dSTing-Kang Chang     return n_str.status();
148*e7b1675dSTing-Kang Chang   }
149*e7b1675dSTing-Kang Chang   util::StatusOr<std::string> e_str =
150*e7b1675dSTing-Kang Chang       internal::BignumToString(e_bn, BN_num_bytes(e_bn));
151*e7b1675dSTing-Kang Chang   if (!e_str.ok()) {
152*e7b1675dSTing-Kang Chang     return e_str.status();
153*e7b1675dSTing-Kang Chang   }
154*e7b1675dSTing-Kang Chang   util::StatusOr<util::SecretData> d_str =
155*e7b1675dSTing-Kang Chang       internal::BignumToSecretData(d_bn, BN_num_bytes(d_bn));
156*e7b1675dSTing-Kang Chang   if (!d_str.ok()) {
157*e7b1675dSTing-Kang Chang     return d_str.status();
158*e7b1675dSTing-Kang Chang   }
159*e7b1675dSTing-Kang Chang   private_key->n = *std::move(n_str);
160*e7b1675dSTing-Kang Chang   private_key->e = *std::move(e_str);
161*e7b1675dSTing-Kang Chang   private_key->d = *std::move(d_str);
162*e7b1675dSTing-Kang Chang   public_key->n = private_key->n;
163*e7b1675dSTing-Kang Chang   public_key->e = private_key->e;
164*e7b1675dSTing-Kang Chang 
165*e7b1675dSTing-Kang Chang   // Save factors.
166*e7b1675dSTing-Kang Chang   const BIGNUM *p_bn, *q_bn;
167*e7b1675dSTing-Kang Chang   RSA_get0_factors(rsa.get(), &p_bn, &q_bn);
168*e7b1675dSTing-Kang Chang   util::StatusOr<util::SecretData> p_str =
169*e7b1675dSTing-Kang Chang       internal::BignumToSecretData(p_bn, BN_num_bytes(p_bn));
170*e7b1675dSTing-Kang Chang   if (!p_str.ok()) {
171*e7b1675dSTing-Kang Chang     return p_str.status();
172*e7b1675dSTing-Kang Chang   }
173*e7b1675dSTing-Kang Chang   util::StatusOr<util::SecretData> q_str =
174*e7b1675dSTing-Kang Chang       internal::BignumToSecretData(q_bn, BN_num_bytes(q_bn));
175*e7b1675dSTing-Kang Chang   if (!q_str.ok()) {
176*e7b1675dSTing-Kang Chang     return q_str.status();
177*e7b1675dSTing-Kang Chang   }
178*e7b1675dSTing-Kang Chang   private_key->p = *std::move(p_str);
179*e7b1675dSTing-Kang Chang   private_key->q = *std::move(q_str);
180*e7b1675dSTing-Kang Chang 
181*e7b1675dSTing-Kang Chang   // Save CRT parameters.
182*e7b1675dSTing-Kang Chang   const BIGNUM *dp_bn, *dq_bn, *crt_bn;
183*e7b1675dSTing-Kang Chang   RSA_get0_crt_params(rsa.get(), &dp_bn, &dq_bn, &crt_bn);
184*e7b1675dSTing-Kang Chang   util::StatusOr<util::SecretData> dp_str =
185*e7b1675dSTing-Kang Chang       internal::BignumToSecretData(dp_bn, BN_num_bytes(dp_bn));
186*e7b1675dSTing-Kang Chang   if (!dp_str.ok()) {
187*e7b1675dSTing-Kang Chang     return dp_str.status();
188*e7b1675dSTing-Kang Chang   }
189*e7b1675dSTing-Kang Chang   util::StatusOr<util::SecretData> dq_str =
190*e7b1675dSTing-Kang Chang       internal::BignumToSecretData(dq_bn, BN_num_bytes(dq_bn));
191*e7b1675dSTing-Kang Chang   if (!dq_str.ok()) {
192*e7b1675dSTing-Kang Chang     return dq_str.status();
193*e7b1675dSTing-Kang Chang   }
194*e7b1675dSTing-Kang Chang   util::StatusOr<util::SecretData> crt_str =
195*e7b1675dSTing-Kang Chang       internal::BignumToSecretData(crt_bn, BN_num_bytes(crt_bn));
196*e7b1675dSTing-Kang Chang   if (!crt_str.ok()) {
197*e7b1675dSTing-Kang Chang     return crt_str.status();
198*e7b1675dSTing-Kang Chang   }
199*e7b1675dSTing-Kang Chang   private_key->dp = *std::move(dp_str);
200*e7b1675dSTing-Kang Chang   private_key->dq = *std::move(dq_str);
201*e7b1675dSTing-Kang Chang   private_key->crt = *std::move(crt_str);
202*e7b1675dSTing-Kang Chang 
203*e7b1675dSTing-Kang Chang   return util::OkStatus();
204*e7b1675dSTing-Kang Chang }
205*e7b1675dSTing-Kang Chang 
GetRsaModAndExponents(const RsaPrivateKey & key,RSA * rsa)206*e7b1675dSTing-Kang Chang util::Status GetRsaModAndExponents(const RsaPrivateKey &key, RSA *rsa) {
207*e7b1675dSTing-Kang Chang   util::StatusOr<internal::SslUniquePtr<BIGNUM>> n =
208*e7b1675dSTing-Kang Chang       internal::StringToBignum(key.n);
209*e7b1675dSTing-Kang Chang   util::StatusOr<internal::SslUniquePtr<BIGNUM>> e =
210*e7b1675dSTing-Kang Chang       internal::StringToBignum(key.e);
211*e7b1675dSTing-Kang Chang   util::StatusOr<internal::SslUniquePtr<BIGNUM>> d =
212*e7b1675dSTing-Kang Chang       internal::StringToBignum(util::SecretDataAsStringView(key.d));
213*e7b1675dSTing-Kang Chang   if (!n.ok()) {
214*e7b1675dSTing-Kang Chang     return n.status();
215*e7b1675dSTing-Kang Chang   }
216*e7b1675dSTing-Kang Chang   if (!e.ok()) {
217*e7b1675dSTing-Kang Chang     return e.status();
218*e7b1675dSTing-Kang Chang   }
219*e7b1675dSTing-Kang Chang   if (!d.ok()) {
220*e7b1675dSTing-Kang Chang     return d.status();
221*e7b1675dSTing-Kang Chang   }
222*e7b1675dSTing-Kang Chang   if (RSA_set0_key(rsa, n->get(), e->get(), d->get()) != 1) {
223*e7b1675dSTing-Kang Chang     return util::Status(
224*e7b1675dSTing-Kang Chang         absl::StatusCode::kInternal,
225*e7b1675dSTing-Kang Chang         absl::StrCat("Could not load RSA key: ", internal::GetSslErrors()));
226*e7b1675dSTing-Kang Chang   }
227*e7b1675dSTing-Kang Chang   // The RSA object takes ownership when RSA_set0_key is called.
228*e7b1675dSTing-Kang Chang   n->release();
229*e7b1675dSTing-Kang Chang   e->release();
230*e7b1675dSTing-Kang Chang   d->release();
231*e7b1675dSTing-Kang Chang   return util::OkStatus();
232*e7b1675dSTing-Kang Chang }
233*e7b1675dSTing-Kang Chang 
GetRsaPrimeFactors(const RsaPrivateKey & key,RSA * rsa)234*e7b1675dSTing-Kang Chang util::Status GetRsaPrimeFactors(const RsaPrivateKey &key, RSA *rsa) {
235*e7b1675dSTing-Kang Chang   util::StatusOr<internal::SslUniquePtr<BIGNUM>> p =
236*e7b1675dSTing-Kang Chang       internal::StringToBignum(util::SecretDataAsStringView(key.p));
237*e7b1675dSTing-Kang Chang   util::StatusOr<internal::SslUniquePtr<BIGNUM>> q =
238*e7b1675dSTing-Kang Chang       internal::StringToBignum(util::SecretDataAsStringView(key.q));
239*e7b1675dSTing-Kang Chang   if (!p.ok()) {
240*e7b1675dSTing-Kang Chang     return p.status();
241*e7b1675dSTing-Kang Chang   }
242*e7b1675dSTing-Kang Chang   if (!q.ok()) {
243*e7b1675dSTing-Kang Chang     return q.status();
244*e7b1675dSTing-Kang Chang   }
245*e7b1675dSTing-Kang Chang   if (RSA_set0_factors(rsa, p->get(), q->get()) != 1) {
246*e7b1675dSTing-Kang Chang     return util::Status(
247*e7b1675dSTing-Kang Chang         absl::StatusCode::kInternal,
248*e7b1675dSTing-Kang Chang         absl::StrCat("Could not load RSA key: ", internal::GetSslErrors()));
249*e7b1675dSTing-Kang Chang   }
250*e7b1675dSTing-Kang Chang   p->release();
251*e7b1675dSTing-Kang Chang   q->release();
252*e7b1675dSTing-Kang Chang   return util::OkStatus();
253*e7b1675dSTing-Kang Chang }
254*e7b1675dSTing-Kang Chang 
GetRsaCrtParams(const RsaPrivateKey & key,RSA * rsa)255*e7b1675dSTing-Kang Chang util::Status GetRsaCrtParams(const RsaPrivateKey &key, RSA *rsa) {
256*e7b1675dSTing-Kang Chang   util::StatusOr<internal::SslUniquePtr<BIGNUM>> dp =
257*e7b1675dSTing-Kang Chang       internal::StringToBignum(util::SecretDataAsStringView(key.dp));
258*e7b1675dSTing-Kang Chang   util::StatusOr<internal::SslUniquePtr<BIGNUM>> dq =
259*e7b1675dSTing-Kang Chang       internal::StringToBignum(util::SecretDataAsStringView(key.dq));
260*e7b1675dSTing-Kang Chang   util::StatusOr<internal::SslUniquePtr<BIGNUM>> crt =
261*e7b1675dSTing-Kang Chang       internal::StringToBignum(util::SecretDataAsStringView(key.crt));
262*e7b1675dSTing-Kang Chang   if (!dp.ok()) {
263*e7b1675dSTing-Kang Chang     return dp.status();
264*e7b1675dSTing-Kang Chang   }
265*e7b1675dSTing-Kang Chang   if (!dq.ok()) {
266*e7b1675dSTing-Kang Chang     return dq.status();
267*e7b1675dSTing-Kang Chang   }
268*e7b1675dSTing-Kang Chang   if (!crt.ok()) {
269*e7b1675dSTing-Kang Chang     return crt.status();
270*e7b1675dSTing-Kang Chang   }
271*e7b1675dSTing-Kang Chang   if (RSA_set0_crt_params(rsa, dp->get(), dq->get(), crt->get()) != 1) {
272*e7b1675dSTing-Kang Chang     return util::Status(
273*e7b1675dSTing-Kang Chang         absl::StatusCode::kInternal,
274*e7b1675dSTing-Kang Chang         absl::StrCat("Could not load RSA key: ", internal::GetSslErrors()));
275*e7b1675dSTing-Kang Chang   }
276*e7b1675dSTing-Kang Chang   dp->release();
277*e7b1675dSTing-Kang Chang   dq->release();
278*e7b1675dSTing-Kang Chang   crt->release();
279*e7b1675dSTing-Kang Chang   return util::OkStatus();
280*e7b1675dSTing-Kang Chang }
281*e7b1675dSTing-Kang Chang 
RsaPrivateKeyToRsa(const RsaPrivateKey & private_key)282*e7b1675dSTing-Kang Chang util::StatusOr<internal::SslUniquePtr<RSA>> RsaPrivateKeyToRsa(
283*e7b1675dSTing-Kang Chang     const RsaPrivateKey &private_key) {
284*e7b1675dSTing-Kang Chang   auto n = internal::StringToBignum(private_key.n);
285*e7b1675dSTing-Kang Chang   if (!n.ok()) {
286*e7b1675dSTing-Kang Chang     return n.status();
287*e7b1675dSTing-Kang Chang   }
288*e7b1675dSTing-Kang Chang   auto validation_result = ValidateRsaModulusSize(BN_num_bits(n->get()));
289*e7b1675dSTing-Kang Chang   if (!validation_result.ok()) {
290*e7b1675dSTing-Kang Chang     return validation_result;
291*e7b1675dSTing-Kang Chang   }
292*e7b1675dSTing-Kang Chang   // Check RSA's public exponent
293*e7b1675dSTing-Kang Chang   auto exponent_status = ValidateRsaPublicExponent(private_key.e);
294*e7b1675dSTing-Kang Chang   if (!exponent_status.ok()) {
295*e7b1675dSTing-Kang Chang     return exponent_status;
296*e7b1675dSTing-Kang Chang   }
297*e7b1675dSTing-Kang Chang   internal::SslUniquePtr<RSA> rsa(RSA_new());
298*e7b1675dSTing-Kang Chang   if (rsa.get() == nullptr) {
299*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInternal,
300*e7b1675dSTing-Kang Chang                         "BoringSsl RSA allocation error");
301*e7b1675dSTing-Kang Chang   }
302*e7b1675dSTing-Kang Chang   util::Status status = GetRsaModAndExponents(private_key, rsa.get());
303*e7b1675dSTing-Kang Chang   if (!status.ok()) {
304*e7b1675dSTing-Kang Chang     return status;
305*e7b1675dSTing-Kang Chang   }
306*e7b1675dSTing-Kang Chang   status = GetRsaPrimeFactors(private_key, rsa.get());
307*e7b1675dSTing-Kang Chang   if (!status.ok()) {
308*e7b1675dSTing-Kang Chang     return status;
309*e7b1675dSTing-Kang Chang   }
310*e7b1675dSTing-Kang Chang   status = GetRsaCrtParams(private_key, rsa.get());
311*e7b1675dSTing-Kang Chang   if (!status.ok()) {
312*e7b1675dSTing-Kang Chang     return status;
313*e7b1675dSTing-Kang Chang   }
314*e7b1675dSTing-Kang Chang 
315*e7b1675dSTing-Kang Chang   if (RSA_check_key(rsa.get()) == 0) {
316*e7b1675dSTing-Kang Chang     return util::Status(
317*e7b1675dSTing-Kang Chang         absl::StatusCode::kInvalidArgument,
318*e7b1675dSTing-Kang Chang         absl::StrCat("Could not load RSA key: ", internal::GetSslErrors()));
319*e7b1675dSTing-Kang Chang   }
320*e7b1675dSTing-Kang Chang #ifdef OPENSSL_IS_BORINGSSL
321*e7b1675dSTing-Kang Chang   if (RSA_check_fips(rsa.get()) == 0) {
322*e7b1675dSTing-Kang Chang     return util::Status(
323*e7b1675dSTing-Kang Chang         absl::StatusCode::kInvalidArgument,
324*e7b1675dSTing-Kang Chang         absl::StrCat("Could not load RSA key: ", internal::GetSslErrors()));
325*e7b1675dSTing-Kang Chang   }
326*e7b1675dSTing-Kang Chang #endif
327*e7b1675dSTing-Kang Chang   return std::move(rsa);
328*e7b1675dSTing-Kang Chang }
329*e7b1675dSTing-Kang Chang 
RsaPublicKeyToRsa(const RsaPublicKey & public_key)330*e7b1675dSTing-Kang Chang util::StatusOr<internal::SslUniquePtr<RSA>> RsaPublicKeyToRsa(
331*e7b1675dSTing-Kang Chang     const RsaPublicKey &public_key) {
332*e7b1675dSTing-Kang Chang   auto n = internal::StringToBignum(public_key.n);
333*e7b1675dSTing-Kang Chang   if (!n.ok()) {
334*e7b1675dSTing-Kang Chang     return n.status();
335*e7b1675dSTing-Kang Chang   }
336*e7b1675dSTing-Kang Chang   auto e = internal::StringToBignum(public_key.e);
337*e7b1675dSTing-Kang Chang   if (!e.ok()) {
338*e7b1675dSTing-Kang Chang     return e.status();
339*e7b1675dSTing-Kang Chang   }
340*e7b1675dSTing-Kang Chang   auto validation_result = ValidateRsaModulusSize(BN_num_bits(n->get()));
341*e7b1675dSTing-Kang Chang   if (!validation_result.ok()) {
342*e7b1675dSTing-Kang Chang     return validation_result;
343*e7b1675dSTing-Kang Chang   }
344*e7b1675dSTing-Kang Chang   internal::SslUniquePtr<RSA> rsa(RSA_new());
345*e7b1675dSTing-Kang Chang   if (rsa.get() == nullptr) {
346*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInternal, "RSA allocation error");
347*e7b1675dSTing-Kang Chang   }
348*e7b1675dSTing-Kang Chang   // The value d is null for a public RSA key.
349*e7b1675dSTing-Kang Chang   if (RSA_set0_key(rsa.get(), n->get(), e->get(),
350*e7b1675dSTing-Kang Chang                    /*d=*/nullptr) != 1) {
351*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInternal, "Could not set RSA key.");
352*e7b1675dSTing-Kang Chang   }
353*e7b1675dSTing-Kang Chang   n->release();
354*e7b1675dSTing-Kang Chang   e->release();
355*e7b1675dSTing-Kang Chang   return std::move(rsa);
356*e7b1675dSTing-Kang Chang }
357*e7b1675dSTing-Kang Chang 
RsaCheckPublicKey(const RSA * key)358*e7b1675dSTing-Kang Chang util::Status RsaCheckPublicKey(const RSA *key) {
359*e7b1675dSTing-Kang Chang   if (key == nullptr) {
360*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument, "RSA key is null");
361*e7b1675dSTing-Kang Chang   }
362*e7b1675dSTing-Kang Chang 
363*e7b1675dSTing-Kang Chang   // BoringSSL `RSA_check_key` supports checking the public key.
364*e7b1675dSTing-Kang Chang   if (internal::IsBoringSsl()) {
365*e7b1675dSTing-Kang Chang     if (RSA_check_key(key) != 1) {
366*e7b1675dSTing-Kang Chang       return util::Status(absl::StatusCode::kInvalidArgument,
367*e7b1675dSTing-Kang Chang                           "Invalid RSA key format");
368*e7b1675dSTing-Kang Chang     }
369*e7b1675dSTing-Kang Chang     return util::OkStatus();
370*e7b1675dSTing-Kang Chang   }
371*e7b1675dSTing-Kang Chang 
372*e7b1675dSTing-Kang Chang   const BIGNUM *n = nullptr;
373*e7b1675dSTing-Kang Chang   const BIGNUM *e = nullptr;
374*e7b1675dSTing-Kang Chang   const BIGNUM *d = nullptr;
375*e7b1675dSTing-Kang Chang   RSA_get0_key(key, &n, &e, &d);
376*e7b1675dSTing-Kang Chang 
377*e7b1675dSTing-Kang Chang   if (e == nullptr) {
378*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
379*e7b1675dSTing-Kang Chang                         "RSA key's public exponent is null");
380*e7b1675dSTing-Kang Chang   }
381*e7b1675dSTing-Kang Chang   if (n == nullptr) {
382*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
383*e7b1675dSTing-Kang Chang                         "RSA key's public modulus is null");
384*e7b1675dSTing-Kang Chang   }
385*e7b1675dSTing-Kang Chang 
386*e7b1675dSTing-Kang Chang   // Check the size of the public modulus.
387*e7b1675dSTing-Kang Chang   unsigned n_bits = BN_num_bits(n);
388*e7b1675dSTing-Kang Chang   if (n_bits > kMaxRsaModulusSizeBits) {
389*e7b1675dSTing-Kang Chang     return util::Status(
390*e7b1675dSTing-Kang Chang         absl::StatusCode::kInvalidArgument,
391*e7b1675dSTing-Kang Chang         absl::StrCat(
392*e7b1675dSTing-Kang Chang             "RSA key's public modulus size is too large; expected at most ",
393*e7b1675dSTing-Kang Chang             kMaxRsaModulusSizeBits, " bits, got ", n_bits));
394*e7b1675dSTing-Kang Chang   }
395*e7b1675dSTing-Kang Chang 
396*e7b1675dSTing-Kang Chang   unsigned e_bits = BN_num_bits(e);
397*e7b1675dSTing-Kang Chang   // Valis size is 1 < e_bits <= kMaxRsaExponentBits.
398*e7b1675dSTing-Kang Chang   if (e_bits > kMaxRsaExponentBits || e_bits < 2) {
399*e7b1675dSTing-Kang Chang     return util::Status(
400*e7b1675dSTing-Kang Chang         absl::StatusCode::kInvalidArgument,
401*e7b1675dSTing-Kang Chang         absl::StrCat("Invalid public exponent size of ", e_bits, " bits"));
402*e7b1675dSTing-Kang Chang   }
403*e7b1675dSTing-Kang Chang 
404*e7b1675dSTing-Kang Chang   // The exponent must be odd to be relatively prime with phi(n).
405*e7b1675dSTing-Kang Chang   if (!BN_is_odd(e)) {
406*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
407*e7b1675dSTing-Kang Chang                         "Public exponent is not odd");
408*e7b1675dSTing-Kang Chang   }
409*e7b1675dSTing-Kang Chang 
410*e7b1675dSTing-Kang Chang   // Verify |n > e| first taking the shortcut of making sure the size in bits of
411*e7b1675dSTing-Kang Chang   // n is larger than the maximum modulus size; if this not the case, directly
412*e7b1675dSTing-Kang Chang   // compare n and e.
413*e7b1675dSTing-Kang Chang   if (n_bits <= kMaxRsaExponentBits || BN_ucmp(n, e) <= 0) {
414*e7b1675dSTing-Kang Chang     return util::Status(
415*e7b1675dSTing-Kang Chang         absl::StatusCode::kInvalidArgument,
416*e7b1675dSTing-Kang Chang         "RSA key's public exponent is smaller than the modulus");
417*e7b1675dSTing-Kang Chang   }
418*e7b1675dSTing-Kang Chang   return util::OkStatus();
419*e7b1675dSTing-Kang Chang }
420*e7b1675dSTing-Kang Chang 
421*e7b1675dSTing-Kang Chang }  // namespace internal
422*e7b1675dSTing-Kang Chang }  // namespace tink
423*e7b1675dSTing-Kang Chang }  // namespace crypto
424