Coverage Report

Created: 2026-06-30 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/src/lib/math/mp/mp_monty.cpp
Line
Count
Source
1
/*
2
* Montgomery Reduction
3
* (C) 1999-2011 Jack Lloyd
4
*     2006 Luca Piccarreta
5
*     2016 Matthias Gierlings
6
*
7
* Botan is released under the Simplified BSD License (see license.txt)
8
*/
9
10
#include <botan/internal/mp_core.h>
11
12
#include <botan/assert.h>
13
#include <botan/exceptn.h>
14
#include <botan/mem_ops.h>
15
#include <botan/internal/ct_utils.h>
16
17
namespace Botan {
18
19
/*
20
* Montgomery reduction - product scanning form
21
*
22
* Algorithm 5 from "Energy-Efficient Software Implementation of Long
23
* Integer Modular Arithmetic"
24
* (https://www.iacr.org/archive/ches2005/006.pdf)
25
*
26
* See also
27
*
28
* https://eprint.iacr.org/2013/882.pdf
29
* https://www.microsoft.com/en-us/research/wp-content/uploads/1996/01/j37acmon.pdf
30
*/
31
void bigint_monty_redc_generic(
32
95.0k
   word r[], const word z[], size_t z_size, const word p[], size_t p_size, word p_dash, word ws[]) {
33
95.0k
   BOTAN_ARG_CHECK(z_size >= 2 * p_size && p_size > 0, "Invalid sizes for bigint_monty_redc_generic");
34
35
95.0k
   word3<word> accum;
36
37
95.0k
   accum.add(z[0]);
38
39
95.0k
   ws[0] = accum.monty_step(p[0], p_dash);
40
41
190k
   for(size_t i = 1; i != p_size; ++i) {
42
190k
      for(size_t j = 0; j < i; ++j) {
43
95.0k
         accum.mul(ws[j], p[i - j]);
44
95.0k
      }
45
46
95.0k
      accum.add(z[i]);
47
95.0k
      ws[i] = accum.monty_step(p[0], p_dash);
48
95.0k
   }
49
50
190k
   for(size_t i = 0; i != p_size - 1; ++i) {
51
190k
      for(size_t j = i + 1; j != p_size; ++j) {
52
95.0k
         accum.mul(ws[j], p[p_size + i - j]);
53
95.0k
      }
54
55
95.0k
      accum.add(z[p_size + i]);
56
95.0k
      ws[i] = accum.extract();
57
95.0k
   }
58
59
95.0k
   accum.add(z[2 * p_size - 1]);
60
61
95.0k
   ws[p_size - 1] = accum.extract();
62
   // w1 is the final part, which is not stored in the workspace
63
95.0k
   const word w1 = accum.extract();
64
65
   /*
66
   * The result might need to be reduced mod p. To avoid a timing
67
   * channel, always perform the subtraction. If in the compution
68
   * of x - p a borrow is required then x was already < p.
69
   *
70
   * x starts at ws[0] and is p_size bytes long plus a possible high
71
   * digit left over in w1.
72
   *
73
   * x - p starts at z[0] and is also p_size bytes long
74
   *
75
   * If borrow was set after the subtraction, then x was already less
76
   * than p and the subtraction was not needed. In that case overwrite
77
   * z[0:p_size] with the original x in ws[0:p_size].
78
   *
79
   * We only copy out p_size in the final step because we know
80
   * the Montgomery result is < P
81
   */
82
83
95.0k
   bigint_monty_maybe_sub(p_size, r, w1, ws, p);
84
95.0k
}
85
86
}  // namespace Botan