1//! Rivest–Shamir–Adleman cryptosystem
2//!
3//! RSA is one of the earliest asymmetric public key encryption schemes.
4//! Like many other cryptosystems, RSA relies on the presumed difficulty of a hard
5//! mathematical problem, namely factorization of the product of two large prime
6//! numbers. At the moment there does not exist an algorithm that can factor such
7//! large numbers in reasonable time. RSA is used in a wide variety of
8//! applications including digital signatures and key exchanges such as
9//! establishing a TLS/SSL connection.
10//!
11//! The RSA acronym is derived from the first letters of the surnames of the
12//! algorithm's founding trio.
13//!
14//! # Example
15//!
16//! Generate a 2048-bit RSA key pair and use the public key to encrypt some data.
17//!
18//! ```rust
19//! use openssl::rsa::{Rsa, Padding};
20//!
21//! let rsa = Rsa::generate(2048).unwrap();
22//! let data = b"foobar";
23//! let mut buf = vec![0; rsa.size() as usize];
24//! let encrypted_len = rsa.public_encrypt(data, &mut buf, Padding::PKCS1).unwrap();
25//! ```
26use cfg_if::cfg_if;
27use foreign_types::{ForeignType, ForeignTypeRef};
28use libc::c_int;
29use std::fmt;
30use std::mem;
31use std::ptr;
32
33use crate::bn::{BigNum, BigNumRef};
34use crate::error::ErrorStack;
35use crate::pkey::{HasPrivate, HasPublic, Private, Public};
36use crate::util::ForeignTypeRefExt;
37use crate::{cvt, cvt_n, cvt_p, LenType};
38use openssl_macros::corresponds;
39
40/// Type of encryption padding to use.
41///
42/// Random length padding is primarily used to prevent attackers from
43/// predicting or knowing the exact length of a plaintext message that
44/// can possibly lead to breaking encryption.
45#[derive(Debug, Copy, Clone, PartialEq, Eq)]
46pub struct Padding(c_int);
47
48impl Padding {
49 pub const NONE: Padding = Padding(ffi::RSA_NO_PADDING);
50 pub const PKCS1: Padding = Padding(ffi::RSA_PKCS1_PADDING);
51 pub const PKCS1_OAEP: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING);
52 pub const PKCS1_PSS: Padding = Padding(ffi::RSA_PKCS1_PSS_PADDING);
53
54 /// Creates a `Padding` from an integer representation.
55 pub fn from_raw(value: c_int) -> Padding {
56 Padding(value)
57 }
58
59 /// Returns the integer representation of `Padding`.
60 #[allow(clippy::trivially_copy_pass_by_ref)]
61 pub fn as_raw(&self) -> c_int {
62 self.0
63 }
64}
65
66generic_foreign_type_and_impl_send_sync! {
67 type CType = ffi::RSA;
68 fn drop = ffi::RSA_free;
69
70 /// An RSA key.
71 pub struct Rsa<T>;
72
73 /// Reference to `RSA`
74 pub struct RsaRef<T>;
75}
76
77impl<T> Clone for Rsa<T> {
78 fn clone(&self) -> Rsa<T> {
79 (**self).to_owned()
80 }
81}
82
83impl<T> ToOwned for RsaRef<T> {
84 type Owned = Rsa<T>;
85
86 fn to_owned(&self) -> Rsa<T> {
87 unsafe {
88 ffi::RSA_up_ref(self.as_ptr());
89 Rsa::from_ptr(self.as_ptr())
90 }
91 }
92}
93
94impl<T> RsaRef<T>
95where
96 T: HasPrivate,
97{
98 private_key_to_pem! {
99 /// Serializes the private key to a PEM-encoded PKCS#1 RSAPrivateKey structure.
100 ///
101 /// The output will have a header of `-----BEGIN RSA PRIVATE KEY-----`.
102 #[corresponds(PEM_write_bio_RSAPrivateKey)]
103 private_key_to_pem,
104 /// Serializes the private key to a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
105 ///
106 /// The output will have a header of `-----BEGIN RSA PRIVATE KEY-----`.
107 #[corresponds(PEM_write_bio_RSAPrivateKey)]
108 private_key_to_pem_passphrase,
109 ffi::PEM_write_bio_RSAPrivateKey
110 }
111
112 to_der! {
113 /// Serializes the private key to a DER-encoded PKCS#1 RSAPrivateKey structure.
114 #[corresponds(i2d_RSAPrivateKey)]
115 private_key_to_der,
116 ffi::i2d_RSAPrivateKey
117 }
118
119 /// Decrypts data using the private key, returning the number of decrypted bytes.
120 ///
121 /// # Panics
122 ///
123 /// Panics if `self` has no private components, or if `to` is smaller
124 /// than `self.size()`.
125 #[corresponds(RSA_private_decrypt)]
126 pub fn private_decrypt(
127 &self,
128 from: &[u8],
129 to: &mut [u8],
130 padding: Padding,
131 ) -> Result<usize, ErrorStack> {
132 assert!(from.len() <= i32::max_value() as usize);
133 assert!(to.len() >= self.size() as usize);
134
135 unsafe {
136 let len = cvt_n(ffi::RSA_private_decrypt(
137 from.len() as LenType,
138 from.as_ptr(),
139 to.as_mut_ptr(),
140 self.as_ptr(),
141 padding.0,
142 ))?;
143 Ok(len as usize)
144 }
145 }
146
147 /// Encrypts data using the private key, returning the number of encrypted bytes.
148 ///
149 /// # Panics
150 ///
151 /// Panics if `self` has no private components, or if `to` is smaller
152 /// than `self.size()`.
153 #[corresponds(RSA_private_encrypt)]
154 pub fn private_encrypt(
155 &self,
156 from: &[u8],
157 to: &mut [u8],
158 padding: Padding,
159 ) -> Result<usize, ErrorStack> {
160 assert!(from.len() <= i32::max_value() as usize);
161 assert!(to.len() >= self.size() as usize);
162
163 unsafe {
164 let len = cvt_n(ffi::RSA_private_encrypt(
165 from.len() as LenType,
166 from.as_ptr(),
167 to.as_mut_ptr(),
168 self.as_ptr(),
169 padding.0,
170 ))?;
171 Ok(len as usize)
172 }
173 }
174
175 /// Returns a reference to the private exponent of the key.
176 #[corresponds(RSA_get0_key)]
177 pub fn d(&self) -> &BigNumRef {
178 unsafe {
179 let mut d = ptr::null();
180 RSA_get0_key(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut d);
181 BigNumRef::from_const_ptr(d)
182 }
183 }
184
185 /// Returns a reference to the first factor of the exponent of the key.
186 #[corresponds(RSA_get0_factors)]
187 pub fn p(&self) -> Option<&BigNumRef> {
188 unsafe {
189 let mut p = ptr::null();
190 RSA_get0_factors(self.as_ptr(), &mut p, ptr::null_mut());
191 BigNumRef::from_const_ptr_opt(p)
192 }
193 }
194
195 /// Returns a reference to the second factor of the exponent of the key.
196 #[corresponds(RSA_get0_factors)]
197 pub fn q(&self) -> Option<&BigNumRef> {
198 unsafe {
199 let mut q = ptr::null();
200 RSA_get0_factors(self.as_ptr(), ptr::null_mut(), &mut q);
201 BigNumRef::from_const_ptr_opt(q)
202 }
203 }
204
205 /// Returns a reference to the first exponent used for CRT calculations.
206 #[corresponds(RSA_get0_crt_params)]
207 pub fn dmp1(&self) -> Option<&BigNumRef> {
208 unsafe {
209 let mut dp = ptr::null();
210 RSA_get0_crt_params(self.as_ptr(), &mut dp, ptr::null_mut(), ptr::null_mut());
211 BigNumRef::from_const_ptr_opt(dp)
212 }
213 }
214
215 /// Returns a reference to the second exponent used for CRT calculations.
216 #[corresponds(RSA_get0_crt_params)]
217 pub fn dmq1(&self) -> Option<&BigNumRef> {
218 unsafe {
219 let mut dq = ptr::null();
220 RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), &mut dq, ptr::null_mut());
221 BigNumRef::from_const_ptr_opt(dq)
222 }
223 }
224
225 /// Returns a reference to the coefficient used for CRT calculations.
226 #[corresponds(RSA_get0_crt_params)]
227 pub fn iqmp(&self) -> Option<&BigNumRef> {
228 unsafe {
229 let mut qi = ptr::null();
230 RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut qi);
231 BigNumRef::from_const_ptr_opt(qi)
232 }
233 }
234
235 /// Validates RSA parameters for correctness
236 #[corresponds(RSA_check_key)]
237 #[allow(clippy::unnecessary_cast)]
238 pub fn check_key(&self) -> Result<bool, ErrorStack> {
239 unsafe {
240 let result = ffi::RSA_check_key(self.as_ptr()) as i32;
241 if result == -1 {
242 Err(ErrorStack::get())
243 } else {
244 Ok(result == 1)
245 }
246 }
247 }
248}
249
250impl<T> RsaRef<T>
251where
252 T: HasPublic,
253{
254 to_pem! {
255 /// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
256 ///
257 /// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
258 #[corresponds(PEM_write_bio_RSA_PUBKEY)]
259 public_key_to_pem,
260 ffi::PEM_write_bio_RSA_PUBKEY
261 }
262
263 to_der! {
264 /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
265 #[corresponds(i2d_RSA_PUBKEY)]
266 public_key_to_der,
267 ffi::i2d_RSA_PUBKEY
268 }
269
270 to_pem! {
271 /// Serializes the public key into a PEM-encoded PKCS#1 RSAPublicKey structure.
272 ///
273 /// The output will have a header of `-----BEGIN RSA PUBLIC KEY-----`.
274 #[corresponds(PEM_write_bio_RSAPublicKey)]
275 public_key_to_pem_pkcs1,
276 ffi::PEM_write_bio_RSAPublicKey
277 }
278
279 to_der! {
280 /// Serializes the public key into a DER-encoded PKCS#1 RSAPublicKey structure.
281 #[corresponds(i2d_RSAPublicKey)]
282 public_key_to_der_pkcs1,
283 ffi::i2d_RSAPublicKey
284 }
285
286 /// Returns the size of the modulus in bytes.
287 #[corresponds(RSA_size)]
288 pub fn size(&self) -> u32 {
289 unsafe { ffi::RSA_size(self.as_ptr()) as u32 }
290 }
291
292 /// Decrypts data using the public key, returning the number of decrypted bytes.
293 ///
294 /// # Panics
295 ///
296 /// Panics if `to` is smaller than `self.size()`.
297 #[corresponds(RSA_public_decrypt)]
298 pub fn public_decrypt(
299 &self,
300 from: &[u8],
301 to: &mut [u8],
302 padding: Padding,
303 ) -> Result<usize, ErrorStack> {
304 assert!(from.len() <= i32::max_value() as usize);
305 assert!(to.len() >= self.size() as usize);
306
307 unsafe {
308 let len = cvt_n(ffi::RSA_public_decrypt(
309 from.len() as LenType,
310 from.as_ptr(),
311 to.as_mut_ptr(),
312 self.as_ptr(),
313 padding.0,
314 ))?;
315 Ok(len as usize)
316 }
317 }
318
319 /// Encrypts data using the public key, returning the number of encrypted bytes.
320 ///
321 /// # Panics
322 ///
323 /// Panics if `to` is smaller than `self.size()`.
324 #[corresponds(RSA_public_encrypt)]
325 pub fn public_encrypt(
326 &self,
327 from: &[u8],
328 to: &mut [u8],
329 padding: Padding,
330 ) -> Result<usize, ErrorStack> {
331 assert!(from.len() <= i32::max_value() as usize);
332 assert!(to.len() >= self.size() as usize);
333
334 unsafe {
335 let len = cvt_n(ffi::RSA_public_encrypt(
336 from.len() as LenType,
337 from.as_ptr(),
338 to.as_mut_ptr(),
339 self.as_ptr(),
340 padding.0,
341 ))?;
342 Ok(len as usize)
343 }
344 }
345
346 /// Returns a reference to the modulus of the key.
347 #[corresponds(RSA_get0_key)]
348 pub fn n(&self) -> &BigNumRef {
349 unsafe {
350 let mut n = ptr::null();
351 RSA_get0_key(self.as_ptr(), &mut n, ptr::null_mut(), ptr::null_mut());
352 BigNumRef::from_const_ptr(n)
353 }
354 }
355
356 /// Returns a reference to the public exponent of the key.
357 #[corresponds(RSA_get0_key)]
358 pub fn e(&self) -> &BigNumRef {
359 unsafe {
360 let mut e = ptr::null();
361 RSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut e, ptr::null_mut());
362 BigNumRef::from_const_ptr(e)
363 }
364 }
365}
366
367impl Rsa<Public> {
368 /// Creates a new RSA key with only public components.
369 ///
370 /// `n` is the modulus common to both public and private key.
371 /// `e` is the public exponent.
372 ///
373 /// This corresponds to [`RSA_new`] and uses [`RSA_set0_key`].
374 ///
375 /// [`RSA_new`]: https://www.openssl.org/docs/manmaster/crypto/RSA_new.html
376 /// [`RSA_set0_key`]: https://www.openssl.org/docs/manmaster/crypto/RSA_set0_key.html
377 pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack> {
378 unsafe {
379 let rsa = cvt_p(ffi::RSA_new())?;
380 RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), ptr::null_mut());
381 mem::forget((n, e));
382 Ok(Rsa::from_ptr(rsa))
383 }
384 }
385
386 from_pem! {
387 /// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing an RSA key.
388 ///
389 /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
390 #[corresponds(PEM_read_bio_RSA_PUBKEY)]
391 public_key_from_pem,
392 Rsa<Public>,
393 ffi::PEM_read_bio_RSA_PUBKEY
394 }
395
396 from_pem! {
397 /// Decodes a PEM-encoded PKCS#1 RSAPublicKey structure.
398 ///
399 /// The input should have a header of `-----BEGIN RSA PUBLIC KEY-----`.
400 #[corresponds(PEM_read_bio_RSAPublicKey)]
401 public_key_from_pem_pkcs1,
402 Rsa<Public>,
403 ffi::PEM_read_bio_RSAPublicKey
404 }
405
406 from_der! {
407 /// Decodes a DER-encoded SubjectPublicKeyInfo structure containing an RSA key.
408 #[corresponds(d2i_RSA_PUBKEY)]
409 public_key_from_der,
410 Rsa<Public>,
411 ffi::d2i_RSA_PUBKEY
412 }
413
414 from_der! {
415 /// Decodes a DER-encoded PKCS#1 RSAPublicKey structure.
416 #[corresponds(d2i_RSAPublicKey)]
417 public_key_from_der_pkcs1,
418 Rsa<Public>,
419 ffi::d2i_RSAPublicKey
420 }
421}
422
423pub struct RsaPrivateKeyBuilder {
424 rsa: Rsa<Private>,
425}
426
427impl RsaPrivateKeyBuilder {
428 /// Creates a new `RsaPrivateKeyBuilder`.
429 ///
430 /// `n` is the modulus common to both public and private key.
431 /// `e` is the public exponent and `d` is the private exponent.
432 ///
433 /// This corresponds to [`RSA_new`] and uses [`RSA_set0_key`].
434 ///
435 /// [`RSA_new`]: https://www.openssl.org/docs/manmaster/crypto/RSA_new.html
436 /// [`RSA_set0_key`]: https://www.openssl.org/docs/manmaster/crypto/RSA_set0_key.html
437 pub fn new(n: BigNum, e: BigNum, d: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
438 unsafe {
439 let rsa = cvt_p(ffi::RSA_new())?;
440 RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), d.as_ptr());
441 mem::forget((n, e, d));
442 Ok(RsaPrivateKeyBuilder {
443 rsa: Rsa::from_ptr(rsa),
444 })
445 }
446 }
447
448 /// Sets the factors of the Rsa key.
449 ///
450 /// `p` and `q` are the first and second factors of `n`.
451 #[corresponds(RSA_set0_factors)]
452 // FIXME should be infallible
453 pub fn set_factors(self, p: BigNum, q: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
454 unsafe {
455 RSA_set0_factors(self.rsa.as_ptr(), p.as_ptr(), q.as_ptr());
456 mem::forget((p, q));
457 }
458 Ok(self)
459 }
460
461 /// Sets the Chinese Remainder Theorem params of the Rsa key.
462 ///
463 /// `dmp1`, `dmq1`, and `iqmp` are the exponents and coefficient for
464 /// CRT calculations which is used to speed up RSA operations.
465 #[corresponds(RSA_set0_crt_params)]
466 // FIXME should be infallible
467 pub fn set_crt_params(
468 self,
469 dmp1: BigNum,
470 dmq1: BigNum,
471 iqmp: BigNum,
472 ) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
473 unsafe {
474 RSA_set0_crt_params(
475 self.rsa.as_ptr(),
476 dmp1.as_ptr(),
477 dmq1.as_ptr(),
478 iqmp.as_ptr(),
479 );
480 mem::forget((dmp1, dmq1, iqmp));
481 }
482 Ok(self)
483 }
484
485 /// Returns the Rsa key.
486 pub fn build(self) -> Rsa<Private> {
487 self.rsa
488 }
489}
490
491impl Rsa<Private> {
492 /// Creates a new RSA key with private components (public components are assumed).
493 ///
494 /// This a convenience method over:
495 /// ```
496 /// # use openssl::rsa::RsaPrivateKeyBuilder;
497 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
498 /// # let bn = || openssl::bn::BigNum::new().unwrap();
499 /// # let (n, e, d, p, q, dmp1, dmq1, iqmp) = (bn(), bn(), bn(), bn(), bn(), bn(), bn(), bn());
500 /// RsaPrivateKeyBuilder::new(n, e, d)?
501 /// .set_factors(p, q)?
502 /// .set_crt_params(dmp1, dmq1, iqmp)?
503 /// .build();
504 /// # Ok(()) }
505 /// ```
506 #[allow(clippy::too_many_arguments, clippy::many_single_char_names)]
507 pub fn from_private_components(
508 n: BigNum,
509 e: BigNum,
510 d: BigNum,
511 p: BigNum,
512 q: BigNum,
513 dmp1: BigNum,
514 dmq1: BigNum,
515 iqmp: BigNum,
516 ) -> Result<Rsa<Private>, ErrorStack> {
517 Ok(RsaPrivateKeyBuilder::new(n, e, d)?
518 .set_factors(p, q)?
519 .set_crt_params(dmp1, dmq1, iqmp)?
520 .build())
521 }
522
523 /// Generates a public/private key pair with the specified size.
524 ///
525 /// The public exponent will be 65537.
526 #[corresponds(RSA_generate_key_ex)]
527 pub fn generate(bits: u32) -> Result<Rsa<Private>, ErrorStack> {
528 let e = BigNum::from_u32(ffi::RSA_F4 as u32)?;
529 Rsa::generate_with_e(bits, &e)
530 }
531
532 /// Generates a public/private key pair with the specified size and a custom exponent.
533 ///
534 /// Unless you have specific needs and know what you're doing, use `Rsa::generate` instead.
535 #[corresponds(RSA_generate_key_ex)]
536 pub fn generate_with_e(bits: u32, e: &BigNumRef) -> Result<Rsa<Private>, ErrorStack> {
537 unsafe {
538 let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?);
539 cvt(ffi::RSA_generate_key_ex(
540 rsa.0,
541 bits as c_int,
542 e.as_ptr(),
543 ptr::null_mut(),
544 ))?;
545 Ok(rsa)
546 }
547 }
548
549 // FIXME these need to identify input formats
550 private_key_from_pem! {
551 /// Deserializes a private key from a PEM-encoded PKCS#1 RSAPrivateKey structure.
552 #[corresponds(PEM_read_bio_RSAPrivateKey)]
553 private_key_from_pem,
554
555 /// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
556 #[corresponds(PEM_read_bio_RSAPrivateKey)]
557 private_key_from_pem_passphrase,
558
559 /// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
560 ///
561 /// The callback should fill the password into the provided buffer and return its length.
562 #[corresponds(PEM_read_bio_RSAPrivateKey)]
563 private_key_from_pem_callback,
564 Rsa<Private>,
565 ffi::PEM_read_bio_RSAPrivateKey
566 }
567
568 from_der! {
569 /// Decodes a DER-encoded PKCS#1 RSAPrivateKey structure.
570 #[corresponds(d2i_RSAPrivateKey)]
571 private_key_from_der,
572 Rsa<Private>,
573 ffi::d2i_RSAPrivateKey
574 }
575}
576
577impl<T> fmt::Debug for Rsa<T> {
578 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
579 write!(f, "Rsa")
580 }
581}
582
583cfg_if! {
584 if #[cfg(any(ossl110, libressl273, boringssl))] {
585 use ffi::{
586 RSA_get0_key, RSA_get0_factors, RSA_get0_crt_params, RSA_set0_key, RSA_set0_factors,
587 RSA_set0_crt_params,
588 };
589 } else {
590 #[allow(bad_style)]
591 unsafe fn RSA_get0_key(
592 r: *const ffi::RSA,
593 n: *mut *const ffi::BIGNUM,
594 e: *mut *const ffi::BIGNUM,
595 d: *mut *const ffi::BIGNUM,
596 ) {
597 if !n.is_null() {
598 *n = (*r).n;
599 }
600 if !e.is_null() {
601 *e = (*r).e;
602 }
603 if !d.is_null() {
604 *d = (*r).d;
605 }
606 }
607
608 #[allow(bad_style)]
609 unsafe fn RSA_get0_factors(
610 r: *const ffi::RSA,
611 p: *mut *const ffi::BIGNUM,
612 q: *mut *const ffi::BIGNUM,
613 ) {
614 if !p.is_null() {
615 *p = (*r).p;
616 }
617 if !q.is_null() {
618 *q = (*r).q;
619 }
620 }
621
622 #[allow(bad_style)]
623 unsafe fn RSA_get0_crt_params(
624 r: *const ffi::RSA,
625 dmp1: *mut *const ffi::BIGNUM,
626 dmq1: *mut *const ffi::BIGNUM,
627 iqmp: *mut *const ffi::BIGNUM,
628 ) {
629 if !dmp1.is_null() {
630 *dmp1 = (*r).dmp1;
631 }
632 if !dmq1.is_null() {
633 *dmq1 = (*r).dmq1;
634 }
635 if !iqmp.is_null() {
636 *iqmp = (*r).iqmp;
637 }
638 }
639
640 #[allow(bad_style)]
641 unsafe fn RSA_set0_key(
642 r: *mut ffi::RSA,
643 n: *mut ffi::BIGNUM,
644 e: *mut ffi::BIGNUM,
645 d: *mut ffi::BIGNUM,
646 ) -> c_int {
647 (*r).n = n;
648 (*r).e = e;
649 (*r).d = d;
650 1
651 }
652
653 #[allow(bad_style)]
654 unsafe fn RSA_set0_factors(
655 r: *mut ffi::RSA,
656 p: *mut ffi::BIGNUM,
657 q: *mut ffi::BIGNUM,
658 ) -> c_int {
659 (*r).p = p;
660 (*r).q = q;
661 1
662 }
663
664 #[allow(bad_style)]
665 unsafe fn RSA_set0_crt_params(
666 r: *mut ffi::RSA,
667 dmp1: *mut ffi::BIGNUM,
668 dmq1: *mut ffi::BIGNUM,
669 iqmp: *mut ffi::BIGNUM,
670 ) -> c_int {
671 (*r).dmp1 = dmp1;
672 (*r).dmq1 = dmq1;
673 (*r).iqmp = iqmp;
674 1
675 }
676 }
677}
678
679#[cfg(test)]
680mod test {
681 use crate::symm::Cipher;
682
683 use super::*;
684
685 #[test]
686 fn test_from_password() {
687 let key = include_bytes!("../test/rsa-encrypted.pem");
688 Rsa::private_key_from_pem_passphrase(key, b"mypass").unwrap();
689 }
690
691 #[test]
692 fn test_from_password_callback() {
693 let mut password_queried = false;
694 let key = include_bytes!("../test/rsa-encrypted.pem");
695 Rsa::private_key_from_pem_callback(key, |password| {
696 password_queried = true;
697 password[..6].copy_from_slice(b"mypass");
698 Ok(6)
699 })
700 .unwrap();
701
702 assert!(password_queried);
703 }
704
705 #[test]
706 fn test_to_password() {
707 let key = Rsa::generate(2048).unwrap();
708 let pem = key
709 .private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar")
710 .unwrap();
711 Rsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
712 assert!(Rsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
713 }
714
715 #[test]
716 fn test_public_encrypt_private_decrypt_with_padding() {
717 let key = include_bytes!("../test/rsa.pem.pub");
718 let public_key = Rsa::public_key_from_pem(key).unwrap();
719
720 let mut result = vec![0; public_key.size() as usize];
721 let original_data = b"This is test";
722 let len = public_key
723 .public_encrypt(original_data, &mut result, Padding::PKCS1)
724 .unwrap();
725 assert_eq!(len, 256);
726
727 let pkey = include_bytes!("../test/rsa.pem");
728 let private_key = Rsa::private_key_from_pem(pkey).unwrap();
729 let mut dec_result = vec![0; private_key.size() as usize];
730 let len = private_key
731 .private_decrypt(&result, &mut dec_result, Padding::PKCS1)
732 .unwrap();
733
734 assert_eq!(&dec_result[..len], original_data);
735 }
736
737 #[test]
738 fn test_private_encrypt() {
739 let k0 = super::Rsa::generate(512).unwrap();
740 let k0pkey = k0.public_key_to_pem().unwrap();
741 let k1 = super::Rsa::public_key_from_pem(&k0pkey).unwrap();
742
743 let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
744
745 let mut emesg = vec![0; k0.size() as usize];
746 k0.private_encrypt(&msg, &mut emesg, Padding::PKCS1)
747 .unwrap();
748 let mut dmesg = vec![0; k1.size() as usize];
749 let len = k1
750 .public_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
751 .unwrap();
752 assert_eq!(msg, &dmesg[..len]);
753 }
754
755 #[test]
756 fn test_public_encrypt() {
757 let k0 = super::Rsa::generate(512).unwrap();
758 let k0pkey = k0.private_key_to_pem().unwrap();
759 let k1 = super::Rsa::private_key_from_pem(&k0pkey).unwrap();
760
761 let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
762
763 let mut emesg = vec![0; k0.size() as usize];
764 k0.public_encrypt(&msg, &mut emesg, Padding::PKCS1).unwrap();
765 let mut dmesg = vec![0; k1.size() as usize];
766 let len = k1
767 .private_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
768 .unwrap();
769 assert_eq!(msg, &dmesg[..len]);
770 }
771
772 #[test]
773 fn test_public_key_from_pem_pkcs1() {
774 let key = include_bytes!("../test/pkcs1.pem.pub");
775 Rsa::public_key_from_pem_pkcs1(key).unwrap();
776 }
777
778 #[test]
779 #[should_panic]
780 fn test_public_key_from_pem_pkcs1_file_panic() {
781 let key = include_bytes!("../test/key.pem.pub");
782 Rsa::public_key_from_pem_pkcs1(key).unwrap();
783 }
784
785 #[test]
786 fn test_public_key_to_pem_pkcs1() {
787 let keypair = super::Rsa::generate(512).unwrap();
788 let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
789 super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
790 }
791
792 #[test]
793 #[should_panic]
794 fn test_public_key_from_pem_pkcs1_generate_panic() {
795 let keypair = super::Rsa::generate(512).unwrap();
796 let pubkey_pem = keypair.public_key_to_pem().unwrap();
797 super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
798 }
799
800 #[test]
801 fn test_pem_pkcs1_encrypt() {
802 let keypair = super::Rsa::generate(2048).unwrap();
803 let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
804 let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
805 let msg = b"Hello, world!";
806
807 let mut encrypted = vec![0; pubkey.size() as usize];
808 let len = pubkey
809 .public_encrypt(msg, &mut encrypted, Padding::PKCS1)
810 .unwrap();
811 assert!(len > msg.len());
812 let mut decrypted = vec![0; keypair.size() as usize];
813 let len = keypair
814 .private_decrypt(&encrypted, &mut decrypted, Padding::PKCS1)
815 .unwrap();
816 assert_eq!(len, msg.len());
817 assert_eq!(&decrypted[..len], msg);
818 }
819
820 #[test]
821 fn test_pem_pkcs1_padding() {
822 let keypair = super::Rsa::generate(2048).unwrap();
823 let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
824 let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
825 let msg = b"foo";
826
827 let mut encrypted1 = vec![0; pubkey.size() as usize];
828 let mut encrypted2 = vec![0; pubkey.size() as usize];
829 let len1 = pubkey
830 .public_encrypt(msg, &mut encrypted1, Padding::PKCS1)
831 .unwrap();
832 let len2 = pubkey
833 .public_encrypt(msg, &mut encrypted2, Padding::PKCS1)
834 .unwrap();
835 assert!(len1 > (msg.len() + 1));
836 assert_eq!(len1, len2);
837 assert_ne!(encrypted1, encrypted2);
838 }
839
840 #[test]
841 #[allow(clippy::redundant_clone)]
842 fn clone() {
843 let key = Rsa::generate(2048).unwrap();
844 drop(key.clone());
845 }
846
847 #[test]
848 fn generate_with_e() {
849 let e = BigNum::from_u32(0x10001).unwrap();
850 Rsa::generate_with_e(2048, &e).unwrap();
851 }
852}
853