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