Botan 3.10.0
Crypto and TLS for C&
mp_monty.cpp
Go to the documentation of this file.
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
14namespace Botan {
15
16/*
17* Montgomery reduction - product scanning form
18*
19* Algorithm 5 from "Energy-Efficient Software Implementation of Long
20* Integer Modular Arithmetic"
21* (https://www.iacr.org/archive/ches2005/006.pdf)
22*
23* See also
24*
25* https://eprint.iacr.org/2013/882.pdf
26* https://www.microsoft.com/en-us/research/wp-content/uploads/1996/01/j37acmon.pdf
27*/
29 word r[], const word z[], size_t z_size, const word p[], size_t p_size, word p_dash, word ws[]) {
30 BOTAN_ARG_CHECK(z_size >= 2 * p_size && p_size > 0, "Invalid sizes for bigint_monty_redc_generic");
31
32 word3<word> accum;
33
34 accum.add(z[0]);
35
36 ws[0] = accum.monty_step(p[0], p_dash);
37
38 for(size_t i = 1; i != p_size; ++i) {
39 for(size_t j = 0; j < i; ++j) {
40 accum.mul(ws[j], p[i - j]);
41 }
42
43 accum.add(z[i]);
44 ws[i] = accum.monty_step(p[0], p_dash);
45 }
46
47 for(size_t i = 0; i != p_size - 1; ++i) {
48 for(size_t j = i + 1; j != p_size; ++j) {
49 accum.mul(ws[j], p[p_size + i - j]);
50 }
51
52 accum.add(z[p_size + i]);
53 ws[i] = accum.extract();
54 }
55
56 accum.add(z[2 * p_size - 1]);
57
58 ws[p_size - 1] = accum.extract();
59 // w1 is the final part, which is not stored in the workspace
60 const word w1 = accum.extract();
61
62 /*
63 * The result might need to be reduced mod p. To avoid a timing
64 * channel, always perform the subtraction. If in the compution
65 * of x - p a borrow is required then x was already < p.
66 *
67 * x starts at ws[0] and is p_size bytes long plus a possible high
68 * digit left over in w1.
69 *
70 * x - p starts at z[0] and is also p_size bytes long
71 *
72 * If borrow was set after the subtraction, then x was already less
73 * than p and the subtraction was not needed. In that case overwrite
74 * z[0:p_size] with the original x in ws[0:p_size].
75 *
76 * We only copy out p_size in the final step because we know
77 * the Montgomery result is < P
78 */
79
80 bigint_monty_maybe_sub(p_size, r, w1, ws, p);
81}
82
83} // namespace Botan
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
constexpr void add(W x)
Definition mp_asmi.h:520
constexpr W monty_step(W p0, W p_dash)
Definition mp_asmi.h:537
constexpr W extract()
Definition mp_asmi.h:529
constexpr void mul(W x, W y)
Definition mp_asmi.h:455
BOTAN_FUZZER_API void bigint_monty_redc_generic(word r[], const word z[], size_t z_size, const word p[], size_t p_size, word p_dash, word ws[])
Definition mp_monty.cpp:28
constexpr void bigint_monty_maybe_sub(size_t N, W z[], W x0, const W x[], const W p[])
Definition mp_core.h:227
std::conditional_t< HasNative64BitRegisters, std::uint64_t, uint32_t > word
Definition types.h:119