/src/openssl/crypto/ec/ecp_nistputil.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /*  | 
2  |  |  * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.  | 
3  |  |  *  | 
4  |  |  * Licensed under the Apache License 2.0 (the "License").  You may not use  | 
5  |  |  * this file except in compliance with the License.  You can obtain a copy  | 
6  |  |  * in the file LICENSE in the source distribution or at  | 
7  |  |  * https://www.openssl.org/source/license.html  | 
8  |  |  */  | 
9  |  |  | 
10  |  | /* Copyright 2011 Google Inc.  | 
11  |  |  *  | 
12  |  |  * Licensed under the Apache License, Version 2.0 (the "License");  | 
13  |  |  *  | 
14  |  |  * you may not use this file except in compliance with the License.  | 
15  |  |  * You may obtain a copy of the License at  | 
16  |  |  *  | 
17  |  |  *     http://www.apache.org/licenses/LICENSE-2.0  | 
18  |  |  *  | 
19  |  |  *  Unless required by applicable law or agreed to in writing, software  | 
20  |  |  *  distributed under the License is distributed on an "AS IS" BASIS,  | 
21  |  |  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | 
22  |  |  *  See the License for the specific language governing permissions and  | 
23  |  |  *  limitations under the License.  | 
24  |  |  */  | 
25  |  |  | 
26  |  | /*  | 
27  |  |  * ECDSA low level APIs are deprecated for public use, but still ok for  | 
28  |  |  * internal use.  | 
29  |  |  */  | 
30  |  | #include "internal/deprecated.h"  | 
31  |  |  | 
32  |  | #include <openssl/opensslconf.h>  | 
33  |  |  | 
34  |  | /*  | 
35  |  |  * Common utility functions for ecp_nistp224.c, ecp_nistp256.c, ecp_nistp521.c.  | 
36  |  |  */  | 
37  |  |  | 
38  |  | #include <stddef.h>  | 
39  |  | #include "ec_local.h"  | 
40  |  |  | 
41  |  | /*  | 
42  |  |  * Convert an array of points into affine coordinates. (If the point at  | 
43  |  |  * infinity is found (Z = 0), it remains unchanged.) This function is  | 
44  |  |  * essentially an equivalent to EC_POINTs_make_affine(), but works with the  | 
45  |  |  * internal representation of points as used by ecp_nistp###.c rather than  | 
46  |  |  * with (BIGNUM-based) EC_POINT data structures. point_array is the  | 
47  |  |  * input/output buffer ('num' points in projective form, i.e. three | 
48  |  |  * coordinates each), based on an internal representation of field elements  | 
49  |  |  * of size 'felem_size'. tmp_felems needs to point to a temporary array of  | 
50  |  |  * 'num'+1 field elements for storage of intermediate values.  | 
51  |  |  */  | 
52  |  | void  | 
53  |  | ossl_ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,  | 
54  |  |                                               size_t felem_size,  | 
55  |  |                                               void *tmp_felems,  | 
56  |  |                                               void (*felem_one) (void *out),  | 
57  |  |                                               int (*felem_is_zero) (const void  | 
58  |  |                                                                     *in),  | 
59  |  |                                               void (*felem_assign) (void *out,  | 
60  |  |                                                                     const void  | 
61  |  |                                                                     *in),  | 
62  |  |                                               void (*felem_square) (void *out,  | 
63  |  |                                                                     const void  | 
64  |  |                                                                     *in),  | 
65  |  |                                               void (*felem_mul) (void *out,  | 
66  |  |                                                                  const void  | 
67  |  |                                                                  *in1,  | 
68  |  |                                                                  const void  | 
69  |  |                                                                  *in2),  | 
70  |  |                                               void (*felem_inv) (void *out,  | 
71  |  |                                                                  const void  | 
72  |  |                                                                  *in),  | 
73  |  |                                               void (*felem_contract) (void  | 
74  |  |                                                                       *out,  | 
75  |  |                                                                       const  | 
76  |  |                                                                       void  | 
77  |  |                                                                       *in))  | 
78  | 0  | { | 
79  | 0  |     int i = 0;  | 
80  |  | 
  | 
81  | 0  | #define tmp_felem(I) (&((char *)tmp_felems)[(I) * felem_size])  | 
82  | 0  | #define X(I) (&((char *)point_array)[3*(I) * felem_size])  | 
83  | 0  | #define Y(I) (&((char *)point_array)[(3*(I) + 1) * felem_size])  | 
84  | 0  | #define Z(I) (&((char *)point_array)[(3*(I) + 2) * felem_size])  | 
85  |  | 
  | 
86  | 0  |     if (!felem_is_zero(Z(0)))  | 
87  | 0  |         felem_assign(tmp_felem(0), Z(0));  | 
88  | 0  |     else  | 
89  | 0  |         felem_one(tmp_felem(0));  | 
90  | 0  |     for (i = 1; i < (int)num; i++) { | 
91  | 0  |         if (!felem_is_zero(Z(i)))  | 
92  | 0  |             felem_mul(tmp_felem(i), tmp_felem(i - 1), Z(i));  | 
93  | 0  |         else  | 
94  | 0  |             felem_assign(tmp_felem(i), tmp_felem(i - 1));  | 
95  | 0  |     }  | 
96  |  |     /*  | 
97  |  |      * Now each tmp_felem(i) is the product of Z(0) .. Z(i), skipping any  | 
98  |  |      * zero-valued factors: if Z(i) = 0, we essentially pretend that Z(i) = 1  | 
99  |  |      */  | 
100  |  | 
  | 
101  | 0  |     felem_inv(tmp_felem(num - 1), tmp_felem(num - 1));  | 
102  | 0  |     for (i = num - 1; i >= 0; i--) { | 
103  | 0  |         if (i > 0)  | 
104  |  |             /*  | 
105  |  |              * tmp_felem(i-1) is the product of Z(0) .. Z(i-1), tmp_felem(i)  | 
106  |  |              * is the inverse of the product of Z(0) .. Z(i)  | 
107  |  |              */  | 
108  |  |             /* 1/Z(i) */  | 
109  | 0  |             felem_mul(tmp_felem(num), tmp_felem(i - 1), tmp_felem(i));  | 
110  | 0  |         else  | 
111  | 0  |             felem_assign(tmp_felem(num), tmp_felem(0)); /* 1/Z(0) */  | 
112  |  | 
  | 
113  | 0  |         if (!felem_is_zero(Z(i))) { | 
114  | 0  |             if (i > 0)  | 
115  |  |                 /*  | 
116  |  |                  * For next iteration, replace tmp_felem(i-1) by its inverse  | 
117  |  |                  */  | 
118  | 0  |                 felem_mul(tmp_felem(i - 1), tmp_felem(i), Z(i));  | 
119  |  |  | 
120  |  |             /*  | 
121  |  |              * Convert point (X, Y, Z) into affine form (X/(Z^2), Y/(Z^3), 1)  | 
122  |  |              */  | 
123  | 0  |             felem_square(Z(i), tmp_felem(num)); /* 1/(Z^2) */  | 
124  | 0  |             felem_mul(X(i), X(i), Z(i)); /* X/(Z^2) */  | 
125  | 0  |             felem_mul(Z(i), Z(i), tmp_felem(num)); /* 1/(Z^3) */  | 
126  | 0  |             felem_mul(Y(i), Y(i), Z(i)); /* Y/(Z^3) */  | 
127  | 0  |             felem_contract(X(i), X(i));  | 
128  | 0  |             felem_contract(Y(i), Y(i));  | 
129  | 0  |             felem_one(Z(i));  | 
130  | 0  |         } else { | 
131  | 0  |             if (i > 0)  | 
132  |  |                 /*  | 
133  |  |                  * For next iteration, replace tmp_felem(i-1) by its inverse  | 
134  |  |                  */  | 
135  | 0  |                 felem_assign(tmp_felem(i - 1), tmp_felem(i));  | 
136  | 0  |         }  | 
137  | 0  |     }  | 
138  | 0  | }  | 
139  |  |  | 
140  |  | /*-  | 
141  |  |  * This function looks at 5+1 scalar bits (5 current, 1 adjacent less  | 
142  |  |  * significant bit), and recodes them into a signed digit for use in fast point  | 
143  |  |  * multiplication: the use of signed rather than unsigned digits means that  | 
144  |  |  * fewer points need to be precomputed, given that point inversion is easy  | 
145  |  |  * (a precomputed point dP makes -dP available as well).  | 
146  |  |  *  | 
147  |  |  * BACKGROUND:  | 
148  |  |  *  | 
149  |  |  * Signed digits for multiplication were introduced by Booth ("A signed binary | 
150  |  |  * multiplication technique", Quart. Journ. Mech. and Applied Math., vol. IV,  | 
151  |  |  * pt. 2 (1951), pp. 236-240), in that case for multiplication of integers.  | 
152  |  |  * Booth's original encoding did not generally improve the density of nonzero  | 
153  |  |  * digits over the binary representation, and was merely meant to simplify the  | 
154  |  |  * handling of signed factors given in two's complement; but it has since been  | 
155  |  |  * shown to be the basis of various signed-digit representations that do have  | 
156  |  |  * further advantages, including the wNAF, using the following general approach:  | 
157  |  |  *  | 
158  |  |  * (1) Given a binary representation  | 
159  |  |  *  | 
160  |  |  *       b_k  ...  b_2  b_1  b_0,  | 
161  |  |  *  | 
162  |  |  *     of a nonnegative integer (b_k in {0, 1}), rewrite it in digits 0, 1, -1 | 
163  |  |  *     by using bit-wise subtraction as follows:  | 
164  |  |  *  | 
165  |  |  *        b_k     b_(k-1)  ...  b_2  b_1  b_0  | 
166  |  |  *      -         b_k      ...  b_3  b_2  b_1  b_0  | 
167  |  |  *       -----------------------------------------  | 
168  |  |  *        s_(k+1) s_k      ...  s_3  s_2  s_1  s_0  | 
169  |  |  *  | 
170  |  |  *     A left-shift followed by subtraction of the original value yields a new  | 
171  |  |  *     representation of the same value, using signed bits s_i = b_(i-1) - b_i.  | 
172  |  |  *     This representation from Booth's paper has since appeared in the  | 
173  |  |  *     literature under a variety of different names including "reversed binary  | 
174  |  |  *     form", "alternating greedy expansion", "mutual opposite form", and  | 
175  |  |  *     "sign-alternating {+-1}-representation". | 
176  |  |  *  | 
177  |  |  *     An interesting property is that among the nonzero bits, values 1 and -1  | 
178  |  |  *     strictly alternate.  | 
179  |  |  *  | 
180  |  |  * (2) Various window schemes can be applied to the Booth representation of  | 
181  |  |  *     integers: for example, right-to-left sliding windows yield the wNAF  | 
182  |  |  *     (a signed-digit encoding independently discovered by various researchers  | 
183  |  |  *     in the 1990s), and left-to-right sliding windows yield a left-to-right  | 
184  |  |  *     equivalent of the wNAF (independently discovered by various researchers  | 
185  |  |  *     around 2004).  | 
186  |  |  *  | 
187  |  |  * To prevent leaking information through side channels in point multiplication,  | 
188  |  |  * we need to recode the given integer into a regular pattern: sliding windows  | 
189  |  |  * as in wNAFs won't do, we need their fixed-window equivalent -- which is a few  | 
190  |  |  * decades older: we'll be using the so-called "modified Booth encoding" due to  | 
191  |  |  * MacSorley ("High-speed arithmetic in binary computers", Proc. IRE, vol. 49 | 
192  |  |  * (1961), pp. 67-91), in a radix-2^5 setting.  That is, we always combine five  | 
193  |  |  * signed bits into a signed digit:  | 
194  |  |  *  | 
195  |  |  *       s_(5j + 4) s_(5j + 3) s_(5j + 2) s_(5j + 1) s_(5j)  | 
196  |  |  *  | 
197  |  |  * The sign-alternating property implies that the resulting digit values are  | 
198  |  |  * integers from -16 to 16.  | 
199  |  |  *  | 
200  |  |  * Of course, we don't actually need to compute the signed digits s_i as an  | 
201  |  |  * intermediate step (that's just a nice way to see how this scheme relates  | 
202  |  |  * to the wNAF): a direct computation obtains the recoded digit from the  | 
203  |  |  * six bits b_(5j + 4) ... b_(5j - 1).  | 
204  |  |  *  | 
205  |  |  * This function takes those six bits as an integer (0 .. 63), writing the  | 
206  |  |  * recoded digit to *sign (0 for positive, 1 for negative) and *digit (absolute  | 
207  |  |  * value, in the range 0 .. 16).  Note that this integer essentially provides  | 
208  |  |  * the input bits "shifted to the left" by one position: for example, the input  | 
209  |  |  * to compute the least significant recoded digit, given that there's no bit  | 
210  |  |  * b_-1, has to be b_4 b_3 b_2 b_1 b_0 0.  | 
211  |  |  *  | 
212  |  |  */  | 
213  |  | void ossl_ec_GFp_nistp_recode_scalar_bits(unsigned char *sign,  | 
214  |  |                                           unsigned char *digit, unsigned char in)  | 
215  | 0  | { | 
216  | 0  |     unsigned char s, d;  | 
217  |  | 
  | 
218  | 0  |     s = ~((in >> 5) - 1);       /* sets all bits to MSB(in), 'in' seen as  | 
219  |  |                                  * 6-bit value */  | 
220  | 0  |     d = (1 << 6) - in - 1;  | 
221  | 0  |     d = (d & s) | (in & ~s);  | 
222  | 0  |     d = (d >> 1) + (d & 1);  | 
223  |  | 
  | 
224  | 0  |     *sign = s & 1;  | 
225  | 0  |     *digit = d;  | 
226  | 0  | }  |