Skip to main content

rama_boring/
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 rama_boring::bn::BigNum;
13//! use rama_boring::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 crate::ffi;
26use crate::libc_types::c_int;
27use foreign_types::{ForeignType, ForeignTypeRef};
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::ffi::BN_is_negative;
36use crate::string::OpensslString;
37use crate::{cvt, cvt_n, cvt_p};
38use openssl_macros::corresponds;
39
40/// Options for the most significant bits of a randomly generated `BigNum`.
41pub struct MsbOption(c_int);
42
43impl MsbOption {
44    /// The most significant bit of the number may be 0.
45    pub const MAYBE_ZERO: MsbOption = MsbOption(-1);
46
47    /// The most significant bit of the number must be 1.
48    pub const ONE: MsbOption = MsbOption(0);
49
50    /// The most significant two bits of the number must be 1.
51    ///
52    /// The number of bits in the product of two such numbers will always be exactly twice the
53    /// number of bits in the original numbers.
54    pub const TWO_ONES: MsbOption = MsbOption(1);
55}
56
57foreign_type_and_impl_send_sync! {
58    type CType = ffi::BN_CTX;
59    fn drop = ffi::BN_CTX_free;
60
61    /// Temporary storage for BigNums on the secure heap
62    ///
63    /// BigNum values are stored dynamically and therefore can be expensive
64    /// to allocate.  BigNumContext and the OpenSSL [`BN_CTX`] structure are used
65    /// internally when passing BigNum values between subroutines.
66    ///
67    /// [`BN_CTX`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_CTX_new.html
68    pub struct BigNumContext;
69}
70
71impl BigNumContext {
72    /// Returns a new `BigNumContext`.
73    #[corresponds(BN_CTX_new)]
74    pub fn new() -> Result<BigNumContext, ErrorStack> {
75        unsafe {
76            ffi::init();
77            cvt_p(ffi::BN_CTX_new()).map(|p| BigNumContext::from_ptr(p))
78        }
79    }
80}
81
82foreign_type_and_impl_send_sync! {
83    type CType = ffi::BIGNUM;
84    fn drop = ffi::BN_free;
85
86    /// Dynamically sized large number impelementation
87    ///
88    /// Perform large number mathematics.  Create a new BigNum
89    /// with [`new`].  Perform standard mathematics on large numbers using
90    /// methods from [`Dref<Target = BigNumRef>`]
91    ///
92    /// OpenSSL documentation at [`BN_new`].
93    ///
94    /// [`new`]: struct.BigNum.html#method.new
95    /// [`Dref<Target = BigNumRef>`]: struct.BigNum.html#deref-methods
96    /// [`BN_new`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_new.html
97    ///
98    /// # Examples
99    /// ```
100    /// use rama_boring::bn::BigNum;
101    /// # use rama_boring::error::ErrorStack;
102    /// # fn bignums() -> Result< (), ErrorStack > {
103    /// let little_big = BigNum::from_u32(std::u32::MAX)?;
104    /// assert_eq!(*&little_big.num_bytes(), 4);
105    /// # Ok(())
106    /// # }
107    /// # fn main () { bignums(); }
108    /// ```
109    pub struct BigNum;
110}
111
112impl BigNumRef {
113    /// Erases the memory used by this `BigNum`, resetting its value to 0.
114    ///
115    /// This can be used to destroy sensitive data such as keys when they are no longer needed.
116    #[corresponds(BN_clear)]
117    pub fn clear(&mut self) {
118        unsafe { ffi::BN_clear(self.as_ptr()) }
119    }
120
121    /// Adds a `u32` to `self`.
122    #[corresponds(BN_add_word)]
123    pub fn add_word(&mut self, w: u32) -> Result<(), ErrorStack> {
124        unsafe { cvt(ffi::BN_add_word(self.as_ptr(), ffi::BN_ULONG::from(w))) }
125    }
126
127    /// Subtracts a `u32` from `self`.
128    #[corresponds(BN_sub_word)]
129    pub fn sub_word(&mut self, w: u32) -> Result<(), ErrorStack> {
130        unsafe { cvt(ffi::BN_sub_word(self.as_ptr(), ffi::BN_ULONG::from(w))) }
131    }
132
133    /// Multiplies a `u32` by `self`.
134    #[corresponds(BN_mul_word)]
135    pub fn mul_word(&mut self, w: u32) -> Result<(), ErrorStack> {
136        unsafe { cvt(ffi::BN_mul_word(self.as_ptr(), ffi::BN_ULONG::from(w))) }
137    }
138
139    /// Divides `self` by a `u32`, returning the remainder.
140    #[corresponds(BN_div_word)]
141    #[allow(clippy::useless_conversion)]
142    pub fn div_word(&mut self, w: u32) -> Result<u64, ErrorStack> {
143        unsafe {
144            let r = ffi::BN_div_word(self.as_ptr(), w.into());
145            if r == ffi::BN_ULONG::MAX {
146                Err(ErrorStack::get())
147            } else {
148                Ok(r.into())
149            }
150        }
151    }
152
153    /// Returns the result of `self` modulo `w`.
154    #[corresponds(BN_mod_word)]
155    #[allow(clippy::useless_conversion)]
156    pub fn mod_word(&self, w: u32) -> Result<u64, ErrorStack> {
157        unsafe {
158            let r = ffi::BN_mod_word(self.as_ptr(), w.into());
159            if r == ffi::BN_ULONG::MAX {
160                Err(ErrorStack::get())
161            } else {
162                Ok(r.into())
163            }
164        }
165    }
166
167    /// Places a cryptographically-secure pseudo-random nonnegative
168    /// number less than `self` in `rnd`.
169    #[corresponds(BN_rand_range)]
170    pub fn rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> {
171        unsafe { cvt(ffi::BN_rand_range(rnd.as_ptr(), self.as_ptr())) }
172    }
173
174    /// The cryptographically weak counterpart to `rand_in_range`.
175    #[corresponds(BN_pseudo_rand_range)]
176    pub fn pseudo_rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> {
177        unsafe { cvt(ffi::BN_pseudo_rand_range(rnd.as_ptr(), self.as_ptr())) }
178    }
179
180    /// Sets bit `n`. Equivalent to `self |= (1 << n)`.
181    ///
182    /// When setting a bit outside of `self`, it is expanded.
183    #[corresponds(BN_set_bit)]
184    #[allow(clippy::useless_conversion)]
185    pub fn set_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
186        unsafe { cvt(ffi::BN_clear_bit(self.as_ptr(), n.into())) }
187    }
188
189    /// Clears bit `n`, setting it to 0. Equivalent to `self &= ~(1 << n)`.
190    ///
191    /// When clearing a bit outside of `self`, an error is returned.
192    #[corresponds(BN_clear_bit)]
193    #[allow(clippy::useless_conversion)]
194    pub fn clear_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
195        unsafe { cvt(ffi::BN_clear_bit(self.as_ptr(), n.into())) }
196    }
197
198    /// Returns `true` if the `n`th bit of `self` is set to 1, `false` otherwise.
199    #[corresponds(BN_is_bit_set)]
200    #[allow(clippy::useless_conversion)]
201    #[must_use]
202    pub fn is_bit_set(&self, n: i32) -> bool {
203        unsafe { ffi::BN_is_bit_set(self.as_ptr(), n.into()) == 1 }
204    }
205
206    /// Truncates `self` to the lowest `n` bits.
207    ///
208    /// An error occurs if `self` is already shorter than `n` bits.
209    #[corresponds(BN_mask_bits)]
210    #[allow(clippy::useless_conversion)]
211    pub fn mask_bits(&mut self, n: i32) -> Result<(), ErrorStack> {
212        unsafe { cvt(ffi::BN_mask_bits(self.as_ptr(), n.into())) }
213    }
214
215    /// Places `a << 1` in `self`.  Equivalent to `self * 2`.
216    #[corresponds(BN_lshift1)]
217    pub fn lshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack> {
218        unsafe { cvt(ffi::BN_lshift1(self.as_ptr(), a.as_ptr())) }
219    }
220
221    /// Places `a >> 1` in `self`. Equivalent to `self / 2`.
222    #[corresponds(BN_rshift1)]
223    pub fn rshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack> {
224        unsafe { cvt(ffi::BN_rshift1(self.as_ptr(), a.as_ptr())) }
225    }
226
227    /// Places `a + b` in `self`.  [`core::ops::Add`] is also implemented for `BigNumRef`.
228    ///
229    /// [`core::ops::Add`]: struct.BigNumRef.html#method.add
230    #[corresponds(BN_add)]
231    pub fn checked_add(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack> {
232        unsafe { cvt(ffi::BN_add(self.as_ptr(), a.as_ptr(), b.as_ptr())) }
233    }
234
235    /// Places `a - b` in `self`. [`core::ops::Sub`] is also implemented for `BigNumRef`.
236    ///
237    /// [`core::ops::Sub`]: struct.BigNumRef.html#method.sub
238    #[corresponds(BN_sub)]
239    pub fn checked_sub(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack> {
240        unsafe { cvt(ffi::BN_sub(self.as_ptr(), a.as_ptr(), b.as_ptr())) }
241    }
242
243    /// Places `a << n` in `self`.  Equivalent to `a * 2 ^ n`.
244    #[corresponds(BN_lshift)]
245    #[allow(clippy::useless_conversion)]
246    pub fn lshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack> {
247        unsafe { cvt(ffi::BN_lshift(self.as_ptr(), a.as_ptr(), n.into())) }
248    }
249
250    /// Places `a >> n` in `self`. Equivalent to `a / 2 ^ n`.
251    #[corresponds(BN_rshift)]
252    #[allow(clippy::useless_conversion)]
253    pub fn rshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack> {
254        unsafe { cvt(ffi::BN_rshift(self.as_ptr(), a.as_ptr(), n.into())) }
255    }
256
257    /// Creates a new BigNum with the same value.
258    #[corresponds(BN_dup)]
259    pub fn to_owned(&self) -> Result<BigNum, ErrorStack> {
260        unsafe { cvt_p(ffi::BN_dup(self.as_ptr())).map(|b| BigNum::from_ptr(b)) }
261    }
262
263    /// Sets the sign of `self`.  Pass true to set `self` to a negative.  False sets
264    /// `self` positive.
265    #[corresponds(BN_set_negative)]
266    pub fn set_negative(&mut self, negative: bool) {
267        unsafe { ffi::BN_set_negative(self.as_ptr(), c_int::from(negative)) }
268    }
269
270    /// Compare the absolute values of `self` and `oth`.
271    ///
272    /// # Examples
273    ///
274    /// ```
275    /// # use rama_boring::bn::BigNum;
276    /// # use std::cmp::Ordering;
277    /// let s = -BigNum::from_u32(8).unwrap();
278    /// let o = BigNum::from_u32(8).unwrap();
279    ///
280    /// assert_eq!(s.ucmp(&o), Ordering::Equal);
281    /// ```
282    #[corresponds(BN_ucmp)]
283    #[must_use]
284    pub fn ucmp(&self, oth: &BigNumRef) -> Ordering {
285        unsafe { ffi::BN_ucmp(self.as_ptr(), oth.as_ptr()).cmp(&0) }
286    }
287
288    /// Returns `true` if `self` is negative.
289    #[corresponds(BN_is_negative)]
290    #[must_use]
291    pub fn is_negative(&self) -> bool {
292        unsafe { BN_is_negative(self.as_ptr()) == 1 }
293    }
294
295    /// Returns the number of significant bits in `self`.
296    #[corresponds(BN_num_bits)]
297    #[must_use]
298    pub fn num_bits(&self) -> i32 {
299        unsafe { ffi::BN_num_bits(self.as_ptr()) as i32 }
300    }
301
302    /// Returns the size of `self` in bytes. Implemented natively.
303    #[must_use]
304    pub fn num_bytes(&self) -> i32 {
305        (self.num_bits() + 7) / 8
306    }
307
308    /// Generates a cryptographically strong pseudo-random `BigNum`, placing it in `self`.
309    ///
310    /// # Parameters
311    ///
312    /// * `bits`: Length of the number in bits.
313    /// * `msb`: The desired properties of the most significant bit. See [`constants`].
314    /// * `odd`: If `true`, the generated number will be odd.
315    ///
316    /// # Examples
317    ///
318    /// ```
319    /// use rama_boring::bn::{BigNum, MsbOption};
320    /// use rama_boring::error::ErrorStack;
321    ///
322    /// fn generate_random() -> Result< BigNum, ErrorStack > {
323    ///    let mut big = BigNum::new()?;
324    ///
325    ///    // Generates a 128-bit odd random number
326    ///    big.rand(128, MsbOption::MAYBE_ZERO, true);
327    ///    Ok((big))
328    /// }
329    /// ```
330    ///
331    /// [`constants`]: index.html#constants
332    #[corresponds(BN_rand)]
333    #[allow(clippy::useless_conversion)]
334    pub fn rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> {
335        unsafe {
336            cvt(ffi::BN_rand(
337                self.as_ptr(),
338                bits.into(),
339                msb.0,
340                c_int::from(odd),
341            ))
342        }
343    }
344
345    /// The cryptographically weak counterpart to `rand`.  Not suitable for key generation.
346    #[corresponds(BN_pseudo_rand)]
347    #[allow(clippy::useless_conversion)]
348    pub fn pseudo_rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> {
349        unsafe {
350            cvt(ffi::BN_pseudo_rand(
351                self.as_ptr(),
352                bits.into(),
353                msb.0,
354                c_int::from(odd),
355            ))
356        }
357    }
358
359    /// Generates a prime number, placing it in `self`.
360    ///
361    /// # Parameters
362    ///
363    /// * `bits`: The length of the prime in bits (lower bound).
364    /// * `safe`: If true, returns a "safe" prime `p` so that `(p-1)/2` is also prime.
365    /// * `add`/`rem`: If `add` is set to `Some(add)`, `p % add == rem` will hold, where `p` is the
366    ///   generated prime and `rem` is `1` if not specified (`None`).
367    ///
368    /// # Examples
369    ///
370    /// ```
371    /// use rama_boring::bn::BigNum;
372    /// use rama_boring::error::ErrorStack;
373    ///
374    /// fn generate_weak_prime() -> Result< BigNum, ErrorStack > {
375    ///    let mut big = BigNum::new()?;
376    ///
377    ///    // Generates a 128-bit simple prime number
378    ///    big.generate_prime(128, false, None, None);
379    ///    Ok((big))
380    /// }
381    /// ```
382    #[corresponds(BN_generate_prime_ex)]
383    pub fn generate_prime(
384        &mut self,
385        bits: i32,
386        safe: bool,
387        add: Option<&BigNumRef>,
388        rem: Option<&BigNumRef>,
389    ) -> Result<(), ErrorStack> {
390        unsafe {
391            cvt(ffi::BN_generate_prime_ex(
392                self.as_ptr(),
393                c_int::from(bits),
394                c_int::from(safe),
395                add.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()),
396                rem.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()),
397                ptr::null_mut(),
398            ))
399        }
400    }
401
402    /// Places the result of `a * b` in `self`.
403    /// [`core::ops::Mul`] is also implemented for `BigNumRef`.
404    ///
405    /// [`core::ops::Mul`]: struct.BigNumRef.html#method.mul
406    #[corresponds(BN_mul)]
407    pub fn checked_mul(
408        &mut self,
409        a: &BigNumRef,
410        b: &BigNumRef,
411        ctx: &mut BigNumContextRef,
412    ) -> Result<(), ErrorStack> {
413        unsafe {
414            cvt(ffi::BN_mul(
415                self.as_ptr(),
416                a.as_ptr(),
417                b.as_ptr(),
418                ctx.as_ptr(),
419            ))
420        }
421    }
422
423    /// Places the result of `a / b` in `self`. The remainder is discarded.
424    /// [`core::ops::Div`] is also implemented for `BigNumRef`.
425    ///
426    /// [`core::ops::Div`]: struct.BigNumRef.html#method.div
427    #[corresponds(BN_div)]
428    pub fn checked_div(
429        &mut self,
430        a: &BigNumRef,
431        b: &BigNumRef,
432        ctx: &mut BigNumContextRef,
433    ) -> Result<(), ErrorStack> {
434        unsafe {
435            cvt(ffi::BN_div(
436                self.as_ptr(),
437                ptr::null_mut(),
438                a.as_ptr(),
439                b.as_ptr(),
440                ctx.as_ptr(),
441            ))
442        }
443    }
444
445    /// Places the result of `a % b` in `self`.
446    #[corresponds(BN_div)]
447    pub fn checked_rem(
448        &mut self,
449        a: &BigNumRef,
450        b: &BigNumRef,
451        ctx: &mut BigNumContextRef,
452    ) -> Result<(), ErrorStack> {
453        unsafe {
454            cvt(ffi::BN_div(
455                ptr::null_mut(),
456                self.as_ptr(),
457                a.as_ptr(),
458                b.as_ptr(),
459                ctx.as_ptr(),
460            ))
461        }
462    }
463
464    /// Places the result of `a / b` in `self` and `a % b` in `rem`.
465    #[corresponds(BN_div)]
466    pub fn div_rem(
467        &mut self,
468        rem: &mut BigNumRef,
469        a: &BigNumRef,
470        b: &BigNumRef,
471        ctx: &mut BigNumContextRef,
472    ) -> Result<(), ErrorStack> {
473        unsafe {
474            cvt(ffi::BN_div(
475                self.as_ptr(),
476                rem.as_ptr(),
477                a.as_ptr(),
478                b.as_ptr(),
479                ctx.as_ptr(),
480            ))
481        }
482    }
483
484    /// Places the result of `a²` in `self`.
485    #[corresponds(BN_sqr)]
486    pub fn sqr(&mut self, a: &BigNumRef, ctx: &mut BigNumContextRef) -> Result<(), ErrorStack> {
487        unsafe { cvt(ffi::BN_sqr(self.as_ptr(), a.as_ptr(), ctx.as_ptr())) }
488    }
489
490    /// Places the result of `a mod m` in `self`.  As opposed to `div_rem`
491    /// the result is non-negative.
492    #[corresponds(BN_nnmod)]
493    pub fn nnmod(
494        &mut self,
495        a: &BigNumRef,
496        m: &BigNumRef,
497        ctx: &mut BigNumContextRef,
498    ) -> Result<(), ErrorStack> {
499        unsafe {
500            cvt(ffi::BN_nnmod(
501                self.as_ptr(),
502                a.as_ptr(),
503                m.as_ptr(),
504                ctx.as_ptr(),
505            ))
506        }
507    }
508
509    /// Places the result of `(a + b) mod m` in `self`.
510    #[corresponds(BN_mod_add)]
511    pub fn mod_add(
512        &mut self,
513        a: &BigNumRef,
514        b: &BigNumRef,
515        m: &BigNumRef,
516        ctx: &mut BigNumContextRef,
517    ) -> Result<(), ErrorStack> {
518        unsafe {
519            cvt(ffi::BN_mod_add(
520                self.as_ptr(),
521                a.as_ptr(),
522                b.as_ptr(),
523                m.as_ptr(),
524                ctx.as_ptr(),
525            ))
526        }
527    }
528
529    /// Places the result of `(a - b) mod m` in `self`.
530    #[corresponds(BN_mod_sub)]
531    pub fn mod_sub(
532        &mut self,
533        a: &BigNumRef,
534        b: &BigNumRef,
535        m: &BigNumRef,
536        ctx: &mut BigNumContextRef,
537    ) -> Result<(), ErrorStack> {
538        unsafe {
539            cvt(ffi::BN_mod_sub(
540                self.as_ptr(),
541                a.as_ptr(),
542                b.as_ptr(),
543                m.as_ptr(),
544                ctx.as_ptr(),
545            ))
546        }
547    }
548
549    /// Places the result of `(a * b) mod m` in `self`.
550    #[corresponds(BN_mod_mul)]
551    pub fn mod_mul(
552        &mut self,
553        a: &BigNumRef,
554        b: &BigNumRef,
555        m: &BigNumRef,
556        ctx: &mut BigNumContextRef,
557    ) -> Result<(), ErrorStack> {
558        unsafe {
559            cvt(ffi::BN_mod_mul(
560                self.as_ptr(),
561                a.as_ptr(),
562                b.as_ptr(),
563                m.as_ptr(),
564                ctx.as_ptr(),
565            ))
566        }
567    }
568
569    /// Places the result of `a² mod m` in `self`.
570    #[corresponds(BN_mod_sqr)]
571    pub fn mod_sqr(
572        &mut self,
573        a: &BigNumRef,
574        m: &BigNumRef,
575        ctx: &mut BigNumContextRef,
576    ) -> Result<(), ErrorStack> {
577        unsafe {
578            cvt(ffi::BN_mod_sqr(
579                self.as_ptr(),
580                a.as_ptr(),
581                m.as_ptr(),
582                ctx.as_ptr(),
583            ))
584        }
585    }
586
587    /// Places the result of `a^p` in `self`.
588    #[corresponds(BN_exp)]
589    pub fn exp(
590        &mut self,
591        a: &BigNumRef,
592        p: &BigNumRef,
593        ctx: &mut BigNumContextRef,
594    ) -> Result<(), ErrorStack> {
595        unsafe {
596            cvt(ffi::BN_exp(
597                self.as_ptr(),
598                a.as_ptr(),
599                p.as_ptr(),
600                ctx.as_ptr(),
601            ))
602        }
603    }
604
605    /// Places the result of `a^p mod m` in `self`.
606    #[corresponds(BN_mod_exp)]
607    pub fn mod_exp(
608        &mut self,
609        a: &BigNumRef,
610        p: &BigNumRef,
611        m: &BigNumRef,
612        ctx: &mut BigNumContextRef,
613    ) -> Result<(), ErrorStack> {
614        unsafe {
615            cvt(ffi::BN_mod_exp(
616                self.as_ptr(),
617                a.as_ptr(),
618                p.as_ptr(),
619                m.as_ptr(),
620                ctx.as_ptr(),
621            ))
622        }
623    }
624
625    /// Places the inverse of `a` modulo `n` in `self`.
626    #[corresponds(BN_mod_inverse)]
627    pub fn mod_inverse(
628        &mut self,
629        a: &BigNumRef,
630        n: &BigNumRef,
631        ctx: &mut BigNumContextRef,
632    ) -> Result<(), ErrorStack> {
633        unsafe {
634            cvt_p(ffi::BN_mod_inverse(
635                self.as_ptr(),
636                a.as_ptr(),
637                n.as_ptr(),
638                ctx.as_ptr(),
639            ))
640            .map(|_| ())
641        }
642    }
643
644    /// Places the greatest common denominator of `a` and `b` in `self`.
645    #[corresponds(BN_gcd)]
646    pub fn gcd(
647        &mut self,
648        a: &BigNumRef,
649        b: &BigNumRef,
650        ctx: &mut BigNumContextRef,
651    ) -> Result<(), ErrorStack> {
652        unsafe {
653            cvt(ffi::BN_gcd(
654                self.as_ptr(),
655                a.as_ptr(),
656                b.as_ptr(),
657                ctx.as_ptr(),
658            ))
659        }
660    }
661
662    /// Checks whether `self` is prime.
663    ///
664    /// Performs a Miller-Rabin probabilistic primality test with `checks` iterations.
665    ///
666    /// # Return Value
667    ///
668    /// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`.
669    #[corresponds(BN_is_prime_ex)]
670    #[allow(clippy::useless_conversion)]
671    pub fn is_prime(&self, checks: i32, ctx: &mut BigNumContextRef) -> Result<bool, ErrorStack> {
672        unsafe {
673            cvt_n(ffi::BN_is_prime_ex(
674                self.as_ptr(),
675                checks.into(),
676                ctx.as_ptr(),
677                ptr::null_mut(),
678            ))
679            .map(|r| r != 0)
680        }
681    }
682
683    /// Checks whether `self` is prime with optional trial division.
684    ///
685    /// If `do_trial_division` is `true`, first performs trial division by a number of small primes.
686    /// Then, like `is_prime`, performs a Miller-Rabin probabilistic primality test with `checks`
687    /// iterations.
688    ///
689    /// # Return Value
690    ///
691    /// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`.
692    #[corresponds(BN_is_prime_fasttest_ex)]
693    #[allow(clippy::useless_conversion)]
694    pub fn is_prime_fasttest(
695        &self,
696        checks: i32,
697        ctx: &mut BigNumContextRef,
698        do_trial_division: bool,
699    ) -> Result<bool, ErrorStack> {
700        unsafe {
701            cvt_n(ffi::BN_is_prime_fasttest_ex(
702                self.as_ptr(),
703                checks.into(),
704                ctx.as_ptr(),
705                c_int::from(do_trial_division),
706                ptr::null_mut(),
707            ))
708            .map(|r| r != 0)
709        }
710    }
711
712    /// Returns a big-endian byte vector representation of the absolute value of `self`.
713    ///
714    /// `self` can be recreated by using `from_slice`.
715    ///
716    /// ```
717    /// # use rama_boring::bn::BigNum;
718    /// let s = -BigNum::from_u32(4543).unwrap();
719    /// let r = BigNum::from_u32(4543).unwrap();
720    ///
721    /// let s_vec = s.to_vec();
722    /// assert_eq!(BigNum::from_slice(&s_vec).unwrap(), r);
723    /// ```
724    #[corresponds(BN_bn2bin)]
725    #[must_use]
726    pub fn to_vec(&self) -> Vec<u8> {
727        let size = self.num_bytes() as usize;
728        let mut v = Vec::with_capacity(size);
729        unsafe {
730            ffi::BN_bn2bin(self.as_ptr(), v.as_mut_ptr());
731            v.set_len(size);
732        }
733        v
734    }
735
736    /// Returns a big-endian byte vector representation of the absolute value of `self` padded
737    /// to `pad_to` bytes.
738    ///
739    /// If `pad_to` is less than `self.num_bytes()` then an error is returned.
740    ///
741    /// `self` can be recreated by using `from_slice`.
742    ///
743    /// ```
744    /// # use rama_boring::bn::BigNum;
745    /// let bn = BigNum::from_u32(0x4543).unwrap();
746    ///
747    /// let bn_vec = bn.to_vec_padded(4).unwrap();
748    /// assert_eq!(&bn_vec, &[0, 0, 0x45, 0x43]);
749    ///
750    /// let r = bn.to_vec_padded(1);
751    /// assert!(r.is_err());
752    ///
753    /// let bn = -BigNum::from_u32(0x4543).unwrap();
754    /// let bn_vec = bn.to_vec_padded(4).unwrap();
755    /// assert_eq!(&bn_vec, &[0, 0, 0x45, 0x43]);
756    /// ```
757    pub fn to_vec_padded(&self, pad_to: usize) -> Result<Vec<u8>, ErrorStack> {
758        let mut v = Vec::with_capacity(pad_to);
759        unsafe {
760            cvt(ffi::BN_bn2bin_padded(v.as_mut_ptr(), pad_to, self.as_ptr()))?;
761            v.set_len(pad_to);
762        }
763        Ok(v)
764    }
765
766    /// Returns a decimal string representation of `self`.
767    ///
768    /// ```
769    /// # use rama_boring::bn::BigNum;
770    /// let s = -BigNum::from_u32(12345).unwrap();
771    ///
772    /// assert_eq!(&**s.to_dec_str().unwrap(), "-12345");
773    /// ```
774    #[corresponds(BN_bn2dec)]
775    pub fn to_dec_str(&self) -> Result<OpensslString, ErrorStack> {
776        unsafe {
777            let buf = cvt_p(ffi::BN_bn2dec(self.as_ptr()))?;
778            Ok(OpensslString::from_ptr(buf))
779        }
780    }
781
782    /// Returns a hexadecimal string representation of `self`.
783    ///
784    /// ```
785    /// # use rama_boring::bn::BigNum;
786    /// let s = -BigNum::from_u32(0x99ff).unwrap();
787    ///
788    /// assert_eq!(&**s.to_hex_str().unwrap(), "-99ff");
789    /// ```
790    #[corresponds(BN_bn2hex)]
791    pub fn to_hex_str(&self) -> Result<OpensslString, ErrorStack> {
792        unsafe {
793            let buf = cvt_p(ffi::BN_bn2hex(self.as_ptr()))?;
794            Ok(OpensslString::from_ptr(buf))
795        }
796    }
797
798    /// Returns an `Asn1Integer` containing the value of `self`.
799    #[corresponds(BN_to_ASN1_INTEGER)]
800    pub fn to_asn1_integer(&self) -> Result<Asn1Integer, ErrorStack> {
801        unsafe {
802            cvt_p(ffi::BN_to_ASN1_INTEGER(self.as_ptr(), ptr::null_mut()))
803                .map(|p| Asn1Integer::from_ptr(p))
804        }
805    }
806}
807
808impl BigNum {
809    /// Creates a new `BigNum` with the value 0.
810    #[corresponds(BN_new)]
811    pub fn new() -> Result<BigNum, ErrorStack> {
812        unsafe {
813            ffi::init();
814            let v = cvt_p(ffi::BN_new())?;
815            Ok(BigNum::from_ptr(v))
816        }
817    }
818
819    /// Creates a new `BigNum` with the given value.
820    #[corresponds(BN_set_word)]
821    pub fn from_u32(n: u32) -> Result<BigNum, ErrorStack> {
822        BigNum::new().and_then(|v| unsafe {
823            cvt(ffi::BN_set_word(v.as_ptr(), ffi::BN_ULONG::from(n))).map(|_| v)
824        })
825    }
826
827    /// Creates a `BigNum` from a decimal string.
828    #[corresponds(BN_dec2bn)]
829    pub fn from_dec_str(s: &str) -> Result<BigNum, ErrorStack> {
830        unsafe {
831            ffi::init();
832            let c_str = CString::new(s.as_bytes()).map_err(ErrorStack::internal_error)?;
833            let mut bn = ptr::null_mut();
834            cvt(ffi::BN_dec2bn(&mut bn, c_str.as_ptr()))?;
835            Ok(BigNum::from_ptr(bn))
836        }
837    }
838
839    /// Creates a `BigNum` from a hexadecimal string.
840    #[corresponds(BN_hex2bn)]
841    pub fn from_hex_str(s: &str) -> Result<BigNum, ErrorStack> {
842        unsafe {
843            ffi::init();
844            let c_str = CString::new(s.as_bytes()).unwrap();
845            let mut bn = ptr::null_mut();
846            cvt(ffi::BN_hex2bn(&mut bn, c_str.as_ptr()))?;
847            Ok(BigNum::from_ptr(bn))
848        }
849    }
850
851    /// Creates a new `BigNum` from an unsigned, big-endian encoded number of arbitrary length.
852    ///
853    /// OpenSSL documentation at [`BN_bin2bn`]
854    ///
855    /// [`BN_bin2bn`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_bin2bn.html
856    ///
857    /// ```
858    /// # use rama_boring::bn::BigNum;
859    /// let bignum = BigNum::from_slice(&[0x12, 0x00, 0x34]).unwrap();
860    ///
861    /// assert_eq!(bignum, BigNum::from_u32(0x120034).unwrap());
862    /// ```
863    #[corresponds(BN_bin2bn)]
864    pub fn from_slice(n: &[u8]) -> Result<BigNum, ErrorStack> {
865        unsafe {
866            ffi::init();
867            assert!(n.len() <= c_int::MAX as usize);
868            cvt_p(ffi::BN_bin2bn(n.as_ptr(), n.len(), ptr::null_mut())).map(|p| BigNum::from_ptr(p))
869        }
870    }
871}
872
873impl fmt::Debug for BigNumRef {
874    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
875        match self.to_dec_str() {
876            Ok(s) => f.write_str(&s),
877            Err(e) => Err(e.into()),
878        }
879    }
880}
881
882impl fmt::Debug for BigNum {
883    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
884        match self.to_dec_str() {
885            Ok(s) => f.write_str(&s),
886            Err(e) => Err(e.into()),
887        }
888    }
889}
890
891impl fmt::Display for BigNumRef {
892    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
893        match self.to_dec_str() {
894            Ok(s) => f.write_str(&s),
895            Err(e) => Err(e.into()),
896        }
897    }
898}
899
900impl fmt::Display for BigNum {
901    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
902        match self.to_dec_str() {
903            Ok(s) => f.write_str(&s),
904            Err(e) => Err(e.into()),
905        }
906    }
907}
908
909impl PartialEq<BigNumRef> for BigNumRef {
910    fn eq(&self, oth: &BigNumRef) -> bool {
911        self.cmp(oth) == Ordering::Equal
912    }
913}
914
915impl PartialEq<BigNum> for BigNumRef {
916    fn eq(&self, oth: &BigNum) -> bool {
917        self.eq(&**oth)
918    }
919}
920
921impl Eq for BigNumRef {}
922
923impl PartialEq for BigNum {
924    fn eq(&self, oth: &BigNum) -> bool {
925        self.deref().eq(oth)
926    }
927}
928
929impl PartialEq<BigNumRef> for BigNum {
930    fn eq(&self, oth: &BigNumRef) -> bool {
931        self.deref().eq(oth)
932    }
933}
934
935impl Eq for BigNum {}
936
937impl PartialOrd<BigNumRef> for BigNumRef {
938    fn partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering> {
939        Some(self.cmp(oth))
940    }
941}
942
943impl PartialOrd<BigNum> for BigNumRef {
944    fn partial_cmp(&self, oth: &BigNum) -> Option<Ordering> {
945        Some(self.cmp(&**oth))
946    }
947}
948
949impl Ord for BigNumRef {
950    fn cmp(&self, oth: &BigNumRef) -> Ordering {
951        unsafe { ffi::BN_cmp(self.as_ptr(), oth.as_ptr()).cmp(&0) }
952    }
953}
954
955impl PartialOrd for BigNum {
956    fn partial_cmp(&self, oth: &BigNum) -> Option<Ordering> {
957        Some(self.cmp(oth))
958    }
959}
960
961impl PartialOrd<BigNumRef> for BigNum {
962    fn partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering> {
963        self.deref().partial_cmp(oth)
964    }
965}
966
967impl Ord for BigNum {
968    fn cmp(&self, oth: &BigNum) -> Ordering {
969        self.deref().cmp(&**oth)
970    }
971}
972
973macro_rules! delegate {
974    ($t:ident, $m:ident) => {
975        impl<'a, 'b> $t<&'b BigNum> for &'a BigNumRef {
976            type Output = BigNum;
977
978            fn $m(self, oth: &BigNum) -> BigNum {
979                $t::$m(self, oth.deref())
980            }
981        }
982
983        impl<'a, 'b> $t<&'b BigNumRef> for &'a BigNum {
984            type Output = BigNum;
985
986            fn $m(self, oth: &BigNumRef) -> BigNum {
987                $t::$m(self.deref(), oth)
988            }
989        }
990
991        impl<'a, 'b> $t<&'b BigNum> for &'a BigNum {
992            type Output = BigNum;
993
994            fn $m(self, oth: &BigNum) -> BigNum {
995                $t::$m(self.deref(), oth.deref())
996            }
997        }
998    };
999}
1000
1001impl Add<&BigNumRef> for &BigNumRef {
1002    type Output = BigNum;
1003
1004    fn add(self, oth: &BigNumRef) -> BigNum {
1005        let mut r = BigNum::new().unwrap();
1006        r.checked_add(self, oth).unwrap();
1007        r
1008    }
1009}
1010
1011delegate!(Add, add);
1012
1013impl Sub<&BigNumRef> for &BigNumRef {
1014    type Output = BigNum;
1015
1016    fn sub(self, oth: &BigNumRef) -> BigNum {
1017        let mut r = BigNum::new().unwrap();
1018        r.checked_sub(self, oth).unwrap();
1019        r
1020    }
1021}
1022
1023delegate!(Sub, sub);
1024
1025impl Mul<&BigNumRef> for &BigNumRef {
1026    type Output = BigNum;
1027
1028    fn mul(self, oth: &BigNumRef) -> BigNum {
1029        let mut ctx = BigNumContext::new().unwrap();
1030        let mut r = BigNum::new().unwrap();
1031        r.checked_mul(self, oth, &mut ctx).unwrap();
1032        r
1033    }
1034}
1035
1036delegate!(Mul, mul);
1037
1038impl<'b> Div<&'b BigNumRef> for &BigNumRef {
1039    type Output = BigNum;
1040
1041    fn div(self, oth: &'b BigNumRef) -> BigNum {
1042        let mut ctx = BigNumContext::new().unwrap();
1043        let mut r = BigNum::new().unwrap();
1044        r.checked_div(self, oth, &mut ctx).unwrap();
1045        r
1046    }
1047}
1048
1049delegate!(Div, div);
1050
1051impl<'b> Rem<&'b BigNumRef> for &BigNumRef {
1052    type Output = BigNum;
1053
1054    fn rem(self, oth: &'b BigNumRef) -> BigNum {
1055        let mut ctx = BigNumContext::new().unwrap();
1056        let mut r = BigNum::new().unwrap();
1057        r.checked_rem(self, oth, &mut ctx).unwrap();
1058        r
1059    }
1060}
1061
1062delegate!(Rem, rem);
1063
1064impl Shl<i32> for &BigNumRef {
1065    type Output = BigNum;
1066
1067    fn shl(self, n: i32) -> BigNum {
1068        let mut r = BigNum::new().unwrap();
1069        r.lshift(self, n).unwrap();
1070        r
1071    }
1072}
1073
1074impl Shl<i32> for &BigNum {
1075    type Output = BigNum;
1076
1077    fn shl(self, n: i32) -> BigNum {
1078        self.deref().shl(n)
1079    }
1080}
1081
1082impl Shr<i32> for &BigNumRef {
1083    type Output = BigNum;
1084
1085    fn shr(self, n: i32) -> BigNum {
1086        let mut r = BigNum::new().unwrap();
1087        r.rshift(self, n).unwrap();
1088        r
1089    }
1090}
1091
1092impl Shr<i32> for &BigNum {
1093    type Output = BigNum;
1094
1095    fn shr(self, n: i32) -> BigNum {
1096        self.deref().shr(n)
1097    }
1098}
1099
1100impl Neg for &BigNumRef {
1101    type Output = BigNum;
1102
1103    fn neg(self) -> BigNum {
1104        self.to_owned().unwrap().neg()
1105    }
1106}
1107
1108impl Neg for &BigNum {
1109    type Output = BigNum;
1110
1111    fn neg(self) -> BigNum {
1112        self.deref().neg()
1113    }
1114}
1115
1116impl Neg for BigNum {
1117    type Output = BigNum;
1118
1119    fn neg(mut self) -> BigNum {
1120        let negative = self.is_negative();
1121        self.set_negative(!negative);
1122        self
1123    }
1124}
1125
1126#[cfg(test)]
1127mod tests {
1128    use crate::bn::{BigNum, BigNumContext};
1129
1130    #[test]
1131    fn test_to_from_slice() {
1132        let v0 = BigNum::from_u32(10_203_004).unwrap();
1133        let vec = v0.to_vec();
1134        let v1 = BigNum::from_slice(&vec).unwrap();
1135
1136        assert_eq!(v0, v1);
1137    }
1138
1139    #[test]
1140    fn test_negation() {
1141        let a = BigNum::from_u32(909_829_283).unwrap();
1142
1143        assert!(!a.is_negative());
1144        assert!((-a).is_negative());
1145    }
1146
1147    #[test]
1148    fn test_shift() {
1149        let a = BigNum::from_u32(909_829_283).unwrap();
1150
1151        assert_eq!(a, &(&a << 1) >> 1);
1152    }
1153
1154    #[test]
1155    fn test_rand_range() {
1156        let range = BigNum::from_u32(909_829_283).unwrap();
1157        let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap();
1158        range.rand_range(&mut result).unwrap();
1159        assert!(result >= BigNum::from_u32(0).unwrap() && result < range);
1160    }
1161
1162    #[test]
1163    fn test_pseudo_rand_range() {
1164        let range = BigNum::from_u32(909_829_283).unwrap();
1165        let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap();
1166        range.pseudo_rand_range(&mut result).unwrap();
1167        assert!(result >= BigNum::from_u32(0).unwrap() && result < range);
1168    }
1169
1170    #[test]
1171    fn test_prime_numbers() {
1172        let a = BigNum::from_u32(19_029_017).unwrap();
1173        let mut p = BigNum::new().unwrap();
1174        p.generate_prime(128, true, None, Some(&a)).unwrap();
1175
1176        let mut ctx = BigNumContext::new().unwrap();
1177        assert!(p.is_prime(100, &mut ctx).unwrap());
1178        assert!(p.is_prime_fasttest(100, &mut ctx, true).unwrap());
1179    }
1180}