Coverage Report

Created: 2025-12-07 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/fipsmodule/bn/sqrt.cc.inc
Line
Count
Source
1
// Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <openssl/bn.h>
16
17
#include <openssl/err.h>
18
19
#include "internal.h"
20
21
22
3.57k
BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
23
  // Compute a square root of |a| mod |p| using the Tonelli/Shanks algorithm
24
  // (cf. Henri Cohen, "A Course in Algebraic Computational Number Theory",
25
  // algorithm 1.5.1). |p| is assumed to be a prime.
26
27
3.57k
  BIGNUM *ret = in;
28
3.57k
  int err = 1;
29
3.57k
  int r;
30
3.57k
  BIGNUM *A, *b, *q, *t, *x, *y;
31
3.57k
  int e, i, j;
32
33
3.57k
  if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) {
34
0
    if (BN_abs_is_word(p, 2)) {
35
0
      if (ret == nullptr) {
36
0
        ret = BN_new();
37
0
      }
38
0
      if (ret == nullptr || !BN_set_word(ret, BN_is_bit_set(a, 0))) {
39
0
        if (ret != in) {
40
0
          BN_free(ret);
41
0
        }
42
0
        return nullptr;
43
0
      }
44
0
      return ret;
45
0
    }
46
47
0
    OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME);
48
0
    return nullptr;
49
0
  }
50
51
3.57k
  if (BN_is_zero(a) || BN_is_one(a)) {
52
0
    if (ret == nullptr) {
53
0
      ret = BN_new();
54
0
    }
55
0
    if (ret == nullptr || !BN_set_word(ret, BN_is_one(a))) {
56
0
      if (ret != in) {
57
0
        BN_free(ret);
58
0
      }
59
0
      return nullptr;
60
0
    }
61
0
    return ret;
62
0
  }
63
64
3.57k
  bssl::BN_CTXScope scope(ctx);
65
3.57k
  A = BN_CTX_get(ctx);
66
3.57k
  b = BN_CTX_get(ctx);
67
3.57k
  q = BN_CTX_get(ctx);
68
3.57k
  t = BN_CTX_get(ctx);
69
3.57k
  x = BN_CTX_get(ctx);
70
3.57k
  y = BN_CTX_get(ctx);
71
3.57k
  if (y == nullptr) {
72
0
    goto end;
73
0
  }
74
75
3.57k
  if (ret == nullptr) {
76
0
    ret = BN_new();
77
0
  }
78
3.57k
  if (ret == nullptr) {
79
0
    goto end;
80
0
  }
81
82
  // A = a mod p
83
3.57k
  if (!BN_nnmod(A, a, p, ctx)) {
84
0
    goto end;
85
0
  }
86
87
  // now write  |p| - 1  as  2^e*q  where  q  is odd
88
3.57k
  e = 1;
89
263k
  while (!BN_is_bit_set(p, e)) {
90
260k
    e++;
91
260k
  }
92
  // we'll set  q  later (if needed)
93
94
3.57k
  if (e == 1) {
95
    // The easy case:  (|p|-1)/2  is odd, so 2 has an inverse
96
    // modulo  (|p|-1)/2,  and square roots can be computed
97
    // directly by modular exponentiation.
98
    // We have
99
    //     2 * (|p|+1)/4 == 1   (mod (|p|-1)/2),
100
    // so we can use exponent  (|p|+1)/4,  i.e.  (|p|-3)/4 + 1.
101
837
    if (!BN_rshift(q, p, 2)) {
102
0
      goto end;
103
0
    }
104
837
    q->neg = 0;
105
837
    if (!BN_add_word(q, 1) || !BN_mod_exp_mont(ret, A, q, p, ctx, nullptr)) {
106
0
      goto end;
107
0
    }
108
837
    err = 0;
109
837
    goto vrfy;
110
837
  }
111
112
2.73k
  if (e == 2) {
113
    // |p| == 5  (mod 8)
114
    //
115
    // In this case  2  is always a non-square since
116
    // Legendre(2,p) = (-1)^((p^2-1)/8)  for any odd prime.
117
    // So if  a  really is a square, then  2*a  is a non-square.
118
    // Thus for
119
    //      b := (2*a)^((|p|-5)/8),
120
    //      i := (2*a)*b^2
121
    // we have
122
    //     i^2 = (2*a)^((1 + (|p|-5)/4)*2)
123
    //         = (2*a)^((p-1)/2)
124
    //         = -1;
125
    // so if we set
126
    //      x := a*b*(i-1),
127
    // then
128
    //     x^2 = a^2 * b^2 * (i^2 - 2*i + 1)
129
    //         = a^2 * b^2 * (-2*i)
130
    //         = a*(-i)*(2*a*b^2)
131
    //         = a*(-i)*i
132
    //         = a.
133
    //
134
    // (This is due to A.O.L. Atkin,
135
    // <URL:
136
    //http://listserv.nodak.edu/scripts/wa.exe?A2=ind9211&L=nmbrthry&O=T&P=562>,
137
    // November 1992.)
138
139
    // t := 2*a
140
0
    if (!bn_mod_lshift1_consttime(t, A, p, ctx)) {
141
0
      goto end;
142
0
    }
143
144
    // b := (2*a)^((|p|-5)/8)
145
0
    if (!BN_rshift(q, p, 3)) {
146
0
      goto end;
147
0
    }
148
0
    q->neg = 0;
149
0
    if (!BN_mod_exp_mont(b, t, q, p, ctx, nullptr)) {
150
0
      goto end;
151
0
    }
152
153
    // y := b^2
154
0
    if (!BN_mod_sqr(y, b, p, ctx)) {
155
0
      goto end;
156
0
    }
157
158
    // t := (2*a)*b^2 - 1
159
0
    if (!BN_mod_mul(t, t, y, p, ctx) ||
160
0
        !BN_sub_word(t, 1)) {
161
0
      goto end;
162
0
    }
163
164
    // x = a*b*t
165
0
    if (!BN_mod_mul(x, A, b, p, ctx) ||
166
0
        !BN_mod_mul(x, x, t, p, ctx)) {
167
0
      goto end;
168
0
    }
169
170
0
    if (!BN_copy(ret, x)) {
171
0
      goto end;
172
0
    }
173
0
    err = 0;
174
0
    goto vrfy;
175
0
  }
176
177
  // e > 2, so we really have to use the Tonelli/Shanks algorithm.
178
  // First, find some  y  that is not a square.
179
2.73k
  if (!BN_copy(q, p)) {
180
0
    goto end;  // use 'q' as temp
181
0
  }
182
2.73k
  q->neg = 0;
183
2.73k
  i = 2;
184
27.3k
  do {
185
    // For efficiency, try small numbers first;
186
    // if this fails, try random numbers.
187
27.3k
    if (i < 22) {
188
27.3k
      if (!BN_set_word(y, i)) {
189
0
        goto end;
190
0
      }
191
27.3k
    } else {
192
0
      if (!BN_rand_range_ex(y, 22, p)) {
193
0
        goto end;
194
0
      }
195
0
    }
196
197
27.3k
    r = bn_jacobi(y, q, ctx);  // here 'q' is |p|
198
27.3k
    if (r < -1) {
199
0
      goto end;
200
0
    }
201
27.3k
    if (r == 0) {
202
      // m divides p
203
0
      OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME);
204
0
      goto end;
205
0
    }
206
27.3k
  } while (r == 1 && ++i < 82);
207
208
2.73k
  if (r != -1) {
209
    // Many rounds and still no non-square -- this is more likely
210
    // a bug than just bad luck.
211
    // Even if  p  is not prime, we should have found some  y
212
    // such that r == -1.
213
0
    OPENSSL_PUT_ERROR(BN, BN_R_TOO_MANY_ITERATIONS);
214
0
    goto end;
215
0
  }
216
217
  // Here's our actual 'q':
218
2.73k
  if (!BN_rshift(q, q, e)) {
219
0
    goto end;
220
0
  }
221
222
  // Now that we have some non-square, we can find an element
223
  // of order  2^e  by computing its q'th power.
224
2.73k
  if (!BN_mod_exp_mont(y, y, q, p, ctx, nullptr)) {
225
0
    goto end;
226
0
  }
227
2.73k
  if (BN_is_one(y)) {
228
0
    OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME);
229
0
    goto end;
230
0
  }
231
232
  // Now we know that (if  p  is indeed prime) there is an integer
233
  // k,  0 <= k < 2^e,  such that
234
  //
235
  //      a^q * y^k == 1   (mod p).
236
  //
237
  // As  a^q  is a square and  y  is not,  k  must be even.
238
  // q+1  is even, too, so there is an element
239
  //
240
  //     X := a^((q+1)/2) * y^(k/2),
241
  //
242
  // and it satisfies
243
  //
244
  //     X^2 = a^q * a     * y^k
245
  //         = a,
246
  //
247
  // so it is the square root that we are looking for.
248
249
  // t := (q-1)/2  (note that  q  is odd)
250
2.73k
  if (!BN_rshift1(t, q)) {
251
0
    goto end;
252
0
  }
253
254
  // x := a^((q-1)/2)
255
2.73k
  if (BN_is_zero(t)) {  // special case: p = 2^e + 1
256
0
    if (!BN_nnmod(t, A, p, ctx)) {
257
0
      goto end;
258
0
    }
259
0
    if (BN_is_zero(t)) {
260
      // special case: a == 0  (mod p)
261
0
      BN_zero(ret);
262
0
      err = 0;
263
0
      goto end;
264
0
    } else if (!BN_one(x)) {
265
0
      goto end;
266
0
    }
267
2.73k
  } else {
268
2.73k
    if (!BN_mod_exp_mont(x, A, t, p, ctx, nullptr)) {
269
0
      goto end;
270
0
    }
271
2.73k
    if (BN_is_zero(x)) {
272
      // special case: a == 0  (mod p)
273
0
      BN_zero(ret);
274
0
      err = 0;
275
0
      goto end;
276
0
    }
277
2.73k
  }
278
279
  // b := a*x^2  (= a^q)
280
2.73k
  if (!BN_mod_sqr(b, x, p, ctx) ||
281
2.73k
      !BN_mod_mul(b, b, A, p, ctx)) {
282
0
    goto end;
283
0
  }
284
285
  // x := a*x    (= a^((q+1)/2))
286
2.73k
  if (!BN_mod_mul(x, x, A, p, ctx)) {
287
0
    goto end;
288
0
  }
289
290
109k
  while (1) {
291
    // Now  b  is  a^q * y^k  for some even  k  (0 <= k < 2^E
292
    // where  E  refers to the original value of  e,  which we
293
    // don't keep in a variable),  and  x  is  a^((q+1)/2) * y^(k/2).
294
    //
295
    // We have  a*b = x^2,
296
    //    y^2^(e-1) = -1,
297
    //    b^2^(e-1) = 1.
298
109k
    if (BN_is_one(b)) {
299
2.24k
      if (!BN_copy(ret, x)) {
300
0
        goto end;
301
0
      }
302
2.24k
      err = 0;
303
2.24k
      goto vrfy;
304
2.24k
    }
305
306
    // Find the smallest i, 0 < i < e, such that b^(2^i) = 1
307
5.16M
    for (i = 1; i < e; i++) {
308
5.16M
      if (i == 1) {
309
106k
        if (!BN_mod_sqr(t, b, p, ctx)) {
310
0
          goto end;
311
0
        }
312
5.05M
      } else {
313
5.05M
        if (!BN_mod_mul(t, t, t, p, ctx)) {
314
0
          goto end;
315
0
        }
316
5.05M
      }
317
5.16M
      if (BN_is_one(t)) {
318
106k
        break;
319
106k
      }
320
5.16M
    }
321
    // If not found, a is not a square or p is not a prime.
322
106k
    if (i >= e) {
323
498
      OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE);
324
498
      goto end;
325
498
    }
326
327
    // t := y^2^(e - i - 1)
328
106k
    if (!BN_copy(t, y)) {
329
0
      goto end;
330
0
    }
331
210k
    for (j = e - i - 1; j > 0; j--) {
332
104k
      if (!BN_mod_sqr(t, t, p, ctx)) {
333
0
        goto end;
334
0
      }
335
104k
    }
336
106k
    if (!BN_mod_mul(y, t, t, p, ctx) ||
337
106k
        !BN_mod_mul(x, x, t, p, ctx) ||
338
106k
        !BN_mod_mul(b, b, y, p, ctx)) {
339
0
      goto end;
340
0
    }
341
342
    // e decreases each iteration, so this loop will terminate.
343
106k
    assert(i < e);
344
106k
    e = i;
345
106k
  }
346
347
3.07k
vrfy:
348
3.07k
  if (!err) {
349
    // Verify the result. The input might have been not a square.
350
3.07k
    if (!BN_mod_sqr(x, ret, p, ctx)) {
351
0
      err = 1;
352
0
    }
353
354
3.07k
    if (!err && 0 != BN_cmp(x, A)) {
355
268
      OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE);
356
268
      err = 1;
357
268
    }
358
3.07k
  }
359
360
3.57k
end:
361
3.57k
  if (err) {
362
766
    if (ret != in) {
363
0
      BN_clear_free(ret);
364
0
    }
365
766
    ret = nullptr;
366
766
  }
367
3.57k
  return ret;
368
3.07k
}