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, libressl, 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, libressl))] {
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, libressl, awslc))]
351 pub fn is_even(&self) -> bool {
352 !self.is_odd()
353 }
354
355 #[corresponds(BN_is_odd)]
357 #[cfg(any(ossl110, boringssl, libressl, 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, libressl, 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)]
1114 pub fn from_slice(n: &[u8]) -> Result<BigNum, ErrorStack> {
1115 unsafe {
1116 ffi::init();
1117 assert!(n.len() <= LenType::MAX as usize);
1118
1119 cvt_p(ffi::BN_bin2bn(
1120 n.as_ptr(),
1121 n.len() as LenType,
1122 ptr::null_mut(),
1123 ))
1124 .map(|p| BigNum::from_ptr(p))
1125 }
1126 }
1127
1128 #[corresponds(BN_bin2bn)]
1143 pub fn copy_from_slice(&mut self, n: &[u8]) -> Result<(), ErrorStack> {
1144 unsafe {
1145 assert!(n.len() <= LenType::MAX as usize);
1146
1147 cvt_p(ffi::BN_bin2bn(n.as_ptr(), n.len() as LenType, self.0))?;
1148 Ok(())
1149 }
1150 }
1151}
1152
1153impl fmt::Debug for BigNumRef {
1154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1155 match self.to_dec_str() {
1156 Ok(s) => f.write_str(&s),
1157 Err(e) => Err(e.into()),
1158 }
1159 }
1160}
1161
1162impl fmt::Debug for BigNum {
1163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1164 match self.to_dec_str() {
1165 Ok(s) => f.write_str(&s),
1166 Err(e) => Err(e.into()),
1167 }
1168 }
1169}
1170
1171impl fmt::Display for BigNumRef {
1172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1173 match self.to_dec_str() {
1174 Ok(s) => f.write_str(&s),
1175 Err(e) => Err(e.into()),
1176 }
1177 }
1178}
1179
1180impl fmt::Display for BigNum {
1181 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1182 match self.to_dec_str() {
1183 Ok(s) => f.write_str(&s),
1184 Err(e) => Err(e.into()),
1185 }
1186 }
1187}
1188
1189impl PartialEq<BigNumRef> for BigNumRef {
1190 fn eq(&self, oth: &BigNumRef) -> bool {
1191 self.cmp(oth) == Ordering::Equal
1192 }
1193}
1194
1195impl PartialEq<BigNum> for BigNumRef {
1196 fn eq(&self, oth: &BigNum) -> bool {
1197 self.eq(oth.deref())
1198 }
1199}
1200
1201impl Eq for BigNumRef {}
1202
1203impl PartialEq for BigNum {
1204 fn eq(&self, oth: &BigNum) -> bool {
1205 self.deref().eq(oth)
1206 }
1207}
1208
1209impl PartialEq<BigNumRef> for BigNum {
1210 fn eq(&self, oth: &BigNumRef) -> bool {
1211 self.deref().eq(oth)
1212 }
1213}
1214
1215impl Eq for BigNum {}
1216
1217impl PartialOrd<BigNumRef> for BigNumRef {
1218 fn partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering> {
1219 Some(self.cmp(oth))
1220 }
1221}
1222
1223impl PartialOrd<BigNum> for BigNumRef {
1224 fn partial_cmp(&self, oth: &BigNum) -> Option<Ordering> {
1225 Some(self.cmp(oth.deref()))
1226 }
1227}
1228
1229impl Ord for BigNumRef {
1230 fn cmp(&self, oth: &BigNumRef) -> Ordering {
1231 unsafe { ffi::BN_cmp(self.as_ptr(), oth.as_ptr()).cmp(&0) }
1232 }
1233}
1234
1235impl PartialOrd for BigNum {
1236 fn partial_cmp(&self, oth: &BigNum) -> Option<Ordering> {
1237 Some(self.cmp(oth))
1238 }
1239}
1240
1241impl PartialOrd<BigNumRef> for BigNum {
1242 fn partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering> {
1243 self.deref().partial_cmp(oth)
1244 }
1245}
1246
1247impl Ord for BigNum {
1248 fn cmp(&self, oth: &BigNum) -> Ordering {
1249 self.deref().cmp(oth.deref())
1250 }
1251}
1252
1253macro_rules! delegate {
1254 ($t:ident, $m:ident) => {
1255 impl<'a, 'b> $t<&'b BigNum> for &'a BigNumRef {
1256 type Output = BigNum;
1257
1258 fn $m(self, oth: &BigNum) -> BigNum {
1259 $t::$m(self, oth.deref())
1260 }
1261 }
1262
1263 impl<'a, 'b> $t<&'b BigNumRef> for &'a BigNum {
1264 type Output = BigNum;
1265
1266 fn $m(self, oth: &BigNumRef) -> BigNum {
1267 $t::$m(self.deref(), oth)
1268 }
1269 }
1270
1271 impl<'a, 'b> $t<&'b BigNum> for &'a BigNum {
1272 type Output = BigNum;
1273
1274 fn $m(self, oth: &BigNum) -> BigNum {
1275 $t::$m(self.deref(), oth.deref())
1276 }
1277 }
1278 };
1279}
1280
1281impl Add<&BigNumRef> for &BigNumRef {
1282 type Output = BigNum;
1283
1284 fn add(self, oth: &BigNumRef) -> BigNum {
1285 let mut r = BigNum::new().unwrap();
1286 r.checked_add(self, oth).unwrap();
1287 r
1288 }
1289}
1290
1291delegate!(Add, add);
1292
1293impl Sub<&BigNumRef> for &BigNumRef {
1294 type Output = BigNum;
1295
1296 fn sub(self, oth: &BigNumRef) -> BigNum {
1297 let mut r = BigNum::new().unwrap();
1298 r.checked_sub(self, oth).unwrap();
1299 r
1300 }
1301}
1302
1303delegate!(Sub, sub);
1304
1305impl Mul<&BigNumRef> for &BigNumRef {
1306 type Output = BigNum;
1307
1308 fn mul(self, oth: &BigNumRef) -> BigNum {
1309 let mut ctx = BigNumContext::new().unwrap();
1310 let mut r = BigNum::new().unwrap();
1311 r.checked_mul(self, oth, &mut ctx).unwrap();
1312 r
1313 }
1314}
1315
1316delegate!(Mul, mul);
1317
1318impl<'b> Div<&'b BigNumRef> for &BigNumRef {
1319 type Output = BigNum;
1320
1321 fn div(self, oth: &'b BigNumRef) -> BigNum {
1322 let mut ctx = BigNumContext::new().unwrap();
1323 let mut r = BigNum::new().unwrap();
1324 r.checked_div(self, oth, &mut ctx).unwrap();
1325 r
1326 }
1327}
1328
1329delegate!(Div, div);
1330
1331impl<'b> Rem<&'b BigNumRef> for &BigNumRef {
1332 type Output = BigNum;
1333
1334 fn rem(self, oth: &'b BigNumRef) -> BigNum {
1335 let mut ctx = BigNumContext::new().unwrap();
1336 let mut r = BigNum::new().unwrap();
1337 r.checked_rem(self, oth, &mut ctx).unwrap();
1338 r
1339 }
1340}
1341
1342delegate!(Rem, rem);
1343
1344impl Shl<i32> for &BigNumRef {
1345 type Output = BigNum;
1346
1347 fn shl(self, n: i32) -> BigNum {
1348 let mut r = BigNum::new().unwrap();
1349 r.lshift(self, n).unwrap();
1350 r
1351 }
1352}
1353
1354impl Shl<i32> for &BigNum {
1355 type Output = BigNum;
1356
1357 fn shl(self, n: i32) -> BigNum {
1358 self.deref().shl(n)
1359 }
1360}
1361
1362impl Shr<i32> for &BigNumRef {
1363 type Output = BigNum;
1364
1365 fn shr(self, n: i32) -> BigNum {
1366 let mut r = BigNum::new().unwrap();
1367 r.rshift(self, n).unwrap();
1368 r
1369 }
1370}
1371
1372impl Shr<i32> for &BigNum {
1373 type Output = BigNum;
1374
1375 fn shr(self, n: i32) -> BigNum {
1376 self.deref().shr(n)
1377 }
1378}
1379
1380impl Neg for &BigNumRef {
1381 type Output = BigNum;
1382
1383 fn neg(self) -> BigNum {
1384 self.to_owned().unwrap().neg()
1385 }
1386}
1387
1388impl Neg for &BigNum {
1389 type Output = BigNum;
1390
1391 fn neg(self) -> BigNum {
1392 self.deref().neg()
1393 }
1394}
1395
1396impl Neg for BigNum {
1397 type Output = BigNum;
1398
1399 fn neg(mut self) -> BigNum {
1400 let negative = self.is_negative();
1401 self.set_negative(!negative);
1402 self
1403 }
1404}
1405
1406#[cfg(test)]
1407mod tests {
1408 use crate::bn::{BigNum, BigNumContext};
1409
1410 #[test]
1411 fn test_to_from_slice() {
1412 let v0 = BigNum::from_u32(10_203_004).unwrap();
1413 let vec = v0.to_vec();
1414 let v1 = BigNum::from_slice(&vec).unwrap();
1415
1416 assert_eq!(v0, v1);
1417 }
1418
1419 #[test]
1420 fn test_negation() {
1421 let a = BigNum::from_u32(909_829_283).unwrap();
1422
1423 assert!(!a.is_negative());
1424 assert!((-a).is_negative());
1425 }
1426
1427 #[test]
1428 fn test_shift() {
1429 let a = BigNum::from_u32(909_829_283).unwrap();
1430
1431 assert_eq!(a, &(&a << 1) >> 1);
1432 }
1433
1434 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1435 #[test]
1436 fn test_rand_range() {
1437 let range = BigNum::from_u32(909_829_283).unwrap();
1438 let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap();
1439 range.rand_range(&mut result).unwrap();
1440 assert!(result >= BigNum::from_u32(0).unwrap() && result < range);
1441 }
1442
1443 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1444 #[test]
1445 fn test_pseudo_rand_range() {
1446 let range = BigNum::from_u32(909_829_283).unwrap();
1447 let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap();
1448 range.pseudo_rand_range(&mut result).unwrap();
1449 assert!(result >= BigNum::from_u32(0).unwrap() && result < range);
1450 }
1451
1452 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1453 #[test]
1454 fn test_prime_numbers() {
1455 let a = BigNum::from_u32(19_029_017).unwrap();
1456 let mut p = BigNum::new().unwrap();
1457 p.generate_prime(128, true, None, Some(&a)).unwrap();
1458
1459 let mut ctx = BigNumContext::new().unwrap();
1460 assert!(p.is_prime(100, &mut ctx).unwrap());
1461 assert!(p.is_prime_fasttest(100, &mut ctx, true).unwrap());
1462 }
1463
1464 #[cfg(ossl110)]
1465 #[test]
1466 fn test_secure_bn_ctx() {
1467 let mut cxt = BigNumContext::new_secure().unwrap();
1468 let a = BigNum::from_u32(8).unwrap();
1469 let b = BigNum::from_u32(3).unwrap();
1470
1471 let mut remainder = BigNum::new().unwrap();
1472 remainder.nnmod(&a, &b, &mut cxt).unwrap();
1473
1474 assert!(remainder.eq(&BigNum::from_u32(2).unwrap()));
1475 }
1476
1477 #[cfg(ossl110)]
1478 #[test]
1479 fn test_secure_bn() {
1480 let a = BigNum::new().unwrap();
1481 assert!(!a.is_secure());
1482
1483 let b = BigNum::new_secure().unwrap();
1484 assert!(b.is_secure())
1485 }
1486
1487 #[cfg(ossl110)]
1488 #[test]
1489 fn test_const_time_bn() {
1490 let a = BigNum::new().unwrap();
1491 assert!(!a.is_const_time());
1492
1493 let mut b = BigNum::new().unwrap();
1494 b.set_const_time();
1495 assert!(b.is_const_time())
1496 }
1497
1498 #[test]
1499 fn test_mod_sqrt() {
1500 let mut ctx = BigNumContext::new().unwrap();
1501
1502 let s = BigNum::from_hex_str("2").unwrap();
1503 let p = BigNum::from_hex_str("7DEB1").unwrap();
1504 let mut sqrt = BigNum::new().unwrap();
1505 let mut out = BigNum::new().unwrap();
1506
1507 sqrt.mod_sqrt(&s, &p, &mut ctx).unwrap();
1509 out.mod_sqr(&sqrt, &p, &mut ctx).unwrap();
1510 assert!(out == s);
1511
1512 let s = BigNum::from_hex_str("3").unwrap();
1513 let p = BigNum::from_hex_str("5").unwrap();
1514 assert!(out.mod_sqrt(&s, &p, &mut ctx).is_err());
1515 }
1516
1517 #[test]
1518 #[cfg(any(ossl110, boringssl, libressl, awslc))]
1519 fn test_odd_even() {
1520 let a = BigNum::from_u32(17).unwrap();
1521 let b = BigNum::from_u32(18).unwrap();
1522
1523 assert!(a.is_odd());
1524 assert!(!b.is_odd());
1525
1526 assert!(!a.is_even());
1527 assert!(b.is_even());
1528 }
1529}