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