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