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