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