File Coverage

src/int/i15_modpow2.c
Criterion Covered Total %
statement 0 49 0.0
branch 0 26 0.0
condition n/a
subroutine n/a
pod n/a
total 0 75 0.0


line stmt bran cond sub pod time code
1             /*
2             * Copyright (c) 2017 Thomas Pornin
3             *
4             * Permission is hereby granted, free of charge, to any person obtaining
5             * a copy of this software and associated documentation files (the
6             * "Software"), to deal in the Software without restriction, including
7             * without limitation the rights to use, copy, modify, merge, publish,
8             * distribute, sublicense, and/or sell copies of the Software, and to
9             * permit persons to whom the Software is furnished to do so, subject to
10             * the following conditions:
11             *
12             * The above copyright notice and this permission notice shall be
13             * included in all copies or substantial portions of the Software.
14             *
15             * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16             * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17             * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18             * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19             * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20             * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21             * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22             * SOFTWARE.
23             */
24              
25             #include "inner.h"
26              
27             /* see inner.h */
28             uint32_t
29 0           br_i15_modpow_opt(uint16_t *x,
30             const unsigned char *e, size_t elen,
31             const uint16_t *m, uint16_t m0i, uint16_t *tmp, size_t twlen)
32             {
33             size_t mlen, mwlen;
34             uint16_t *t1, *t2, *base;
35             size_t u, v;
36             uint32_t acc;
37             int acc_len, win_len;
38              
39             /*
40             * Get modulus size.
41             */
42 0           mwlen = (m[0] + 31) >> 4;
43 0           mlen = mwlen * sizeof m[0];
44 0           mwlen += (mwlen & 1);
45 0           t1 = tmp;
46 0           t2 = tmp + mwlen;
47              
48             /*
49             * Compute possible window size, with a maximum of 5 bits.
50             * When the window has size 1 bit, we use a specific code
51             * that requires only two temporaries. Otherwise, for a
52             * window of k bits, we need 2^k+1 temporaries.
53             */
54 0 0         if (twlen < (mwlen << 1)) {
55 0           return 0;
56             }
57 0 0         for (win_len = 5; win_len > 1; win_len --) {
58 0 0         if ((((uint32_t)1 << win_len) + 1) * mwlen <= twlen) {
59 0           break;
60             }
61             }
62              
63             /*
64             * Everything is done in Montgomery representation.
65             */
66 0           br_i15_to_monty(x, m);
67              
68             /*
69             * Compute window contents. If the window has size one bit only,
70             * then t2 is set to x; otherwise, t2[0] is left untouched, and
71             * t2[k] is set to x^k (for k >= 1).
72             */
73 0 0         if (win_len == 1) {
74 0           memcpy(t2, x, mlen);
75             } else {
76 0           memcpy(t2 + mwlen, x, mlen);
77 0           base = t2 + mwlen;
78 0 0         for (u = 2; u < ((unsigned)1 << win_len); u ++) {
79 0           br_i15_montymul(base + mwlen, base, x, m, m0i);
80 0           base += mwlen;
81             }
82             }
83              
84             /*
85             * We need to set x to 1, in Montgomery representation. This can
86             * be done efficiently by setting the high word to 1, then doing
87             * one word-sized shift.
88             */
89 0           br_i15_zero(x, m[0]);
90 0           x[(m[0] + 15) >> 4] = 1;
91 0           br_i15_muladd_small(x, 0, m);
92              
93             /*
94             * We process bits from most to least significant. At each
95             * loop iteration, we have acc_len bits in acc.
96             */
97 0           acc = 0;
98 0           acc_len = 0;
99 0 0         while (acc_len > 0 || elen > 0) {
    0          
100             int i, k;
101             uint32_t bits;
102              
103             /*
104             * Get the next bits.
105             */
106 0           k = win_len;
107 0 0         if (acc_len < win_len) {
108 0 0         if (elen > 0) {
109 0           acc = (acc << 8) | *e ++;
110 0           elen --;
111 0           acc_len += 8;
112             } else {
113 0           k = acc_len;
114             }
115             }
116 0           bits = (acc >> (acc_len - k)) & (((uint32_t)1 << k) - 1);
117 0           acc_len -= k;
118              
119             /*
120             * We could get exactly k bits. Compute k squarings.
121             */
122 0 0         for (i = 0; i < k; i ++) {
123 0           br_i15_montymul(t1, x, x, m, m0i);
124 0           memcpy(x, t1, mlen);
125             }
126              
127             /*
128             * Window lookup: we want to set t2 to the window
129             * lookup value, assuming the bits are non-zero. If
130             * the window length is 1 bit only, then t2 is
131             * already set; otherwise, we do a constant-time lookup.
132             */
133 0 0         if (win_len > 1) {
134 0           br_i15_zero(t2, m[0]);
135 0           base = t2 + mwlen;
136 0 0         for (u = 1; u < ((uint32_t)1 << k); u ++) {
137             uint32_t mask;
138              
139 0           mask = -EQ(u, bits);
140 0 0         for (v = 1; v < mwlen; v ++) {
141 0           t2[v] |= mask & base[v];
142             }
143 0           base += mwlen;
144             }
145             }
146              
147             /*
148             * Multiply with the looked-up value. We keep the
149             * product only if the exponent bits are not all-zero.
150             */
151 0           br_i15_montymul(t1, x, t2, m, m0i);
152 0           CCOPY(NEQ(bits, 0), x, t1, mlen);
153             }
154              
155             /*
156             * Convert back from Montgomery representation, and exit.
157             */
158 0           br_i15_from_monty(x, m, m0i);
159 0           return 1;
160             }