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 cfg_if::cfg_if; 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 crate::asn1::Asn1Integer; 34 use crate::error::ErrorStack; 35 use crate::string::OpensslString; 36 use crate::{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 new() -> Result<BigNumContext, ErrorStack>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 implementation 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 clear(&mut self)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 add_word(&mut self, w: u32) -> Result<(), ErrorStack>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 sub_word(&mut self, w: u32) -> Result<(), ErrorStack>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 mul_word(&mut self, w: u32) -> Result<(), ErrorStack>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::useless_conversion)] div_word(&mut self, w: u32) -> Result<u64, ErrorStack>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::useless_conversion)] mod_word(&self, w: u32) -> Result<u64, ErrorStack>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 rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack>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 pseudo_rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack>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::useless_conversion)] set_bit(&mut self, n: i32) -> Result<(), ErrorStack>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::useless_conversion)] clear_bit(&mut self, n: i32) -> Result<(), ErrorStack>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::useless_conversion)] is_bit_set(&self, n: i32) -> bool269 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::useless_conversion)] mask_bits(&mut self, n: i32) -> Result<(), ErrorStack>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 lshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack>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 rshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack>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 checked_add(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack>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 checked_sub(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack>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::useless_conversion)] lshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack>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::useless_conversion)] rshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack>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 to_owned(&self) -> Result<BigNum, ErrorStack>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. set_negative(&mut self, negative: bool)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 /// ``` ucmp(&self, oth: &BigNumRef) -> Ordering374 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. is_negative(&self) -> bool379 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 num_bits(&self) -> i32388 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. num_bytes(&self) -> i32393 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::useless_conversion)] rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack>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::useless_conversion)] pseudo_rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack>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 generate_prime( &mut self, bits: i32, safe: bool, add: Option<&BigNumRef>, rem: Option<&BigNumRef>, ) -> Result<(), ErrorStack>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 checked_mul( &mut self, a: &BigNumRef, b: &BigNumRef, ctx: &mut BigNumContextRef, ) -> Result<(), ErrorStack>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 checked_div( &mut self, a: &BigNumRef, b: &BigNumRef, ctx: &mut BigNumContextRef, ) -> Result<(), ErrorStack>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 checked_rem( &mut self, a: &BigNumRef, b: &BigNumRef, ctx: &mut BigNumContextRef, ) -> Result<(), ErrorStack>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 div_rem( &mut self, rem: &mut BigNumRef, a: &BigNumRef, b: &BigNumRef, ctx: &mut BigNumContextRef, ) -> Result<(), ErrorStack>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 sqr(&mut self, a: &BigNumRef, ctx: &mut BigNumContextRef) -> Result<(), ErrorStack>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 nnmod( &mut self, a: &BigNumRef, m: &BigNumRef, ctx: &mut BigNumContextRef, ) -> Result<(), ErrorStack>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 mod_add( &mut self, a: &BigNumRef, b: &BigNumRef, m: &BigNumRef, ctx: &mut BigNumContextRef, ) -> Result<(), ErrorStack>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 mod_sub( &mut self, a: &BigNumRef, b: &BigNumRef, m: &BigNumRef, ctx: &mut BigNumContextRef, ) -> Result<(), ErrorStack>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 mod_mul( &mut self, a: &BigNumRef, b: &BigNumRef, m: &BigNumRef, ctx: &mut BigNumContextRef, ) -> Result<(), ErrorStack>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 mod_sqr( &mut self, a: &BigNumRef, m: &BigNumRef, ctx: &mut BigNumContextRef, ) -> Result<(), ErrorStack>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 exp( &mut self, a: &BigNumRef, p: &BigNumRef, ctx: &mut BigNumContextRef, ) -> Result<(), ErrorStack>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 mod_exp( &mut self, a: &BigNumRef, p: &BigNumRef, m: &BigNumRef, ctx: &mut BigNumContextRef, ) -> Result<(), ErrorStack>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`. mod_inverse( &mut self, a: &BigNumRef, n: &BigNumRef, ctx: &mut BigNumContextRef, ) -> Result<(), ErrorStack>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 gcd( &mut self, a: &BigNumRef, b: &BigNumRef, ctx: &mut BigNumContextRef, ) -> Result<(), ErrorStack>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::useless_conversion)] is_prime(&self, checks: i32, ctx: &mut BigNumContextRef) -> Result<bool, ErrorStack>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::useless_conversion)] is_prime_fasttest( &self, checks: i32, ctx: &mut BigNumContextRef, do_trial_division: bool, ) -> Result<bool, ErrorStack>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 /// ``` to_vec(&self) -> Vec<u8>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 /// ``` to_dec_str(&self) -> Result<OpensslString, ErrorStack>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 /// ``` to_hex_str(&self) -> Result<OpensslString, ErrorStack>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`. to_asn1_integer(&self) -> Result<Asn1Integer, ErrorStack>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. new() -> Result<BigNum, ErrorStack>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 from_u32(n: u32) -> Result<BigNum, ErrorStack>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 from_dec_str(s: &str) -> Result<BigNum, ErrorStack>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 from_hex_str(s: &str) -> Result<BigNum, ErrorStack>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 get_rfc2409_prime_768() -> Result<BigNum, ErrorStack>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 get_rfc2409_prime_1024() -> Result<BigNum, ErrorStack>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 get_rfc3526_prime_1536() -> Result<BigNum, ErrorStack>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 get_rfc3526_prime_2048() -> Result<BigNum, ErrorStack>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 get_rfc3526_prime_3072() -> Result<BigNum, ErrorStack>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 get_rfc3526_prime_4096() -> Result<BigNum, ErrorStack>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 get_rfc3526_prime_6144() -> Result<BigNum, ErrorStack>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 get_rfc3526_prime_8192() -> Result<BigNum, ErrorStack>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 /// ``` from_slice(n: &[u8]) -> Result<BigNum, ErrorStack>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 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1125 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 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1134 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 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1143 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 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1152 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 { eq(&self, oth: &BigNumRef) -> bool1161 fn eq(&self, oth: &BigNumRef) -> bool { 1162 self.cmp(oth) == Ordering::Equal 1163 } 1164 } 1165 1166 impl PartialEq<BigNum> for BigNumRef { eq(&self, oth: &BigNum) -> bool1167 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 { eq(&self, oth: &BigNum) -> bool1175 fn eq(&self, oth: &BigNum) -> bool { 1176 self.deref().eq(oth) 1177 } 1178 } 1179 1180 impl PartialEq<BigNumRef> for BigNum { eq(&self, oth: &BigNumRef) -> bool1181 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 { partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering>1189 fn partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering> { 1190 Some(self.cmp(oth)) 1191 } 1192 } 1193 1194 impl PartialOrd<BigNum> for BigNumRef { partial_cmp(&self, oth: &BigNum) -> Option<Ordering>1195 fn partial_cmp(&self, oth: &BigNum) -> Option<Ordering> { 1196 Some(self.cmp(oth.deref())) 1197 } 1198 } 1199 1200 impl Ord for BigNumRef { cmp(&self, oth: &BigNumRef) -> Ordering1201 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 { partial_cmp(&self, oth: &BigNum) -> Option<Ordering>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 { partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering>1213 fn partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering> { 1214 self.deref().partial_cmp(oth) 1215 } 1216 } 1217 1218 impl Ord for BigNum { cmp(&self, oth: &BigNum) -> Ordering1219 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 add(self, oth: &BigNumRef) -> BigNum1255 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 sub(self, oth: &BigNumRef) -> BigNum1267 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 mul(self, oth: &BigNumRef) -> BigNum1279 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 div(self, oth: &'b BigNumRef) -> BigNum1292 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 rem(self, oth: &'b BigNumRef) -> BigNum1305 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 shl(self, n: i32) -> BigNum1318 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 shl(self, n: i32) -> BigNum1328 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 shr(self, n: i32) -> BigNum1336 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 shr(self, n: i32) -> BigNum1346 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 neg(self) -> BigNum1354 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 neg(self) -> BigNum1362 fn neg(self) -> BigNum { 1363 self.deref().neg() 1364 } 1365 } 1366 1367 impl Neg for BigNum { 1368 type Output = BigNum; 1369 neg(mut self) -> BigNum1370 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 crate::bn::{BigNum, BigNumContext}; 1380 1381 #[test] test_to_from_slice()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] test_negation()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] test_shift()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] test_rand_range()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] test_pseudo_rand_range()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] test_prime_numbers()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 } 1432