@@ -79,6 +79,13 @@ impl EcGroup {
79
79
Ok ( ret)
80
80
}
81
81
82
+ /// Initialize an EcGroup with custom group parameters.
83
+ ///
84
+ /// HAZMAT: This function DOES NOT perform a full check on parameters
85
+ /// against all known attacks. The caller MUST make sure that parameters are
86
+ /// trusted. Failing to comply with this requirement may result in the use
87
+ /// of INSECURE curves. Prefer [EcGroup::new] with known curves listed in
88
+ /// [EcGroupId].
82
89
pub fn from_parameters (
83
90
p : Mpi ,
84
91
a : Mpi ,
@@ -96,15 +103,16 @@ impl EcGroup {
96
103
let zero = Mpi :: new ( 0 ) ?;
97
104
98
105
// basic bounds checking
99
- if & a <= & zero
106
+ if & a < & zero
100
107
|| & a >= & p
101
- || & b <= & zero
108
+ || & b < & zero
102
109
|| & b >= & p
103
- || & g_x <= & zero
110
+ || & g_x < & zero
104
111
|| & g_x >= & p
105
- || & g_y <= & zero
112
+ || & g_y < & zero
106
113
|| & g_y >= & p
107
114
|| & order <= & zero
115
+ || ( & a == & zero && & b == & zero)
108
116
{
109
117
return Err ( Error :: EcpBadInputData ) ;
110
118
}
@@ -191,6 +199,8 @@ impl EcGroup {
191
199
match self . group_id ( ) ? {
192
200
EcGroupId :: Curve25519 => Ok ( 8 ) ,
193
201
EcGroupId :: Curve448 => Ok ( 4 ) ,
202
+ // Requires a point-counting algorithm such as SEA.
203
+ EcGroupId :: None => Err ( Error :: EcpFeatureUnavailable ) ,
194
204
_ => Ok ( 1 ) ,
195
205
}
196
206
}
@@ -754,4 +764,154 @@ mod tests {
754
764
let pt3 = pt1. clone ( ) ;
755
765
assert_eq ! ( pt2. eq( & pt3) . unwrap( ) , true ) ;
756
766
}
767
+
768
+ #[ cfg( feature = "std" ) ]
769
+ struct Params < ' a > {
770
+ p : & ' a str ,
771
+ a : & ' a str ,
772
+ b : & ' a str ,
773
+ g_x : & ' a str ,
774
+ g_y : & ' a str ,
775
+ n : & ' a str ,
776
+ }
777
+
778
+ #[ cfg( feature = "std" ) ]
779
+ impl Into < super :: Result < EcGroup > > for Params < ' _ > {
780
+ fn into ( self ) -> super :: Result < EcGroup > {
781
+ use std:: str:: FromStr ;
782
+ EcGroup :: from_parameters (
783
+ Mpi :: from_str ( self . p ) ?,
784
+ Mpi :: from_str ( self . a ) ?,
785
+ Mpi :: from_str ( self . b ) ?,
786
+ Mpi :: from_str ( self . g_x ) ?,
787
+ Mpi :: from_str ( self . g_y ) ?,
788
+ Mpi :: from_str ( self . n ) ?,
789
+ )
790
+ }
791
+ }
792
+
793
+ #[ test]
794
+ #[ cfg( feature = "std" ) ]
795
+ fn pathological_parameters ( ) {
796
+ // y² = x³ mod 7 (note a == b == 0)
797
+ let singular: super :: Result < _ > = Params {
798
+ p : "0x07" ,
799
+ a : "0x00" ,
800
+ b : "0x00" ,
801
+ g_x : "0x01" ,
802
+ g_y : "0x02" ,
803
+ n : "0x0b" ,
804
+ } . into ( ) ;
805
+ assert ! ( singular. is_err( ) ) ;
806
+ }
807
+
808
+ #[ test]
809
+ #[ cfg( feature = "std" ) ]
810
+ fn bad_generators ( ) {
811
+ // y² = x³ + x + 6 (mod 7) with bad generator (1, 2) and prime order 11
812
+ let small_curve: super :: Result < _ > = Params {
813
+ p : "0x07" ,
814
+ a : "0x01" ,
815
+ b : "0x06" ,
816
+ g_x : "0x01" ,
817
+ g_y : "0x02" ,
818
+ n : "0x0b" ,
819
+ } . into ( ) ;
820
+ assert ! ( small_curve. is_err( ) ) ;
821
+
822
+ // y² = x³ + x + 6 (mod 7) with bad generator (0, 0) and prime order 11
823
+ let small_curve_zero_gen: super :: Result < _ > = Params {
824
+ p : "0x07" ,
825
+ a : "0x01" ,
826
+ b : "0x06" ,
827
+ g_x : "0x00" ,
828
+ g_y : "0x00" ,
829
+ n : "0x0b" ,
830
+ } . into ( ) ;
831
+ assert ! ( small_curve_zero_gen. is_err( ) ) ;
832
+ }
833
+
834
+ #[ test]
835
+ #[ cfg( feature = "std" ) ]
836
+ fn unknown_cofactor ( ) {
837
+ // y² = x³ + x + 6 (mod 7) with generator (1, 6) and prime order 11
838
+ let small_curve: super :: Result < _ > = Params {
839
+ p : "0x07" ,
840
+ a : "0x01" ,
841
+ b : "0x06" ,
842
+ g_x : "0x01" ,
843
+ g_y : "0x06" ,
844
+ n : "0x0b" ,
845
+ } . into ( ) ;
846
+ assert ! ( small_curve. unwrap( ) . cofactor( ) . is_err( ) ) ;
847
+ }
848
+
849
+ #[ test]
850
+ #[ cfg( feature = "std" ) ]
851
+ fn zero_params_curves ( ) {
852
+ use super :: Result ;
853
+ // Barreto-Naehrig 254, note a = 0
854
+ let bn254: Result < _ > = Params {
855
+ p : "0x2523648240000001BA344D80000000086121000000000013A700000000000013" ,
856
+ a : "0x0000000000000000000000000000000000000000000000000000000000000000" ,
857
+ b : "0x0000000000000000000000000000000000000000000000000000000000000002" ,
858
+ g_x : "0x2523648240000001BA344D80000000086121000000000013A700000000000012" ,
859
+ g_y : "0x0000000000000000000000000000000000000000000000000000000000000001" ,
860
+ n : "0x2523648240000001BA344D8000000007FF9F800000000010A10000000000000D" ,
861
+ } . into ( ) ;
862
+ assert ! ( bn254. is_ok( ) ) ;
863
+
864
+ // Prescribed embedded degree of 12, BLS12-381
865
+ let bls12_381: Result < _ > = Params {
866
+ p : "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab" ,
867
+ a : "0x00" ,
868
+ b : "0x04" ,
869
+ g_x : "0x17F1D3A73197D7942695638C4FA9AC0FC3688C4F9774B905A14E3A3F171BAC586C55E83FF97A1AEFFB3AF00ADB22C6BB" ,
870
+ g_y : "0x08B3F481E3AAA0F1A09E30ED741D8AE4FCF5E095D5D00AF600DB18CB2C04B3EDD03CC744A2888AE40CAA232946C5E7E1" ,
871
+ n : "0x73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001" ,
872
+ } . into ( ) ;
873
+ assert ! ( bls12_381. is_ok( ) ) ;
874
+
875
+ // Fp256BN
876
+ let fp256_bn: Result < _ > = Params {
877
+ p : "0xfffffffffffcf0cd46e5f25eee71a49f0cdc65fb12980a82d3292ddbaed33013" ,
878
+ a : "0x00" ,
879
+ b : "0x03" ,
880
+ g_x : "0x01" ,
881
+ g_y : "0x02" ,
882
+ n : "0xfffffffffffcf0cd46e5f25eee71a49e0cdc65fb1299921af62d536cd10b500d" ,
883
+ } . into ( ) ;
884
+ assert ! ( fp256_bn. is_ok( ) ) ;
885
+
886
+ // id-GostR3410-2001-CryptoPro-C-ParamSet, note g_x = 0
887
+ let gost_r3410: Result < _ > = Params {
888
+ p : "0x9b9f605f5a858107ab1ec85e6b41c8aacf846e86789051d37998f7b9022d759b" ,
889
+ a : "0x9b9f605f5a858107ab1ec85e6b41c8aacf846e86789051d37998f7b9022d7598" ,
890
+ b : "0x805a" ,
891
+ g_x : "0x00" ,
892
+ g_y : "0x41ece55743711a8c3cbf3783cd08c0ee4d4dc440d4641a8f366e550dfdb3bb67" ,
893
+ n : "0x9b9f605f5a858107ab1ec85e6b41c8aa582ca3511eddfb74f02f3a6598980bb9" ,
894
+ } . into ( ) ;
895
+ assert ! ( gost_r3410. is_ok( ) ) ;
896
+
897
+ // secp256k1 (Bitcoin), note a = 0
898
+ let my_secp256k1: Result < EcGroup > = Params {
899
+ p : "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" ,
900
+ a : "0x0000000000000000000000000000000000000000000000000000000000000000" ,
901
+ b : "0x0000000000000000000000000000000000000000000000000000000000000007" ,
902
+ g_x : "0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" ,
903
+ g_y : "0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" ,
904
+ n : "0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141" ,
905
+ } . into ( ) ;
906
+ assert ! ( my_secp256k1. is_ok( ) ) ;
907
+ let my_secp256k1 = my_secp256k1. unwrap ( ) ;
908
+
909
+ // We compare against the known SecP256K1
910
+ let secp256k1 = EcGroup :: new ( EcGroupId :: SecP256K1 ) . unwrap ( ) ;
911
+ assert ! ( my_secp256k1. p( ) == secp256k1. p( ) ) ;
912
+ assert ! ( my_secp256k1. a( ) == secp256k1. a( ) ) ;
913
+ assert ! ( my_secp256k1. b( ) == secp256k1. b( ) ) ;
914
+ assert ! ( my_secp256k1. generator( ) == secp256k1. generator( ) ) ;
915
+ assert ! ( my_secp256k1. order( ) == secp256k1. order( ) ) ;
916
+ }
757
917
}
0 commit comments