1use cfg_if::cfg_if;
26use foreign_types::{ForeignType, ForeignTypeRef};
27use libc::c_int;
28use std::cmp::Ordering;
29use std::ffi::CString;
30use std::ops::{Add, Deref, Div, Mul, Neg, Rem, Shl, Shr, Sub};
31use std::{fmt, ptr};
32
33use crate::asn1::Asn1Integer;
34use crate::error::ErrorStack;
35use crate::string::OpensslString;
36use crate::{cvt, cvt_n, cvt_p, LenType};
37use openssl_macros::corresponds;
38
39cfg_if! {
40 if #[cfg(any(ossl110, libressl350, awslc))] {
41 use ffi::{
42 BN_get_rfc3526_prime_1536, 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 if #[cfg(boringssl)] {
46 use ffi::BN_is_negative;
47 } else {
48 use ffi::{
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
64cfg_if! {
65 if #[cfg(any(ossl110, libressl350))] {
66 use ffi::{
67 BN_get_rfc2409_prime_1024, BN_get_rfc2409_prime_768
68 };
69 } else if #[cfg(not(any(boringssl, awslc)))] {
70 use ffi::{
71 get_rfc2409_prime_1024 as BN_get_rfc2409_prime_1024,
72 get_rfc2409_prime_768 as BN_get_rfc2409_prime_768,
73 };
74 }
75}
76
77pub struct MsbOption(c_int);
79
80impl MsbOption {
81 pub const MAYBE_ZERO: MsbOption = MsbOption(-1);
83
84 pub const ONE: MsbOption = MsbOption(0);
86
87 pub const TWO_ONES: MsbOption = MsbOption(1);
92}
93
94foreign_type_and_impl_send_sync! {
95 type CType = ffi::BN_CTX;
96 fn drop = ffi::BN_CTX_free;
97
98 pub struct BigNumContext;
106 pub struct BigNumContextRef;
110}
111
112impl BigNumContext {
113 #[corresponds(BN_CTX_new)]
115 pub fn new() -> Result<BigNumContext, ErrorStack> {
116 unsafe {
117 ffi::init();
118 cvt_p(ffi::BN_CTX_new()).map(BigNumContext)
119 }
120 }
121
122 #[corresponds(BN_CTX_secure_new)]
124 #[cfg(ossl110)]
125 pub fn new_secure() -> Result<BigNumContext, ErrorStack> {
126 unsafe {
127 ffi::init();
128 cvt_p(ffi::BN_CTX_secure_new()).map(BigNumContext)
129 }
130 }
131}
132
133foreign_type_and_impl_send_sync! {
134 type CType = ffi::BIGNUM;
135 fn drop = ffi::BN_free;
136
137 pub struct BigNum;
161 pub struct BigNumRef;
165}
166
167impl BigNumRef {
168 #[corresponds(BN_clear)]
172 pub fn clear(&mut self) {
173 unsafe { ffi::BN_clear(self.as_ptr()) }
174 }
175
176 #[corresponds(BN_add_word)]
178 pub fn add_word(&mut self, w: u32) -> Result<(), ErrorStack> {
179 unsafe { cvt(ffi::BN_add_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
180 }
181
182 #[corresponds(BN_sub_word)]
184 pub fn sub_word(&mut self, w: u32) -> Result<(), ErrorStack> {
185 unsafe { cvt(ffi::BN_sub_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
186 }
187
188 #[corresponds(BN_mul_word)]
190 pub fn mul_word(&mut self, w: u32) -> Result<(), ErrorStack> {
191 unsafe { cvt(ffi::BN_mul_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
192 }
193
194 #[corresponds(BN_div_word)]
196 #[allow(clippy::useless_conversion)]
197 pub fn div_word(&mut self, w: u32) -> Result<u64, ErrorStack> {
198 unsafe {
199 let r = ffi::BN_div_word(self.as_ptr(), w.into());
200 if r == ffi::BN_ULONG::MAX {
201 Err(ErrorStack::get())
202 } else {
203 Ok(r.into())
204 }
205 }
206 }
207
208 #[corresponds(BN_mod_word)]
210 #[allow(clippy::useless_conversion)]
211 pub fn mod_word(&self, w: u32) -> Result<u64, ErrorStack> {
212 unsafe {
213 let r = ffi::BN_mod_word(self.as_ptr(), w.into());
214 if r == ffi::BN_ULONG::MAX {
215 Err(ErrorStack::get())
216 } else {
217 Ok(r.into())
218 }
219 }
220 }
221
222 #[corresponds(BN_rand_range)]
225 pub fn rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> {
226 unsafe { cvt(ffi::BN_rand_range(rnd.as_ptr(), self.as_ptr())).map(|_| ()) }
227 }
228
229 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
231 #[corresponds(BN_pseudo_rand_range)]
232 pub fn pseudo_rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> {
233 unsafe { cvt(ffi::BN_pseudo_rand_range(rnd.as_ptr(), self.as_ptr())).map(|_| ()) }
234 }
235
236 #[corresponds(BN_set_bit)]
240 #[allow(clippy::useless_conversion)]
241 pub fn set_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
242 unsafe { cvt(ffi::BN_set_bit(self.as_ptr(), n.into())).map(|_| ()) }
243 }
244
245 #[corresponds(BN_clear_bit)]
249 #[allow(clippy::useless_conversion)]
250 pub fn clear_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
251 unsafe { cvt(ffi::BN_clear_bit(self.as_ptr(), n.into())).map(|_| ()) }
252 }
253
254 #[corresponds(BN_is_bit_set)]
256 #[allow(clippy::useless_conversion)]
257 pub fn is_bit_set(&self, n: i32) -> bool {
258 unsafe { ffi::BN_is_bit_set(self.as_ptr(), n.into()) == 1 }
259 }
260
261 #[corresponds(BN_mask_bits)]
265 #[allow(clippy::useless_conversion)]
266 pub fn mask_bits(&mut self, n: i32) -> Result<(), ErrorStack> {
267 unsafe { cvt(ffi::BN_mask_bits(self.as_ptr(), n.into())).map(|_| ()) }
268 }
269
270 #[corresponds(BN_lshift1)]
272 pub fn lshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack> {
273 unsafe { cvt(ffi::BN_lshift1(self.as_ptr(), a.as_ptr())).map(|_| ()) }
274 }
275
276 #[corresponds(BN_rshift1)]
278 pub fn rshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack> {
279 unsafe { cvt(ffi::BN_rshift1(self.as_ptr(), a.as_ptr())).map(|_| ()) }
280 }
281
282 #[corresponds(BN_add)]
286 pub fn checked_add(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack> {
287 unsafe { cvt(ffi::BN_add(self.as_ptr(), a.as_ptr(), b.as_ptr())).map(|_| ()) }
288 }
289
290 #[corresponds(BN_sub)]
294 pub fn checked_sub(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack> {
295 unsafe { cvt(ffi::BN_sub(self.as_ptr(), a.as_ptr(), b.as_ptr())).map(|_| ()) }
296 }
297
298 #[corresponds(BN_lshift)]
300 #[allow(clippy::useless_conversion)]
301 pub fn lshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack> {
302 unsafe { cvt(ffi::BN_lshift(self.as_ptr(), a.as_ptr(), n.into())).map(|_| ()) }
303 }
304
305 #[corresponds(BN_rshift)]
307 #[allow(clippy::useless_conversion)]
308 pub fn rshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack> {
309 unsafe { cvt(ffi::BN_rshift(self.as_ptr(), a.as_ptr(), n.into())).map(|_| ()) }
310 }
311
312 #[corresponds(BN_dup)]
314 pub fn to_owned(&self) -> Result<BigNum, ErrorStack> {
315 unsafe { cvt_p(ffi::BN_dup(self.as_ptr())).map(|b| BigNum::from_ptr(b)) }
316 }
317
318 #[corresponds(BN_set_negative)]
321 pub fn set_negative(&mut self, negative: bool) {
322 unsafe { ffi::BN_set_negative(self.as_ptr(), negative as c_int) }
323 }
324
325 #[corresponds(BN_ucmp)]
338 pub fn ucmp(&self, oth: &BigNumRef) -> Ordering {
339 unsafe { ffi::BN_ucmp(self.as_ptr(), oth.as_ptr()).cmp(&0) }
340 }
341
342 #[corresponds(BN_is_negative)]
344 pub fn is_negative(&self) -> bool {
345 unsafe { BN_is_negative(self.as_ptr()) == 1 }
346 }
347
348 #[corresponds(BN_is_even)]
350 #[cfg(any(ossl110, boringssl, libressl350, awslc))]
351 pub fn is_even(&self) -> bool {
352 !self.is_odd()
353 }
354
355 #[corresponds(BN_is_odd)]
357 #[cfg(any(ossl110, boringssl, libressl350, awslc))]
358 pub fn is_odd(&self) -> bool {
359 unsafe { ffi::BN_is_odd(self.as_ptr()) == 1 }
360 }
361
362 #[corresponds(BN_num_bits)]
364 #[allow(clippy::unnecessary_cast)]
365 pub fn num_bits(&self) -> i32 {
366 unsafe { ffi::BN_num_bits(self.as_ptr()) as i32 }
367 }
368
369 pub fn num_bytes(&self) -> i32 {
371 (self.num_bits() + 7) / 8
372 }
373
374 #[corresponds(BN_rand)]
399 #[allow(clippy::useless_conversion)]
400 pub fn rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> {
401 unsafe {
402 cvt(ffi::BN_rand(
403 self.as_ptr(),
404 bits.into(),
405 msb.0,
406 odd as c_int,
407 ))
408 .map(|_| ())
409 }
410 }
411
412 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
414 #[corresponds(BN_pseudo_rand)]
415 #[allow(clippy::useless_conversion)]
416 pub fn pseudo_rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> {
417 unsafe {
418 cvt(ffi::BN_pseudo_rand(
419 self.as_ptr(),
420 bits.into(),
421 msb.0,
422 odd as c_int,
423 ))
424 .map(|_| ())
425 }
426 }
427
428 #[corresponds(BN_generate_prime_ex)]
452 pub fn generate_prime(
453 &mut self,
454 bits: i32,
455 safe: bool,
456 add: Option<&BigNumRef>,
457 rem: Option<&BigNumRef>,
458 ) -> Result<(), ErrorStack> {
459 unsafe {
460 cvt(ffi::BN_generate_prime_ex(
461 self.as_ptr(),
462 bits as c_int,
463 safe as c_int,
464 add.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()),
465 rem.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()),
466 ptr::null_mut(),
467 ))
468 .map(|_| ())
469 }
470 }
471
472 #[corresponds(BN_mul)]
477 pub fn checked_mul(
478 &mut self,
479 a: &BigNumRef,
480 b: &BigNumRef,
481 ctx: &mut BigNumContextRef,
482 ) -> Result<(), ErrorStack> {
483 unsafe {
484 cvt(ffi::BN_mul(
485 self.as_ptr(),
486 a.as_ptr(),
487 b.as_ptr(),
488 ctx.as_ptr(),
489 ))
490 .map(|_| ())
491 }
492 }
493
494 #[corresponds(BN_div)]
499 pub fn checked_div(
500 &mut self,
501 a: &BigNumRef,
502 b: &BigNumRef,
503 ctx: &mut BigNumContextRef,
504 ) -> Result<(), ErrorStack> {
505 unsafe {
506 cvt(ffi::BN_div(
507 self.as_ptr(),
508 ptr::null_mut(),
509 a.as_ptr(),
510 b.as_ptr(),
511 ctx.as_ptr(),
512 ))
513 .map(|_| ())
514 }
515 }
516
517 #[corresponds(BN_div)]
519 pub fn checked_rem(
520 &mut self,
521 a: &BigNumRef,
522 b: &BigNumRef,
523 ctx: &mut BigNumContextRef,
524 ) -> Result<(), ErrorStack> {
525 unsafe {
526 cvt(ffi::BN_div(
527 ptr::null_mut(),
528 self.as_ptr(),
529 a.as_ptr(),
530 b.as_ptr(),
531 ctx.as_ptr(),
532 ))
533 .map(|_| ())
534 }
535 }
536
537 #[corresponds(BN_div)]
539 pub fn div_rem(
540 &mut self,
541 rem: &mut BigNumRef,
542 a: &BigNumRef,
543 b: &BigNumRef,
544 ctx: &mut BigNumContextRef,
545 ) -> Result<(), ErrorStack> {
546 unsafe {
547 cvt(ffi::BN_div(
548 self.as_ptr(),
549 rem.as_ptr(),
550 a.as_ptr(),
551 b.as_ptr(),
552 ctx.as_ptr(),
553 ))
554 .map(|_| ())
555 }
556 }
557
558 #[corresponds(BN_sqr)]
560 pub fn sqr(&mut self, a: &BigNumRef, ctx: &mut BigNumContextRef) -> Result<(), ErrorStack> {
561 unsafe { cvt(ffi::BN_sqr(self.as_ptr(), a.as_ptr(), ctx.as_ptr())).map(|_| ()) }
562 }
563
564 #[corresponds(BN_nnmod)]
567 pub fn nnmod(
568 &mut self,
569 a: &BigNumRef,
570 m: &BigNumRef,
571 ctx: &mut BigNumContextRef,
572 ) -> Result<(), ErrorStack> {
573 unsafe {
574 cvt(ffi::BN_nnmod(
575 self.as_ptr(),
576 a.as_ptr(),
577 m.as_ptr(),
578 ctx.as_ptr(),
579 ))
580 .map(|_| ())
581 }
582 }
583
584 #[corresponds(BN_mod_add)]
586 pub fn mod_add(
587 &mut self,
588 a: &BigNumRef,
589 b: &BigNumRef,
590 m: &BigNumRef,
591 ctx: &mut BigNumContextRef,
592 ) -> Result<(), ErrorStack> {
593 unsafe {
594 cvt(ffi::BN_mod_add(
595 self.as_ptr(),
596 a.as_ptr(),
597 b.as_ptr(),
598 m.as_ptr(),
599 ctx.as_ptr(),
600 ))
601 .map(|_| ())
602 }
603 }
604
605 #[corresponds(BN_mod_sub)]
607 pub fn mod_sub(
608 &mut self,
609 a: &BigNumRef,
610 b: &BigNumRef,
611 m: &BigNumRef,
612 ctx: &mut BigNumContextRef,
613 ) -> Result<(), ErrorStack> {
614 unsafe {
615 cvt(ffi::BN_mod_sub(
616 self.as_ptr(),
617 a.as_ptr(),
618 b.as_ptr(),
619 m.as_ptr(),
620 ctx.as_ptr(),
621 ))
622 .map(|_| ())
623 }
624 }
625
626 #[corresponds(BN_mod_mul)]
628 pub fn mod_mul(
629 &mut self,
630 a: &BigNumRef,
631 b: &BigNumRef,
632 m: &BigNumRef,
633 ctx: &mut BigNumContextRef,
634 ) -> Result<(), ErrorStack> {
635 unsafe {
636 cvt(ffi::BN_mod_mul(
637 self.as_ptr(),
638 a.as_ptr(),
639 b.as_ptr(),
640 m.as_ptr(),
641 ctx.as_ptr(),
642 ))
643 .map(|_| ())
644 }
645 }
646
647 #[corresponds(BN_mod_sqr)]
649 pub fn mod_sqr(
650 &mut self,
651 a: &BigNumRef,
652 m: &BigNumRef,
653 ctx: &mut BigNumContextRef,
654 ) -> Result<(), ErrorStack> {
655 unsafe {
656 cvt(ffi::BN_mod_sqr(
657 self.as_ptr(),
658 a.as_ptr(),
659 m.as_ptr(),
660 ctx.as_ptr(),
661 ))
662 .map(|_| ())
663 }
664 }
665
666 #[corresponds(BN_mod_sqrt)]
668 pub fn mod_sqrt(
669 &mut self,
670 a: &BigNumRef,
671 p: &BigNumRef,
672 ctx: &mut BigNumContextRef,
673 ) -> Result<(), ErrorStack> {
674 unsafe {
675 cvt_p(ffi::BN_mod_sqrt(
676 self.as_ptr(),
677 a.as_ptr(),
678 p.as_ptr(),
679 ctx.as_ptr(),
680 ))
681 .map(|_| ())
682 }
683 }
684
685 #[corresponds(BN_exp)]
687 pub fn exp(
688 &mut self,
689 a: &BigNumRef,
690 p: &BigNumRef,
691 ctx: &mut BigNumContextRef,
692 ) -> Result<(), ErrorStack> {
693 unsafe {
694 cvt(ffi::BN_exp(
695 self.as_ptr(),
696 a.as_ptr(),
697 p.as_ptr(),
698 ctx.as_ptr(),
699 ))
700 .map(|_| ())
701 }
702 }
703
704 #[corresponds(BN_mod_exp)]
706 pub fn mod_exp(
707 &mut self,
708 a: &BigNumRef,
709 p: &BigNumRef,
710 m: &BigNumRef,
711 ctx: &mut BigNumContextRef,
712 ) -> Result<(), ErrorStack> {
713 unsafe {
714 cvt(ffi::BN_mod_exp(
715 self.as_ptr(),
716 a.as_ptr(),
717 p.as_ptr(),
718 m.as_ptr(),
719 ctx.as_ptr(),
720 ))
721 .map(|_| ())
722 }
723 }
724
725 #[corresponds(BN_mod_inverse)]
727 pub fn mod_inverse(
728 &mut self,
729 a: &BigNumRef,
730 n: &BigNumRef,
731 ctx: &mut BigNumContextRef,
732 ) -> Result<(), ErrorStack> {
733 unsafe {
734 cvt_p(ffi::BN_mod_inverse(
735 self.as_ptr(),
736 a.as_ptr(),
737 n.as_ptr(),
738 ctx.as_ptr(),
739 ))
740 .map(|_| ())
741 }
742 }
743
744 #[corresponds(BN_gcd)]
746 pub fn gcd(
747 &mut self,
748 a: &BigNumRef,
749 b: &BigNumRef,
750 ctx: &mut BigNumContextRef,
751 ) -> Result<(), ErrorStack> {
752 unsafe {
753 cvt(ffi::BN_gcd(
754 self.as_ptr(),
755 a.as_ptr(),
756 b.as_ptr(),
757 ctx.as_ptr(),
758 ))
759 .map(|_| ())
760 }
761 }
762
763 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
771 #[corresponds(BN_is_prime_ex)]
772 #[allow(clippy::useless_conversion)]
773 pub fn is_prime(&self, checks: i32, ctx: &mut BigNumContextRef) -> Result<bool, ErrorStack> {
774 unsafe {
775 cvt_n(ffi::BN_is_prime_ex(
776 self.as_ptr(),
777 checks.into(),
778 ctx.as_ptr(),
779 ptr::null_mut(),
780 ))
781 .map(|r| r != 0)
782 }
783 }
784
785 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
795 #[corresponds(BN_is_prime_fasttest_ex)]
796 #[allow(clippy::useless_conversion)]
797 pub fn is_prime_fasttest(
798 &self,
799 checks: i32,
800 ctx: &mut BigNumContextRef,
801 do_trial_division: bool,
802 ) -> Result<bool, ErrorStack> {
803 unsafe {
804 cvt_n(ffi::BN_is_prime_fasttest_ex(
805 self.as_ptr(),
806 checks.into(),
807 ctx.as_ptr(),
808 do_trial_division as c_int,
809 ptr::null_mut(),
810 ))
811 .map(|r| r != 0)
812 }
813 }
814
815 #[corresponds(BN_bn2bin)]
828 pub fn to_vec(&self) -> Vec<u8> {
829 let size = self.num_bytes() as usize;
830 let mut v = Vec::with_capacity(size);
831 unsafe {
832 ffi::BN_bn2bin(self.as_ptr(), v.as_mut_ptr());
833 v.set_len(size);
834 }
835 v
836 }
837
838 #[corresponds(BN_bn2binpad)]
860 #[cfg(any(ossl110, libressl340, boringssl, awslc))]
861 pub fn to_vec_padded(&self, pad_to: i32) -> Result<Vec<u8>, ErrorStack> {
862 let mut v = Vec::with_capacity(pad_to as usize);
863 unsafe {
864 cvt(ffi::BN_bn2binpad(self.as_ptr(), v.as_mut_ptr(), pad_to))?;
865 v.set_len(pad_to as usize);
866 }
867 Ok(v)
868 }
869
870 #[corresponds(BN_bn2dec)]
879 pub fn to_dec_str(&self) -> Result<OpensslString, ErrorStack> {
880 unsafe {
881 let buf = cvt_p(ffi::BN_bn2dec(self.as_ptr()))?;
882 Ok(OpensslString::from_ptr(buf))
883 }
884 }
885
886 #[corresponds(BN_bn2hex)]
895 pub fn to_hex_str(&self) -> Result<OpensslString, ErrorStack> {
896 unsafe {
897 let buf = cvt_p(ffi::BN_bn2hex(self.as_ptr()))?;
898 Ok(OpensslString::from_ptr(buf))
899 }
900 }
901
902 #[corresponds(BN_to_ASN1_INTEGER)]
904 pub fn to_asn1_integer(&self) -> Result<Asn1Integer, ErrorStack> {
905 unsafe {
906 cvt_p(ffi::BN_to_ASN1_INTEGER(self.as_ptr(), ptr::null_mut()))
907 .map(|p| Asn1Integer::from_ptr(p))
908 }
909 }
910
911 #[corresponds(BN_set_flags)]
913 #[cfg(ossl110)]
914 pub fn set_const_time(&mut self) {
915 unsafe { ffi::BN_set_flags(self.as_ptr(), ffi::BN_FLG_CONSTTIME) }
916 }
917
918 #[corresponds(BN_get_flags)]
920 #[cfg(ossl110)]
921 pub fn is_const_time(&self) -> bool {
922 unsafe {
923 let ret = ffi::BN_get_flags(self.as_ptr(), ffi::BN_FLG_CONSTTIME);
924 ret == ffi::BN_FLG_CONSTTIME
925 }
926 }
927
928 #[corresponds(BN_get_flags)]
930 #[cfg(ossl110)]
931 pub fn is_secure(&self) -> bool {
932 unsafe {
933 let ret = ffi::BN_get_flags(self.as_ptr(), ffi::BN_FLG_SECURE);
934 ret == ffi::BN_FLG_SECURE
935 }
936 }
937}
938
939impl BigNum {
940 #[corresponds(BN_new)]
942 pub fn new() -> Result<BigNum, ErrorStack> {
943 unsafe {
944 ffi::init();
945 let v = cvt_p(ffi::BN_new())?;
946 Ok(BigNum::from_ptr(v))
947 }
948 }
949
950 #[corresponds(BN_secure_new)]
952 #[cfg(ossl110)]
953 pub fn new_secure() -> Result<BigNum, ErrorStack> {
954 unsafe {
955 ffi::init();
956 let v = cvt_p(ffi::BN_secure_new())?;
957 Ok(BigNum::from_ptr(v))
958 }
959 }
960
961 #[corresponds(BN_set_word)]
963 pub fn from_u32(n: u32) -> Result<BigNum, ErrorStack> {
964 BigNum::new().and_then(|v| unsafe {
965 cvt(ffi::BN_set_word(v.as_ptr(), n as ffi::BN_ULONG)).map(|_| v)
966 })
967 }
968
969 #[corresponds(BN_dec2bn)]
971 pub fn from_dec_str(s: &str) -> Result<BigNum, ErrorStack> {
972 unsafe {
973 ffi::init();
974 let c_str = CString::new(s.as_bytes()).unwrap();
975 let mut bn = ptr::null_mut();
976 cvt(ffi::BN_dec2bn(&mut bn, c_str.as_ptr() as *const _))?;
977 Ok(BigNum::from_ptr(bn))
978 }
979 }
980
981 #[corresponds(BN_hex2bn)]
983 pub fn from_hex_str(s: &str) -> Result<BigNum, ErrorStack> {
984 unsafe {
985 ffi::init();
986 let c_str = CString::new(s.as_bytes()).unwrap();
987 let mut bn = ptr::null_mut();
988 cvt(ffi::BN_hex2bn(&mut bn, c_str.as_ptr() as *const _))?;
989 Ok(BigNum::from_ptr(bn))
990 }
991 }
992
993 #[corresponds(BN_get_rfc2409_prime_768)]
999 #[cfg(not(any(boringssl, awslc)))]
1000 pub fn get_rfc2409_prime_768() -> Result<BigNum, ErrorStack> {
1001 unsafe {
1002 ffi::init();
1003 cvt_p(BN_get_rfc2409_prime_768(ptr::null_mut())).map(BigNum)
1004 }
1005 }
1006
1007 #[corresponds(BN_get_rfc2409_prime_1024)]
1013 #[cfg(not(any(boringssl, awslc)))]
1014 pub fn get_rfc2409_prime_1024() -> Result<BigNum, ErrorStack> {
1015 unsafe {
1016 ffi::init();
1017 cvt_p(BN_get_rfc2409_prime_1024(ptr::null_mut())).map(BigNum)
1018 }
1019 }
1020
1021 #[corresponds(BN_get_rfc3526_prime_1536)]
1027 #[cfg(not(boringssl))]
1028 pub fn get_rfc3526_prime_1536() -> Result<BigNum, ErrorStack> {
1029 unsafe {
1030 ffi::init();
1031 cvt_p(BN_get_rfc3526_prime_1536(ptr::null_mut())).map(BigNum)
1032 }
1033 }
1034
1035 #[corresponds(BN_get_rfc3526_prime_2048)]
1041 #[cfg(not(boringssl))]
1042 pub fn get_rfc3526_prime_2048() -> Result<BigNum, ErrorStack> {
1043 unsafe {
1044 ffi::init();
1045 cvt_p(BN_get_rfc3526_prime_2048(ptr::null_mut())).map(BigNum)
1046 }
1047 }
1048
1049 #[corresponds(BN_get_rfc3526_prime_3072)]
1055 #[cfg(not(boringssl))]
1056 pub fn get_rfc3526_prime_3072() -> Result<BigNum, ErrorStack> {
1057 unsafe {
1058 ffi::init();
1059 cvt_p(BN_get_rfc3526_prime_3072(ptr::null_mut())).map(BigNum)
1060 }
1061 }
1062
1063 #[corresponds(BN_get_rfc3526_prime_4096)]
1069 #[cfg(not(boringssl))]
1070 pub fn get_rfc3526_prime_4096() -> Result<BigNum, ErrorStack> {
1071 unsafe {
1072 ffi::init();
1073 cvt_p(BN_get_rfc3526_prime_4096(ptr::null_mut())).map(BigNum)
1074 }
1075 }
1076
1077 #[corresponds(BN_get_rfc3526_prime_6114)]
1083 #[cfg(not(boringssl))]
1084 pub fn get_rfc3526_prime_6144() -> Result<BigNum, ErrorStack> {
1085 unsafe {
1086 ffi::init();
1087 cvt_p(BN_get_rfc3526_prime_6144(ptr::null_mut())).map(BigNum)
1088 }
1089 }
1090
1091 #[corresponds(BN_get_rfc3526_prime_8192)]
1097 #[cfg(not(boringssl))]
1098 pub fn get_rfc3526_prime_8192() -> Result<BigNum, ErrorStack> {
1099 unsafe {
1100 ffi::init();
1101 cvt_p(BN_get_rfc3526_prime_8192(ptr::null_mut())).map(BigNum)
1102 }
1103 }
1104
1105 #[corresponds(BN_bin2bn)]
1118 pub fn from_slice(n: &[u8]) -> Result<BigNum, ErrorStack> {
1119 unsafe {
1120 ffi::init();
1121 assert!(n.len() <= LenType::MAX as usize);
1122
1123 cvt_p(ffi::BN_bin2bn(
1124 n.as_ptr(),
1125 n.len() as LenType,
1126 ptr::null_mut(),
1127 ))
1128 .map(|p| BigNum::from_ptr(p))
1129 }
1130 }
1131
1132 #[corresponds(BN_bin2bn)]
1147 pub fn copy_from_slice(&mut self, n: &[u8]) -> Result<(), ErrorStack> {
1148 unsafe {
1149 assert!(n.len() <= LenType::MAX as usize);
1150
1151 cvt_p(ffi::BN_bin2bn(n.as_ptr(), n.len() as LenType, self.0))?;
1152 Ok(())
1153 }
1154 }
1155}
1156
1157impl fmt::Debug for BigNumRef {
1158 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1159 match self.to_dec_str() {
1160 Ok(s) => f.write_str(&s),
1161 Err(e) => Err(e.into()),
1162 }
1163 }
1164}
1165
1166impl fmt::Debug for BigNum {
1167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1168 match self.to_dec_str() {
1169 Ok(s) => f.write_str(&s),
1170 Err(e) => Err(e.into()),
1171 }
1172 }
1173}
1174
1175impl fmt::Display for BigNumRef {
1176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1177 match self.to_dec_str() {
1178 Ok(s) => f.write_str(&s),
1179 Err(e) => Err(e.into()),
1180 }
1181 }
1182}
1183
1184impl fmt::Display for BigNum {
1185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1186 match self.to_dec_str() {
1187 Ok(s) => f.write_str(&s),
1188 Err(e) => Err(e.into()),
1189 }
1190 }
1191}
1192
1193impl PartialEq<BigNumRef> for BigNumRef {
1194 fn eq(&self, oth: &BigNumRef) -> bool {
1195 self.cmp(oth) == Ordering::Equal
1196 }
1197}
1198
1199impl PartialEq<BigNum> for BigNumRef {
1200 fn eq(&self, oth: &BigNum) -> bool {
1201 self.eq(oth.deref())
1202 }
1203}
1204
1205impl Eq for BigNumRef {}
1206
1207impl PartialEq for BigNum {
1208 fn eq(&self, oth: &BigNum) -> bool {
1209 self.deref().eq(oth)
1210 }
1211}
1212
1213impl PartialEq<BigNumRef> for BigNum {
1214 fn eq(&self, oth: &BigNumRef) -> bool {
1215 self.deref().eq(oth)
1216 }
1217}
1218
1219impl Eq for BigNum {}
1220
1221impl PartialOrd<BigNumRef> for BigNumRef {
1222 fn partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering> {
1223 Some(self.cmp(oth))
1224 }
1225}
1226
1227impl PartialOrd<BigNum> for BigNumRef {
1228 fn partial_cmp(&self, oth: &BigNum) -> Option<Ordering> {
1229 Some(self.cmp(oth.deref()))
1230 }
1231}
1232
1233impl Ord for BigNumRef {
1234 fn cmp(&self, oth: &BigNumRef) -> Ordering {
1235 unsafe { ffi::BN_cmp(self.as_ptr(), oth.as_ptr()).cmp(&0) }
1236 }
1237}
1238
1239impl PartialOrd for BigNum {
1240 fn partial_cmp(&self, oth: &BigNum) -> Option<Ordering> {
1241 Some(self.cmp(oth))
1242 }
1243}
1244
1245impl PartialOrd<BigNumRef> for BigNum {
1246 fn partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering> {
1247 self.deref().partial_cmp(oth)
1248 }
1249}
1250
1251impl Ord for BigNum {
1252 fn cmp(&self, oth: &BigNum) -> Ordering {
1253 self.deref().cmp(oth.deref())
1254 }
1255}
1256
1257macro_rules! delegate {
1258 ($t:ident, $m:ident) => {
1259 impl<'a, 'b> $t<&'b BigNum> for &'a BigNumRef {
1260 type Output = BigNum;
1261
1262 fn $m(self, oth: &BigNum) -> BigNum {
1263 $t::$m(self, oth.deref())
1264 }
1265 }
1266
1267 impl<'a, 'b> $t<&'b BigNumRef> for &'a BigNum {
1268 type Output = BigNum;
1269
1270 fn $m(self, oth: &BigNumRef) -> BigNum {
1271 $t::$m(self.deref(), oth)
1272 }
1273 }
1274
1275 impl<'a, 'b> $t<&'b BigNum> for &'a BigNum {
1276 type Output = BigNum;
1277
1278 fn $m(self, oth: &BigNum) -> BigNum {
1279 $t::$m(self.deref(), oth.deref())
1280 }
1281 }
1282 };
1283}
1284
1285impl Add<&BigNumRef> for &BigNumRef {
1286 type Output = BigNum;
1287
1288 fn add(self, oth: &BigNumRef) -> BigNum {
1289 let mut r = BigNum::new().unwrap();
1290 r.checked_add(self, oth).unwrap();
1291 r
1292 }
1293}
1294
1295delegate!(Add, add);
1296
1297impl Sub<&BigNumRef> for &BigNumRef {
1298 type Output = BigNum;
1299
1300 fn sub(self, oth: &BigNumRef) -> BigNum {
1301 let mut r = BigNum::new().unwrap();
1302 r.checked_sub(self, oth).unwrap();
1303 r
1304 }
1305}
1306
1307delegate!(Sub, sub);
1308
1309impl Mul<&BigNumRef> for &BigNumRef {
1310 type Output = BigNum;
1311
1312 fn mul(self, oth: &BigNumRef) -> BigNum {
1313 let mut ctx = BigNumContext::new().unwrap();
1314 let mut r = BigNum::new().unwrap();
1315 r.checked_mul(self, oth, &mut ctx).unwrap();
1316 r
1317 }
1318}
1319
1320delegate!(Mul, mul);
1321
1322impl<'b> Div<&'b BigNumRef> for &BigNumRef {
1323 type Output = BigNum;
1324
1325 fn div(self, oth: &'b BigNumRef) -> BigNum {
1326 let mut ctx = BigNumContext::new().unwrap();
1327 let mut r = BigNum::new().unwrap();
1328 r.checked_div(self, oth, &mut ctx).unwrap();
1329 r
1330 }
1331}
1332
1333delegate!(Div, div);
1334
1335impl<'b> Rem<&'b BigNumRef> for &BigNumRef {
1336 type Output = BigNum;
1337
1338 fn rem(self, oth: &'b BigNumRef) -> BigNum {
1339 let mut ctx = BigNumContext::new().unwrap();
1340 let mut r = BigNum::new().unwrap();
1341 r.checked_rem(self, oth, &mut ctx).unwrap();
1342 r
1343 }
1344}
1345
1346delegate!(Rem, rem);
1347
1348impl Shl<i32> for &BigNumRef {
1349 type Output = BigNum;
1350
1351 fn shl(self, n: i32) -> BigNum {
1352 let mut r = BigNum::new().unwrap();
1353 r.lshift(self, n).unwrap();
1354 r
1355 }
1356}
1357
1358impl Shl<i32> for &BigNum {
1359 type Output = BigNum;
1360
1361 fn shl(self, n: i32) -> BigNum {
1362 self.deref().shl(n)
1363 }
1364}
1365
1366impl Shr<i32> for &BigNumRef {
1367 type Output = BigNum;
1368
1369 fn shr(self, n: i32) -> BigNum {
1370 let mut r = BigNum::new().unwrap();
1371 r.rshift(self, n).unwrap();
1372 r
1373 }
1374}
1375
1376impl Shr<i32> for &BigNum {
1377 type Output = BigNum;
1378
1379 fn shr(self, n: i32) -> BigNum {
1380 self.deref().shr(n)
1381 }
1382}
1383
1384impl Neg for &BigNumRef {
1385 type Output = BigNum;
1386
1387 fn neg(self) -> BigNum {
1388 self.to_owned().unwrap().neg()
1389 }
1390}
1391
1392impl Neg for &BigNum {
1393 type Output = BigNum;
1394
1395 fn neg(self) -> BigNum {
1396 self.deref().neg()
1397 }
1398}
1399
1400impl Neg for BigNum {
1401 type Output = BigNum;
1402
1403 fn neg(mut self) -> BigNum {
1404 let negative = self.is_negative();
1405 self.set_negative(!negative);
1406 self
1407 }
1408}
1409
1410#[cfg(test)]
1411mod tests {
1412 use crate::bn::{BigNum, BigNumContext};
1413
1414 #[test]
1415 fn test_to_from_slice() {
1416 let v0 = BigNum::from_u32(10_203_004).unwrap();
1417 let vec = v0.to_vec();
1418 let v1 = BigNum::from_slice(&vec).unwrap();
1419
1420 assert_eq!(v0, v1);
1421 }
1422
1423 #[test]
1424 fn test_negation() {
1425 let a = BigNum::from_u32(909_829_283).unwrap();
1426
1427 assert!(!a.is_negative());
1428 assert!((-a).is_negative());
1429 }
1430
1431 #[test]
1432 fn test_shift() {
1433 let a = BigNum::from_u32(909_829_283).unwrap();
1434
1435 assert_eq!(a, &(&a << 1) >> 1);
1436 }
1437
1438 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1439 #[test]
1440 fn test_rand_range() {
1441 let range = BigNum::from_u32(909_829_283).unwrap();
1442 let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap();
1443 range.rand_range(&mut result).unwrap();
1444 assert!(result >= BigNum::from_u32(0).unwrap() && result < range);
1445 }
1446
1447 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1448 #[test]
1449 fn test_pseudo_rand_range() {
1450 let range = BigNum::from_u32(909_829_283).unwrap();
1451 let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap();
1452 range.pseudo_rand_range(&mut result).unwrap();
1453 assert!(result >= BigNum::from_u32(0).unwrap() && result < range);
1454 }
1455
1456 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1457 #[test]
1458 fn test_prime_numbers() {
1459 let a = BigNum::from_u32(19_029_017).unwrap();
1460 let mut p = BigNum::new().unwrap();
1461 p.generate_prime(128, true, None, Some(&a)).unwrap();
1462
1463 let mut ctx = BigNumContext::new().unwrap();
1464 assert!(p.is_prime(100, &mut ctx).unwrap());
1465 assert!(p.is_prime_fasttest(100, &mut ctx, true).unwrap());
1466 }
1467
1468 #[cfg(ossl110)]
1469 #[test]
1470 fn test_secure_bn_ctx() {
1471 let mut cxt = BigNumContext::new_secure().unwrap();
1472 let a = BigNum::from_u32(8).unwrap();
1473 let b = BigNum::from_u32(3).unwrap();
1474
1475 let mut remainder = BigNum::new().unwrap();
1476 remainder.nnmod(&a, &b, &mut cxt).unwrap();
1477
1478 assert!(remainder.eq(&BigNum::from_u32(2).unwrap()));
1479 }
1480
1481 #[cfg(ossl110)]
1482 #[test]
1483 fn test_secure_bn() {
1484 let a = BigNum::new().unwrap();
1485 assert!(!a.is_secure());
1486
1487 let b = BigNum::new_secure().unwrap();
1488 assert!(b.is_secure())
1489 }
1490
1491 #[cfg(ossl110)]
1492 #[test]
1493 fn test_const_time_bn() {
1494 let a = BigNum::new().unwrap();
1495 assert!(!a.is_const_time());
1496
1497 let mut b = BigNum::new().unwrap();
1498 b.set_const_time();
1499 assert!(b.is_const_time())
1500 }
1501
1502 #[test]
1503 fn test_mod_sqrt() {
1504 let mut ctx = BigNumContext::new().unwrap();
1505
1506 let s = BigNum::from_hex_str("2").unwrap();
1507 let p = BigNum::from_hex_str("7DEB1").unwrap();
1508 let mut sqrt = BigNum::new().unwrap();
1509 let mut out = BigNum::new().unwrap();
1510
1511 sqrt.mod_sqrt(&s, &p, &mut ctx).unwrap();
1513 out.mod_sqr(&sqrt, &p, &mut ctx).unwrap();
1514 assert!(out == s);
1515
1516 let s = BigNum::from_hex_str("3").unwrap();
1517 let p = BigNum::from_hex_str("5").unwrap();
1518 assert!(out.mod_sqrt(&s, &p, &mut ctx).is_err());
1519 }
1520
1521 #[test]
1522 #[cfg(any(ossl110, boringssl, libressl350, awslc))]
1523 fn test_odd_even() {
1524 let a = BigNum::from_u32(17).unwrap();
1525 let b = BigNum::from_u32(18).unwrap();
1526
1527 assert!(a.is_odd());
1528 assert!(!b.is_odd());
1529
1530 assert!(!a.is_even());
1531 assert!(b.is_even());
1532 }
1533}