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))] {
41 use ffi::{
42 BN_get_rfc2409_prime_1024, BN_get_rfc2409_prime_768, BN_get_rfc3526_prime_1536,
43 BN_get_rfc3526_prime_2048, BN_get_rfc3526_prime_3072, BN_get_rfc3526_prime_4096,
44 BN_get_rfc3526_prime_6144, BN_get_rfc3526_prime_8192, BN_is_negative,
45 };
46 } else if #[cfg(boringssl)] {
47 use ffi::BN_is_negative;
48 } else {
49 use ffi::{
50 get_rfc2409_prime_1024 as BN_get_rfc2409_prime_1024,
51 get_rfc2409_prime_768 as BN_get_rfc2409_prime_768,
52 get_rfc3526_prime_1536 as BN_get_rfc3526_prime_1536,
53 get_rfc3526_prime_2048 as BN_get_rfc3526_prime_2048,
54 get_rfc3526_prime_3072 as BN_get_rfc3526_prime_3072,
55 get_rfc3526_prime_4096 as BN_get_rfc3526_prime_4096,
56 get_rfc3526_prime_6144 as BN_get_rfc3526_prime_6144,
57 get_rfc3526_prime_8192 as BN_get_rfc3526_prime_8192,
58 };
59
60 #[allow(bad_style)]
61 unsafe fn BN_is_negative(bn: *const ffi::BIGNUM) -> c_int {
62 (*bn).neg
63 }
64 }
65}
66
67pub struct MsbOption(c_int);
69
70impl MsbOption {
71 pub const MAYBE_ZERO: MsbOption = MsbOption(-1);
73
74 pub const ONE: MsbOption = MsbOption(0);
76
77 pub const TWO_ONES: MsbOption = MsbOption(1);
82}
83
84foreign_type_and_impl_send_sync! {
85 type CType = ffi::BN_CTX;
86 fn drop = ffi::BN_CTX_free;
87
88 pub struct BigNumContext;
96 pub struct BigNumContextRef;
100}
101
102impl BigNumContext {
103 #[corresponds(BN_CTX_new)]
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 #[corresponds(BN_CTX_secure_new)]
114 #[cfg(ossl110)]
115 pub fn new_secure() -> Result<BigNumContext, ErrorStack> {
116 unsafe {
117 ffi::init();
118 cvt_p(ffi::BN_CTX_secure_new()).map(BigNumContext)
119 }
120 }
121}
122
123foreign_type_and_impl_send_sync! {
124 type CType = ffi::BIGNUM;
125 fn drop = ffi::BN_free;
126
127 pub struct BigNum;
151 pub struct BigNumRef;
155}
156
157impl BigNumRef {
158 #[corresponds(BN_clear)]
162 pub fn clear(&mut self) {
163 unsafe { ffi::BN_clear(self.as_ptr()) }
164 }
165
166 #[corresponds(BN_add_word)]
168 pub fn add_word(&mut self, w: u32) -> Result<(), ErrorStack> {
169 unsafe { cvt(ffi::BN_add_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
170 }
171
172 #[corresponds(BN_sub_word)]
174 pub fn sub_word(&mut self, w: u32) -> Result<(), ErrorStack> {
175 unsafe { cvt(ffi::BN_sub_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
176 }
177
178 #[corresponds(BN_mul_word)]
180 pub fn mul_word(&mut self, w: u32) -> Result<(), ErrorStack> {
181 unsafe { cvt(ffi::BN_mul_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
182 }
183
184 #[corresponds(BN_div_word)]
186 #[allow(clippy::useless_conversion)]
187 pub fn div_word(&mut self, w: u32) -> Result<u64, ErrorStack> {
188 unsafe {
189 let r = ffi::BN_div_word(self.as_ptr(), w.into());
190 if r == ffi::BN_ULONG::MAX {
191 Err(ErrorStack::get())
192 } else {
193 Ok(r.into())
194 }
195 }
196 }
197
198 #[corresponds(BN_mod_word)]
200 #[allow(clippy::useless_conversion)]
201 pub fn mod_word(&self, w: u32) -> Result<u64, ErrorStack> {
202 unsafe {
203 let r = ffi::BN_mod_word(self.as_ptr(), w.into());
204 if r == ffi::BN_ULONG::MAX {
205 Err(ErrorStack::get())
206 } else {
207 Ok(r.into())
208 }
209 }
210 }
211
212 #[corresponds(BN_rand_range)]
215 pub fn rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> {
216 unsafe { cvt(ffi::BN_rand_range(rnd.as_ptr(), self.as_ptr())).map(|_| ()) }
217 }
218
219 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
221 #[corresponds(BN_pseudo_rand_range)]
222 pub fn pseudo_rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> {
223 unsafe { cvt(ffi::BN_pseudo_rand_range(rnd.as_ptr(), self.as_ptr())).map(|_| ()) }
224 }
225
226 #[corresponds(BN_set_bit)]
230 #[allow(clippy::useless_conversion)]
231 pub fn set_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
232 unsafe { cvt(ffi::BN_set_bit(self.as_ptr(), n.into())).map(|_| ()) }
233 }
234
235 #[corresponds(BN_clear_bit)]
239 #[allow(clippy::useless_conversion)]
240 pub fn clear_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
241 unsafe { cvt(ffi::BN_clear_bit(self.as_ptr(), n.into())).map(|_| ()) }
242 }
243
244 #[corresponds(BN_is_bit_set)]
246 #[allow(clippy::useless_conversion)]
247 pub fn is_bit_set(&self, n: i32) -> bool {
248 unsafe { ffi::BN_is_bit_set(self.as_ptr(), n.into()) == 1 }
249 }
250
251 #[corresponds(BN_mask_bits)]
255 #[allow(clippy::useless_conversion)]
256 pub fn mask_bits(&mut self, n: i32) -> Result<(), ErrorStack> {
257 unsafe { cvt(ffi::BN_mask_bits(self.as_ptr(), n.into())).map(|_| ()) }
258 }
259
260 #[corresponds(BN_lshift1)]
262 pub fn lshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack> {
263 unsafe { cvt(ffi::BN_lshift1(self.as_ptr(), a.as_ptr())).map(|_| ()) }
264 }
265
266 #[corresponds(BN_rshift1)]
268 pub fn rshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack> {
269 unsafe { cvt(ffi::BN_rshift1(self.as_ptr(), a.as_ptr())).map(|_| ()) }
270 }
271
272 #[corresponds(BN_add)]
276 pub fn checked_add(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack> {
277 unsafe { cvt(ffi::BN_add(self.as_ptr(), a.as_ptr(), b.as_ptr())).map(|_| ()) }
278 }
279
280 #[corresponds(BN_sub)]
284 pub fn checked_sub(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack> {
285 unsafe { cvt(ffi::BN_sub(self.as_ptr(), a.as_ptr(), b.as_ptr())).map(|_| ()) }
286 }
287
288 #[corresponds(BN_lshift)]
290 #[allow(clippy::useless_conversion)]
291 pub fn lshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack> {
292 unsafe { cvt(ffi::BN_lshift(self.as_ptr(), a.as_ptr(), n.into())).map(|_| ()) }
293 }
294
295 #[corresponds(BN_rshift)]
297 #[allow(clippy::useless_conversion)]
298 pub fn rshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack> {
299 unsafe { cvt(ffi::BN_rshift(self.as_ptr(), a.as_ptr(), n.into())).map(|_| ()) }
300 }
301
302 #[corresponds(BN_dup)]
304 pub fn to_owned(&self) -> Result<BigNum, ErrorStack> {
305 unsafe { cvt_p(ffi::BN_dup(self.as_ptr())).map(|b| BigNum::from_ptr(b)) }
306 }
307
308 #[corresponds(BN_set_negative)]
311 pub fn set_negative(&mut self, negative: bool) {
312 unsafe { ffi::BN_set_negative(self.as_ptr(), negative as c_int) }
313 }
314
315 #[corresponds(BN_ucmp)]
328 pub fn ucmp(&self, oth: &BigNumRef) -> Ordering {
329 unsafe { ffi::BN_ucmp(self.as_ptr(), oth.as_ptr()).cmp(&0) }
330 }
331
332 #[corresponds(BN_is_negative)]
334 pub fn is_negative(&self) -> bool {
335 unsafe { BN_is_negative(self.as_ptr()) == 1 }
336 }
337
338 #[corresponds(BN_is_even)]
340 #[cfg(any(ossl110, boringssl, libressl350))]
341 pub fn is_even(&self) -> bool {
342 !self.is_odd()
343 }
344
345 #[corresponds(BN_is_odd)]
347 #[cfg(any(ossl110, boringssl, libressl350))]
348 pub fn is_odd(&self) -> bool {
349 unsafe { ffi::BN_is_odd(self.as_ptr()) == 1 }
350 }
351
352 #[corresponds(BN_num_bits)]
354 #[allow(clippy::unnecessary_cast)]
355 pub fn num_bits(&self) -> i32 {
356 unsafe { ffi::BN_num_bits(self.as_ptr()) as i32 }
357 }
358
359 pub fn num_bytes(&self) -> i32 {
361 (self.num_bits() + 7) / 8
362 }
363
364 #[corresponds(BN_rand)]
389 #[allow(clippy::useless_conversion)]
390 pub fn rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> {
391 unsafe {
392 cvt(ffi::BN_rand(
393 self.as_ptr(),
394 bits.into(),
395 msb.0,
396 odd as c_int,
397 ))
398 .map(|_| ())
399 }
400 }
401
402 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
404 #[corresponds(BN_pseudo_rand)]
405 #[allow(clippy::useless_conversion)]
406 pub fn pseudo_rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> {
407 unsafe {
408 cvt(ffi::BN_pseudo_rand(
409 self.as_ptr(),
410 bits.into(),
411 msb.0,
412 odd as c_int,
413 ))
414 .map(|_| ())
415 }
416 }
417
418 #[corresponds(BN_generate_prime_ex)]
442 pub fn generate_prime(
443 &mut self,
444 bits: i32,
445 safe: bool,
446 add: Option<&BigNumRef>,
447 rem: Option<&BigNumRef>,
448 ) -> Result<(), ErrorStack> {
449 unsafe {
450 cvt(ffi::BN_generate_prime_ex(
451 self.as_ptr(),
452 bits as c_int,
453 safe as c_int,
454 add.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()),
455 rem.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()),
456 ptr::null_mut(),
457 ))
458 .map(|_| ())
459 }
460 }
461
462 #[corresponds(BN_mul)]
467 pub fn checked_mul(
468 &mut self,
469 a: &BigNumRef,
470 b: &BigNumRef,
471 ctx: &mut BigNumContextRef,
472 ) -> Result<(), ErrorStack> {
473 unsafe {
474 cvt(ffi::BN_mul(
475 self.as_ptr(),
476 a.as_ptr(),
477 b.as_ptr(),
478 ctx.as_ptr(),
479 ))
480 .map(|_| ())
481 }
482 }
483
484 #[corresponds(BN_div)]
489 pub fn checked_div(
490 &mut self,
491 a: &BigNumRef,
492 b: &BigNumRef,
493 ctx: &mut BigNumContextRef,
494 ) -> Result<(), ErrorStack> {
495 unsafe {
496 cvt(ffi::BN_div(
497 self.as_ptr(),
498 ptr::null_mut(),
499 a.as_ptr(),
500 b.as_ptr(),
501 ctx.as_ptr(),
502 ))
503 .map(|_| ())
504 }
505 }
506
507 #[corresponds(BN_div)]
509 pub fn checked_rem(
510 &mut self,
511 a: &BigNumRef,
512 b: &BigNumRef,
513 ctx: &mut BigNumContextRef,
514 ) -> Result<(), ErrorStack> {
515 unsafe {
516 cvt(ffi::BN_div(
517 ptr::null_mut(),
518 self.as_ptr(),
519 a.as_ptr(),
520 b.as_ptr(),
521 ctx.as_ptr(),
522 ))
523 .map(|_| ())
524 }
525 }
526
527 #[corresponds(BN_div)]
529 pub fn div_rem(
530 &mut self,
531 rem: &mut BigNumRef,
532 a: &BigNumRef,
533 b: &BigNumRef,
534 ctx: &mut BigNumContextRef,
535 ) -> Result<(), ErrorStack> {
536 unsafe {
537 cvt(ffi::BN_div(
538 self.as_ptr(),
539 rem.as_ptr(),
540 a.as_ptr(),
541 b.as_ptr(),
542 ctx.as_ptr(),
543 ))
544 .map(|_| ())
545 }
546 }
547
548 #[corresponds(BN_sqr)]
550 pub fn sqr(&mut self, a: &BigNumRef, ctx: &mut BigNumContextRef) -> Result<(), ErrorStack> {
551 unsafe { cvt(ffi::BN_sqr(self.as_ptr(), a.as_ptr(), ctx.as_ptr())).map(|_| ()) }
552 }
553
554 #[corresponds(BN_nnmod)]
557 pub fn nnmod(
558 &mut self,
559 a: &BigNumRef,
560 m: &BigNumRef,
561 ctx: &mut BigNumContextRef,
562 ) -> Result<(), ErrorStack> {
563 unsafe {
564 cvt(ffi::BN_nnmod(
565 self.as_ptr(),
566 a.as_ptr(),
567 m.as_ptr(),
568 ctx.as_ptr(),
569 ))
570 .map(|_| ())
571 }
572 }
573
574 #[corresponds(BN_mod_add)]
576 pub fn mod_add(
577 &mut self,
578 a: &BigNumRef,
579 b: &BigNumRef,
580 m: &BigNumRef,
581 ctx: &mut BigNumContextRef,
582 ) -> Result<(), ErrorStack> {
583 unsafe {
584 cvt(ffi::BN_mod_add(
585 self.as_ptr(),
586 a.as_ptr(),
587 b.as_ptr(),
588 m.as_ptr(),
589 ctx.as_ptr(),
590 ))
591 .map(|_| ())
592 }
593 }
594
595 #[corresponds(BN_mod_sub)]
597 pub fn mod_sub(
598 &mut self,
599 a: &BigNumRef,
600 b: &BigNumRef,
601 m: &BigNumRef,
602 ctx: &mut BigNumContextRef,
603 ) -> Result<(), ErrorStack> {
604 unsafe {
605 cvt(ffi::BN_mod_sub(
606 self.as_ptr(),
607 a.as_ptr(),
608 b.as_ptr(),
609 m.as_ptr(),
610 ctx.as_ptr(),
611 ))
612 .map(|_| ())
613 }
614 }
615
616 #[corresponds(BN_mod_mul)]
618 pub fn mod_mul(
619 &mut self,
620 a: &BigNumRef,
621 b: &BigNumRef,
622 m: &BigNumRef,
623 ctx: &mut BigNumContextRef,
624 ) -> Result<(), ErrorStack> {
625 unsafe {
626 cvt(ffi::BN_mod_mul(
627 self.as_ptr(),
628 a.as_ptr(),
629 b.as_ptr(),
630 m.as_ptr(),
631 ctx.as_ptr(),
632 ))
633 .map(|_| ())
634 }
635 }
636
637 #[corresponds(BN_mod_sqr)]
639 pub fn mod_sqr(
640 &mut self,
641 a: &BigNumRef,
642 m: &BigNumRef,
643 ctx: &mut BigNumContextRef,
644 ) -> Result<(), ErrorStack> {
645 unsafe {
646 cvt(ffi::BN_mod_sqr(
647 self.as_ptr(),
648 a.as_ptr(),
649 m.as_ptr(),
650 ctx.as_ptr(),
651 ))
652 .map(|_| ())
653 }
654 }
655
656 #[corresponds(BN_mod_sqrt)]
658 pub fn mod_sqrt(
659 &mut self,
660 a: &BigNumRef,
661 p: &BigNumRef,
662 ctx: &mut BigNumContextRef,
663 ) -> Result<(), ErrorStack> {
664 unsafe {
665 cvt_p(ffi::BN_mod_sqrt(
666 self.as_ptr(),
667 a.as_ptr(),
668 p.as_ptr(),
669 ctx.as_ptr(),
670 ))
671 .map(|_| ())
672 }
673 }
674
675 #[corresponds(BN_exp)]
677 pub fn exp(
678 &mut self,
679 a: &BigNumRef,
680 p: &BigNumRef,
681 ctx: &mut BigNumContextRef,
682 ) -> Result<(), ErrorStack> {
683 unsafe {
684 cvt(ffi::BN_exp(
685 self.as_ptr(),
686 a.as_ptr(),
687 p.as_ptr(),
688 ctx.as_ptr(),
689 ))
690 .map(|_| ())
691 }
692 }
693
694 #[corresponds(BN_mod_exp)]
696 pub fn mod_exp(
697 &mut self,
698 a: &BigNumRef,
699 p: &BigNumRef,
700 m: &BigNumRef,
701 ctx: &mut BigNumContextRef,
702 ) -> Result<(), ErrorStack> {
703 unsafe {
704 cvt(ffi::BN_mod_exp(
705 self.as_ptr(),
706 a.as_ptr(),
707 p.as_ptr(),
708 m.as_ptr(),
709 ctx.as_ptr(),
710 ))
711 .map(|_| ())
712 }
713 }
714
715 #[corresponds(BN_mod_inverse)]
717 pub fn mod_inverse(
718 &mut self,
719 a: &BigNumRef,
720 n: &BigNumRef,
721 ctx: &mut BigNumContextRef,
722 ) -> Result<(), ErrorStack> {
723 unsafe {
724 cvt_p(ffi::BN_mod_inverse(
725 self.as_ptr(),
726 a.as_ptr(),
727 n.as_ptr(),
728 ctx.as_ptr(),
729 ))
730 .map(|_| ())
731 }
732 }
733
734 #[corresponds(BN_gcd)]
736 pub fn gcd(
737 &mut self,
738 a: &BigNumRef,
739 b: &BigNumRef,
740 ctx: &mut BigNumContextRef,
741 ) -> Result<(), ErrorStack> {
742 unsafe {
743 cvt(ffi::BN_gcd(
744 self.as_ptr(),
745 a.as_ptr(),
746 b.as_ptr(),
747 ctx.as_ptr(),
748 ))
749 .map(|_| ())
750 }
751 }
752
753 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
761 #[corresponds(BN_is_prime_ex)]
762 #[allow(clippy::useless_conversion)]
763 pub fn is_prime(&self, checks: i32, ctx: &mut BigNumContextRef) -> Result<bool, ErrorStack> {
764 unsafe {
765 cvt_n(ffi::BN_is_prime_ex(
766 self.as_ptr(),
767 checks.into(),
768 ctx.as_ptr(),
769 ptr::null_mut(),
770 ))
771 .map(|r| r != 0)
772 }
773 }
774
775 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
785 #[corresponds(BN_is_prime_fasttest_ex)]
786 #[allow(clippy::useless_conversion)]
787 pub fn is_prime_fasttest(
788 &self,
789 checks: i32,
790 ctx: &mut BigNumContextRef,
791 do_trial_division: bool,
792 ) -> Result<bool, ErrorStack> {
793 unsafe {
794 cvt_n(ffi::BN_is_prime_fasttest_ex(
795 self.as_ptr(),
796 checks.into(),
797 ctx.as_ptr(),
798 do_trial_division as c_int,
799 ptr::null_mut(),
800 ))
801 .map(|r| r != 0)
802 }
803 }
804
805 #[corresponds(BN_bn2bin)]
818 pub fn to_vec(&self) -> Vec<u8> {
819 let size = self.num_bytes() as usize;
820 let mut v = Vec::with_capacity(size);
821 unsafe {
822 ffi::BN_bn2bin(self.as_ptr(), v.as_mut_ptr());
823 v.set_len(size);
824 }
825 v
826 }
827
828 #[corresponds(BN_bn2binpad)]
850 #[cfg(any(ossl110, libressl340, boringssl))]
851 pub fn to_vec_padded(&self, pad_to: i32) -> Result<Vec<u8>, ErrorStack> {
852 let mut v = Vec::with_capacity(pad_to as usize);
853 unsafe {
854 cvt(ffi::BN_bn2binpad(self.as_ptr(), v.as_mut_ptr(), pad_to))?;
855 v.set_len(pad_to as usize);
856 }
857 Ok(v)
858 }
859
860 #[corresponds(BN_bn2dec)]
869 pub fn to_dec_str(&self) -> Result<OpensslString, ErrorStack> {
870 unsafe {
871 let buf = cvt_p(ffi::BN_bn2dec(self.as_ptr()))?;
872 Ok(OpensslString::from_ptr(buf))
873 }
874 }
875
876 #[corresponds(BN_bn2hex)]
885 pub fn to_hex_str(&self) -> Result<OpensslString, ErrorStack> {
886 unsafe {
887 let buf = cvt_p(ffi::BN_bn2hex(self.as_ptr()))?;
888 Ok(OpensslString::from_ptr(buf))
889 }
890 }
891
892 #[corresponds(BN_to_ASN1_INTEGER)]
894 pub fn to_asn1_integer(&self) -> Result<Asn1Integer, ErrorStack> {
895 unsafe {
896 cvt_p(ffi::BN_to_ASN1_INTEGER(self.as_ptr(), ptr::null_mut()))
897 .map(|p| Asn1Integer::from_ptr(p))
898 }
899 }
900
901 #[corresponds(BN_set_flags)]
903 #[cfg(ossl110)]
904 pub fn set_const_time(&mut self) {
905 unsafe { ffi::BN_set_flags(self.as_ptr(), ffi::BN_FLG_CONSTTIME) }
906 }
907
908 #[corresponds(BN_get_flags)]
910 #[cfg(ossl110)]
911 pub fn is_const_time(&self) -> bool {
912 unsafe {
913 let ret = ffi::BN_get_flags(self.as_ptr(), ffi::BN_FLG_CONSTTIME);
914 ret == ffi::BN_FLG_CONSTTIME
915 }
916 }
917
918 #[corresponds(BN_get_flags)]
920 #[cfg(ossl110)]
921 pub fn is_secure(&self) -> bool {
922 unsafe {
923 let ret = ffi::BN_get_flags(self.as_ptr(), ffi::BN_FLG_SECURE);
924 ret == ffi::BN_FLG_SECURE
925 }
926 }
927}
928
929impl BigNum {
930 #[corresponds(BN_new)]
932 pub fn new() -> Result<BigNum, ErrorStack> {
933 unsafe {
934 ffi::init();
935 let v = cvt_p(ffi::BN_new())?;
936 Ok(BigNum::from_ptr(v))
937 }
938 }
939
940 #[corresponds(BN_secure_new)]
942 #[cfg(ossl110)]
943 pub fn new_secure() -> Result<BigNum, ErrorStack> {
944 unsafe {
945 ffi::init();
946 let v = cvt_p(ffi::BN_secure_new())?;
947 Ok(BigNum::from_ptr(v))
948 }
949 }
950
951 #[corresponds(BN_set_word)]
953 pub fn from_u32(n: u32) -> Result<BigNum, ErrorStack> {
954 BigNum::new().and_then(|v| unsafe {
955 cvt(ffi::BN_set_word(v.as_ptr(), n as ffi::BN_ULONG)).map(|_| v)
956 })
957 }
958
959 #[corresponds(BN_dec2bn)]
961 pub fn from_dec_str(s: &str) -> Result<BigNum, ErrorStack> {
962 unsafe {
963 ffi::init();
964 let c_str = CString::new(s.as_bytes()).unwrap();
965 let mut bn = ptr::null_mut();
966 cvt(ffi::BN_dec2bn(&mut bn, c_str.as_ptr() as *const _))?;
967 Ok(BigNum::from_ptr(bn))
968 }
969 }
970
971 #[corresponds(BN_hex2bn)]
973 pub fn from_hex_str(s: &str) -> Result<BigNum, ErrorStack> {
974 unsafe {
975 ffi::init();
976 let c_str = CString::new(s.as_bytes()).unwrap();
977 let mut bn = ptr::null_mut();
978 cvt(ffi::BN_hex2bn(&mut bn, c_str.as_ptr() as *const _))?;
979 Ok(BigNum::from_ptr(bn))
980 }
981 }
982
983 #[corresponds(BN_get_rfc2409_prime_768)]
989 #[cfg(not(boringssl))]
990 pub fn get_rfc2409_prime_768() -> Result<BigNum, ErrorStack> {
991 unsafe {
992 ffi::init();
993 cvt_p(BN_get_rfc2409_prime_768(ptr::null_mut())).map(BigNum)
994 }
995 }
996
997 #[corresponds(BN_get_rfc2409_prime_1024)]
1003 #[cfg(not(boringssl))]
1004 pub fn get_rfc2409_prime_1024() -> Result<BigNum, ErrorStack> {
1005 unsafe {
1006 ffi::init();
1007 cvt_p(BN_get_rfc2409_prime_1024(ptr::null_mut())).map(BigNum)
1008 }
1009 }
1010
1011 #[corresponds(BN_get_rfc3526_prime_1536)]
1017 #[cfg(not(boringssl))]
1018 pub fn get_rfc3526_prime_1536() -> Result<BigNum, ErrorStack> {
1019 unsafe {
1020 ffi::init();
1021 cvt_p(BN_get_rfc3526_prime_1536(ptr::null_mut())).map(BigNum)
1022 }
1023 }
1024
1025 #[corresponds(BN_get_rfc3526_prime_2048)]
1031 #[cfg(not(boringssl))]
1032 pub fn get_rfc3526_prime_2048() -> Result<BigNum, ErrorStack> {
1033 unsafe {
1034 ffi::init();
1035 cvt_p(BN_get_rfc3526_prime_2048(ptr::null_mut())).map(BigNum)
1036 }
1037 }
1038
1039 #[corresponds(BN_get_rfc3526_prime_3072)]
1045 #[cfg(not(boringssl))]
1046 pub fn get_rfc3526_prime_3072() -> Result<BigNum, ErrorStack> {
1047 unsafe {
1048 ffi::init();
1049 cvt_p(BN_get_rfc3526_prime_3072(ptr::null_mut())).map(BigNum)
1050 }
1051 }
1052
1053 #[corresponds(BN_get_rfc3526_prime_4096)]
1059 #[cfg(not(boringssl))]
1060 pub fn get_rfc3526_prime_4096() -> Result<BigNum, ErrorStack> {
1061 unsafe {
1062 ffi::init();
1063 cvt_p(BN_get_rfc3526_prime_4096(ptr::null_mut())).map(BigNum)
1064 }
1065 }
1066
1067 #[corresponds(BN_get_rfc3526_prime_6114)]
1073 #[cfg(not(boringssl))]
1074 pub fn get_rfc3526_prime_6144() -> Result<BigNum, ErrorStack> {
1075 unsafe {
1076 ffi::init();
1077 cvt_p(BN_get_rfc3526_prime_6144(ptr::null_mut())).map(BigNum)
1078 }
1079 }
1080
1081 #[corresponds(BN_get_rfc3526_prime_8192)]
1087 #[cfg(not(boringssl))]
1088 pub fn get_rfc3526_prime_8192() -> Result<BigNum, ErrorStack> {
1089 unsafe {
1090 ffi::init();
1091 cvt_p(BN_get_rfc3526_prime_8192(ptr::null_mut())).map(BigNum)
1092 }
1093 }
1094
1095 #[corresponds(BN_bin2bn)]
1108 pub fn from_slice(n: &[u8]) -> Result<BigNum, ErrorStack> {
1109 unsafe {
1110 ffi::init();
1111 assert!(n.len() <= LenType::MAX as usize);
1112
1113 cvt_p(ffi::BN_bin2bn(
1114 n.as_ptr(),
1115 n.len() as LenType,
1116 ptr::null_mut(),
1117 ))
1118 .map(|p| BigNum::from_ptr(p))
1119 }
1120 }
1121
1122 #[corresponds(BN_bin2bn)]
1137 pub fn copy_from_slice(&mut self, n: &[u8]) -> Result<(), ErrorStack> {
1138 unsafe {
1139 assert!(n.len() <= LenType::MAX as usize);
1140
1141 cvt_p(ffi::BN_bin2bn(n.as_ptr(), n.len() as LenType, self.0))?;
1142 Ok(())
1143 }
1144 }
1145}
1146
1147impl fmt::Debug for BigNumRef {
1148 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1149 match self.to_dec_str() {
1150 Ok(s) => f.write_str(&s),
1151 Err(e) => Err(e.into()),
1152 }
1153 }
1154}
1155
1156impl fmt::Debug for BigNum {
1157 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1158 match self.to_dec_str() {
1159 Ok(s) => f.write_str(&s),
1160 Err(e) => Err(e.into()),
1161 }
1162 }
1163}
1164
1165impl fmt::Display for BigNumRef {
1166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1167 match self.to_dec_str() {
1168 Ok(s) => f.write_str(&s),
1169 Err(e) => Err(e.into()),
1170 }
1171 }
1172}
1173
1174impl fmt::Display for BigNum {
1175 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1176 match self.to_dec_str() {
1177 Ok(s) => f.write_str(&s),
1178 Err(e) => Err(e.into()),
1179 }
1180 }
1181}
1182
1183impl PartialEq<BigNumRef> for BigNumRef {
1184 fn eq(&self, oth: &BigNumRef) -> bool {
1185 self.cmp(oth) == Ordering::Equal
1186 }
1187}
1188
1189impl PartialEq<BigNum> for BigNumRef {
1190 fn eq(&self, oth: &BigNum) -> bool {
1191 self.eq(oth.deref())
1192 }
1193}
1194
1195impl Eq for BigNumRef {}
1196
1197impl PartialEq for BigNum {
1198 fn eq(&self, oth: &BigNum) -> bool {
1199 self.deref().eq(oth)
1200 }
1201}
1202
1203impl PartialEq<BigNumRef> for BigNum {
1204 fn eq(&self, oth: &BigNumRef) -> bool {
1205 self.deref().eq(oth)
1206 }
1207}
1208
1209impl Eq for BigNum {}
1210
1211impl PartialOrd<BigNumRef> for BigNumRef {
1212 fn partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering> {
1213 Some(self.cmp(oth))
1214 }
1215}
1216
1217impl PartialOrd<BigNum> for BigNumRef {
1218 fn partial_cmp(&self, oth: &BigNum) -> Option<Ordering> {
1219 Some(self.cmp(oth.deref()))
1220 }
1221}
1222
1223impl Ord for BigNumRef {
1224 fn cmp(&self, oth: &BigNumRef) -> Ordering {
1225 unsafe { ffi::BN_cmp(self.as_ptr(), oth.as_ptr()).cmp(&0) }
1226 }
1227}
1228
1229impl PartialOrd for BigNum {
1230 fn partial_cmp(&self, oth: &BigNum) -> Option<Ordering> {
1231 Some(self.cmp(oth))
1232 }
1233}
1234
1235impl PartialOrd<BigNumRef> for BigNum {
1236 fn partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering> {
1237 self.deref().partial_cmp(oth)
1238 }
1239}
1240
1241impl Ord for BigNum {
1242 fn cmp(&self, oth: &BigNum) -> Ordering {
1243 self.deref().cmp(oth.deref())
1244 }
1245}
1246
1247macro_rules! delegate {
1248 ($t:ident, $m:ident) => {
1249 impl<'a, 'b> $t<&'b BigNum> for &'a BigNumRef {
1250 type Output = BigNum;
1251
1252 fn $m(self, oth: &BigNum) -> BigNum {
1253 $t::$m(self, oth.deref())
1254 }
1255 }
1256
1257 impl<'a, 'b> $t<&'b BigNumRef> for &'a BigNum {
1258 type Output = BigNum;
1259
1260 fn $m(self, oth: &BigNumRef) -> BigNum {
1261 $t::$m(self.deref(), oth)
1262 }
1263 }
1264
1265 impl<'a, 'b> $t<&'b BigNum> for &'a BigNum {
1266 type Output = BigNum;
1267
1268 fn $m(self, oth: &BigNum) -> BigNum {
1269 $t::$m(self.deref(), oth.deref())
1270 }
1271 }
1272 };
1273}
1274
1275impl Add<&BigNumRef> for &BigNumRef {
1276 type Output = BigNum;
1277
1278 fn add(self, oth: &BigNumRef) -> BigNum {
1279 let mut r = BigNum::new().unwrap();
1280 r.checked_add(self, oth).unwrap();
1281 r
1282 }
1283}
1284
1285delegate!(Add, add);
1286
1287impl Sub<&BigNumRef> for &BigNumRef {
1288 type Output = BigNum;
1289
1290 fn sub(self, oth: &BigNumRef) -> BigNum {
1291 let mut r = BigNum::new().unwrap();
1292 r.checked_sub(self, oth).unwrap();
1293 r
1294 }
1295}
1296
1297delegate!(Sub, sub);
1298
1299impl Mul<&BigNumRef> for &BigNumRef {
1300 type Output = BigNum;
1301
1302 fn mul(self, oth: &BigNumRef) -> BigNum {
1303 let mut ctx = BigNumContext::new().unwrap();
1304 let mut r = BigNum::new().unwrap();
1305 r.checked_mul(self, oth, &mut ctx).unwrap();
1306 r
1307 }
1308}
1309
1310delegate!(Mul, mul);
1311
1312impl<'b> Div<&'b BigNumRef> for &BigNumRef {
1313 type Output = BigNum;
1314
1315 fn div(self, oth: &'b BigNumRef) -> BigNum {
1316 let mut ctx = BigNumContext::new().unwrap();
1317 let mut r = BigNum::new().unwrap();
1318 r.checked_div(self, oth, &mut ctx).unwrap();
1319 r
1320 }
1321}
1322
1323delegate!(Div, div);
1324
1325impl<'b> Rem<&'b BigNumRef> for &BigNumRef {
1326 type Output = BigNum;
1327
1328 fn rem(self, oth: &'b BigNumRef) -> BigNum {
1329 let mut ctx = BigNumContext::new().unwrap();
1330 let mut r = BigNum::new().unwrap();
1331 r.checked_rem(self, oth, &mut ctx).unwrap();
1332 r
1333 }
1334}
1335
1336delegate!(Rem, rem);
1337
1338impl Shl<i32> for &BigNumRef {
1339 type Output = BigNum;
1340
1341 fn shl(self, n: i32) -> BigNum {
1342 let mut r = BigNum::new().unwrap();
1343 r.lshift(self, n).unwrap();
1344 r
1345 }
1346}
1347
1348impl Shl<i32> for &BigNum {
1349 type Output = BigNum;
1350
1351 fn shl(self, n: i32) -> BigNum {
1352 self.deref().shl(n)
1353 }
1354}
1355
1356impl Shr<i32> for &BigNumRef {
1357 type Output = BigNum;
1358
1359 fn shr(self, n: i32) -> BigNum {
1360 let mut r = BigNum::new().unwrap();
1361 r.rshift(self, n).unwrap();
1362 r
1363 }
1364}
1365
1366impl Shr<i32> for &BigNum {
1367 type Output = BigNum;
1368
1369 fn shr(self, n: i32) -> BigNum {
1370 self.deref().shr(n)
1371 }
1372}
1373
1374impl Neg for &BigNumRef {
1375 type Output = BigNum;
1376
1377 fn neg(self) -> BigNum {
1378 self.to_owned().unwrap().neg()
1379 }
1380}
1381
1382impl Neg for &BigNum {
1383 type Output = BigNum;
1384
1385 fn neg(self) -> BigNum {
1386 self.deref().neg()
1387 }
1388}
1389
1390impl Neg for BigNum {
1391 type Output = BigNum;
1392
1393 fn neg(mut self) -> BigNum {
1394 let negative = self.is_negative();
1395 self.set_negative(!negative);
1396 self
1397 }
1398}
1399
1400#[cfg(test)]
1401mod tests {
1402 use crate::bn::{BigNum, BigNumContext};
1403
1404 #[test]
1405 fn test_to_from_slice() {
1406 let v0 = BigNum::from_u32(10_203_004).unwrap();
1407 let vec = v0.to_vec();
1408 let v1 = BigNum::from_slice(&vec).unwrap();
1409
1410 assert_eq!(v0, v1);
1411 }
1412
1413 #[test]
1414 fn test_negation() {
1415 let a = BigNum::from_u32(909_829_283).unwrap();
1416
1417 assert!(!a.is_negative());
1418 assert!((-a).is_negative());
1419 }
1420
1421 #[test]
1422 fn test_shift() {
1423 let a = BigNum::from_u32(909_829_283).unwrap();
1424
1425 assert_eq!(a, &(&a << 1) >> 1);
1426 }
1427
1428 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1429 #[test]
1430 fn test_rand_range() {
1431 let range = BigNum::from_u32(909_829_283).unwrap();
1432 let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap();
1433 range.rand_range(&mut result).unwrap();
1434 assert!(result >= BigNum::from_u32(0).unwrap() && result < range);
1435 }
1436
1437 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1438 #[test]
1439 fn test_pseudo_rand_range() {
1440 let range = BigNum::from_u32(909_829_283).unwrap();
1441 let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap();
1442 range.pseudo_rand_range(&mut result).unwrap();
1443 assert!(result >= BigNum::from_u32(0).unwrap() && result < range);
1444 }
1445
1446 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1447 #[test]
1448 fn test_prime_numbers() {
1449 let a = BigNum::from_u32(19_029_017).unwrap();
1450 let mut p = BigNum::new().unwrap();
1451 p.generate_prime(128, true, None, Some(&a)).unwrap();
1452
1453 let mut ctx = BigNumContext::new().unwrap();
1454 assert!(p.is_prime(100, &mut ctx).unwrap());
1455 assert!(p.is_prime_fasttest(100, &mut ctx, true).unwrap());
1456 }
1457
1458 #[cfg(ossl110)]
1459 #[test]
1460 fn test_secure_bn_ctx() {
1461 let mut cxt = BigNumContext::new_secure().unwrap();
1462 let a = BigNum::from_u32(8).unwrap();
1463 let b = BigNum::from_u32(3).unwrap();
1464
1465 let mut remainder = BigNum::new().unwrap();
1466 remainder.nnmod(&a, &b, &mut cxt).unwrap();
1467
1468 assert!(remainder.eq(&BigNum::from_u32(2).unwrap()));
1469 }
1470
1471 #[cfg(ossl110)]
1472 #[test]
1473 fn test_secure_bn() {
1474 let a = BigNum::new().unwrap();
1475 assert!(!a.is_secure());
1476
1477 let b = BigNum::new_secure().unwrap();
1478 assert!(b.is_secure())
1479 }
1480
1481 #[cfg(ossl110)]
1482 #[test]
1483 fn test_const_time_bn() {
1484 let a = BigNum::new().unwrap();
1485 assert!(!a.is_const_time());
1486
1487 let mut b = BigNum::new().unwrap();
1488 b.set_const_time();
1489 assert!(b.is_const_time())
1490 }
1491
1492 #[test]
1493 fn test_mod_sqrt() {
1494 let mut ctx = BigNumContext::new().unwrap();
1495
1496 let s = BigNum::from_hex_str("2").unwrap();
1497 let p = BigNum::from_hex_str("7DEB1").unwrap();
1498 let mut sqrt = BigNum::new().unwrap();
1499 let mut out = BigNum::new().unwrap();
1500
1501 sqrt.mod_sqrt(&s, &p, &mut ctx).unwrap();
1503 out.mod_sqr(&sqrt, &p, &mut ctx).unwrap();
1504 assert!(out == s);
1505
1506 let s = BigNum::from_hex_str("3").unwrap();
1507 let p = BigNum::from_hex_str("5").unwrap();
1508 assert!(out.mod_sqrt(&s, &p, &mut ctx).is_err());
1509 }
1510
1511 #[test]
1512 #[cfg(any(ossl110, boringssl, libressl350))]
1513 fn test_odd_even() {
1514 let a = BigNum::from_u32(17).unwrap();
1515 let b = BigNum::from_u32(18).unwrap();
1516
1517 assert!(a.is_odd());
1518 assert!(!b.is_odd());
1519
1520 assert!(!a.is_even());
1521 assert!(b.is_even());
1522 }
1523}