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(boringssl)] {
41 use ffi::BN_is_negative;
42 } else {
43 use ffi::{
44 BN_get_rfc3526_prime_1536, BN_get_rfc3526_prime_2048, BN_get_rfc3526_prime_3072, BN_get_rfc3526_prime_4096,
45 BN_get_rfc3526_prime_6144, BN_get_rfc3526_prime_8192, BN_is_negative,
46 };
47 }
48}
49
50#[cfg(any(ossl110, libressl))]
51use ffi::{BN_get_rfc2409_prime_1024, BN_get_rfc2409_prime_768};
52
53pub struct MsbOption(c_int);
55
56impl MsbOption {
57 pub const MAYBE_ZERO: MsbOption = MsbOption(-1);
59
60 pub const ONE: MsbOption = MsbOption(0);
62
63 pub const TWO_ONES: MsbOption = MsbOption(1);
68}
69
70foreign_type_and_impl_send_sync! {
71 type CType = ffi::BN_CTX;
72 fn drop = ffi::BN_CTX_free;
73
74 pub struct BigNumContext;
82 pub struct BigNumContextRef;
86}
87
88impl BigNumContext {
89 #[corresponds(BN_CTX_new)]
91 pub fn new() -> Result<BigNumContext, ErrorStack> {
92 unsafe {
93 ffi::init();
94 cvt_p(ffi::BN_CTX_new()).map(BigNumContext)
95 }
96 }
97
98 #[corresponds(BN_CTX_secure_new)]
100 #[cfg(ossl110)]
101 pub fn new_secure() -> Result<BigNumContext, ErrorStack> {
102 unsafe {
103 ffi::init();
104 cvt_p(ffi::BN_CTX_secure_new()).map(BigNumContext)
105 }
106 }
107}
108
109foreign_type_and_impl_send_sync! {
110 type CType = ffi::BIGNUM;
111 fn drop = ffi::BN_free;
112
113 pub struct BigNum;
137 pub struct BigNumRef;
141}
142
143impl BigNumRef {
144 #[corresponds(BN_clear)]
148 pub fn clear(&mut self) {
149 unsafe { ffi::BN_clear(self.as_ptr()) }
150 }
151
152 #[corresponds(BN_add_word)]
154 pub fn add_word(&mut self, w: u32) -> Result<(), ErrorStack> {
155 unsafe { cvt(ffi::BN_add_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
156 }
157
158 #[corresponds(BN_sub_word)]
160 pub fn sub_word(&mut self, w: u32) -> Result<(), ErrorStack> {
161 unsafe { cvt(ffi::BN_sub_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
162 }
163
164 #[corresponds(BN_mul_word)]
166 pub fn mul_word(&mut self, w: u32) -> Result<(), ErrorStack> {
167 unsafe { cvt(ffi::BN_mul_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) }
168 }
169
170 #[corresponds(BN_div_word)]
172 #[allow(clippy::useless_conversion)]
173 pub fn div_word(&mut self, w: u32) -> Result<u64, ErrorStack> {
174 unsafe {
175 let r = ffi::BN_div_word(self.as_ptr(), w.into());
176 if r == ffi::BN_ULONG::MAX {
177 Err(ErrorStack::get())
178 } else {
179 Ok(r.into())
180 }
181 }
182 }
183
184 #[corresponds(BN_mod_word)]
186 #[allow(clippy::useless_conversion)]
187 pub fn mod_word(&self, w: u32) -> Result<u64, ErrorStack> {
188 unsafe {
189 let r = ffi::BN_mod_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_rand_range)]
201 pub fn rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> {
202 unsafe { cvt(ffi::BN_rand_range(rnd.as_ptr(), self.as_ptr())).map(|_| ()) }
203 }
204
205 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
207 #[corresponds(BN_pseudo_rand_range)]
208 pub fn pseudo_rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> {
209 unsafe { cvt(ffi::BN_pseudo_rand_range(rnd.as_ptr(), self.as_ptr())).map(|_| ()) }
210 }
211
212 #[corresponds(BN_set_bit)]
216 #[allow(clippy::useless_conversion)]
217 pub fn set_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
218 unsafe { cvt(ffi::BN_set_bit(self.as_ptr(), n.into())).map(|_| ()) }
219 }
220
221 #[corresponds(BN_clear_bit)]
225 #[allow(clippy::useless_conversion)]
226 pub fn clear_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
227 unsafe { cvt(ffi::BN_clear_bit(self.as_ptr(), n.into())).map(|_| ()) }
228 }
229
230 #[corresponds(BN_is_bit_set)]
232 #[allow(clippy::useless_conversion)]
233 pub fn is_bit_set(&self, n: i32) -> bool {
234 unsafe { ffi::BN_is_bit_set(self.as_ptr(), n.into()) == 1 }
235 }
236
237 #[corresponds(BN_mask_bits)]
241 #[allow(clippy::useless_conversion)]
242 pub fn mask_bits(&mut self, n: i32) -> Result<(), ErrorStack> {
243 unsafe { cvt(ffi::BN_mask_bits(self.as_ptr(), n.into())).map(|_| ()) }
244 }
245
246 #[corresponds(BN_lshift1)]
248 pub fn lshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack> {
249 unsafe { cvt(ffi::BN_lshift1(self.as_ptr(), a.as_ptr())).map(|_| ()) }
250 }
251
252 #[corresponds(BN_rshift1)]
254 pub fn rshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack> {
255 unsafe { cvt(ffi::BN_rshift1(self.as_ptr(), a.as_ptr())).map(|_| ()) }
256 }
257
258 #[corresponds(BN_add)]
262 pub fn checked_add(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack> {
263 unsafe { cvt(ffi::BN_add(self.as_ptr(), a.as_ptr(), b.as_ptr())).map(|_| ()) }
264 }
265
266 #[corresponds(BN_sub)]
270 pub fn checked_sub(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack> {
271 unsafe { cvt(ffi::BN_sub(self.as_ptr(), a.as_ptr(), b.as_ptr())).map(|_| ()) }
272 }
273
274 #[corresponds(BN_lshift)]
276 #[allow(clippy::useless_conversion)]
277 pub fn lshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack> {
278 unsafe { cvt(ffi::BN_lshift(self.as_ptr(), a.as_ptr(), n.into())).map(|_| ()) }
279 }
280
281 #[corresponds(BN_rshift)]
283 #[allow(clippy::useless_conversion)]
284 pub fn rshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack> {
285 unsafe { cvt(ffi::BN_rshift(self.as_ptr(), a.as_ptr(), n.into())).map(|_| ()) }
286 }
287
288 #[corresponds(BN_dup)]
290 pub fn to_owned(&self) -> Result<BigNum, ErrorStack> {
291 unsafe { cvt_p(ffi::BN_dup(self.as_ptr())).map(|b| BigNum::from_ptr(b)) }
292 }
293
294 #[corresponds(BN_set_negative)]
297 pub fn set_negative(&mut self, negative: bool) {
298 unsafe { ffi::BN_set_negative(self.as_ptr(), negative as c_int) }
299 }
300
301 #[corresponds(BN_ucmp)]
314 pub fn ucmp(&self, oth: &BigNumRef) -> Ordering {
315 unsafe { ffi::BN_ucmp(self.as_ptr(), oth.as_ptr()).cmp(&0) }
316 }
317
318 #[corresponds(BN_is_negative)]
320 pub fn is_negative(&self) -> bool {
321 unsafe { BN_is_negative(self.as_ptr()) == 1 }
322 }
323
324 #[corresponds(BN_is_even)]
326 pub fn is_even(&self) -> bool {
327 !self.is_odd()
328 }
329
330 #[corresponds(BN_is_odd)]
332 pub fn is_odd(&self) -> bool {
333 unsafe { ffi::BN_is_odd(self.as_ptr()) == 1 }
334 }
335
336 #[corresponds(BN_num_bits)]
338 #[allow(clippy::unnecessary_cast)]
339 pub fn num_bits(&self) -> i32 {
340 unsafe { ffi::BN_num_bits(self.as_ptr()) as i32 }
341 }
342
343 pub fn num_bytes(&self) -> i32 {
345 (self.num_bits() + 7) / 8
346 }
347
348 #[corresponds(BN_rand)]
373 #[allow(clippy::useless_conversion)]
374 pub fn rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> {
375 unsafe {
376 cvt(ffi::BN_rand(
377 self.as_ptr(),
378 bits.into(),
379 msb.0,
380 odd as c_int,
381 ))
382 .map(|_| ())
383 }
384 }
385
386 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
388 #[corresponds(BN_pseudo_rand)]
389 #[allow(clippy::useless_conversion)]
390 pub fn pseudo_rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> {
391 unsafe {
392 cvt(ffi::BN_pseudo_rand(
393 self.as_ptr(),
394 bits.into(),
395 msb.0,
396 odd as c_int,
397 ))
398 .map(|_| ())
399 }
400 }
401
402 #[corresponds(BN_generate_prime_ex)]
426 pub fn generate_prime(
427 &mut self,
428 bits: i32,
429 safe: bool,
430 add: Option<&BigNumRef>,
431 rem: Option<&BigNumRef>,
432 ) -> Result<(), ErrorStack> {
433 unsafe {
434 cvt(ffi::BN_generate_prime_ex(
435 self.as_ptr(),
436 bits as c_int,
437 safe as c_int,
438 add.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()),
439 rem.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()),
440 ptr::null_mut(),
441 ))
442 .map(|_| ())
443 }
444 }
445
446 #[corresponds(BN_mul)]
451 pub fn checked_mul(
452 &mut self,
453 a: &BigNumRef,
454 b: &BigNumRef,
455 ctx: &mut BigNumContextRef,
456 ) -> Result<(), ErrorStack> {
457 unsafe {
458 cvt(ffi::BN_mul(
459 self.as_ptr(),
460 a.as_ptr(),
461 b.as_ptr(),
462 ctx.as_ptr(),
463 ))
464 .map(|_| ())
465 }
466 }
467
468 #[corresponds(BN_div)]
473 pub fn checked_div(
474 &mut self,
475 a: &BigNumRef,
476 b: &BigNumRef,
477 ctx: &mut BigNumContextRef,
478 ) -> Result<(), ErrorStack> {
479 unsafe {
480 cvt(ffi::BN_div(
481 self.as_ptr(),
482 ptr::null_mut(),
483 a.as_ptr(),
484 b.as_ptr(),
485 ctx.as_ptr(),
486 ))
487 .map(|_| ())
488 }
489 }
490
491 #[corresponds(BN_div)]
493 pub fn checked_rem(
494 &mut self,
495 a: &BigNumRef,
496 b: &BigNumRef,
497 ctx: &mut BigNumContextRef,
498 ) -> Result<(), ErrorStack> {
499 unsafe {
500 cvt(ffi::BN_div(
501 ptr::null_mut(),
502 self.as_ptr(),
503 a.as_ptr(),
504 b.as_ptr(),
505 ctx.as_ptr(),
506 ))
507 .map(|_| ())
508 }
509 }
510
511 #[corresponds(BN_div)]
513 pub fn div_rem(
514 &mut self,
515 rem: &mut BigNumRef,
516 a: &BigNumRef,
517 b: &BigNumRef,
518 ctx: &mut BigNumContextRef,
519 ) -> Result<(), ErrorStack> {
520 unsafe {
521 cvt(ffi::BN_div(
522 self.as_ptr(),
523 rem.as_ptr(),
524 a.as_ptr(),
525 b.as_ptr(),
526 ctx.as_ptr(),
527 ))
528 .map(|_| ())
529 }
530 }
531
532 #[corresponds(BN_sqr)]
534 pub fn sqr(&mut self, a: &BigNumRef, ctx: &mut BigNumContextRef) -> Result<(), ErrorStack> {
535 unsafe { cvt(ffi::BN_sqr(self.as_ptr(), a.as_ptr(), ctx.as_ptr())).map(|_| ()) }
536 }
537
538 #[corresponds(BN_nnmod)]
541 pub fn nnmod(
542 &mut self,
543 a: &BigNumRef,
544 m: &BigNumRef,
545 ctx: &mut BigNumContextRef,
546 ) -> Result<(), ErrorStack> {
547 unsafe {
548 cvt(ffi::BN_nnmod(
549 self.as_ptr(),
550 a.as_ptr(),
551 m.as_ptr(),
552 ctx.as_ptr(),
553 ))
554 .map(|_| ())
555 }
556 }
557
558 #[corresponds(BN_mod_add)]
560 pub fn mod_add(
561 &mut self,
562 a: &BigNumRef,
563 b: &BigNumRef,
564 m: &BigNumRef,
565 ctx: &mut BigNumContextRef,
566 ) -> Result<(), ErrorStack> {
567 unsafe {
568 cvt(ffi::BN_mod_add(
569 self.as_ptr(),
570 a.as_ptr(),
571 b.as_ptr(),
572 m.as_ptr(),
573 ctx.as_ptr(),
574 ))
575 .map(|_| ())
576 }
577 }
578
579 #[corresponds(BN_mod_sub)]
581 pub fn mod_sub(
582 &mut self,
583 a: &BigNumRef,
584 b: &BigNumRef,
585 m: &BigNumRef,
586 ctx: &mut BigNumContextRef,
587 ) -> Result<(), ErrorStack> {
588 unsafe {
589 cvt(ffi::BN_mod_sub(
590 self.as_ptr(),
591 a.as_ptr(),
592 b.as_ptr(),
593 m.as_ptr(),
594 ctx.as_ptr(),
595 ))
596 .map(|_| ())
597 }
598 }
599
600 #[corresponds(BN_mod_mul)]
602 pub fn mod_mul(
603 &mut self,
604 a: &BigNumRef,
605 b: &BigNumRef,
606 m: &BigNumRef,
607 ctx: &mut BigNumContextRef,
608 ) -> Result<(), ErrorStack> {
609 unsafe {
610 cvt(ffi::BN_mod_mul(
611 self.as_ptr(),
612 a.as_ptr(),
613 b.as_ptr(),
614 m.as_ptr(),
615 ctx.as_ptr(),
616 ))
617 .map(|_| ())
618 }
619 }
620
621 #[corresponds(BN_mod_sqr)]
623 pub fn mod_sqr(
624 &mut self,
625 a: &BigNumRef,
626 m: &BigNumRef,
627 ctx: &mut BigNumContextRef,
628 ) -> Result<(), ErrorStack> {
629 unsafe {
630 cvt(ffi::BN_mod_sqr(
631 self.as_ptr(),
632 a.as_ptr(),
633 m.as_ptr(),
634 ctx.as_ptr(),
635 ))
636 .map(|_| ())
637 }
638 }
639
640 #[corresponds(BN_mod_sqrt)]
642 pub fn mod_sqrt(
643 &mut self,
644 a: &BigNumRef,
645 p: &BigNumRef,
646 ctx: &mut BigNumContextRef,
647 ) -> Result<(), ErrorStack> {
648 unsafe {
649 cvt_p(ffi::BN_mod_sqrt(
650 self.as_ptr(),
651 a.as_ptr(),
652 p.as_ptr(),
653 ctx.as_ptr(),
654 ))
655 .map(|_| ())
656 }
657 }
658
659 #[corresponds(BN_exp)]
661 pub fn exp(
662 &mut self,
663 a: &BigNumRef,
664 p: &BigNumRef,
665 ctx: &mut BigNumContextRef,
666 ) -> Result<(), ErrorStack> {
667 unsafe {
668 cvt(ffi::BN_exp(
669 self.as_ptr(),
670 a.as_ptr(),
671 p.as_ptr(),
672 ctx.as_ptr(),
673 ))
674 .map(|_| ())
675 }
676 }
677
678 #[corresponds(BN_mod_exp)]
680 pub fn mod_exp(
681 &mut self,
682 a: &BigNumRef,
683 p: &BigNumRef,
684 m: &BigNumRef,
685 ctx: &mut BigNumContextRef,
686 ) -> Result<(), ErrorStack> {
687 unsafe {
688 cvt(ffi::BN_mod_exp(
689 self.as_ptr(),
690 a.as_ptr(),
691 p.as_ptr(),
692 m.as_ptr(),
693 ctx.as_ptr(),
694 ))
695 .map(|_| ())
696 }
697 }
698
699 #[corresponds(BN_mod_inverse)]
701 pub fn mod_inverse(
702 &mut self,
703 a: &BigNumRef,
704 n: &BigNumRef,
705 ctx: &mut BigNumContextRef,
706 ) -> Result<(), ErrorStack> {
707 unsafe {
708 cvt_p(ffi::BN_mod_inverse(
709 self.as_ptr(),
710 a.as_ptr(),
711 n.as_ptr(),
712 ctx.as_ptr(),
713 ))
714 .map(|_| ())
715 }
716 }
717
718 #[corresponds(BN_gcd)]
720 pub fn gcd(
721 &mut self,
722 a: &BigNumRef,
723 b: &BigNumRef,
724 ctx: &mut BigNumContextRef,
725 ) -> Result<(), ErrorStack> {
726 unsafe {
727 cvt(ffi::BN_gcd(
728 self.as_ptr(),
729 a.as_ptr(),
730 b.as_ptr(),
731 ctx.as_ptr(),
732 ))
733 .map(|_| ())
734 }
735 }
736
737 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
745 #[corresponds(BN_is_prime_ex)]
746 #[allow(clippy::useless_conversion)]
747 pub fn is_prime(&self, checks: i32, ctx: &mut BigNumContextRef) -> Result<bool, ErrorStack> {
748 unsafe {
749 cvt_n(ffi::BN_is_prime_ex(
750 self.as_ptr(),
751 checks.into(),
752 ctx.as_ptr(),
753 ptr::null_mut(),
754 ))
755 .map(|r| r != 0)
756 }
757 }
758
759 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
769 #[corresponds(BN_is_prime_fasttest_ex)]
770 #[allow(clippy::useless_conversion)]
771 pub fn is_prime_fasttest(
772 &self,
773 checks: i32,
774 ctx: &mut BigNumContextRef,
775 do_trial_division: bool,
776 ) -> Result<bool, ErrorStack> {
777 unsafe {
778 cvt_n(ffi::BN_is_prime_fasttest_ex(
779 self.as_ptr(),
780 checks.into(),
781 ctx.as_ptr(),
782 do_trial_division as c_int,
783 ptr::null_mut(),
784 ))
785 .map(|r| r != 0)
786 }
787 }
788
789 #[corresponds(BN_bn2bin)]
802 pub fn to_vec(&self) -> Vec<u8> {
803 let size = self.num_bytes() as usize;
804 let mut v = Vec::with_capacity(size);
805 unsafe {
806 ffi::BN_bn2bin(self.as_ptr(), v.as_mut_ptr());
807 v.set_len(size);
808 }
809 v
810 }
811
812 #[corresponds(BN_bn2binpad)]
834 pub fn to_vec_padded(&self, pad_to: i32) -> Result<Vec<u8>, ErrorStack> {
835 let mut v = Vec::with_capacity(pad_to as usize);
836 unsafe {
837 cvt(ffi::BN_bn2binpad(self.as_ptr(), v.as_mut_ptr(), pad_to))?;
838 v.set_len(pad_to as usize);
839 }
840 Ok(v)
841 }
842
843 #[corresponds(BN_bn2dec)]
852 pub fn to_dec_str(&self) -> Result<OpensslString, ErrorStack> {
853 unsafe {
854 let buf = cvt_p(ffi::BN_bn2dec(self.as_ptr()))?;
855 Ok(OpensslString::from_ptr(buf))
856 }
857 }
858
859 #[corresponds(BN_bn2hex)]
868 pub fn to_hex_str(&self) -> Result<OpensslString, ErrorStack> {
869 unsafe {
870 let buf = cvt_p(ffi::BN_bn2hex(self.as_ptr()))?;
871 Ok(OpensslString::from_ptr(buf))
872 }
873 }
874
875 #[corresponds(BN_to_ASN1_INTEGER)]
877 pub fn to_asn1_integer(&self) -> Result<Asn1Integer, ErrorStack> {
878 unsafe {
879 cvt_p(ffi::BN_to_ASN1_INTEGER(self.as_ptr(), ptr::null_mut()))
880 .map(|p| Asn1Integer::from_ptr(p))
881 }
882 }
883
884 #[corresponds(BN_set_flags)]
886 #[cfg(ossl110)]
887 pub fn set_const_time(&mut self) {
888 unsafe { ffi::BN_set_flags(self.as_ptr(), ffi::BN_FLG_CONSTTIME) }
889 }
890
891 #[corresponds(BN_get_flags)]
893 #[cfg(ossl110)]
894 pub fn is_const_time(&self) -> bool {
895 unsafe {
896 let ret = ffi::BN_get_flags(self.as_ptr(), ffi::BN_FLG_CONSTTIME);
897 ret == ffi::BN_FLG_CONSTTIME
898 }
899 }
900
901 #[corresponds(BN_get_flags)]
903 #[cfg(ossl110)]
904 pub fn is_secure(&self) -> bool {
905 unsafe {
906 let ret = ffi::BN_get_flags(self.as_ptr(), ffi::BN_FLG_SECURE);
907 ret == ffi::BN_FLG_SECURE
908 }
909 }
910}
911
912impl BigNum {
913 #[corresponds(BN_new)]
915 pub fn new() -> Result<BigNum, ErrorStack> {
916 unsafe {
917 ffi::init();
918 let v = cvt_p(ffi::BN_new())?;
919 Ok(BigNum::from_ptr(v))
920 }
921 }
922
923 #[corresponds(BN_secure_new)]
925 #[cfg(ossl110)]
926 pub fn new_secure() -> Result<BigNum, ErrorStack> {
927 unsafe {
928 ffi::init();
929 let v = cvt_p(ffi::BN_secure_new())?;
930 Ok(BigNum::from_ptr(v))
931 }
932 }
933
934 #[corresponds(BN_set_word)]
936 pub fn from_u32(n: u32) -> Result<BigNum, ErrorStack> {
937 BigNum::new().and_then(|v| unsafe {
938 cvt(ffi::BN_set_word(v.as_ptr(), n as ffi::BN_ULONG)).map(|_| v)
939 })
940 }
941
942 #[corresponds(BN_dec2bn)]
944 pub fn from_dec_str(s: &str) -> Result<BigNum, ErrorStack> {
945 unsafe {
946 ffi::init();
947 let c_str = CString::new(s.as_bytes()).unwrap();
948 let mut bn = ptr::null_mut();
949 cvt(ffi::BN_dec2bn(&mut bn, c_str.as_ptr() as *const _))?;
950 Ok(BigNum::from_ptr(bn))
951 }
952 }
953
954 #[corresponds(BN_hex2bn)]
956 pub fn from_hex_str(s: &str) -> Result<BigNum, ErrorStack> {
957 unsafe {
958 ffi::init();
959 let c_str = CString::new(s.as_bytes()).unwrap();
960 let mut bn = ptr::null_mut();
961 cvt(ffi::BN_hex2bn(&mut bn, c_str.as_ptr() as *const _))?;
962 Ok(BigNum::from_ptr(bn))
963 }
964 }
965
966 #[corresponds(BN_get_rfc2409_prime_768)]
972 #[cfg(not(any(boringssl, awslc)))]
973 pub fn get_rfc2409_prime_768() -> Result<BigNum, ErrorStack> {
974 unsafe {
975 ffi::init();
976 cvt_p(BN_get_rfc2409_prime_768(ptr::null_mut())).map(BigNum)
977 }
978 }
979
980 #[corresponds(BN_get_rfc2409_prime_1024)]
986 #[cfg(not(any(boringssl, awslc)))]
987 pub fn get_rfc2409_prime_1024() -> Result<BigNum, ErrorStack> {
988 unsafe {
989 ffi::init();
990 cvt_p(BN_get_rfc2409_prime_1024(ptr::null_mut())).map(BigNum)
991 }
992 }
993
994 #[corresponds(BN_get_rfc3526_prime_1536)]
1000 #[cfg(not(boringssl))]
1001 pub fn get_rfc3526_prime_1536() -> Result<BigNum, ErrorStack> {
1002 unsafe {
1003 ffi::init();
1004 cvt_p(BN_get_rfc3526_prime_1536(ptr::null_mut())).map(BigNum)
1005 }
1006 }
1007
1008 #[corresponds(BN_get_rfc3526_prime_2048)]
1014 #[cfg(not(boringssl))]
1015 pub fn get_rfc3526_prime_2048() -> Result<BigNum, ErrorStack> {
1016 unsafe {
1017 ffi::init();
1018 cvt_p(BN_get_rfc3526_prime_2048(ptr::null_mut())).map(BigNum)
1019 }
1020 }
1021
1022 #[corresponds(BN_get_rfc3526_prime_3072)]
1028 #[cfg(not(boringssl))]
1029 pub fn get_rfc3526_prime_3072() -> Result<BigNum, ErrorStack> {
1030 unsafe {
1031 ffi::init();
1032 cvt_p(BN_get_rfc3526_prime_3072(ptr::null_mut())).map(BigNum)
1033 }
1034 }
1035
1036 #[corresponds(BN_get_rfc3526_prime_4096)]
1042 #[cfg(not(boringssl))]
1043 pub fn get_rfc3526_prime_4096() -> Result<BigNum, ErrorStack> {
1044 unsafe {
1045 ffi::init();
1046 cvt_p(BN_get_rfc3526_prime_4096(ptr::null_mut())).map(BigNum)
1047 }
1048 }
1049
1050 #[corresponds(BN_get_rfc3526_prime_6114)]
1056 #[cfg(not(boringssl))]
1057 pub fn get_rfc3526_prime_6144() -> Result<BigNum, ErrorStack> {
1058 unsafe {
1059 ffi::init();
1060 cvt_p(BN_get_rfc3526_prime_6144(ptr::null_mut())).map(BigNum)
1061 }
1062 }
1063
1064 #[corresponds(BN_get_rfc3526_prime_8192)]
1070 #[cfg(not(boringssl))]
1071 pub fn get_rfc3526_prime_8192() -> Result<BigNum, ErrorStack> {
1072 unsafe {
1073 ffi::init();
1074 cvt_p(BN_get_rfc3526_prime_8192(ptr::null_mut())).map(BigNum)
1075 }
1076 }
1077
1078 #[corresponds(BN_bin2bn)]
1087 pub fn from_slice(n: &[u8]) -> Result<BigNum, ErrorStack> {
1088 unsafe {
1089 ffi::init();
1090 assert!(n.len() <= LenType::MAX as usize);
1091
1092 cvt_p(ffi::BN_bin2bn(
1093 n.as_ptr(),
1094 n.len() as LenType,
1095 ptr::null_mut(),
1096 ))
1097 .map(|p| BigNum::from_ptr(p))
1098 }
1099 }
1100
1101 #[corresponds(BN_bin2bn)]
1116 pub fn copy_from_slice(&mut self, n: &[u8]) -> Result<(), ErrorStack> {
1117 unsafe {
1118 assert!(n.len() <= LenType::MAX as usize);
1119
1120 cvt_p(ffi::BN_bin2bn(n.as_ptr(), n.len() as LenType, self.0))?;
1121 Ok(())
1122 }
1123 }
1124}
1125
1126impl fmt::Debug for BigNumRef {
1127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1128 match self.to_dec_str() {
1129 Ok(s) => f.write_str(&s),
1130 Err(e) => Err(e.into()),
1131 }
1132 }
1133}
1134
1135impl fmt::Debug for BigNum {
1136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1137 match self.to_dec_str() {
1138 Ok(s) => f.write_str(&s),
1139 Err(e) => Err(e.into()),
1140 }
1141 }
1142}
1143
1144impl fmt::Display for BigNumRef {
1145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1146 match self.to_dec_str() {
1147 Ok(s) => f.write_str(&s),
1148 Err(e) => Err(e.into()),
1149 }
1150 }
1151}
1152
1153impl fmt::Display for BigNum {
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::UpperHex for BigNumRef {
1163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1164 match self.to_hex_str() {
1165 Ok(s) => {
1166 let s = s.to_uppercase();
1170
1171 if f.alternate() {
1172 <String as fmt::Display>::fmt(&format!("0x{}", &s), f)
1173 } else {
1174 <str as fmt::Display>::fmt(&s, f)
1175 }
1176 }
1177 Err(e) => Err(e.into()),
1178 }
1179 }
1180}
1181
1182impl fmt::UpperHex for BigNum {
1183 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1184 self.as_ref().fmt(f)
1185 }
1186}
1187
1188impl PartialEq<BigNumRef> for BigNumRef {
1189 fn eq(&self, oth: &BigNumRef) -> bool {
1190 self.cmp(oth) == Ordering::Equal
1191 }
1192}
1193
1194impl PartialEq<BigNum> for BigNumRef {
1195 fn eq(&self, oth: &BigNum) -> bool {
1196 self.eq(oth.deref())
1197 }
1198}
1199
1200impl Eq for BigNumRef {}
1201
1202impl PartialEq for BigNum {
1203 fn eq(&self, oth: &BigNum) -> bool {
1204 self.deref().eq(oth)
1205 }
1206}
1207
1208impl PartialEq<BigNumRef> for BigNum {
1209 fn eq(&self, oth: &BigNumRef) -> bool {
1210 self.deref().eq(oth)
1211 }
1212}
1213
1214impl Eq for BigNum {}
1215
1216impl PartialOrd<BigNumRef> for BigNumRef {
1217 fn partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering> {
1218 Some(self.cmp(oth))
1219 }
1220}
1221
1222impl PartialOrd<BigNum> for BigNumRef {
1223 fn partial_cmp(&self, oth: &BigNum) -> Option<Ordering> {
1224 Some(self.cmp(oth.deref()))
1225 }
1226}
1227
1228impl Ord for BigNumRef {
1229 fn cmp(&self, oth: &BigNumRef) -> Ordering {
1230 unsafe { ffi::BN_cmp(self.as_ptr(), oth.as_ptr()).cmp(&0) }
1231 }
1232}
1233
1234impl PartialOrd for BigNum {
1235 fn partial_cmp(&self, oth: &BigNum) -> Option<Ordering> {
1236 Some(self.cmp(oth))
1237 }
1238}
1239
1240impl PartialOrd<BigNumRef> for BigNum {
1241 fn partial_cmp(&self, oth: &BigNumRef) -> Option<Ordering> {
1242 self.deref().partial_cmp(oth)
1243 }
1244}
1245
1246impl Ord for BigNum {
1247 fn cmp(&self, oth: &BigNum) -> Ordering {
1248 self.deref().cmp(oth.deref())
1249 }
1250}
1251
1252macro_rules! delegate {
1253 ($t:ident, $m:ident) => {
1254 impl<'a, 'b> $t<&'b BigNum> for &'a BigNumRef {
1255 type Output = BigNum;
1256
1257 fn $m(self, oth: &BigNum) -> BigNum {
1258 $t::$m(self, oth.deref())
1259 }
1260 }
1261
1262 impl<'a, 'b> $t<&'b BigNumRef> for &'a BigNum {
1263 type Output = BigNum;
1264
1265 fn $m(self, oth: &BigNumRef) -> BigNum {
1266 $t::$m(self.deref(), oth)
1267 }
1268 }
1269
1270 impl<'a, 'b> $t<&'b BigNum> for &'a BigNum {
1271 type Output = BigNum;
1272
1273 fn $m(self, oth: &BigNum) -> BigNum {
1274 $t::$m(self.deref(), oth.deref())
1275 }
1276 }
1277 };
1278}
1279
1280impl Add<&BigNumRef> for &BigNumRef {
1281 type Output = BigNum;
1282
1283 fn add(self, oth: &BigNumRef) -> BigNum {
1284 let mut r = BigNum::new().unwrap();
1285 r.checked_add(self, oth).unwrap();
1286 r
1287 }
1288}
1289
1290delegate!(Add, add);
1291
1292impl Sub<&BigNumRef> for &BigNumRef {
1293 type Output = BigNum;
1294
1295 fn sub(self, oth: &BigNumRef) -> BigNum {
1296 let mut r = BigNum::new().unwrap();
1297 r.checked_sub(self, oth).unwrap();
1298 r
1299 }
1300}
1301
1302delegate!(Sub, sub);
1303
1304impl Mul<&BigNumRef> for &BigNumRef {
1305 type Output = BigNum;
1306
1307 fn mul(self, oth: &BigNumRef) -> BigNum {
1308 let mut ctx = BigNumContext::new().unwrap();
1309 let mut r = BigNum::new().unwrap();
1310 r.checked_mul(self, oth, &mut ctx).unwrap();
1311 r
1312 }
1313}
1314
1315delegate!(Mul, mul);
1316
1317impl<'b> Div<&'b BigNumRef> for &BigNumRef {
1318 type Output = BigNum;
1319
1320 fn div(self, oth: &'b BigNumRef) -> BigNum {
1321 let mut ctx = BigNumContext::new().unwrap();
1322 let mut r = BigNum::new().unwrap();
1323 r.checked_div(self, oth, &mut ctx).unwrap();
1324 r
1325 }
1326}
1327
1328delegate!(Div, div);
1329
1330impl<'b> Rem<&'b BigNumRef> for &BigNumRef {
1331 type Output = BigNum;
1332
1333 fn rem(self, oth: &'b BigNumRef) -> BigNum {
1334 let mut ctx = BigNumContext::new().unwrap();
1335 let mut r = BigNum::new().unwrap();
1336 r.checked_rem(self, oth, &mut ctx).unwrap();
1337 r
1338 }
1339}
1340
1341delegate!(Rem, rem);
1342
1343impl Shl<i32> for &BigNumRef {
1344 type Output = BigNum;
1345
1346 fn shl(self, n: i32) -> BigNum {
1347 let mut r = BigNum::new().unwrap();
1348 r.lshift(self, n).unwrap();
1349 r
1350 }
1351}
1352
1353impl Shl<i32> for &BigNum {
1354 type Output = BigNum;
1355
1356 fn shl(self, n: i32) -> BigNum {
1357 self.deref().shl(n)
1358 }
1359}
1360
1361impl Shr<i32> for &BigNumRef {
1362 type Output = BigNum;
1363
1364 fn shr(self, n: i32) -> BigNum {
1365 let mut r = BigNum::new().unwrap();
1366 r.rshift(self, n).unwrap();
1367 r
1368 }
1369}
1370
1371impl Shr<i32> for &BigNum {
1372 type Output = BigNum;
1373
1374 fn shr(self, n: i32) -> BigNum {
1375 self.deref().shr(n)
1376 }
1377}
1378
1379impl Neg for &BigNumRef {
1380 type Output = BigNum;
1381
1382 fn neg(self) -> BigNum {
1383 self.to_owned().unwrap().neg()
1384 }
1385}
1386
1387impl Neg for &BigNum {
1388 type Output = BigNum;
1389
1390 fn neg(self) -> BigNum {
1391 self.deref().neg()
1392 }
1393}
1394
1395impl Neg for BigNum {
1396 type Output = BigNum;
1397
1398 fn neg(mut self) -> BigNum {
1399 let negative = self.is_negative();
1400 self.set_negative(!negative);
1401 self
1402 }
1403}
1404
1405#[cfg(test)]
1406mod tests {
1407 use crate::bn::{BigNum, BigNumContext};
1408
1409 #[test]
1410 fn test_to_from_slice() {
1411 let v0 = BigNum::from_u32(10_203_004).unwrap();
1412 let vec = v0.to_vec();
1413 let v1 = BigNum::from_slice(&vec).unwrap();
1414
1415 assert_eq!(v0, v1);
1416 }
1417
1418 #[test]
1419 fn test_negation() {
1420 let a = BigNum::from_u32(909_829_283).unwrap();
1421
1422 assert!(!a.is_negative());
1423 assert!((-a).is_negative());
1424 }
1425
1426 #[test]
1427 fn test_shift() {
1428 let a = BigNum::from_u32(909_829_283).unwrap();
1429
1430 assert_eq!(a, &(&a << 1) >> 1);
1431 }
1432
1433 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1434 #[test]
1435 fn test_rand_range() {
1436 let range = BigNum::from_u32(909_829_283).unwrap();
1437 let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap();
1438 range.rand_range(&mut result).unwrap();
1439 assert!(result >= BigNum::from_u32(0).unwrap() && result < range);
1440 }
1441
1442 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1443 #[test]
1444 fn test_pseudo_rand_range() {
1445 let range = BigNum::from_u32(909_829_283).unwrap();
1446 let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap();
1447 range.pseudo_rand_range(&mut result).unwrap();
1448 assert!(result >= BigNum::from_u32(0).unwrap() && result < range);
1449 }
1450
1451 #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
1452 #[test]
1453 fn test_prime_numbers() {
1454 let a = BigNum::from_u32(19_029_017).unwrap();
1455 let mut p = BigNum::new().unwrap();
1456 p.generate_prime(128, true, None, Some(&a)).unwrap();
1457
1458 let mut ctx = BigNumContext::new().unwrap();
1459 assert!(p.is_prime(100, &mut ctx).unwrap());
1460 assert!(p.is_prime_fasttest(100, &mut ctx, true).unwrap());
1461 }
1462
1463 #[cfg(ossl110)]
1464 #[test]
1465 fn test_secure_bn_ctx() {
1466 let mut cxt = BigNumContext::new_secure().unwrap();
1467 let a = BigNum::from_u32(8).unwrap();
1468 let b = BigNum::from_u32(3).unwrap();
1469
1470 let mut remainder = BigNum::new().unwrap();
1471 remainder.nnmod(&a, &b, &mut cxt).unwrap();
1472
1473 assert!(remainder.eq(&BigNum::from_u32(2).unwrap()));
1474 }
1475
1476 #[cfg(ossl110)]
1477 #[test]
1478 fn test_secure_bn() {
1479 let a = BigNum::new().unwrap();
1480 assert!(!a.is_secure());
1481
1482 let b = BigNum::new_secure().unwrap();
1483 assert!(b.is_secure())
1484 }
1485
1486 #[cfg(ossl110)]
1487 #[test]
1488 fn test_const_time_bn() {
1489 let a = BigNum::new().unwrap();
1490 assert!(!a.is_const_time());
1491
1492 let mut b = BigNum::new().unwrap();
1493 b.set_const_time();
1494 assert!(b.is_const_time())
1495 }
1496
1497 #[test]
1498 fn test_mod_sqrt() {
1499 let mut ctx = BigNumContext::new().unwrap();
1500
1501 let s = BigNum::from_hex_str("2").unwrap();
1502 let p = BigNum::from_hex_str("7DEB1").unwrap();
1503 let mut sqrt = BigNum::new().unwrap();
1504 let mut out = BigNum::new().unwrap();
1505
1506 sqrt.mod_sqrt(&s, &p, &mut ctx).unwrap();
1508 out.mod_sqr(&sqrt, &p, &mut ctx).unwrap();
1509 assert!(out == s);
1510
1511 let s = BigNum::from_hex_str("3").unwrap();
1512 let p = BigNum::from_hex_str("5").unwrap();
1513 assert!(out.mod_sqrt(&s, &p, &mut ctx).is_err());
1514 }
1515
1516 #[test]
1517 fn test_odd_even() {
1518 let a = BigNum::from_u32(17).unwrap();
1519 let b = BigNum::from_u32(18).unwrap();
1520
1521 assert!(a.is_odd());
1522 assert!(!b.is_odd());
1523
1524 assert!(!a.is_even());
1525 assert!(b.is_even());
1526 }
1527
1528 #[test]
1529 fn test_format() {
1530 let a = BigNum::from_u32(12345678).unwrap();
1531
1532 assert_eq!(format!("{}", a), "12345678");
1533 }
1534
1535 #[test]
1536 fn test_format_upperhex() {
1537 let a = BigNum::from_u32(12345678).unwrap();
1538
1539 assert_eq!(format!("{:X}", a), "BC614E");
1540
1541 assert_eq!(format!("{:<20X}", a), "BC614E ");
1542 assert_eq!(format!("{:-<20X}", a), "BC614E--------------");
1543 assert_eq!(format!("{:^20X}", a), " BC614E ");
1544 assert_eq!(format!("{:>20X}", a), " BC614E");
1545
1546 assert_eq!(format!("{:#X}", a), "0xBC614E");
1547
1548 assert_eq!(format!("{:<#20X}", a), "0xBC614E ");
1549 assert_eq!(format!("{:-<#20X}", a), "0xBC614E------------");
1550 assert_eq!(format!("{:^#20X}", a), " 0xBC614E ");
1551 assert_eq!(format!("{:>#20X}", a), " 0xBC614E");
1552 }
1553}