Coverage Report

Created: 2024-05-20 06:38

/rust/registry/src/index.crates.io-6f17d22bba15001f/openssl-0.10.62/src/rsa.rs
Line
Count
Source (jump to first uncovered line)
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
0
#[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.
55
0
    pub fn from_raw(value: c_int) -> Padding {
56
0
        Padding(value)
57
0
    }
58
59
    /// Returns the integer representation of `Padding`.
60
    #[allow(clippy::trivially_copy_pass_by_ref)]
61
0
    pub fn as_raw(&self) -> c_int {
62
0
        self.0
63
0
    }
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> {
78
0
    fn clone(&self) -> Rsa<T> {
79
0
        (**self).to_owned()
80
0
    }
81
}
82
83
impl<T> ToOwned for RsaRef<T> {
84
    type Owned = Rsa<T>;
85
86
0
    fn to_owned(&self) -> Rsa<T> {
87
0
        unsafe {
88
0
            ffi::RSA_up_ref(self.as_ptr());
89
0
            Rsa::from_ptr(self.as_ptr())
90
0
        }
91
0
    }
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)]
126
0
    pub fn private_decrypt(
127
0
        &self,
128
0
        from: &[u8],
129
0
        to: &mut [u8],
130
0
        padding: Padding,
131
0
    ) -> Result<usize, ErrorStack> {
132
0
        assert!(from.len() <= i32::max_value() as usize);
133
0
        assert!(to.len() >= self.size() as usize);
134
135
        unsafe {
136
0
            let len = cvt_n(ffi::RSA_private_decrypt(
137
0
                from.len() as LenType,
138
0
                from.as_ptr(),
139
0
                to.as_mut_ptr(),
140
0
                self.as_ptr(),
141
0
                padding.0,
142
0
            ))?;
143
0
            Ok(len as usize)
144
        }
145
0
    }
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)]
154
0
    pub fn private_encrypt(
155
0
        &self,
156
0
        from: &[u8],
157
0
        to: &mut [u8],
158
0
        padding: Padding,
159
0
    ) -> Result<usize, ErrorStack> {
160
0
        assert!(from.len() <= i32::max_value() as usize);
161
0
        assert!(to.len() >= self.size() as usize);
162
163
        unsafe {
164
0
            let len = cvt_n(ffi::RSA_private_encrypt(
165
0
                from.len() as LenType,
166
0
                from.as_ptr(),
167
0
                to.as_mut_ptr(),
168
0
                self.as_ptr(),
169
0
                padding.0,
170
0
            ))?;
171
0
            Ok(len as usize)
172
        }
173
0
    }
174
175
    /// Returns a reference to the private exponent of the key.
176
    #[corresponds(RSA_get0_key)]
177
0
    pub fn d(&self) -> &BigNumRef {
178
0
        unsafe {
179
0
            let mut d = ptr::null();
180
0
            RSA_get0_key(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut d);
181
0
            BigNumRef::from_const_ptr(d)
182
0
        }
183
0
    }
184
185
    /// Returns a reference to the first factor of the exponent of the key.
186
    #[corresponds(RSA_get0_factors)]
187
0
    pub fn p(&self) -> Option<&BigNumRef> {
188
0
        unsafe {
189
0
            let mut p = ptr::null();
190
0
            RSA_get0_factors(self.as_ptr(), &mut p, ptr::null_mut());
191
0
            BigNumRef::from_const_ptr_opt(p)
192
0
        }
193
0
    }
194
195
    /// Returns a reference to the second factor of the exponent of the key.
196
    #[corresponds(RSA_get0_factors)]
197
0
    pub fn q(&self) -> Option<&BigNumRef> {
198
0
        unsafe {
199
0
            let mut q = ptr::null();
200
0
            RSA_get0_factors(self.as_ptr(), ptr::null_mut(), &mut q);
201
0
            BigNumRef::from_const_ptr_opt(q)
202
0
        }
203
0
    }
204
205
    /// Returns a reference to the first exponent used for CRT calculations.
206
    #[corresponds(RSA_get0_crt_params)]
207
0
    pub fn dmp1(&self) -> Option<&BigNumRef> {
208
0
        unsafe {
209
0
            let mut dp = ptr::null();
210
0
            RSA_get0_crt_params(self.as_ptr(), &mut dp, ptr::null_mut(), ptr::null_mut());
211
0
            BigNumRef::from_const_ptr_opt(dp)
212
0
        }
213
0
    }
214
215
    /// Returns a reference to the second exponent used for CRT calculations.
216
    #[corresponds(RSA_get0_crt_params)]
217
0
    pub fn dmq1(&self) -> Option<&BigNumRef> {
218
0
        unsafe {
219
0
            let mut dq = ptr::null();
220
0
            RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), &mut dq, ptr::null_mut());
221
0
            BigNumRef::from_const_ptr_opt(dq)
222
0
        }
223
0
    }
224
225
    /// Returns a reference to the coefficient used for CRT calculations.
226
    #[corresponds(RSA_get0_crt_params)]
227
0
    pub fn iqmp(&self) -> Option<&BigNumRef> {
228
0
        unsafe {
229
0
            let mut qi = ptr::null();
230
0
            RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut qi);
231
0
            BigNumRef::from_const_ptr_opt(qi)
232
0
        }
233
0
    }
234
235
    /// Validates RSA parameters for correctness
236
    #[corresponds(RSA_check_key)]
237
    #[allow(clippy::unnecessary_cast)]
238
0
    pub fn check_key(&self) -> Result<bool, ErrorStack> {
239
0
        unsafe {
240
0
            let result = ffi::RSA_check_key(self.as_ptr()) as i32;
241
0
            if result == -1 {
242
0
                Err(ErrorStack::get())
243
            } else {
244
0
                Ok(result == 1)
245
            }
246
        }
247
0
    }
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)]
288
0
    pub fn size(&self) -> u32 {
289
0
        unsafe { ffi::RSA_size(self.as_ptr()) as u32 }
290
0
    }
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)]
298
0
    pub fn public_decrypt(
299
0
        &self,
300
0
        from: &[u8],
301
0
        to: &mut [u8],
302
0
        padding: Padding,
303
0
    ) -> Result<usize, ErrorStack> {
304
0
        assert!(from.len() <= i32::max_value() as usize);
305
0
        assert!(to.len() >= self.size() as usize);
306
307
        unsafe {
308
0
            let len = cvt_n(ffi::RSA_public_decrypt(
309
0
                from.len() as LenType,
310
0
                from.as_ptr(),
311
0
                to.as_mut_ptr(),
312
0
                self.as_ptr(),
313
0
                padding.0,
314
0
            ))?;
315
0
            Ok(len as usize)
316
        }
317
0
    }
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)]
325
0
    pub fn public_encrypt(
326
0
        &self,
327
0
        from: &[u8],
328
0
        to: &mut [u8],
329
0
        padding: Padding,
330
0
    ) -> Result<usize, ErrorStack> {
331
0
        assert!(from.len() <= i32::max_value() as usize);
332
0
        assert!(to.len() >= self.size() as usize);
333
334
        unsafe {
335
0
            let len = cvt_n(ffi::RSA_public_encrypt(
336
0
                from.len() as LenType,
337
0
                from.as_ptr(),
338
0
                to.as_mut_ptr(),
339
0
                self.as_ptr(),
340
0
                padding.0,
341
0
            ))?;
342
0
            Ok(len as usize)
343
        }
344
0
    }
345
346
    /// Returns a reference to the modulus of the key.
347
    #[corresponds(RSA_get0_key)]
348
0
    pub fn n(&self) -> &BigNumRef {
349
0
        unsafe {
350
0
            let mut n = ptr::null();
351
0
            RSA_get0_key(self.as_ptr(), &mut n, ptr::null_mut(), ptr::null_mut());
352
0
            BigNumRef::from_const_ptr(n)
353
0
        }
354
0
    }
355
356
    /// Returns a reference to the public exponent of the key.
357
    #[corresponds(RSA_get0_key)]
358
0
    pub fn e(&self) -> &BigNumRef {
359
0
        unsafe {
360
0
            let mut e = ptr::null();
361
0
            RSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut e, ptr::null_mut());
362
0
            BigNumRef::from_const_ptr(e)
363
0
        }
364
0
    }
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
377
0
    pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack> {
378
        unsafe {
379
0
            let rsa = cvt_p(ffi::RSA_new())?;
380
0
            RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), ptr::null_mut());
381
0
            mem::forget((n, e));
382
0
            Ok(Rsa::from_ptr(rsa))
383
        }
384
0
    }
385
386
0
    from_pem! {
387
0
        /// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing an RSA key.
388
0
        ///
389
0
        /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
390
0
        #[corresponds(PEM_read_bio_RSA_PUBKEY)]
391
0
        public_key_from_pem,
392
0
        Rsa<Public>,
393
0
        ffi::PEM_read_bio_RSA_PUBKEY
394
0
    }
395
396
0
    from_pem! {
397
0
        /// Decodes a PEM-encoded PKCS#1 RSAPublicKey structure.
398
0
        ///
399
0
        /// The input should have a header of `-----BEGIN RSA PUBLIC KEY-----`.
400
0
        #[corresponds(PEM_read_bio_RSAPublicKey)]
401
0
        public_key_from_pem_pkcs1,
402
0
        Rsa<Public>,
403
0
        ffi::PEM_read_bio_RSAPublicKey
404
0
    }
405
406
0
    from_der! {
407
0
        /// Decodes a DER-encoded SubjectPublicKeyInfo structure containing an RSA key.
408
0
        #[corresponds(d2i_RSA_PUBKEY)]
409
0
        public_key_from_der,
410
0
        Rsa<Public>,
411
0
        ffi::d2i_RSA_PUBKEY
412
0
    }
413
414
0
    from_der! {
415
0
        /// Decodes a DER-encoded PKCS#1 RSAPublicKey structure.
416
0
        #[corresponds(d2i_RSAPublicKey)]
417
0
        public_key_from_der_pkcs1,
418
0
        Rsa<Public>,
419
0
        ffi::d2i_RSAPublicKey
420
0
    }
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
437
0
    pub fn new(n: BigNum, e: BigNum, d: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
438
        unsafe {
439
0
            let rsa = cvt_p(ffi::RSA_new())?;
440
0
            RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), d.as_ptr());
441
0
            mem::forget((n, e, d));
442
0
            Ok(RsaPrivateKeyBuilder {
443
0
                rsa: Rsa::from_ptr(rsa),
444
0
            })
445
        }
446
0
    }
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
453
0
    pub fn set_factors(self, p: BigNum, q: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
454
0
        unsafe {
455
0
            RSA_set0_factors(self.rsa.as_ptr(), p.as_ptr(), q.as_ptr());
456
0
            mem::forget((p, q));
457
0
        }
458
0
        Ok(self)
459
0
    }
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
467
0
    pub fn set_crt_params(
468
0
        self,
469
0
        dmp1: BigNum,
470
0
        dmq1: BigNum,
471
0
        iqmp: BigNum,
472
0
    ) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
473
0
        unsafe {
474
0
            RSA_set0_crt_params(
475
0
                self.rsa.as_ptr(),
476
0
                dmp1.as_ptr(),
477
0
                dmq1.as_ptr(),
478
0
                iqmp.as_ptr(),
479
0
            );
480
0
            mem::forget((dmp1, dmq1, iqmp));
481
0
        }
482
0
        Ok(self)
483
0
    }
484
485
    /// Returns the Rsa key.
486
0
    pub fn build(self) -> Rsa<Private> {
487
0
        self.rsa
488
0
    }
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)]
507
0
    pub fn from_private_components(
508
0
        n: BigNum,
509
0
        e: BigNum,
510
0
        d: BigNum,
511
0
        p: BigNum,
512
0
        q: BigNum,
513
0
        dmp1: BigNum,
514
0
        dmq1: BigNum,
515
0
        iqmp: BigNum,
516
0
    ) -> Result<Rsa<Private>, ErrorStack> {
517
0
        Ok(RsaPrivateKeyBuilder::new(n, e, d)?
518
0
            .set_factors(p, q)?
519
0
            .set_crt_params(dmp1, dmq1, iqmp)?
520
0
            .build())
521
0
    }
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)]
527
0
    pub fn generate(bits: u32) -> Result<Rsa<Private>, ErrorStack> {
528
0
        let e = BigNum::from_u32(ffi::RSA_F4 as u32)?;
529
0
        Rsa::generate_with_e(bits, &e)
530
0
    }
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)]
536
0
    pub fn generate_with_e(bits: u32, e: &BigNumRef) -> Result<Rsa<Private>, ErrorStack> {
537
        unsafe {
538
0
            let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?);
539
0
            cvt(ffi::RSA_generate_key_ex(
540
0
                rsa.0,
541
0
                bits as c_int,
542
0
                e.as_ptr(),
543
0
                ptr::null_mut(),
544
0
            ))?;
545
0
            Ok(rsa)
546
        }
547
0
    }
548
549
    // FIXME these need to identify input formats
550
0
    private_key_from_pem! {
551
0
        /// Deserializes a private key from a PEM-encoded PKCS#1 RSAPrivateKey structure.
552
0
        #[corresponds(PEM_read_bio_RSAPrivateKey)]
553
0
        private_key_from_pem,
554
0
555
0
        /// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
556
0
        #[corresponds(PEM_read_bio_RSAPrivateKey)]
557
0
        private_key_from_pem_passphrase,
558
0
559
0
        /// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
560
0
        ///
561
0
        /// The callback should fill the password into the provided buffer and return its length.
562
0
        #[corresponds(PEM_read_bio_RSAPrivateKey)]
563
0
        private_key_from_pem_callback,
564
0
        Rsa<Private>,
565
0
        ffi::PEM_read_bio_RSAPrivateKey
566
0
    }
Unexecuted instantiation: <openssl::rsa::Rsa<openssl::pkey::Private>>::private_key_from_pem_passphrase::{closure#0}
Unexecuted instantiation: <openssl::rsa::Rsa<openssl::pkey::Private>>::private_key_from_pem::{closure#0}
Unexecuted instantiation: <openssl::rsa::Rsa<openssl::pkey::Private>>::private_key_from_pem_callback::<_>::{closure#0}
567
568
0
    from_der! {
569
0
        /// Decodes a DER-encoded PKCS#1 RSAPrivateKey structure.
570
0
        #[corresponds(d2i_RSAPrivateKey)]
571
0
        private_key_from_der,
572
0
        Rsa<Private>,
573
0
        ffi::d2i_RSAPrivateKey
574
0
    }
575
}
576
577
impl<T> fmt::Debug for Rsa<T> {
578
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
579
0
        write!(f, "Rsa")
580
0
    }
581
}
582
583
cfg_if! {
584
    if #[cfg(any(ossl110, libressl273, boringssl))] {
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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)]
842
    fn clone() {
843
        let key = Rsa::generate(2048).unwrap();
844
        drop(key.clone());
845
    }
846
847
    #[test]
848
    fn generate_with_e() {
849
        let e = BigNum::from_u32(0x10001).unwrap();
850
        Rsa::generate_with_e(2048, &e).unwrap();
851
    }
852
}