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