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 | {
|
---|
79 | int i = 0;
|
---|
80 |
|
---|
81 | #define tmp_felem(I) (&((char *)tmp_felems)[(I) * felem_size])
|
---|
82 | #define X(I) (&((char *)point_array)[3*(I) * felem_size])
|
---|
83 | #define Y(I) (&((char *)point_array)[(3*(I) + 1) * felem_size])
|
---|
84 | #define Z(I) (&((char *)point_array)[(3*(I) + 2) * felem_size])
|
---|
85 |
|
---|
86 | if (!felem_is_zero(Z(0)))
|
---|
87 | felem_assign(tmp_felem(0), Z(0));
|
---|
88 | else
|
---|
89 | felem_one(tmp_felem(0));
|
---|
90 | for (i = 1; i < (int)num; i++) {
|
---|
91 | if (!felem_is_zero(Z(i)))
|
---|
92 | felem_mul(tmp_felem(i), tmp_felem(i - 1), Z(i));
|
---|
93 | else
|
---|
94 | felem_assign(tmp_felem(i), tmp_felem(i - 1));
|
---|
95 | }
|
---|
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 | felem_inv(tmp_felem(num - 1), tmp_felem(num - 1));
|
---|
102 | for (i = num - 1; i >= 0; i--) {
|
---|
103 | 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 | felem_mul(tmp_felem(num), tmp_felem(i - 1), tmp_felem(i));
|
---|
110 | else
|
---|
111 | felem_assign(tmp_felem(num), tmp_felem(0)); /* 1/Z(0) */
|
---|
112 |
|
---|
113 | if (!felem_is_zero(Z(i))) {
|
---|
114 | if (i > 0)
|
---|
115 | /*
|
---|
116 | * For next iteration, replace tmp_felem(i-1) by its inverse
|
---|
117 | */
|
---|
118 | 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 | felem_square(Z(i), tmp_felem(num)); /* 1/(Z^2) */
|
---|
124 | felem_mul(X(i), X(i), Z(i)); /* X/(Z^2) */
|
---|
125 | felem_mul(Z(i), Z(i), tmp_felem(num)); /* 1/(Z^3) */
|
---|
126 | felem_mul(Y(i), Y(i), Z(i)); /* Y/(Z^3) */
|
---|
127 | felem_contract(X(i), X(i));
|
---|
128 | felem_contract(Y(i), Y(i));
|
---|
129 | felem_one(Z(i));
|
---|
130 | } else {
|
---|
131 | if (i > 0)
|
---|
132 | /*
|
---|
133 | * For next iteration, replace tmp_felem(i-1) by its inverse
|
---|
134 | */
|
---|
135 | felem_assign(tmp_felem(i - 1), tmp_felem(i));
|
---|
136 | }
|
---|
137 | }
|
---|
138 | }
|
---|
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 | {
|
---|
216 | unsigned char s, d;
|
---|
217 |
|
---|
218 | s = ~((in >> 5) - 1); /* sets all bits to MSB(in), 'in' seen as
|
---|
219 | * 6-bit value */
|
---|
220 | d = (1 << 6) - in - 1;
|
---|
221 | d = (d & s) | (in & ~s);
|
---|
222 | d = (d >> 1) + (d & 1);
|
---|
223 |
|
---|
224 | *sign = s & 1;
|
---|
225 | *digit = d;
|
---|
226 | }
|
---|