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