variant_ssl/
bn.rs

1//! BigNum implementation
2//!
3//! Large numbers are important for a cryptographic library.  OpenSSL implementation
4//! of BigNum uses dynamically assigned memory to store an array of bit chunks.  This
5//! allows numbers of any size to be compared and mathematical functions performed.
6//!
7//! OpenSSL wiki describes the [`BIGNUM`] data structure.
8//!
9//! # Examples
10//!
11//! ```
12//! use openssl::bn::BigNum;
13//! use openssl::error::ErrorStack;
14//!
15//! fn main() -> Result<(), ErrorStack> {
16//!   let a = BigNum::new()?; // a = 0
17//!   let b = BigNum::from_dec_str("1234567890123456789012345")?;
18//!   let c = &a * &b;
19//!   assert_eq!(a, c);
20//!   Ok(())
21//! }
22//! ```
23//!
24//! [`BIGNUM`]: https://wiki.openssl.org/index.php/Manual:Bn_internal(3)
25use cfg_if::cfg_if;
26use foreign_types::{ForeignType, ForeignTypeRef};
27use libc::c_int;
28use std::cmp::Ordering;
29use std::ffi::CString;
30use std::ops::{Add, Deref, Div, Mul, Neg, Rem, Shl, Shr, Sub};
31use std::{fmt, ptr};
32
33use crate::asn1::Asn1Integer;
34use crate::error::ErrorStack;
35use crate::string::OpensslString;
36use crate::{cvt, cvt_n, cvt_p, LenType};
37use openssl_macros::corresponds;
38
39cfg_if! {
40    if #[cfg(any(ossl110, libressl, awslc))] {
41        use ffi::{
42            BN_get_rfc3526_prime_1536, BN_get_rfc3526_prime_2048, BN_get_rfc3526_prime_3072, BN_get_rfc3526_prime_4096,
43            BN_get_rfc3526_prime_6144, BN_get_rfc3526_prime_8192, BN_is_negative,
44        };
45    } else if #[cfg(boringssl)] {
46        use ffi::BN_is_negative;
47    } else {
48        use ffi::{
49            get_rfc3526_prime_1536 as BN_get_rfc3526_prime_1536,
50            get_rfc3526_prime_2048 as BN_get_rfc3526_prime_2048,
51            get_rfc3526_prime_3072 as BN_get_rfc3526_prime_3072,
52            get_rfc3526_prime_4096 as BN_get_rfc3526_prime_4096,
53            get_rfc3526_prime_6144 as BN_get_rfc3526_prime_6144,
54            get_rfc3526_prime_8192 as BN_get_rfc3526_prime_8192,
55        };
56
57        #[allow(bad_style)]
58        unsafe fn BN_is_negative(bn: *const ffi::BIGNUM) -> c_int {
59            (*bn).neg
60        }
61    }
62}
63
64cfg_if! {
65    if #[cfg(any(ossl110, libressl))] {
66        use ffi::{
67            BN_get_rfc2409_prime_1024, BN_get_rfc2409_prime_768
68        };
69    } else if #[cfg(not(any(boringssl, awslc)))] {
70        use ffi::{
71            get_rfc2409_prime_1024 as BN_get_rfc2409_prime_1024,
72            get_rfc2409_prime_768 as BN_get_rfc2409_prime_768,
73        };
74    }
75}
76
77/// Options for the most significant bits of a randomly generated `BigNum`.
78pub struct MsbOption(c_int);
79
80impl MsbOption {
81    /// The most significant bit of the number may be 0.
82    pub const MAYBE_ZERO: MsbOption = MsbOption(-1);
83
84    /// The most significant bit of the number must be 1.
85    pub const ONE: MsbOption = MsbOption(0);
86
87    /// The most significant two bits of the number must be 1.
88    ///
89    /// The number of bits in the product of two such numbers will always be exactly twice the
90    /// number of bits in the original numbers.
91    pub const TWO_ONES: MsbOption = MsbOption(1);
92}
93
94foreign_type_and_impl_send_sync! {
95    type CType = ffi::BN_CTX;
96    fn drop = ffi::BN_CTX_free;
97
98    /// Temporary storage for BigNums on the secure heap
99    ///
100    /// BigNum values are stored dynamically and therefore can be expensive
101    /// to allocate.  BigNumContext and the OpenSSL [`BN_CTX`] structure are used
102    /// internally when passing BigNum values between subroutines.
103    ///
104    /// [`BN_CTX`]: https://docs.openssl.org/master/man3/BN_CTX_new/
105    pub struct BigNumContext;
106    /// Reference to [`BigNumContext`]
107    ///
108    /// [`BigNumContext`]: struct.BigNumContext.html
109    pub struct BigNumContextRef;
110}
111
112impl BigNumContext {
113    /// Returns a new `BigNumContext`.
114    #[corresponds(BN_CTX_new)]
115    pub fn new() -> Result<BigNumContext, ErrorStack> {
116        unsafe {
117            ffi::init();
118            cvt_p(ffi::BN_CTX_new()).map(BigNumContext)
119        }
120    }
121
122    /// Returns a new secure `BigNumContext`.
123    #[corresponds(BN_CTX_secure_new)]
124    #[cfg(ossl110)]
125    pub fn new_secure() -> Result<BigNumContext, ErrorStack> {
126        unsafe {
127            ffi::init();
128            cvt_p(ffi::BN_CTX_secure_new()).map(BigNumContext)
129        }
130    }
131}
132
133foreign_type_and_impl_send_sync! {
134    type CType = ffi::BIGNUM;
135    fn drop = ffi::BN_free;
136
137    /// Dynamically sized large number implementation
138    ///
139    /// Perform large number mathematics.  Create a new BigNum
140    /// with [`new`].  Perform standard mathematics on large numbers using
141    /// methods from [`Dref<Target = BigNumRef>`]
142    ///
143    /// OpenSSL documentation at [`BN_new`].
144    ///
145    /// [`new`]: struct.BigNum.html#method.new
146    /// [`Dref<Target = BigNumRef>`]: struct.BigNum.html#deref-methods
147    /// [`BN_new`]: https://docs.openssl.org/master/man3/BN_new/
148    ///
149    /// # Examples
150    /// ```
151    /// use openssl::bn::BigNum;
152    /// # use openssl::error::ErrorStack;
153    /// # fn bignums() -> Result< (), ErrorStack > {
154    /// let little_big = BigNum::from_u32(std::u32::MAX)?;
155    /// assert_eq!(*&little_big.num_bytes(), 4);
156    /// # Ok(())
157    /// # }
158    /// # fn main () { bignums(); }
159    /// ```
160    pub struct BigNum;
161    /// Reference to a [`BigNum`]
162    ///
163    /// [`BigNum`]: struct.BigNum.html
164    pub struct BigNumRef;
165}
166
167impl BigNumRef {
168    /// Erases the memory used by this `BigNum`, resetting its value to 0.
169    ///
170    /// This can be used to destroy sensitive data such as keys when they are no longer needed.
171    #[corresponds(BN_clear)]
172    pub fn clear(&mut self) {
173        unsafe { ffi::BN_clear(self.as_ptr()) }
174    }
175
176    /// Adds a `u32` to `self`.
177    #[corresponds(BN_add_word)]
178    pub fn add_word(&mut self, w: u32) -> Result<(), ErrorStack> {
179        unsafe { cvt(ffi::BN_add_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
180    }
181
182    /// Subtracts a `u32` from `self`.
183    #[corresponds(BN_sub_word)]
184    pub fn sub_word(&mut self, w: u32) -> Result<(), ErrorStack> {
185        unsafe { cvt(ffi::BN_sub_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
186    }
187
188    /// Multiplies a `u32` by `self`.
189    #[corresponds(BN_mul_word)]
190    pub fn mul_word(&mut self, w: u32) -> Result<(), ErrorStack> {
191        unsafe { cvt(ffi::BN_mul_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
192    }
193
194    /// Divides `self` by a `u32`, returning the remainder.
195    #[corresponds(BN_div_word)]
196    #[allow(clippy::useless_conversion)]
197    pub fn div_word(&mut self, w: u32) -> Result<u64, ErrorStack> {
198        unsafe {
199            let r = ffi::BN_div_word(self.as_ptr(), w.into());
200            if r == ffi::BN_ULONG::MAX {
201                Err(ErrorStack::get())
202            } else {
203                Ok(r.into())
204            }
205        }
206    }
207
208    /// Returns the result of `self` modulo `w`.
209    #[corresponds(BN_mod_word)]
210    #[allow(clippy::useless_conversion)]
211    pub fn mod_word(&self, w: u32) -> Result<u64, ErrorStack> {
212        unsafe {
213            let r = ffi::BN_mod_word(self.as_ptr(), w.into());
214            if r == ffi::BN_ULONG::MAX {
215                Err(ErrorStack::get())
216            } else {
217                Ok(r.into())
218            }
219        }
220    }
221
222    /// Places a cryptographically-secure pseudo-random nonnegative
223    /// number less than `self` in `rnd`.
224    #[corresponds(BN_rand_range)]
225    pub fn rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> {
226        unsafe { cvt(ffi::BN_rand_range(rnd.as_ptr(), self.as_ptr())).map(|_| ()) }
227    }
228
229    /// The cryptographically weak counterpart to `rand_in_range`.
230    #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
231    #[corresponds(BN_pseudo_rand_range)]
232    pub fn pseudo_rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> {
233        unsafe { cvt(ffi::BN_pseudo_rand_range(rnd.as_ptr(), self.as_ptr())).map(|_| ()) }
234    }
235
236    /// Sets bit `n`. Equivalent to `self |= (1 << n)`.
237    ///
238    /// When setting a bit outside of `self`, it is expanded.
239    #[corresponds(BN_set_bit)]
240    #[allow(clippy::useless_conversion)]
241    pub fn set_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
242        unsafe { cvt(ffi::BN_set_bit(self.as_ptr(), n.into())).map(|_| ()) }
243    }
244
245    /// Clears bit `n`, setting it to 0. Equivalent to `self &= ~(1 << n)`.
246    ///
247    /// When clearing a bit outside of `self`, an error is returned.
248    #[corresponds(BN_clear_bit)]
249    #[allow(clippy::useless_conversion)]
250    pub fn clear_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
251        unsafe { cvt(ffi::BN_clear_bit(self.as_ptr(), n.into())).map(|_| ()) }
252    }
253
254    /// Returns `true` if the `n`th bit of `self` is set to 1, `false` otherwise.
255    #[corresponds(BN_is_bit_set)]
256    #[allow(clippy::useless_conversion)]
257    pub fn is_bit_set(&self, n: i32) -> bool {
258        unsafe { ffi::BN_is_bit_set(self.as_ptr(), n.into()) == 1 }
259    }
260
261    /// Truncates `self` to the lowest `n` bits.
262    ///
263    /// An error occurs if `self` is already shorter than `n` bits.
264    #[corresponds(BN_mask_bits)]
265    #[allow(clippy::useless_conversion)]
266    pub fn mask_bits(&mut self, n: i32) -> Result<(), ErrorStack> {
267        unsafe { cvt(ffi::BN_mask_bits(self.as_ptr(), n.into())).map(|_| ()) }
268    }
269
270    /// Places `a << 1` in `self`.  Equivalent to `self * 2`.
271    #[corresponds(BN_lshift1)]
272    pub fn lshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack> {
273        unsafe { cvt(ffi::BN_lshift1(self.as_ptr(), a.as_ptr())).map(|_| ()) }
274    }
275
276    /// Places `a >> 1` in `self`. Equivalent to `self / 2`.
277    #[corresponds(BN_rshift1)]
278    pub fn rshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack> {
279        unsafe { cvt(ffi::BN_rshift1(self.as_ptr(), a.as_ptr())).map(|_| ()) }
280    }
281
282    /// Places `a + b` in `self`.  [`core::ops::Add`] is also implemented for `BigNumRef`.
283    ///
284    /// [`core::ops::Add`]: struct.BigNumRef.html#method.add
285    #[corresponds(BN_add)]
286    pub fn checked_add(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack> {
287        unsafe { cvt(ffi::BN_add(self.as_ptr(), a.as_ptr(), b.as_ptr())).map(|_| ()) }
288    }
289
290    /// Places `a - b` in `self`. [`core::ops::Sub`] is also implemented for `BigNumRef`.
291    ///
292    /// [`core::ops::Sub`]: struct.BigNumRef.html#method.sub
293    #[corresponds(BN_sub)]
294    pub fn checked_sub(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack> {
295        unsafe { cvt(ffi::BN_sub(self.as_ptr(), a.as_ptr(), b.as_ptr())).map(|_| ()) }
296    }
297
298    /// Places `a << n` in `self`.  Equivalent to `a * 2 ^ n`.
299    #[corresponds(BN_lshift)]
300    #[allow(clippy::useless_conversion)]
301    pub fn lshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack> {
302        unsafe { cvt(ffi::BN_lshift(self.as_ptr(), a.as_ptr(), n.into())).map(|_| ()) }
303    }
304
305    /// Places `a >> n` in `self`. Equivalent to `a / 2 ^ n`.
306    #[corresponds(BN_rshift)]
307    #[allow(clippy::useless_conversion)]
308    pub fn rshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack> {
309        unsafe { cvt(ffi::BN_rshift(self.as_ptr(), a.as_ptr(), n.into())).map(|_| ()) }
310    }
311
312    /// Creates a new BigNum with the same value.
313    #[corresponds(BN_dup)]
314    pub fn to_owned(&self) -> Result<BigNum, ErrorStack> {
315        unsafe { cvt_p(ffi::BN_dup(self.as_ptr())).map(|b| BigNum::from_ptr(b)) }
316    }
317
318    /// Sets the sign of `self`.  Pass true to set `self` to a negative.  False sets
319    /// `self` positive.
320    #[corresponds(BN_set_negative)]
321    pub fn set_negative(&mut self, negative: bool) {
322        unsafe { ffi::BN_set_negative(self.as_ptr(), negative as c_int) }
323    }
324
325    /// Compare the absolute values of `self` and `oth`.
326    ///
327    /// # Examples
328    ///
329    /// ```
330    /// # use openssl::bn::BigNum;
331    /// # use std::cmp::Ordering;
332    /// let s = -BigNum::from_u32(8).unwrap();
333    /// let o = BigNum::from_u32(8).unwrap();
334    ///
335    /// assert_eq!(s.ucmp(&o), Ordering::Equal);
336    /// ```
337    #[corresponds(BN_ucmp)]
338    pub fn ucmp(&self, oth: &BigNumRef) -> Ordering {
339        unsafe { ffi::BN_ucmp(self.as_ptr(), oth.as_ptr()).cmp(&0) }
340    }
341
342    /// Returns `true` if `self` is negative.
343    #[corresponds(BN_is_negative)]
344    pub fn is_negative(&self) -> bool {
345        unsafe { BN_is_negative(self.as_ptr()) == 1 }
346    }
347
348    /// Returns `true` is `self` is even.
349    #[corresponds(BN_is_even)]
350    #[cfg(any(ossl110, boringssl, libressl, awslc))]
351    pub fn is_even(&self) -> bool {
352        !self.is_odd()
353    }
354
355    /// Returns `true` is `self` is odd.
356    #[corresponds(BN_is_odd)]
357    #[cfg(any(ossl110, boringssl, libressl, awslc))]
358    pub fn is_odd(&self) -> bool {
359        unsafe { ffi::BN_is_odd(self.as_ptr()) == 1 }
360    }
361
362    /// Returns the number of significant bits in `self`.
363    #[corresponds(BN_num_bits)]
364    #[allow(clippy::unnecessary_cast)]
365    pub fn num_bits(&self) -> i32 {
366        unsafe { ffi::BN_num_bits(self.as_ptr()) as i32 }
367    }
368
369    /// Returns the size of `self` in bytes. Implemented natively.
370    pub fn num_bytes(&self) -> i32 {
371        (self.num_bits() + 7) / 8
372    }
373
374    /// Generates a cryptographically strong pseudo-random `BigNum`, placing it in `self`.
375    ///
376    /// # Parameters
377    ///
378    /// * `bits`: Length of the number in bits.
379    /// * `msb`: The desired properties of the most significant bit. See [`constants`].
380    /// * `odd`: If `true`, the generated number will be odd.
381    ///
382    /// # Examples
383    ///
384    /// ```
385    /// use openssl::bn::{BigNum, MsbOption};
386    /// use openssl::error::ErrorStack;
387    ///
388    /// fn generate_random() -> Result< BigNum, ErrorStack > {
389    ///    let mut big = BigNum::new()?;
390    ///
391    ///    // Generates a 128-bit odd random number
392    ///    big.rand(128, MsbOption::MAYBE_ZERO, true);
393    ///    Ok((big))
394    /// }
395    /// ```
396    ///
397    /// [`constants`]: index.html#constants
398    #[corresponds(BN_rand)]
399    #[allow(clippy::useless_conversion)]
400    pub fn rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> {
401        unsafe {
402            cvt(ffi::BN_rand(
403                self.as_ptr(),
404                bits.into(),
405                msb.0,
406                odd as c_int,
407            ))
408            .map(|_| ())
409        }
410    }
411
412    /// The cryptographically weak counterpart to `rand`.  Not suitable for key generation.
413    #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
414    #[corresponds(BN_pseudo_rand)]
415    #[allow(clippy::useless_conversion)]
416    pub fn pseudo_rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> {
417        unsafe {
418            cvt(ffi::BN_pseudo_rand(
419                self.as_ptr(),
420                bits.into(),
421                msb.0,
422                odd as c_int,
423            ))
424            .map(|_| ())
425        }
426    }
427
428    /// Generates a prime number, placing it in `self`.
429    ///
430    /// # Parameters
431    ///
432    /// * `bits`: The length of the prime in bits (lower bound).
433    /// * `safe`: If true, returns a "safe" prime `p` so that `(p-1)/2` is also prime.
434    /// * `add`/`rem`: If `add` is set to `Some(add)`, `p % add == rem` will hold, where `p` is the
435    ///   generated prime and `rem` is `1` if not specified (`None`).
436    ///
437    /// # Examples
438    ///
439    /// ```
440    /// use openssl::bn::BigNum;
441    /// use openssl::error::ErrorStack;
442    ///
443    /// fn generate_weak_prime() -> Result< BigNum, ErrorStack > {
444    ///    let mut big = BigNum::new()?;
445    ///
446    ///    // Generates a 128-bit simple prime number
447    ///    big.generate_prime(128, false, None, None);
448    ///    Ok((big))
449    /// }
450    /// ```
451    #[corresponds(BN_generate_prime_ex)]
452    pub fn generate_prime(
453        &mut self,
454        bits: i32,
455        safe: bool,
456        add: Option<&BigNumRef>,
457        rem: Option<&BigNumRef>,
458    ) -> Result<(), ErrorStack> {
459        unsafe {
460            cvt(ffi::BN_generate_prime_ex(
461                self.as_ptr(),
462                bits as c_int,
463                safe as c_int,
464                add.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()),
465                rem.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()),
466                ptr::null_mut(),
467            ))
468            .map(|_| ())
469        }
470    }
471
472    /// Places the result of `a * b` in `self`.
473    /// [`core::ops::Mul`] is also implemented for `BigNumRef`.
474    ///
475    /// [`core::ops::Mul`]: struct.BigNumRef.html#method.mul
476    #[corresponds(BN_mul)]
477    pub fn checked_mul(
478        &mut self,
479        a: &BigNumRef,
480        b: &BigNumRef,
481        ctx: &mut BigNumContextRef,
482    ) -> Result<(), ErrorStack> {
483        unsafe {
484            cvt(ffi::BN_mul(
485                self.as_ptr(),
486                a.as_ptr(),
487                b.as_ptr(),
488                ctx.as_ptr(),
489            ))
490            .map(|_| ())
491        }
492    }
493
494    /// Places the result of `a / b` in `self`. The remainder is discarded.
495    /// [`core::ops::Div`] is also implemented for `BigNumRef`.
496    ///
497    /// [`core::ops::Div`]: struct.BigNumRef.html#method.div
498    #[corresponds(BN_div)]
499    pub fn checked_div(
500        &mut self,
501        a: &BigNumRef,
502        b: &BigNumRef,
503        ctx: &mut BigNumContextRef,
504    ) -> Result<(), ErrorStack> {
505        unsafe {
506            cvt(ffi::BN_div(
507                self.as_ptr(),
508                ptr::null_mut(),
509                a.as_ptr(),
510                b.as_ptr(),
511                ctx.as_ptr(),
512            ))
513            .map(|_| ())
514        }
515    }
516
517    /// Places the result of `a % b` in `self`.
518    #[corresponds(BN_div)]
519    pub fn checked_rem(
520        &mut self,
521        a: &BigNumRef,
522        b: &BigNumRef,
523        ctx: &mut BigNumContextRef,
524    ) -> Result<(), ErrorStack> {
525        unsafe {
526            cvt(ffi::BN_div(
527                ptr::null_mut(),
528                self.as_ptr(),
529                a.as_ptr(),
530                b.as_ptr(),
531                ctx.as_ptr(),
532            ))
533            .map(|_| ())
534        }
535    }
536
537    /// Places the result of `a / b` in `self` and `a % b` in `rem`.
538    #[corresponds(BN_div)]
539    pub fn div_rem(
540        &mut self,
541        rem: &mut BigNumRef,
542        a: &BigNumRef,
543        b: &BigNumRef,
544        ctx: &mut BigNumContextRef,
545    ) -> Result<(), ErrorStack> {
546        unsafe {
547            cvt(ffi::BN_div(
548                self.as_ptr(),
549                rem.as_ptr(),
550                a.as_ptr(),
551                b.as_ptr(),
552                ctx.as_ptr(),
553            ))
554            .map(|_| ())
555        }
556    }
557
558    /// Places the result of `a²` in `self`.
559    #[corresponds(BN_sqr)]
560    pub fn sqr(&mut self, a: &BigNumRef, ctx: &mut BigNumContextRef) -> Result<(), ErrorStack> {
561        unsafe { cvt(ffi::BN_sqr(self.as_ptr(), a.as_ptr(), ctx.as_ptr())).map(|_| ()) }
562    }
563
564    /// Places the result of `a mod m` in `self`.  As opposed to `div_rem`
565    /// the result is non-negative.
566    #[corresponds(BN_nnmod)]
567    pub fn nnmod(
568        &mut self,
569        a: &BigNumRef,
570        m: &BigNumRef,
571        ctx: &mut BigNumContextRef,
572    ) -> Result<(), ErrorStack> {
573        unsafe {
574            cvt(ffi::BN_nnmod(
575                self.as_ptr(),
576                a.as_ptr(),
577                m.as_ptr(),
578                ctx.as_ptr(),
579            ))
580            .map(|_| ())
581        }
582    }
583
584    /// Places the result of `(a + b) mod m` in `self`.
585    #[corresponds(BN_mod_add)]
586    pub fn mod_add(
587        &mut self,
588        a: &BigNumRef,
589        b: &BigNumRef,
590        m: &BigNumRef,
591        ctx: &mut BigNumContextRef,
592    ) -> Result<(), ErrorStack> {
593        unsafe {
594            cvt(ffi::BN_mod_add(
595                self.as_ptr(),
596                a.as_ptr(),
597                b.as_ptr(),
598                m.as_ptr(),
599                ctx.as_ptr(),
600            ))
601            .map(|_| ())
602        }
603    }
604
605    /// Places the result of `(a - b) mod m` in `self`.
606    #[corresponds(BN_mod_sub)]
607    pub fn mod_sub(
608        &mut self,
609        a: &BigNumRef,
610        b: &BigNumRef,
611        m: &BigNumRef,
612        ctx: &mut BigNumContextRef,
613    ) -> Result<(), ErrorStack> {
614        unsafe {
615            cvt(ffi::BN_mod_sub(
616                self.as_ptr(),
617                a.as_ptr(),
618                b.as_ptr(),
619                m.as_ptr(),
620                ctx.as_ptr(),
621            ))
622            .map(|_| ())
623        }
624    }
625
626    /// Places the result of `(a * b) mod m` in `self`.
627    #[corresponds(BN_mod_mul)]
628    pub fn mod_mul(
629        &mut self,
630        a: &BigNumRef,
631        b: &BigNumRef,
632        m: &BigNumRef,
633        ctx: &mut BigNumContextRef,
634    ) -> Result<(), ErrorStack> {
635        unsafe {
636            cvt(ffi::BN_mod_mul(
637                self.as_ptr(),
638                a.as_ptr(),
639                b.as_ptr(),
640                m.as_ptr(),
641                ctx.as_ptr(),
642            ))
643            .map(|_| ())
644        }
645    }
646
647    /// Places the result of `a² mod m` in `self`.
648    #[corresponds(BN_mod_sqr)]
649    pub fn mod_sqr(
650        &mut self,
651        a: &BigNumRef,
652        m: &BigNumRef,
653        ctx: &mut BigNumContextRef,
654    ) -> Result<(), ErrorStack> {
655        unsafe {
656            cvt(ffi::BN_mod_sqr(
657                self.as_ptr(),
658                a.as_ptr(),
659                m.as_ptr(),
660                ctx.as_ptr(),
661            ))
662            .map(|_| ())
663        }
664    }
665
666    /// Places into `self` the modular square root of `a` such that `self^2 = a (mod p)`
667    #[corresponds(BN_mod_sqrt)]
668    pub fn mod_sqrt(
669        &mut self,
670        a: &BigNumRef,
671        p: &BigNumRef,
672        ctx: &mut BigNumContextRef,
673    ) -> Result<(), ErrorStack> {
674        unsafe {
675            cvt_p(ffi::BN_mod_sqrt(
676                self.as_ptr(),
677                a.as_ptr(),
678                p.as_ptr(),
679                ctx.as_ptr(),
680            ))
681            .map(|_| ())
682        }
683    }
684
685    /// Places the result of `a^p` in `self`.
686    #[corresponds(BN_exp)]
687    pub fn exp(
688        &mut self,
689        a: &BigNumRef,
690        p: &BigNumRef,
691        ctx: &mut BigNumContextRef,
692    ) -> Result<(), ErrorStack> {
693        unsafe {
694            cvt(ffi::BN_exp(
695                self.as_ptr(),
696                a.as_ptr(),
697                p.as_ptr(),
698                ctx.as_ptr(),
699            ))
700            .map(|_| ())
701        }
702    }
703
704    /// Places the result of `a^p mod m` in `self`.
705    #[corresponds(BN_mod_exp)]
706    pub fn mod_exp(
707        &mut self,
708        a: &BigNumRef,
709        p: &BigNumRef,
710        m: &BigNumRef,
711        ctx: &mut BigNumContextRef,
712    ) -> Result<(), ErrorStack> {
713        unsafe {
714            cvt(ffi::BN_mod_exp(
715                self.as_ptr(),
716                a.as_ptr(),
717                p.as_ptr(),
718                m.as_ptr(),
719                ctx.as_ptr(),
720            ))
721            .map(|_| ())
722        }
723    }
724
725    /// Places the inverse of `a` modulo `n` in `self`.
726    #[corresponds(BN_mod_inverse)]
727    pub fn mod_inverse(
728        &mut self,
729        a: &BigNumRef,
730        n: &BigNumRef,
731        ctx: &mut BigNumContextRef,
732    ) -> Result<(), ErrorStack> {
733        unsafe {
734            cvt_p(ffi::BN_mod_inverse(
735                self.as_ptr(),
736                a.as_ptr(),
737                n.as_ptr(),
738                ctx.as_ptr(),
739            ))
740            .map(|_| ())
741        }
742    }
743
744    /// Places the greatest common denominator of `a` and `b` in `self`.
745    #[corresponds(BN_gcd)]
746    pub fn gcd(
747        &mut self,
748        a: &BigNumRef,
749        b: &BigNumRef,
750        ctx: &mut BigNumContextRef,
751    ) -> Result<(), ErrorStack> {
752        unsafe {
753            cvt(ffi::BN_gcd(
754                self.as_ptr(),
755                a.as_ptr(),
756                b.as_ptr(),
757                ctx.as_ptr(),
758            ))
759            .map(|_| ())
760        }
761    }
762
763    /// Checks whether `self` is prime.
764    ///
765    /// Performs a Miller-Rabin probabilistic primality test with `checks` iterations.
766    ///
767    /// # Return Value
768    ///
769    /// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`.
770    #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
771    #[corresponds(BN_is_prime_ex)]
772    #[allow(clippy::useless_conversion)]
773    pub fn is_prime(&self, checks: i32, ctx: &mut BigNumContextRef) -> Result<bool, ErrorStack> {
774        unsafe {
775            cvt_n(ffi::BN_is_prime_ex(
776                self.as_ptr(),
777                checks.into(),
778                ctx.as_ptr(),
779                ptr::null_mut(),
780            ))
781            .map(|r| r != 0)
782        }
783    }
784
785    /// Checks whether `self` is prime with optional trial division.
786    ///
787    /// If `do_trial_division` is `true`, first performs trial division by a number of small primes.
788    /// Then, like `is_prime`, performs a Miller-Rabin probabilistic primality test with `checks`
789    /// iterations.
790    ///
791    /// # Return Value
792    ///
793    /// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`.
794    #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
795    #[corresponds(BN_is_prime_fasttest_ex)]
796    #[allow(clippy::useless_conversion)]
797    pub fn is_prime_fasttest(
798        &self,
799        checks: i32,
800        ctx: &mut BigNumContextRef,
801        do_trial_division: bool,
802    ) -> Result<bool, ErrorStack> {
803        unsafe {
804            cvt_n(ffi::BN_is_prime_fasttest_ex(
805                self.as_ptr(),
806                checks.into(),
807                ctx.as_ptr(),
808                do_trial_division as c_int,
809                ptr::null_mut(),
810            ))
811            .map(|r| r != 0)
812        }
813    }
814
815    /// Returns a big-endian byte vector representation of the absolute value of `self`.
816    ///
817    /// `self` can be recreated by using `from_slice`.
818    ///
819    /// ```
820    /// # use openssl::bn::BigNum;
821    /// let s = -BigNum::from_u32(4543).unwrap();
822    /// let r = BigNum::from_u32(4543).unwrap();
823    ///
824    /// let s_vec = s.to_vec();
825    /// assert_eq!(BigNum::from_slice(&s_vec).unwrap(), r);
826    /// ```
827    #[corresponds(BN_bn2bin)]
828    pub fn to_vec(&self) -> Vec<u8> {
829        let size = self.num_bytes() as usize;
830        let mut v = Vec::with_capacity(size);
831        unsafe {
832            ffi::BN_bn2bin(self.as_ptr(), v.as_mut_ptr());
833            v.set_len(size);
834        }
835        v
836    }
837
838    /// Returns a big-endian byte vector representation of the absolute value of `self` padded
839    /// to `pad_to` bytes.
840    ///
841    /// If `pad_to` is less than `self.num_bytes()` then an error is returned.
842    ///
843    /// `self` can be recreated by using `from_slice`.
844    ///
845    /// ```
846    /// # use openssl::bn::BigNum;
847    /// let bn = BigNum::from_u32(0x4543).unwrap();
848    ///
849    /// let bn_vec = bn.to_vec_padded(4).unwrap();
850    /// assert_eq!(&bn_vec, &[0, 0, 0x45, 0x43]);
851    ///
852    /// let r = bn.to_vec_padded(1);
853    /// assert!(r.is_err());
854    ///
855    /// let bn = -BigNum::from_u32(0x4543).unwrap();
856    /// let bn_vec = bn.to_vec_padded(4).unwrap();
857    /// assert_eq!(&bn_vec, &[0, 0, 0x45, 0x43]);
858    /// ```
859    #[corresponds(BN_bn2binpad)]
860    #[cfg(any(ossl110, libressl, boringssl, awslc))]
861    pub fn to_vec_padded(&self, pad_to: i32) -> Result<Vec<u8>, ErrorStack> {
862        let mut v = Vec::with_capacity(pad_to as usize);
863        unsafe {
864            cvt(ffi::BN_bn2binpad(self.as_ptr(), v.as_mut_ptr(), pad_to))?;
865            v.set_len(pad_to as usize);
866        }
867        Ok(v)
868    }
869
870    /// Returns a decimal string representation of `self`.
871    ///
872    /// ```
873    /// # use openssl::bn::BigNum;
874    /// let s = -BigNum::from_u32(12345).unwrap();
875    ///
876    /// assert_eq!(&**s.to_dec_str().unwrap(), "-12345");
877    /// ```
878    #[corresponds(BN_bn2dec)]
879    pub fn to_dec_str(&self) -> Result<OpensslString, ErrorStack> {
880        unsafe {
881            let buf = cvt_p(ffi::BN_bn2dec(self.as_ptr()))?;
882            Ok(OpensslString::from_ptr(buf))
883        }
884    }
885
886    /// Returns a hexadecimal string representation of `self`.
887    ///
888    /// ```
889    /// # use openssl::bn::BigNum;
890    /// let s = -BigNum::from_u32(0x99ff).unwrap();
891    ///
892    /// assert_eq!(s.to_hex_str().unwrap().to_uppercase(), "-99FF");
893    /// ```
894    #[corresponds(BN_bn2hex)]
895    pub fn to_hex_str(&self) -> Result<OpensslString, ErrorStack> {
896        unsafe {
897            let buf = cvt_p(ffi::BN_bn2hex(self.as_ptr()))?;
898            Ok(OpensslString::from_ptr(buf))
899        }
900    }
901
902    /// Returns an `Asn1Integer` containing the value of `self`.
903    #[corresponds(BN_to_ASN1_INTEGER)]
904    pub fn to_asn1_integer(&self) -> Result<Asn1Integer, ErrorStack> {
905        unsafe {
906            cvt_p(ffi::BN_to_ASN1_INTEGER(self.as_ptr(), ptr::null_mut()))
907                .map(|p| Asn1Integer::from_ptr(p))
908        }
909    }
910
911    /// Force constant time computation on this value.
912    #[corresponds(BN_set_flags)]
913    #[cfg(ossl110)]
914    pub fn set_const_time(&mut self) {
915        unsafe { ffi::BN_set_flags(self.as_ptr(), ffi::BN_FLG_CONSTTIME) }
916    }
917
918    /// Returns true if `self` is in const time mode.
919    #[corresponds(BN_get_flags)]
920    #[cfg(ossl110)]
921    pub fn is_const_time(&self) -> bool {
922        unsafe {
923            let ret = ffi::BN_get_flags(self.as_ptr(), ffi::BN_FLG_CONSTTIME);
924            ret == ffi::BN_FLG_CONSTTIME
925        }
926    }
927
928    /// Returns true if `self` was created with [`BigNum::new_secure`].
929    #[corresponds(BN_get_flags)]
930    #[cfg(ossl110)]
931    pub fn is_secure(&self) -> bool {
932        unsafe {
933            let ret = ffi::BN_get_flags(self.as_ptr(), ffi::BN_FLG_SECURE);
934            ret == ffi::BN_FLG_SECURE
935        }
936    }
937}
938
939impl BigNum {
940    /// Creates a new `BigNum` with the value 0.
941    #[corresponds(BN_new)]
942    pub fn new() -> Result<BigNum, ErrorStack> {
943        unsafe {
944            ffi::init();
945            let v = cvt_p(ffi::BN_new())?;
946            Ok(BigNum::from_ptr(v))
947        }
948    }
949
950    /// Returns a new secure `BigNum`.
951    #[corresponds(BN_secure_new)]
952    #[cfg(ossl110)]
953    pub fn new_secure() -> Result<BigNum, ErrorStack> {
954        unsafe {
955            ffi::init();
956            let v = cvt_p(ffi::BN_secure_new())?;
957            Ok(BigNum::from_ptr(v))
958        }
959    }
960
961    /// Creates a new `BigNum` with the given value.
962    #[corresponds(BN_set_word)]
963    pub fn from_u32(n: u32) -> Result<BigNum, ErrorStack> {
964        BigNum::new().and_then(|v| unsafe {
965            cvt(ffi::BN_set_word(v.as_ptr(), n as ffi::BN_ULONG)).map(|_| v)
966        })
967    }
968
969    /// Creates a `BigNum` from a decimal string.
970    #[corresponds(BN_dec2bn)]
971    pub fn from_dec_str(s: &str) -> Result<BigNum, ErrorStack> {
972        unsafe {
973            ffi::init();
974            let c_str = CString::new(s.as_bytes()).unwrap();
975            let mut bn = ptr::null_mut();
976            cvt(ffi::BN_dec2bn(&mut bn, c_str.as_ptr() as *const _))?;
977            Ok(BigNum::from_ptr(bn))
978        }
979    }
980
981    /// Creates a `BigNum` from a hexadecimal string.
982    #[corresponds(BN_hex2bn)]
983    pub fn from_hex_str(s: &str) -> Result<BigNum, ErrorStack> {
984        unsafe {
985            ffi::init();
986            let c_str = CString::new(s.as_bytes()).unwrap();
987            let mut bn = ptr::null_mut();
988            cvt(ffi::BN_hex2bn(&mut bn, c_str.as_ptr() as *const _))?;
989            Ok(BigNum::from_ptr(bn))
990        }
991    }
992
993    /// Returns a constant used in IKE as defined in [`RFC 2409`].  This prime number is in
994    /// the order of magnitude of `2 ^ 768`.  This number is used during calculated key
995    /// exchanges such as Diffie-Hellman.  This number is labeled Oakley group id 1.
996    ///
997    /// [`RFC 2409`]: https://tools.ietf.org/html/rfc2409#page-21
998    #[corresponds(BN_get_rfc2409_prime_768)]
999    #[cfg(not(any(boringssl, awslc)))]
1000    pub fn get_rfc2409_prime_768() -> Result<BigNum, ErrorStack> {
1001        unsafe {
1002            ffi::init();
1003            cvt_p(BN_get_rfc2409_prime_768(ptr::null_mut())).map(BigNum)
1004        }
1005    }
1006
1007    /// Returns a constant used in IKE as defined in [`RFC 2409`].  This prime number is in
1008    /// the order of magnitude of `2 ^ 1024`.  This number is used during calculated key
1009    /// exchanges such as Diffie-Hellman.  This number is labeled Oakly group 2.
1010    ///
1011    /// [`RFC 2409`]: https://tools.ietf.org/html/rfc2409#page-21
1012    #[corresponds(BN_get_rfc2409_prime_1024)]
1013    #[cfg(not(any(boringssl, awslc)))]
1014    pub fn get_rfc2409_prime_1024() -> Result<BigNum, ErrorStack> {
1015        unsafe {
1016            ffi::init();
1017            cvt_p(BN_get_rfc2409_prime_1024(ptr::null_mut())).map(BigNum)
1018        }
1019    }
1020
1021    /// Returns a constant used in IKE as defined in [`RFC 3526`].  The prime is in the order
1022    /// of magnitude of `2 ^ 1536`.  This number is used during calculated key
1023    /// exchanges such as Diffie-Hellman.  This number is labeled MODP group 5.
1024    ///
1025    /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-3
1026    #[corresponds(BN_get_rfc3526_prime_1536)]
1027    #[cfg(not(boringssl))]
1028    pub fn get_rfc3526_prime_1536() -> Result<BigNum, ErrorStack> {
1029        unsafe {
1030            ffi::init();
1031            cvt_p(BN_get_rfc3526_prime_1536(ptr::null_mut())).map(BigNum)
1032        }
1033    }
1034
1035    /// Returns a constant used in IKE as defined in [`RFC 3526`].  The prime is in the order
1036    /// of magnitude of `2 ^ 2048`.  This number is used during calculated key
1037    /// exchanges such as Diffie-Hellman.  This number is labeled MODP group 14.
1038    ///
1039    /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-3
1040    #[corresponds(BN_get_rfc3526_prime_2048)]
1041    #[cfg(not(boringssl))]
1042    pub fn get_rfc3526_prime_2048() -> Result<BigNum, ErrorStack> {
1043        unsafe {
1044            ffi::init();
1045            cvt_p(BN_get_rfc3526_prime_2048(ptr::null_mut())).map(BigNum)
1046        }
1047    }
1048
1049    /// Returns a constant used in IKE as defined in [`RFC 3526`].  The prime is in the order
1050    /// of magnitude of `2 ^ 3072`.  This number is used during calculated key
1051    /// exchanges such as Diffie-Hellman.  This number is labeled MODP group 15.
1052    ///
1053    /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-4
1054    #[corresponds(BN_get_rfc3526_prime_3072)]
1055    #[cfg(not(boringssl))]
1056    pub fn get_rfc3526_prime_3072() -> Result<BigNum, ErrorStack> {
1057        unsafe {
1058            ffi::init();
1059            cvt_p(BN_get_rfc3526_prime_3072(ptr::null_mut())).map(BigNum)
1060        }
1061    }
1062
1063    /// Returns a constant used in IKE as defined in [`RFC 3526`].  The prime is in the order
1064    /// of magnitude of `2 ^ 4096`.  This number is used during calculated key
1065    /// exchanges such as Diffie-Hellman.  This number is labeled MODP group 16.
1066    ///
1067    /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-4
1068    #[corresponds(BN_get_rfc3526_prime_4096)]
1069    #[cfg(not(boringssl))]
1070    pub fn get_rfc3526_prime_4096() -> Result<BigNum, ErrorStack> {
1071        unsafe {
1072            ffi::init();
1073            cvt_p(BN_get_rfc3526_prime_4096(ptr::null_mut())).map(BigNum)
1074        }
1075    }
1076
1077    /// Returns a constant used in IKE as defined in [`RFC 3526`].  The prime is in the order
1078    /// of magnitude of `2 ^ 6144`.  This number is used during calculated key
1079    /// exchanges such as Diffie-Hellman.  This number is labeled MODP group 17.
1080    ///
1081    /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-6
1082    #[corresponds(BN_get_rfc3526_prime_6114)]
1083    #[cfg(not(boringssl))]
1084    pub fn get_rfc3526_prime_6144() -> Result<BigNum, ErrorStack> {
1085        unsafe {
1086            ffi::init();
1087            cvt_p(BN_get_rfc3526_prime_6144(ptr::null_mut())).map(BigNum)
1088        }
1089    }
1090
1091    /// Returns a constant used in IKE as defined in [`RFC 3526`].  The prime is in the order
1092    /// of magnitude of `2 ^ 8192`.  This number is used during calculated key
1093    /// exchanges such as Diffie-Hellman.  This number is labeled MODP group 18.
1094    ///
1095    /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-6
1096    #[corresponds(BN_get_rfc3526_prime_8192)]
1097    #[cfg(not(boringssl))]
1098    pub fn get_rfc3526_prime_8192() -> Result<BigNum, ErrorStack> {
1099        unsafe {
1100            ffi::init();
1101            cvt_p(BN_get_rfc3526_prime_8192(ptr::null_mut())).map(BigNum)
1102        }
1103    }
1104
1105    /// Creates a new `BigNum` from an unsigned, big-endian encoded number of arbitrary length.
1106    ///
1107    /// ```
1108    /// # use openssl::bn::BigNum;
1109    /// let bignum = BigNum::from_slice(&[0x12, 0x00, 0x34]).unwrap();
1110    ///
1111    /// assert_eq!(bignum, BigNum::from_u32(0x120034).unwrap());
1112    /// ```
1113    #[corresponds(BN_bin2bn)]
1114    pub fn from_slice(n: &[u8]) -> Result<BigNum, ErrorStack> {
1115        unsafe {
1116            ffi::init();
1117            assert!(n.len() <= LenType::MAX as usize);
1118
1119            cvt_p(ffi::BN_bin2bn(
1120                n.as_ptr(),
1121                n.len() as LenType,
1122                ptr::null_mut(),
1123            ))
1124            .map(|p| BigNum::from_ptr(p))
1125        }
1126    }
1127
1128    /// Copies data from a slice overwriting what was in the BigNum.
1129    ///
1130    /// This function can be used to copy data from a slice to a
1131    /// [secure BigNum][`BigNum::new_secure`].
1132    ///
1133    /// # Examples
1134    ///
1135    /// ```
1136    /// # use openssl::bn::BigNum;
1137    /// let mut bignum = BigNum::new().unwrap();
1138    /// bignum.copy_from_slice(&[0x12, 0x00, 0x34]).unwrap();
1139    ///
1140    /// assert_eq!(bignum, BigNum::from_u32(0x120034).unwrap());
1141    /// ```
1142    #[corresponds(BN_bin2bn)]
1143    pub fn copy_from_slice(&mut self, n: &[u8]) -> Result<(), ErrorStack> {
1144        unsafe {
1145            assert!(n.len() <= LenType::MAX as usize);
1146
1147            cvt_p(ffi::BN_bin2bn(n.as_ptr(), n.len() as LenType, self.0))?;
1148            Ok(())
1149        }
1150    }
1151}
1152
1153impl fmt::Debug for BigNumRef {
1154    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1155        match self.to_dec_str() {
1156            Ok(s) => f.write_str(&s),
1157            Err(e) => Err(e.into()),
1158        }
1159    }
1160}
1161
1162impl fmt::Debug for BigNum {
1163    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1164        match self.to_dec_str() {
1165            Ok(s) => f.write_str(&s),
1166            Err(e) => Err(e.into()),
1167        }
1168    }
1169}
1170
1171impl fmt::Display for BigNumRef {
1172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1173        match self.to_dec_str() {
1174            Ok(s) => f.write_str(&s),
1175            Err(e) => Err(e.into()),
1176        }
1177    }
1178}
1179
1180impl fmt::Display for BigNum {
1181    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1182        match self.to_dec_str() {
1183            Ok(s) => f.write_str(&s),
1184            Err(e) => Err(e.into()),
1185        }
1186    }
1187}
1188
1189impl fmt::UpperHex for BigNumRef {
1190    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1191        match self.to_hex_str() {
1192            Ok(s) => {
1193                // BoringSSL's BN_bn2hex() returns lower-case hexadecimal, while everyone
1194                // else returns upper case.  Unconditionally convert to upper case here
1195                // just in case anyone else decides to change behavior in the future.
1196                let s = s.to_uppercase();
1197
1198                if f.alternate() {
1199                    <String as fmt::Display>::fmt(&format!("0x{}", &s), f)
1200                } else {
1201                    <str as fmt::Display>::fmt(&s, f)
1202                }
1203            }
1204            Err(e) => Err(e.into()),
1205        }
1206    }
1207}
1208
1209impl fmt::UpperHex for BigNum {
1210    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1211        self.as_ref().fmt(f)
1212    }
1213}
1214
1215impl PartialEq<BigNumRef> for BigNumRef {
1216    fn eq(&self, oth: &BigNumRef) -> bool {
1217        self.cmp(oth) == Ordering::Equal
1218    }
1219}
1220
1221impl PartialEq<BigNum> for BigNumRef {
1222    fn eq(&self, oth: &BigNum) -> bool {
1223        self.eq(oth.deref())
1224    }
1225}
1226
1227impl Eq for BigNumRef {}
1228
1229impl PartialEq for BigNum {
1230    fn eq(&self, oth: &BigNum) -> bool {
1231        self.deref().eq(oth)
1232    }
1233}
1234
1235impl PartialEq<BigNumRef> for BigNum {
1236    fn eq(&self, oth: &BigNumRef) -> bool {
1237        self.deref().eq(oth)
1238    }
1239}
1240
1241impl Eq for BigNum {}
1242
1243impl PartialOrd<BigNumRef> for BigNumRef {
1244    fn partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering> {
1245        Some(self.cmp(oth))
1246    }
1247}
1248
1249impl PartialOrd<BigNum> for BigNumRef {
1250    fn partial_cmp(&self, oth: &BigNum) -> Option<Ordering> {
1251        Some(self.cmp(oth.deref()))
1252    }
1253}
1254
1255impl Ord for BigNumRef {
1256    fn cmp(&self, oth: &BigNumRef) -> Ordering {
1257        unsafe { ffi::BN_cmp(self.as_ptr(), oth.as_ptr()).cmp(&0) }
1258    }
1259}
1260
1261impl PartialOrd for BigNum {
1262    fn partial_cmp(&self, oth: &BigNum) -> Option<Ordering> {
1263        Some(self.cmp(oth))
1264    }
1265}
1266
1267impl PartialOrd<BigNumRef> for BigNum {
1268    fn partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering> {
1269        self.deref().partial_cmp(oth)
1270    }
1271}
1272
1273impl Ord for BigNum {
1274    fn cmp(&self, oth: &BigNum) -> Ordering {
1275        self.deref().cmp(oth.deref())
1276    }
1277}
1278
1279macro_rules! delegate {
1280    ($t:ident, $m:ident) => {
1281        impl<'a, 'b> $t<&'b BigNum> for &'a BigNumRef {
1282            type Output = BigNum;
1283
1284            fn $m(self, oth: &BigNum) -> BigNum {
1285                $t::$m(self, oth.deref())
1286            }
1287        }
1288
1289        impl<'a, 'b> $t<&'b BigNumRef> for &'a BigNum {
1290            type Output = BigNum;
1291
1292            fn $m(self, oth: &BigNumRef) -> BigNum {
1293                $t::$m(self.deref(), oth)
1294            }
1295        }
1296
1297        impl<'a, 'b> $t<&'b BigNum> for &'a BigNum {
1298            type Output = BigNum;
1299
1300            fn $m(self, oth: &BigNum) -> BigNum {
1301                $t::$m(self.deref(), oth.deref())
1302            }
1303        }
1304    };
1305}
1306
1307impl Add<&BigNumRef> for &BigNumRef {
1308    type Output = BigNum;
1309
1310    fn add(self, oth: &BigNumRef) -> BigNum {
1311        let mut r = BigNum::new().unwrap();
1312        r.checked_add(self, oth).unwrap();
1313        r
1314    }
1315}
1316
1317delegate!(Add, add);
1318
1319impl Sub<&BigNumRef> for &BigNumRef {
1320    type Output = BigNum;
1321
1322    fn sub(self, oth: &BigNumRef) -> BigNum {
1323        let mut r = BigNum::new().unwrap();
1324        r.checked_sub(self, oth).unwrap();
1325        r
1326    }
1327}
1328
1329delegate!(Sub, sub);
1330
1331impl Mul<&BigNumRef> for &BigNumRef {
1332    type Output = BigNum;
1333
1334    fn mul(self, oth: &BigNumRef) -> BigNum {
1335        let mut ctx = BigNumContext::new().unwrap();
1336        let mut r = BigNum::new().unwrap();
1337        r.checked_mul(self, oth, &mut ctx).unwrap();
1338        r
1339    }
1340}
1341
1342delegate!(Mul, mul);
1343
1344impl<'b> Div<&'b BigNumRef> for &BigNumRef {
1345    type Output = BigNum;
1346
1347    fn div(self, oth: &'b BigNumRef) -> BigNum {
1348        let mut ctx = BigNumContext::new().unwrap();
1349        let mut r = BigNum::new().unwrap();
1350        r.checked_div(self, oth, &mut ctx).unwrap();
1351        r
1352    }
1353}
1354
1355delegate!(Div, div);
1356
1357impl<'b> Rem<&'b BigNumRef> for &BigNumRef {
1358    type Output = BigNum;
1359
1360    fn rem(self, oth: &'b BigNumRef) -> BigNum {
1361        let mut ctx = BigNumContext::new().unwrap();
1362        let mut r = BigNum::new().unwrap();
1363        r.checked_rem(self, oth, &mut ctx).unwrap();
1364        r
1365    }
1366}
1367
1368delegate!(Rem, rem);
1369
1370impl Shl<i32> for &BigNumRef {
1371    type Output = BigNum;
1372
1373    fn shl(self, n: i32) -> BigNum {
1374        let mut r = BigNum::new().unwrap();
1375        r.lshift(self, n).unwrap();
1376        r
1377    }
1378}
1379
1380impl Shl<i32> for &BigNum {
1381    type Output = BigNum;
1382
1383    fn shl(self, n: i32) -> BigNum {
1384        self.deref().shl(n)
1385    }
1386}
1387
1388impl Shr<i32> for &BigNumRef {
1389    type Output = BigNum;
1390
1391    fn shr(self, n: i32) -> BigNum {
1392        let mut r = BigNum::new().unwrap();
1393        r.rshift(self, n).unwrap();
1394        r
1395    }
1396}
1397
1398impl Shr<i32> for &BigNum {
1399    type Output = BigNum;
1400
1401    fn shr(self, n: i32) -> BigNum {
1402        self.deref().shr(n)
1403    }
1404}
1405
1406impl Neg for &BigNumRef {
1407    type Output = BigNum;
1408
1409    fn neg(self) -> BigNum {
1410        self.to_owned().unwrap().neg()
1411    }
1412}
1413
1414impl Neg for &BigNum {
1415    type Output = BigNum;
1416
1417    fn neg(self) -> BigNum {
1418        self.deref().neg()
1419    }
1420}
1421
1422impl Neg for BigNum {
1423    type Output = BigNum;
1424
1425    fn neg(mut self) -> BigNum {
1426        let negative = self.is_negative();
1427        self.set_negative(!negative);
1428        self
1429    }
1430}
1431
1432#[cfg(test)]
1433mod tests {
1434    use crate::bn::{BigNum, BigNumContext};
1435
1436    #[test]
1437    fn test_to_from_slice() {
1438        let v0 = BigNum::from_u32(10_203_004).unwrap();
1439        let vec = v0.to_vec();
1440        let v1 = BigNum::from_slice(&vec).unwrap();
1441
1442        assert_eq!(v0, v1);
1443    }
1444
1445    #[test]
1446    fn test_negation() {
1447        let a = BigNum::from_u32(909_829_283).unwrap();
1448
1449        assert!(!a.is_negative());
1450        assert!((-a).is_negative());
1451    }
1452
1453    #[test]
1454    fn test_shift() {
1455        let a = BigNum::from_u32(909_829_283).unwrap();
1456
1457        assert_eq!(a, &(&a << 1) >> 1);
1458    }
1459
1460    #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1461    #[test]
1462    fn test_rand_range() {
1463        let range = BigNum::from_u32(909_829_283).unwrap();
1464        let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap();
1465        range.rand_range(&mut result).unwrap();
1466        assert!(result >= BigNum::from_u32(0).unwrap() && result < range);
1467    }
1468
1469    #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1470    #[test]
1471    fn test_pseudo_rand_range() {
1472        let range = BigNum::from_u32(909_829_283).unwrap();
1473        let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap();
1474        range.pseudo_rand_range(&mut result).unwrap();
1475        assert!(result >= BigNum::from_u32(0).unwrap() && result < range);
1476    }
1477
1478    #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1479    #[test]
1480    fn test_prime_numbers() {
1481        let a = BigNum::from_u32(19_029_017).unwrap();
1482        let mut p = BigNum::new().unwrap();
1483        p.generate_prime(128, true, None, Some(&a)).unwrap();
1484
1485        let mut ctx = BigNumContext::new().unwrap();
1486        assert!(p.is_prime(100, &mut ctx).unwrap());
1487        assert!(p.is_prime_fasttest(100, &mut ctx, true).unwrap());
1488    }
1489
1490    #[cfg(ossl110)]
1491    #[test]
1492    fn test_secure_bn_ctx() {
1493        let mut cxt = BigNumContext::new_secure().unwrap();
1494        let a = BigNum::from_u32(8).unwrap();
1495        let b = BigNum::from_u32(3).unwrap();
1496
1497        let mut remainder = BigNum::new().unwrap();
1498        remainder.nnmod(&a, &b, &mut cxt).unwrap();
1499
1500        assert!(remainder.eq(&BigNum::from_u32(2).unwrap()));
1501    }
1502
1503    #[cfg(ossl110)]
1504    #[test]
1505    fn test_secure_bn() {
1506        let a = BigNum::new().unwrap();
1507        assert!(!a.is_secure());
1508
1509        let b = BigNum::new_secure().unwrap();
1510        assert!(b.is_secure())
1511    }
1512
1513    #[cfg(ossl110)]
1514    #[test]
1515    fn test_const_time_bn() {
1516        let a = BigNum::new().unwrap();
1517        assert!(!a.is_const_time());
1518
1519        let mut b = BigNum::new().unwrap();
1520        b.set_const_time();
1521        assert!(b.is_const_time())
1522    }
1523
1524    #[test]
1525    fn test_mod_sqrt() {
1526        let mut ctx = BigNumContext::new().unwrap();
1527
1528        let s = BigNum::from_hex_str("2").unwrap();
1529        let p = BigNum::from_hex_str("7DEB1").unwrap();
1530        let mut sqrt = BigNum::new().unwrap();
1531        let mut out = BigNum::new().unwrap();
1532
1533        // Square the root because OpenSSL randomly returns one of 2E42C or 4FA85
1534        sqrt.mod_sqrt(&s, &p, &mut ctx).unwrap();
1535        out.mod_sqr(&sqrt, &p, &mut ctx).unwrap();
1536        assert!(out == s);
1537
1538        let s = BigNum::from_hex_str("3").unwrap();
1539        let p = BigNum::from_hex_str("5").unwrap();
1540        assert!(out.mod_sqrt(&s, &p, &mut ctx).is_err());
1541    }
1542
1543    #[test]
1544    #[cfg(any(ossl110, boringssl, libressl, awslc))]
1545    fn test_odd_even() {
1546        let a = BigNum::from_u32(17).unwrap();
1547        let b = BigNum::from_u32(18).unwrap();
1548
1549        assert!(a.is_odd());
1550        assert!(!b.is_odd());
1551
1552        assert!(!a.is_even());
1553        assert!(b.is_even());
1554    }
1555
1556    #[test]
1557    fn test_format() {
1558        let a = BigNum::from_u32(12345678).unwrap();
1559
1560        assert_eq!(format!("{}", a), "12345678");
1561    }
1562
1563    #[test]
1564    fn test_format_upperhex() {
1565        let a = BigNum::from_u32(12345678).unwrap();
1566
1567        assert_eq!(format!("{:X}", a), "BC614E");
1568
1569        assert_eq!(format!("{:<20X}", a), "BC614E              ");
1570        assert_eq!(format!("{:-<20X}", a), "BC614E--------------");
1571        assert_eq!(format!("{:^20X}", a), "       BC614E       ");
1572        assert_eq!(format!("{:>20X}", a), "              BC614E");
1573
1574        assert_eq!(format!("{:#X}", a), "0xBC614E");
1575
1576        assert_eq!(format!("{:<#20X}", a), "0xBC614E            ");
1577        assert_eq!(format!("{:-<#20X}", a), "0xBC614E------------");
1578        assert_eq!(format!("{:^#20X}", a), "      0xBC614E      ");
1579        assert_eq!(format!("{:>#20X}", a), "            0xBC614E");
1580    }
1581}