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