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