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