1use foreign_types::{ForeignType, ForeignTypeRef};
27use libc::c_int;
28use openssl_macros::corresponds;
29use std::fmt;
30use std::mem;
31use std::ptr;
32
33use crate::bn::{BigNum, BigNumRef};
34use crate::error::ErrorStack;
35use crate::ffi;
36use crate::pkey::{HasPrivate, HasPublic, Private, Public};
37use crate::try_int;
38use crate::{cvt, cvt_n, cvt_p};
39
40pub const EVP_PKEY_OP_SIGN: c_int = 1 << 3;
41pub const EVP_PKEY_OP_VERIFY: c_int = 1 << 4;
42pub const EVP_PKEY_OP_VERIFYRECOVER: c_int = 1 << 5;
43pub const EVP_PKEY_OP_SIGNCTX: c_int = 1 << 6;
44pub const EVP_PKEY_OP_VERIFYCTX: c_int = 1 << 7;
45pub const EVP_PKEY_OP_ENCRYPT: c_int = 1 << 8;
46pub const EVP_PKEY_OP_DECRYPT: c_int = 1 << 9;
47
48pub const EVP_PKEY_OP_TYPE_SIG: c_int = EVP_PKEY_OP_SIGN
49 | EVP_PKEY_OP_VERIFY
50 | EVP_PKEY_OP_VERIFYRECOVER
51 | EVP_PKEY_OP_SIGNCTX
52 | EVP_PKEY_OP_VERIFYCTX;
53
54pub const EVP_PKEY_OP_TYPE_CRYPT: c_int = EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT;
55
56#[derive(Debug, Copy, Clone, PartialEq, Eq)]
62pub struct Padding(c_int);
63
64impl Padding {
65 pub const NONE: Padding = Padding(ffi::RSA_NO_PADDING);
66 pub const PKCS1: Padding = Padding(ffi::RSA_PKCS1_PADDING);
67 pub const PKCS1_OAEP: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING);
68 pub const PKCS1_PSS: Padding = Padding(ffi::RSA_PKCS1_PSS_PADDING);
69
70 #[must_use]
72 pub fn from_raw(value: c_int) -> Padding {
73 Padding(value)
74 }
75
76 #[allow(clippy::trivially_copy_pass_by_ref)]
78 #[must_use]
79 pub fn as_raw(&self) -> c_int {
80 self.0
81 }
82}
83
84generic_foreign_type_and_impl_send_sync! {
85 type CType = ffi::RSA;
86 fn drop = ffi::RSA_free;
87
88 pub struct Rsa<T>;
90
91 pub struct RsaRef<T>;
93}
94
95impl<T> Clone for Rsa<T> {
96 fn clone(&self) -> Rsa<T> {
97 (**self).to_owned()
98 }
99}
100
101impl<T> ToOwned for RsaRef<T> {
102 type Owned = Rsa<T>;
103
104 fn to_owned(&self) -> Rsa<T> {
105 unsafe {
106 ffi::RSA_up_ref(self.as_ptr());
107 Rsa::from_ptr(self.as_ptr())
108 }
109 }
110}
111
112impl<T> RsaRef<T>
113where
114 T: HasPrivate,
115{
116 private_key_to_pem! {
117 #[corresponds(PEM_write_bio_RSAPrivateKey)]
121 private_key_to_pem,
122 #[corresponds(PEM_write_bio_RSAPrivateKey)]
126 private_key_to_pem_passphrase,
127 ffi::PEM_write_bio_RSAPrivateKey
128 }
129
130 to_der! {
131 #[corresponds(i2d_RSAPrivateKey)]
133 private_key_to_der,
134 ffi::i2d_RSAPrivateKey
135 }
136
137 pub fn private_decrypt(
144 &self,
145 from: &[u8],
146 to: &mut [u8],
147 padding: Padding,
148 ) -> Result<usize, ErrorStack> {
149 assert!(i32::try_from(from.len()).is_ok());
150 assert!(to.len() >= self.size() as usize);
151
152 unsafe {
153 let len = cvt_n(ffi::RSA_private_decrypt(
154 from.len(),
155 from.as_ptr(),
156 to.as_mut_ptr(),
157 self.as_ptr(),
158 padding.0,
159 ))?;
160 Ok(len as usize)
161 }
162 }
163
164 pub fn private_encrypt(
171 &self,
172 from: &[u8],
173 to: &mut [u8],
174 padding: Padding,
175 ) -> Result<usize, ErrorStack> {
176 assert!(i32::try_from(from.len()).is_ok());
177 assert!(to.len() >= self.size() as usize);
178
179 unsafe {
180 let len = cvt_n(ffi::RSA_private_encrypt(
181 from.len(),
182 from.as_ptr(),
183 to.as_mut_ptr(),
184 self.as_ptr(),
185 padding.0,
186 ))?;
187 Ok(len as usize)
188 }
189 }
190
191 #[corresponds(RSA_get0_key)]
193 #[must_use]
194 pub fn d(&self) -> &BigNumRef {
195 unsafe {
196 let mut d = ptr::null();
197 RSA_get0_key(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut d);
198 BigNumRef::from_ptr(d.cast_mut())
199 }
200 }
201
202 #[corresponds(RSA_get0_factors)]
204 #[must_use]
205 pub fn p(&self) -> Option<&BigNumRef> {
206 unsafe {
207 let mut p = ptr::null();
208 RSA_get0_factors(self.as_ptr(), &mut p, ptr::null_mut());
209 if p.is_null() {
210 None
211 } else {
212 Some(BigNumRef::from_ptr(p.cast_mut()))
213 }
214 }
215 }
216
217 #[corresponds(RSA_get0_factors)]
219 #[must_use]
220 pub fn q(&self) -> Option<&BigNumRef> {
221 unsafe {
222 let mut q = ptr::null();
223 RSA_get0_factors(self.as_ptr(), ptr::null_mut(), &mut q);
224 if q.is_null() {
225 None
226 } else {
227 Some(BigNumRef::from_ptr(q.cast_mut()))
228 }
229 }
230 }
231
232 #[corresponds(RSA_get0_crt_params)]
234 #[must_use]
235 pub fn dmp1(&self) -> Option<&BigNumRef> {
236 unsafe {
237 let mut dp = ptr::null();
238 RSA_get0_crt_params(self.as_ptr(), &mut dp, ptr::null_mut(), ptr::null_mut());
239 if dp.is_null() {
240 None
241 } else {
242 Some(BigNumRef::from_ptr(dp.cast_mut()))
243 }
244 }
245 }
246
247 #[corresponds(RSA_get0_crt_params)]
249 #[must_use]
250 pub fn dmq1(&self) -> Option<&BigNumRef> {
251 unsafe {
252 let mut dq = ptr::null();
253 RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), &mut dq, ptr::null_mut());
254 if dq.is_null() {
255 None
256 } else {
257 Some(BigNumRef::from_ptr(dq.cast_mut()))
258 }
259 }
260 }
261
262 #[corresponds(RSA_get0_crt_params)]
264 #[must_use]
265 pub fn iqmp(&self) -> Option<&BigNumRef> {
266 unsafe {
267 let mut qi = ptr::null();
268 RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut qi);
269 if qi.is_null() {
270 None
271 } else {
272 Some(BigNumRef::from_ptr(qi.cast_mut()))
273 }
274 }
275 }
276
277 #[corresponds(RSA_check_key)]
279 #[allow(clippy::unnecessary_cast)]
280 pub fn check_key(&self) -> Result<bool, ErrorStack> {
281 unsafe {
282 let result = ffi::RSA_check_key(self.as_ptr()) as i32;
283 if result == -1 {
284 Err(ErrorStack::get())
285 } else {
286 Ok(result == 1)
287 }
288 }
289 }
290}
291
292impl<T> RsaRef<T>
293where
294 T: HasPublic,
295{
296 to_pem! {
297 #[corresponds(PEM_write_bio_RSA_PUBKEY)]
301 public_key_to_pem,
302 ffi::PEM_write_bio_RSA_PUBKEY
303 }
304
305 to_der! {
306 #[corresponds(i2d_RSA_PUBKEY)]
308 public_key_to_der,
309 ffi::i2d_RSA_PUBKEY
310 }
311
312 to_pem! {
313 #[corresponds(PEM_write_bio_RSAPublicKey)]
317 public_key_to_pem_pkcs1,
318 ffi::PEM_write_bio_RSAPublicKey
319 }
320
321 to_der! {
322 #[corresponds(i2d_RSAPublicKey)]
324 public_key_to_der_pkcs1,
325 ffi::i2d_RSAPublicKey
326 }
327
328 #[corresponds(RSA_size)]
330 #[allow(clippy::unnecessary_cast)]
331 #[must_use]
332 pub fn size(&self) -> u32 {
333 unsafe { ffi::RSA_size(self.as_ptr()) as u32 }
334 }
335
336 pub fn public_decrypt(
342 &self,
343 from: &[u8],
344 to: &mut [u8],
345 padding: Padding,
346 ) -> Result<usize, ErrorStack> {
347 assert!(i32::try_from(from.len()).is_ok());
348 assert!(to.len() >= self.size() as usize);
349
350 unsafe {
351 let len = cvt_n(ffi::RSA_public_decrypt(
352 from.len(),
353 from.as_ptr(),
354 to.as_mut_ptr(),
355 self.as_ptr(),
356 padding.0,
357 ))?;
358 Ok(len as usize)
359 }
360 }
361
362 pub fn public_encrypt(
368 &self,
369 from: &[u8],
370 to: &mut [u8],
371 padding: Padding,
372 ) -> Result<usize, ErrorStack> {
373 assert!(i32::try_from(from.len()).is_ok());
374 assert!(to.len() >= self.size() as usize);
375
376 unsafe {
377 let len = cvt_n(ffi::RSA_public_encrypt(
378 from.len(),
379 from.as_ptr(),
380 to.as_mut_ptr(),
381 self.as_ptr(),
382 padding.0,
383 ))?;
384 Ok(len as usize)
385 }
386 }
387
388 #[corresponds(RSA_get0_key)]
390 #[must_use]
391 pub fn n(&self) -> &BigNumRef {
392 unsafe {
393 let mut n = ptr::null();
394 RSA_get0_key(self.as_ptr(), &mut n, ptr::null_mut(), ptr::null_mut());
395 BigNumRef::from_ptr(n.cast_mut())
396 }
397 }
398
399 #[corresponds(RSA_get0_key)]
401 #[must_use]
402 pub fn e(&self) -> &BigNumRef {
403 unsafe {
404 let mut e = ptr::null();
405 RSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut e, ptr::null_mut());
406 BigNumRef::from_ptr(e.cast_mut())
407 }
408 }
409}
410
411impl Rsa<Public> {
412 #[corresponds(RSA_new)]
417 pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack> {
418 unsafe {
419 let rsa = cvt_p(ffi::RSA_new())?;
420 cvt(RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), ptr::null_mut()))?;
421 mem::forget((n, e));
422 Ok(Rsa::from_ptr(rsa))
423 }
424 }
425
426 from_pem! {
427 #[corresponds(PEM_read_bio_RSA_PUBKEY)]
431 public_key_from_pem,
432 Rsa<Public>,
433 ffi::PEM_read_bio_RSA_PUBKEY
434 }
435
436 from_pem! {
437 #[corresponds(PEM_read_bio_RSAPublicKey)]
441 public_key_from_pem_pkcs1,
442 Rsa<Public>,
443 ffi::PEM_read_bio_RSAPublicKey
444 }
445
446 from_der! {
447 #[corresponds(d2i_RSA_PUBKEY)]
449 public_key_from_der,
450 Rsa<Public>,
451 ffi::d2i_RSA_PUBKEY,
452 ::libc::c_long
453 }
454
455 from_der! {
456 #[corresponds(d2i_RSAPublicKey)]
458 public_key_from_der_pkcs1,
459 Rsa<Public>,
460 ffi::d2i_RSAPublicKey,
461 ::libc::c_long
462 }
463}
464
465pub struct RsaPrivateKeyBuilder {
466 rsa: Rsa<Private>,
467}
468
469impl RsaPrivateKeyBuilder {
470 #[corresponds(RSA_new)]
475 pub fn new(n: BigNum, e: BigNum, d: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
476 unsafe {
477 let rsa = cvt_p(ffi::RSA_new())?;
478 cvt(RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), d.as_ptr()))?;
479 mem::forget((n, e, d));
480 Ok(RsaPrivateKeyBuilder {
481 rsa: Rsa::from_ptr(rsa),
482 })
483 }
484 }
485
486 #[corresponds(RSA_set0_factors)]
490 pub fn set_factors(self, p: BigNum, q: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
491 unsafe {
492 cvt(RSA_set0_factors(self.rsa.as_ptr(), p.as_ptr(), q.as_ptr()))?;
493 mem::forget((p, q));
494 }
495 Ok(self)
496 }
497
498 #[corresponds(RSA_set0_crt_params)]
503 pub fn set_crt_params(
504 self,
505 dmp1: BigNum,
506 dmq1: BigNum,
507 iqmp: BigNum,
508 ) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
509 unsafe {
510 cvt(RSA_set0_crt_params(
511 self.rsa.as_ptr(),
512 dmp1.as_ptr(),
513 dmq1.as_ptr(),
514 iqmp.as_ptr(),
515 ))?;
516 mem::forget((dmp1, dmq1, iqmp));
517 }
518 Ok(self)
519 }
520
521 #[must_use]
523 pub fn build(self) -> Rsa<Private> {
524 self.rsa
525 }
526}
527
528impl Rsa<Private> {
529 #[allow(clippy::too_many_arguments, clippy::many_single_char_names)]
534 pub fn from_private_components(
535 n: BigNum,
536 e: BigNum,
537 d: BigNum,
538 p: BigNum,
539 q: BigNum,
540 dmp1: BigNum,
541 dmq1: BigNum,
542 iqmp: BigNum,
543 ) -> Result<Rsa<Private>, ErrorStack> {
544 Ok(RsaPrivateKeyBuilder::new(n, e, d)?
545 .set_factors(p, q)?
546 .set_crt_params(dmp1, dmq1, iqmp)?
547 .build())
548 }
549
550 #[corresponds(RSA_generate_key_ex)]
554 pub fn generate(bits: u32) -> Result<Rsa<Private>, ErrorStack> {
555 let e = BigNum::from_u32(ffi::RSA_F4 as u32)?;
556 Rsa::generate_with_e(bits, &e)
557 }
558
559 #[corresponds(RSA_generate_key_ex)]
563 pub fn generate_with_e(bits: u32, e: &BigNumRef) -> Result<Rsa<Private>, ErrorStack> {
564 unsafe {
565 let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?);
566 cvt(ffi::RSA_generate_key_ex(
567 rsa.0,
568 bits as c_int,
569 e.as_ptr(),
570 ptr::null_mut(),
571 ))?;
572 Ok(rsa)
573 }
574 }
575
576 private_key_from_pem! {
578 #[corresponds(PEM_read_bio_RSAPrivateKey)]
580 private_key_from_pem,
581
582 #[corresponds(PEM_read_bio_RSAPrivateKey)]
584 private_key_from_pem_passphrase,
585
586 #[corresponds(PEM_read_bio_RSAPrivateKey)]
590 private_key_from_pem_callback,
591 Rsa<Private>,
592 ffi::PEM_read_bio_RSAPrivateKey
593 }
594
595 from_der! {
596 #[corresponds(d2i_RSAPrivateKey)]
598 private_key_from_der,
599 Rsa<Private>,
600 ffi::d2i_RSAPrivateKey,
601 ::libc::c_long
602 }
603}
604
605impl<T> fmt::Debug for Rsa<T> {
606 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
607 write!(f, "Rsa")
608 }
609}
610
611use crate::ffi::{
612 RSA_get0_crt_params, RSA_get0_factors, RSA_get0_key, RSA_set0_crt_params, RSA_set0_factors,
613 RSA_set0_key,
614};
615
616#[cfg(test)]
617mod test {
618 use crate::symm::Cipher;
619
620 use super::*;
621
622 #[test]
623 fn test_from_password() {
624 let key = include_bytes!("../test/rsa-encrypted.pem");
625 Rsa::private_key_from_pem_passphrase(key, b"mypass").unwrap();
626 }
627
628 #[test]
629 fn test_from_password_callback() {
630 let mut password_queried = false;
631 let key = include_bytes!("../test/rsa-encrypted.pem");
632 Rsa::private_key_from_pem_callback(key, |password| {
633 password_queried = true;
634 password[..6].copy_from_slice(b"mypass");
635 Ok(6)
636 })
637 .unwrap();
638
639 assert!(password_queried);
640 }
641
642 #[test]
643 fn test_to_password() {
644 let key = Rsa::generate(2048).unwrap();
645 let pem = key
646 .private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar")
647 .unwrap();
648 Rsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
649 assert!(Rsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
650 }
651
652 #[test]
653 fn test_public_encrypt_private_decrypt_with_padding() {
654 let key = include_bytes!("../test/rsa.pem.pub");
655 let public_key = Rsa::public_key_from_pem(key).unwrap();
656
657 let mut result = vec![0; public_key.size() as usize];
658 let original_data = b"This is test";
659 let len = public_key
660 .public_encrypt(original_data, &mut result, Padding::PKCS1)
661 .unwrap();
662 assert_eq!(len, 256);
663
664 let pkey = include_bytes!("../test/rsa.pem");
665 let private_key = Rsa::private_key_from_pem(pkey).unwrap();
666 let mut dec_result = vec![0; private_key.size() as usize];
667 let len = private_key
668 .private_decrypt(&result, &mut dec_result, Padding::PKCS1)
669 .unwrap();
670
671 assert_eq!(&dec_result[..len], original_data);
672 }
673
674 #[test]
675 fn test_private_encrypt() {
676 let k0 = super::Rsa::generate(512).unwrap();
677 let k0pkey = k0.public_key_to_pem().unwrap();
678 let k1 = super::Rsa::public_key_from_pem(&k0pkey).unwrap();
679
680 let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
681
682 let mut emesg = vec![0; k0.size() as usize];
683 k0.private_encrypt(&msg, &mut emesg, Padding::PKCS1)
684 .unwrap();
685 let mut dmesg = vec![0; k1.size() as usize];
686 let len = k1
687 .public_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
688 .unwrap();
689 assert_eq!(msg, &dmesg[..len]);
690 }
691
692 #[test]
693 fn test_public_encrypt() {
694 let k0 = super::Rsa::generate(512).unwrap();
695 let k0pkey = k0.private_key_to_pem().unwrap();
696 let k1 = super::Rsa::private_key_from_pem(&k0pkey).unwrap();
697
698 let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
699
700 let mut emesg = vec![0; k0.size() as usize];
701 k0.public_encrypt(&msg, &mut emesg, Padding::PKCS1).unwrap();
702 let mut dmesg = vec![0; k1.size() as usize];
703 let len = k1
704 .private_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
705 .unwrap();
706 assert_eq!(msg, &dmesg[..len]);
707 }
708
709 #[test]
710 fn test_public_key_from_pem_pkcs1() {
711 let key = include_bytes!("../test/pkcs1.pem.pub");
712 Rsa::public_key_from_pem_pkcs1(key).unwrap();
713 }
714
715 #[test]
716 #[should_panic]
717 fn test_public_key_from_pem_pkcs1_file_panic() {
718 let key = include_bytes!("../test/key.pem.pub");
719 Rsa::public_key_from_pem_pkcs1(key).unwrap();
720 }
721
722 #[test]
723 fn test_public_key_to_pem_pkcs1() {
724 let keypair = super::Rsa::generate(512).unwrap();
725 let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
726 super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
727 }
728
729 #[test]
730 #[should_panic]
731 fn test_public_key_from_pem_pkcs1_generate_panic() {
732 let keypair = super::Rsa::generate(512).unwrap();
733 let pubkey_pem = keypair.public_key_to_pem().unwrap();
734 super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
735 }
736
737 #[test]
738 fn test_pem_pkcs1_encrypt() {
739 let keypair = super::Rsa::generate(2048).unwrap();
740 let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
741 let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
742 let msg = b"Hello, world!";
743
744 let mut encrypted = vec![0; pubkey.size() as usize];
745 let len = pubkey
746 .public_encrypt(msg, &mut encrypted, Padding::PKCS1)
747 .unwrap();
748 assert!(len > msg.len());
749 let mut decrypted = vec![0; keypair.size() as usize];
750 let len = keypair
751 .private_decrypt(&encrypted, &mut decrypted, Padding::PKCS1)
752 .unwrap();
753 assert_eq!(len, msg.len());
754 assert_eq!(&decrypted[..len], msg);
755 }
756
757 #[test]
758 fn test_pem_pkcs1_padding() {
759 let keypair = super::Rsa::generate(2048).unwrap();
760 let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
761 let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
762 let msg = b"foo";
763
764 let mut encrypted1 = vec![0; pubkey.size() as usize];
765 let mut encrypted2 = vec![0; pubkey.size() as usize];
766 let len1 = pubkey
767 .public_encrypt(msg, &mut encrypted1, Padding::PKCS1)
768 .unwrap();
769 let len2 = pubkey
770 .public_encrypt(msg, &mut encrypted2, Padding::PKCS1)
771 .unwrap();
772 assert!(len1 > (msg.len() + 1));
773 assert_eq!(len1, len2);
774 assert_ne!(encrypted1, encrypted2);
775 }
776
777 #[test]
778 #[allow(clippy::redundant_clone)]
779 fn clone() {
780 let key = Rsa::generate(2048).unwrap();
781 drop(key.clone());
782 }
783
784 #[test]
785 fn generate_with_e() {
786 let e = BigNum::from_u32(0x10001).unwrap();
787 Rsa::generate_with_e(2048, &e).unwrap();
788 }
789}