/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ring-0.17.14/crypto/limbs/limbs.c
Line  | Count  | Source  | 
1  |  | /* Copyright 2016-2017 Brian Smith.  | 
2  |  |  *  | 
3  |  |  * Permission to use, copy, modify, and/or distribute this software for any  | 
4  |  |  * purpose with or without fee is hereby granted, provided that the above  | 
5  |  |  * copyright notice and this permission notice appear in all copies.  | 
6  |  |  *  | 
7  |  |  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES  | 
8  |  |  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF  | 
9  |  |  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY  | 
10  |  |  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES  | 
11  |  |  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION  | 
12  |  |  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN  | 
13  |  |  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */  | 
14  |  |  | 
15  |  | #include "limbs.h"  | 
16  |  |  | 
17  |  | #include "../internal.h"  | 
18  |  | #include "../fipsmodule/bn/internal.h"  | 
19  |  | #include "limbs.inl"  | 
20  |  |  | 
21  |  |  | 
22  |  | /* XXX: We assume that the conversion from |Carry| to |Limb| is constant-time,  | 
23  |  |  * but we haven't verified that assumption. TODO: Fix it so we don't need to  | 
24  |  |  * make that assumption. */  | 
25  |  |  | 
26  |  | /* Returns 0xfff..f if |a| is zero, and zero otherwise. */  | 
27  | 0  | Limb LIMB_is_zero(const Limb a) { | 
28  | 0  |   return constant_time_is_zero_w(a);  | 
29  | 0  | }  | 
30  |  |  | 
31  |  | /* Returns 0xfff..f if |a| is all zero limbs, and zero otherwise. |num_limbs|  | 
32  |  |  * may be zero. */  | 
33  | 0  | Limb LIMBS_are_zero(const Limb a[], size_t num_limbs) { | 
34  | 0  |   Limb all = 0;  | 
35  | 0  |   for (size_t i = 0; i < num_limbs; ++i) { | 
36  | 0  |     all |= a[i];  | 
37  | 0  |   }  | 
38  | 0  |   return LIMB_is_zero(all);  | 
39  | 0  | }  | 
40  |  |  | 
41  |  | /* Returns 0xffff..f if |a == b|, and zero otherwise. |num_limbs| may be zero. */  | 
42  | 0  | Limb LIMBS_equal(const Limb a[], const Limb b[], size_t num_limbs) { | 
43  | 0  |   Limb eq = CONSTTIME_TRUE_W;  | 
44  | 0  |   for (size_t i = 0; i < num_limbs; ++i) { | 
45  | 0  |     eq = constant_time_select_w(eq, constant_time_eq_w(a[i], b[i]), eq);  | 
46  | 0  |   }  | 
47  | 0  |   return eq;  | 
48  | 0  | }  | 
49  |  |  | 
50  |  | /* Returns 0xffff...f if |a| is less than |b|, and zero otherwise. */  | 
51  | 0  | Limb LIMBS_less_than(const Limb a[], const Limb b[], size_t num_limbs) { | 
52  | 0  |   debug_assert_nonsecret(num_limbs >= 1);  | 
53  |  |   /* There are lots of ways to implement this. It is implemented this way to  | 
54  |  |    * be consistent with |LIMBS_limbs_reduce_once| and other code that makes such  | 
55  |  |    * comparisons as part of doing conditional reductions. */  | 
56  | 0  |   Limb dummy;  | 
57  | 0  |   Carry borrow = limb_sub(&dummy, a[0], b[0]);  | 
58  | 0  |   for (size_t i = 1; i < num_limbs; ++i) { | 
59  | 0  |     borrow = limb_sbb(&dummy, a[i], b[i], borrow);  | 
60  | 0  |   }  | 
61  | 0  |   return constant_time_is_nonzero_w(borrow);  | 
62  | 0  | }  | 
63  |  |  | 
64  |  | /* if (r >= m) { r -= m; } */ | 
65  | 0  | void LIMBS_reduce_once(Limb r[], const Limb m[], size_t num_limbs) { | 
66  | 0  |   debug_assert_nonsecret(num_limbs >= 1);  | 
67  |  |   /* This could be done more efficiently if we had |num_limbs| of extra space  | 
68  |  |    * available, by storing |r - m| and then doing a conditional copy of either  | 
69  |  |    * |r| or |r - m|. But, in order to operate in constant space, with an eye  | 
70  |  |    * towards this function being used in RSA in the future, we do things a  | 
71  |  |    * slightly less efficient way. */  | 
72  | 0  |   Limb lt = LIMBS_less_than(r, m, num_limbs);  | 
73  | 0  |   Carry borrow =  | 
74  | 0  |       limb_sub(&r[0], r[0], constant_time_select_w(lt, 0, m[0]));  | 
75  | 0  |   for (size_t i = 1; i < num_limbs; ++i) { | 
76  |  |     /* XXX: This is probably particularly inefficient because the operations in  | 
77  |  |      * constant_time_select affect the carry flag, so there will likely be  | 
78  |  |      * loads and stores of |borrow|. */  | 
79  | 0  |     borrow =  | 
80  | 0  |         limb_sbb(&r[i], r[i], constant_time_select_w(lt, 0, m[i]), borrow);  | 
81  | 0  |   }  | 
82  | 0  |   dev_assert_secret(borrow == 0);  | 
83  | 0  | }  | 
84  |  |  | 
85  |  | void LIMBS_add_mod(Limb r[], const Limb a[], const Limb b[], const Limb m[],  | 
86  | 0  |                    size_t num_limbs) { | 
87  | 0  |   Limb overflow1 =  | 
88  | 0  |       constant_time_is_nonzero_w(limbs_add(r, a, b, num_limbs));  | 
89  | 0  |   Limb overflow2 = ~LIMBS_less_than(r, m, num_limbs);  | 
90  | 0  |   Limb overflow = overflow1 | overflow2;  | 
91  | 0  |   Carry borrow = limb_sub(&r[0], r[0], m[0] & overflow);  | 
92  | 0  |   for (size_t i = 1; i < num_limbs; ++i) { | 
93  | 0  |     borrow = limb_sbb(&r[i], r[i], m[i] & overflow, borrow);  | 
94  | 0  |   }  | 
95  | 0  | }  | 
96  |  |  | 
97  |  | void LIMBS_sub_mod(Limb r[], const Limb a[], const Limb b[], const Limb m[],  | 
98  | 0  |                    size_t num_limbs) { | 
99  | 0  |   Limb underflow =  | 
100  | 0  |       constant_time_is_nonzero_w(limbs_sub(r, a, b, num_limbs));  | 
101  | 0  |   Carry carry = limb_add(&r[0], r[0], m[0] & underflow);  | 
102  | 0  |   for (size_t i = 1; i < num_limbs; ++i) { | 
103  | 0  |     carry = limb_adc(&r[i], r[i], m[i] & underflow, carry);  | 
104  | 0  |   }  | 
105  | 0  | }  | 
106  |  |  | 
107  | 0  | void LIMBS_shl_mod(Limb r[], const Limb a[], const Limb m[], size_t num_limbs) { | 
108  | 0  |   Limb overflow1 =  | 
109  | 0  |       constant_time_is_nonzero_w(a[num_limbs - 1] & LIMB_HIGH_BIT);  | 
110  | 0  |   Limb carry = 0;  | 
111  | 0  |   for (size_t i = 0; i < num_limbs; ++i) { | 
112  | 0  |     Limb limb = a[i];  | 
113  | 0  |     Limb new_carry = limb >> (LIMB_BITS - 1);  | 
114  | 0  |     r[i] = (limb << 1) | carry;  | 
115  | 0  |     carry = new_carry;  | 
116  | 0  |   }  | 
117  | 0  |   Limb overflow2 = ~LIMBS_less_than(r, m, num_limbs);  | 
118  | 0  |   Limb overflow = overflow1 | overflow2;  | 
119  | 0  |   Carry borrow = limb_sub(&r[0], r[0], m[0] & overflow);  | 
120  | 0  |   for (size_t i = 1; i < num_limbs; ++i) { | 
121  | 0  |     borrow = limb_sbb(&r[i], r[i], m[i] & overflow, borrow);  | 
122  | 0  |   }  | 
123  | 0  | }  | 
124  |  |  | 
125  |  | int LIMBS_select_512_32(Limb r[], const Limb table[], size_t num_limbs,  | 
126  | 0  |                         crypto_word_t index) { | 
127  | 0  |   if (num_limbs % (512 / LIMB_BITS) != 0) { | 
128  | 0  |     return 0;  | 
129  | 0  |   }  | 
130  | 0  |   limbs_select(r, table, num_limbs, 32, index);  | 
131  | 0  |   return 1;  | 
132  | 0  | }  | 
133  |  |  | 
134  |  | static const Limb FIVE_BITS_MASK = 0x1f;  | 
135  |  |  | 
136  | 0  | crypto_word_t LIMBS_window5_split_window(Limb lower_limb, Limb higher_limb, size_t index_within_word) { | 
137  | 0  |   Limb high_bits = (higher_limb << (LIMB_BITS - index_within_word))  | 
138  | 0  |     & FIVE_BITS_MASK;  | 
139  |  |   // There are no bits outside the window above |index_within_word| (if there  | 
140  |  |   // were then this wouldn't be a split window), so we don't need to mask  | 
141  |  |   // |low_bits|.  | 
142  | 0  |   Limb low_bits = lower_limb >> index_within_word;  | 
143  | 0  |   return low_bits | high_bits;  | 
144  | 0  | }  | 
145  |  |  | 
146  | 0  | crypto_word_t LIMBS_window5_unsplit_window(Limb limb, size_t index_within_word) { | 
147  | 0  |   return (limb >> index_within_word) & FIVE_BITS_MASK;  | 
148  | 0  | }  | 
149  |  |  | 
150  | 0  | Limb LIMB_shr(Limb a, size_t shift) { | 
151  | 0  |   return a >> shift;  | 
152  | 0  | }  | 
153  |  |  | 
154  | 0  | Limb limbs_mul_add_limb(Limb r[], const Limb a[], Limb b, size_t num_limbs) { | 
155  | 0  |   Limb carried = 0;  | 
156  | 0  |   for (size_t i = 0; i < num_limbs; ++i) { | 
157  | 0  |     Limb lo;  | 
158  | 0  |     Limb hi;  | 
159  | 0  |     bn_umult_lohi(&lo, &hi, a[i], b);  | 
160  | 0  |     Limb tmp;  | 
161  | 0  |     Carry c = limb_add(&tmp, lo, carried);  | 
162  | 0  |     c = limb_adc(&carried, hi, 0, c);  | 
163  | 0  |     dev_assert_secret(c == 0);  | 
164  | 0  |     c = limb_add(&r[i], r[i], tmp);  | 
165  | 0  |     c = limb_adc(&carried, carried, 0, c);  | 
166  |  |     // (A * B) + C + D never carries.  | 
167  | 0  |     dev_assert_secret(c == 0);  | 
168  | 0  |   }  | 
169  | 0  |   return carried;  | 
170  | 0  | }  |