@@ -13,28 +13,32 @@ mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret)
13
13
{
14
14
mp_err err ;
15
15
int legendre ;
16
- mp_int t1 , C , Q , S , Z , M , T , R , two ;
17
- mp_digit i ;
16
+ /* The type is "int" because of the types in the mp_int struct.
17
+ Don't forget to change them here when you change them there! */
18
+ int S , M , i ;
19
+ mp_int t1 , C , Q , Z , T , R , two ;
18
20
19
21
/* first handle the simple cases */
20
22
if (mp_cmp_d (n , 0uL ) == MP_EQ ) {
21
23
mp_zero (ret );
22
24
return MP_OKAY ;
23
25
}
24
- if (mp_cmp_d (prime , 2uL ) == MP_EQ ) return MP_VAL ; /* prime must be odd */
25
- if ((err = mp_kronecker (n , prime , & legendre )) != MP_OKAY ) return err ;
26
- if (legendre == -1 ) return MP_VAL ; /* quadratic non-residue mod prime */
26
+ /* "prime" must be odd and > 2 */
27
+ if (mp_iseven (prime ) || (mp_cmp_d (prime , 3uL ) == MP_LT )) return MP_VAL ;
28
+ if ((err = mp_kronecker (n , prime , & legendre )) != MP_OKAY ) return err ;
29
+ /* n \not\cong 0 (mod p) and n \cong r^2 (mod p) for some r \in N^+ */
30
+ if (legendre != 1 ) return MP_VAL ;
27
31
28
- if ((err = mp_init_multi (& t1 , & C , & Q , & S , & Z , & M , & T , & R , & two , NULL )) != MP_OKAY ) {
32
+ if ((err = mp_init_multi (& t1 , & C , & Q , & Z , & T , & R , & two , NULL )) != MP_OKAY ) {
29
33
return err ;
30
34
}
31
35
32
36
/* SPECIAL CASE: if prime mod 4 == 3
33
37
* compute directly: err = n^(prime+1)/4 mod prime
34
38
* Handbook of Applied Cryptography algorithm 3.36
35
39
*/
36
- if (( err = mp_mod_d ( prime , 4uL , & i )) != MP_OKAY ) goto LBL_END ;
37
- if (i == 3u ) {
40
+ /* x%4 == x&3 for x in N and x>0 */
41
+ if (( prime -> dp [ 0 ] & 3u ) == 3u ) {
38
42
if ((err = mp_add_d (prime , 1uL , & t1 )) != MP_OKAY ) goto LBL_END ;
39
43
if ((err = mp_div_2 (& t1 , & t1 )) != MP_OKAY ) goto LBL_END ;
40
44
if ((err = mp_div_2 (& t1 , & t1 )) != MP_OKAY ) goto LBL_END ;
@@ -49,12 +53,12 @@ mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret)
49
53
if ((err = mp_copy (prime , & Q )) != MP_OKAY ) goto LBL_END ;
50
54
if ((err = mp_sub_d (& Q , 1uL , & Q )) != MP_OKAY ) goto LBL_END ;
51
55
/* Q = prime - 1 */
52
- mp_zero ( & S ) ;
56
+ S = 0 ;
53
57
/* S = 0 */
54
58
while (mp_iseven (& Q )) {
55
59
if ((err = mp_div_2 (& Q , & Q )) != MP_OKAY ) goto LBL_END ;
56
60
/* Q = Q / 2 */
57
- if (( err = mp_add_d ( & S , 1uL , & S )) != MP_OKAY ) goto LBL_END ;
61
+ S ++ ;
58
62
/* S = S + 1 */
59
63
}
60
64
@@ -63,6 +67,12 @@ mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret)
63
67
/* Z = 2 */
64
68
for (;;) {
65
69
if ((err = mp_kronecker (& Z , prime , & legendre )) != MP_OKAY ) goto LBL_END ;
70
+ /* If "prime" (p) is an odd prime Jacobi(k|p) = 0 for k \cong 0 (mod p) */
71
+ /* but there is at least one non-quadratic residue before k>=p if p is an odd prime. */
72
+ if (legendre == 0 ) {
73
+ err = MP_VAL ;
74
+ goto LBL_END ;
75
+ }
66
76
if (legendre == -1 ) break ;
67
77
if ((err = mp_add_d (& Z , 1uL , & Z )) != MP_OKAY ) goto LBL_END ;
68
78
/* Z = Z + 1 */
@@ -77,7 +87,7 @@ mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret)
77
87
/* R = n ^ ((Q + 1) / 2) mod prime */
78
88
if ((err = mp_exptmod (n , & Q , prime , & T )) != MP_OKAY ) goto LBL_END ;
79
89
/* T = n ^ Q mod prime */
80
- if (( err = mp_copy ( & S , & M )) != MP_OKAY ) goto LBL_END ;
90
+ M = S ;
81
91
/* M = S */
82
92
mp_set (& two , 2uL );
83
93
@@ -86,16 +96,21 @@ mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret)
86
96
i = 0 ;
87
97
for (;;) {
88
98
if (mp_cmp_d (& t1 , 1uL ) == MP_EQ ) break ;
99
+ /* No exponent in the range 0 < i < M found
100
+ (M is at least 1 in the first round because "prime" > 2) */
101
+ if (M == i ) {
102
+ err = MP_VAL ;
103
+ goto LBL_END ;
104
+ }
89
105
if ((err = mp_exptmod (& t1 , & two , prime , & t1 )) != MP_OKAY ) goto LBL_END ;
90
106
i ++ ;
91
107
}
92
- if (i == 0u ) {
108
+ if (i == 0 ) {
93
109
if ((err = mp_copy (& R , ret )) != MP_OKAY ) goto LBL_END ;
94
110
err = MP_OKAY ;
95
111
goto LBL_END ;
96
112
}
97
- if ((err = mp_sub_d (& M , i , & t1 )) != MP_OKAY ) goto LBL_END ;
98
- if ((err = mp_sub_d (& t1 , 1uL , & t1 )) != MP_OKAY ) goto LBL_END ;
113
+ mp_set_i32 (& t1 , M - i - 1 );
99
114
if ((err = mp_exptmod (& two , & t1 , prime , & t1 )) != MP_OKAY ) goto LBL_END ;
100
115
/* t1 = 2 ^ (M - i - 1) */
101
116
if ((err = mp_exptmod (& C , & t1 , prime , & t1 )) != MP_OKAY ) goto LBL_END ;
@@ -106,12 +121,12 @@ mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret)
106
121
/* R = (R * t1) mod prime */
107
122
if ((err = mp_mulmod (& T , & C , prime , & T )) != MP_OKAY ) goto LBL_END ;
108
123
/* T = (T * C) mod prime */
109
- mp_set ( & M , i ) ;
124
+ M = i ;
110
125
/* M = i */
111
126
}
112
127
113
128
LBL_END :
114
- mp_clear_multi (& t1 , & C , & Q , & S , & Z , & M , & T , & R , & two , NULL );
129
+ mp_clear_multi (& t1 , & C , & Q , & Z , & T , & R , & two , NULL );
115
130
return err ;
116
131
}
117
132
0 commit comments