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 //! ``` 26 use cfg_if::cfg_if; 27 use foreign_types::{ForeignType, ForeignTypeRef}; 28 use libc::c_int; 29 use std::fmt; 30 use std::mem; 31 use std::ptr; 32 33 use crate::bn::{BigNum, BigNumRef}; 34 use crate::error::ErrorStack; 35 use crate::pkey::{HasPrivate, HasPublic, Private, Public}; 36 use crate::util::ForeignTypeRefExt; 37 use crate::{cvt, cvt_n, cvt_p, LenType}; 38 use 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)] 46 pub struct Padding(c_int); 47 48 impl 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. from_raw(value: c_int) -> Padding55 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)] as_raw(&self) -> c_int61 pub fn as_raw(&self) -> c_int { 62 self.0 63 } 64 } 65 66 generic_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 77 impl<T> Clone for Rsa<T> { clone(&self) -> Rsa<T>78 fn clone(&self) -> Rsa<T> { 79 (**self).to_owned() 80 } 81 } 82 83 impl<T> ToOwned for RsaRef<T> { 84 type Owned = Rsa<T>; 85 to_owned(&self) -> Rsa<T>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 94 impl<T> RsaRef<T> 95 where 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)] private_decrypt( &self, from: &[u8], to: &mut [u8], padding: Padding, ) -> Result<usize, ErrorStack>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)] private_encrypt( &self, from: &[u8], to: &mut [u8], padding: Padding, ) -> Result<usize, ErrorStack>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)] d(&self) -> &BigNumRef177 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)] p(&self) -> Option<&BigNumRef>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)] q(&self) -> Option<&BigNumRef>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)] dmp1(&self) -> Option<&BigNumRef>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)] dmq1(&self) -> Option<&BigNumRef>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)] iqmp(&self) -> Option<&BigNumRef>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)] check_key(&self) -> Result<bool, ErrorStack>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 250 impl<T> RsaRef<T> 251 where 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)] size(&self) -> u32288 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)] public_decrypt( &self, from: &[u8], to: &mut [u8], padding: Padding, ) -> Result<usize, ErrorStack>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)] public_encrypt( &self, from: &[u8], to: &mut [u8], padding: Padding, ) -> Result<usize, ErrorStack>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)] n(&self) -> &BigNumRef348 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)] e(&self) -> &BigNumRef358 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 367 impl 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 from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack>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 423 pub struct RsaPrivateKeyBuilder { 424 rsa: Rsa<Private>, 425 } 426 427 impl 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 new(n: BigNum, e: BigNum, d: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack>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 set_factors(self, p: BigNum, q: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack>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 set_crt_params( self, dmp1: BigNum, dmq1: BigNum, iqmp: BigNum, ) -> Result<RsaPrivateKeyBuilder, ErrorStack>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. build(self) -> Rsa<Private>486 pub fn build(self) -> Rsa<Private> { 487 self.rsa 488 } 489 } 490 491 impl 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)] from_private_components( n: BigNum, e: BigNum, d: BigNum, p: BigNum, q: BigNum, dmp1: BigNum, dmq1: BigNum, iqmp: BigNum, ) -> Result<Rsa<Private>, ErrorStack>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)] generate(bits: u32) -> Result<Rsa<Private>, ErrorStack>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)] generate_with_e(bits: u32, e: &BigNumRef) -> Result<Rsa<Private>, ErrorStack>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 577 impl<T> fmt::Debug for Rsa<T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result578 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 579 write!(f, "Rsa") 580 } 581 } 582 583 cfg_if! { 584 if #[cfg(any(ossl110, libressl273))] { 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)] 680 mod test { 681 use crate::symm::Cipher; 682 683 use super::*; 684 685 #[test] test_from_password()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] test_from_password_callback()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] test_to_password()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] test_public_encrypt_private_decrypt_with_padding()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] test_private_encrypt()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] test_public_encrypt()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] test_public_key_from_pem_pkcs1()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] test_public_key_from_pem_pkcs1_file_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] test_public_key_to_pem_pkcs1()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] test_public_key_from_pem_pkcs1_generate_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] test_pem_pkcs1_encrypt()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] test_pem_pkcs1_padding()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)] clone()842 fn clone() { 843 let key = Rsa::generate(2048).unwrap(); 844 drop(key.clone()); 845 } 846 847 #[test] generate_with_e()848 fn generate_with_e() { 849 let e = BigNum::from_u32(0x10001).unwrap(); 850 Rsa::generate_with_e(2048, &e).unwrap(); 851 } 852 } 853