1238384Sjkim/* crypto/ec/ecp_nistputil.c */
2238384Sjkim/*
3238384Sjkim * Written by Bodo Moeller for the OpenSSL project.
4238384Sjkim */
5238384Sjkim/* Copyright 2011 Google Inc.
6238384Sjkim *
7238384Sjkim * Licensed under the Apache License, Version 2.0 (the "License");
8238384Sjkim *
9238384Sjkim * you may not use this file except in compliance with the License.
10238384Sjkim * You may obtain a copy of the License at
11238384Sjkim *
12238384Sjkim *     http://www.apache.org/licenses/LICENSE-2.0
13238384Sjkim *
14238384Sjkim *  Unless required by applicable law or agreed to in writing, software
15238384Sjkim *  distributed under the License is distributed on an "AS IS" BASIS,
16238384Sjkim *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17238384Sjkim *  See the License for the specific language governing permissions and
18238384Sjkim *  limitations under the License.
19238384Sjkim */
20238384Sjkim
21238384Sjkim#include <openssl/opensslconf.h>
22238384Sjkim#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
23238384Sjkim
24238384Sjkim/*
25238384Sjkim * Common utility functions for ecp_nistp224.c, ecp_nistp256.c, ecp_nistp521.c.
26238384Sjkim */
27238384Sjkim
28280304Sjkim# include <stddef.h>
29280304Sjkim# include "ec_lcl.h"
30238384Sjkim
31280304Sjkim/*
32280304Sjkim * Convert an array of points into affine coordinates. (If the point at
33280304Sjkim * infinity is found (Z = 0), it remains unchanged.) This function is
34280304Sjkim * essentially an equivalent to EC_POINTs_make_affine(), but works with the
35280304Sjkim * internal representation of points as used by ecp_nistp###.c rather than
36280304Sjkim * with (BIGNUM-based) EC_POINT data structures. point_array is the
37280304Sjkim * input/output buffer ('num' points in projective form, i.e. three
38280304Sjkim * coordinates each), based on an internal representation of field elements
39280304Sjkim * of size 'felem_size'. tmp_felems needs to point to a temporary array of
40280304Sjkim * 'num'+1 field elements for storage of intermediate values.
41238384Sjkim */
42238384Sjkimvoid ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
43280304Sjkim                                              size_t felem_size,
44280304Sjkim                                              void *tmp_felems,
45280304Sjkim                                              void (*felem_one) (void *out),
46280304Sjkim                                              int (*felem_is_zero) (const void
47280304Sjkim                                                                    *in),
48280304Sjkim                                              void (*felem_assign) (void *out,
49280304Sjkim                                                                    const void
50280304Sjkim                                                                    *in),
51280304Sjkim                                              void (*felem_square) (void *out,
52280304Sjkim                                                                    const void
53280304Sjkim                                                                    *in),
54280304Sjkim                                              void (*felem_mul) (void *out,
55280304Sjkim                                                                 const void
56280304Sjkim                                                                 *in1,
57280304Sjkim                                                                 const void
58280304Sjkim                                                                 *in2),
59280304Sjkim                                              void (*felem_inv) (void *out,
60280304Sjkim                                                                 const void
61280304Sjkim                                                                 *in),
62280304Sjkim                                              void (*felem_contract) (void
63280304Sjkim                                                                      *out,
64280304Sjkim                                                                      const
65280304Sjkim                                                                      void
66280304Sjkim                                                                      *in))
67280304Sjkim{
68280304Sjkim    int i = 0;
69238384Sjkim
70280304Sjkim# define tmp_felem(I) (&((char *)tmp_felems)[(I) * felem_size])
71280304Sjkim# define X(I) (&((char *)point_array)[3*(I) * felem_size])
72280304Sjkim# define Y(I) (&((char *)point_array)[(3*(I) + 1) * felem_size])
73280304Sjkim# define Z(I) (&((char *)point_array)[(3*(I) + 2) * felem_size])
74238384Sjkim
75280304Sjkim    if (!felem_is_zero(Z(0)))
76280304Sjkim        felem_assign(tmp_felem(0), Z(0));
77280304Sjkim    else
78280304Sjkim        felem_one(tmp_felem(0));
79280304Sjkim    for (i = 1; i < (int)num; i++) {
80280304Sjkim        if (!felem_is_zero(Z(i)))
81280304Sjkim            felem_mul(tmp_felem(i), tmp_felem(i - 1), Z(i));
82280304Sjkim        else
83280304Sjkim            felem_assign(tmp_felem(i), tmp_felem(i - 1));
84280304Sjkim    }
85280304Sjkim    /*
86280304Sjkim     * Now each tmp_felem(i) is the product of Z(0) .. Z(i), skipping any
87280304Sjkim     * zero-valued factors: if Z(i) = 0, we essentially pretend that Z(i) = 1
88280304Sjkim     */
89238384Sjkim
90280304Sjkim    felem_inv(tmp_felem(num - 1), tmp_felem(num - 1));
91280304Sjkim    for (i = num - 1; i >= 0; i--) {
92280304Sjkim        if (i > 0)
93280304Sjkim            /*
94280304Sjkim             * tmp_felem(i-1) is the product of Z(0) .. Z(i-1), tmp_felem(i)
95280304Sjkim             * is the inverse of the product of Z(0) .. Z(i)
96280304Sjkim             */
97280304Sjkim            /* 1/Z(i) */
98280304Sjkim            felem_mul(tmp_felem(num), tmp_felem(i - 1), tmp_felem(i));
99280304Sjkim        else
100280304Sjkim            felem_assign(tmp_felem(num), tmp_felem(0)); /* 1/Z(0) */
101238384Sjkim
102280304Sjkim        if (!felem_is_zero(Z(i))) {
103280304Sjkim            if (i > 0)
104280304Sjkim                /*
105280304Sjkim                 * For next iteration, replace tmp_felem(i-1) by its inverse
106280304Sjkim                 */
107280304Sjkim                felem_mul(tmp_felem(i - 1), tmp_felem(i), Z(i));
108238384Sjkim
109280304Sjkim            /*
110280304Sjkim             * Convert point (X, Y, Z) into affine form (X/(Z^2), Y/(Z^3), 1)
111280304Sjkim             */
112280304Sjkim            felem_square(Z(i), tmp_felem(num)); /* 1/(Z^2) */
113280304Sjkim            felem_mul(X(i), X(i), Z(i)); /* X/(Z^2) */
114280304Sjkim            felem_mul(Z(i), Z(i), tmp_felem(num)); /* 1/(Z^3) */
115280304Sjkim            felem_mul(Y(i), Y(i), Z(i)); /* Y/(Z^3) */
116280304Sjkim            felem_contract(X(i), X(i));
117280304Sjkim            felem_contract(Y(i), Y(i));
118280304Sjkim            felem_one(Z(i));
119280304Sjkim        } else {
120280304Sjkim            if (i > 0)
121280304Sjkim                /*
122280304Sjkim                 * For next iteration, replace tmp_felem(i-1) by its inverse
123280304Sjkim                 */
124280304Sjkim                felem_assign(tmp_felem(i - 1), tmp_felem(i));
125280304Sjkim        }
126280304Sjkim    }
127280304Sjkim}
128238384Sjkim
129280304Sjkim/*-
130238384Sjkim * This function looks at 5+1 scalar bits (5 current, 1 adjacent less
131238384Sjkim * significant bit), and recodes them into a signed digit for use in fast point
132238384Sjkim * multiplication: the use of signed rather than unsigned digits means that
133238384Sjkim * fewer points need to be precomputed, given that point inversion is easy
134238384Sjkim * (a precomputed point dP makes -dP available as well).
135238384Sjkim *
136238384Sjkim * BACKGROUND:
137238384Sjkim *
138238384Sjkim * Signed digits for multiplication were introduced by Booth ("A signed binary
139238384Sjkim * multiplication technique", Quart. Journ. Mech. and Applied Math., vol. IV,
140238384Sjkim * pt. 2 (1951), pp. 236-240), in that case for multiplication of integers.
141238384Sjkim * Booth's original encoding did not generally improve the density of nonzero
142238384Sjkim * digits over the binary representation, and was merely meant to simplify the
143238384Sjkim * handling of signed factors given in two's complement; but it has since been
144238384Sjkim * shown to be the basis of various signed-digit representations that do have
145238384Sjkim * further advantages, including the wNAF, using the following general approach:
146238384Sjkim *
147238384Sjkim * (1) Given a binary representation
148238384Sjkim *
149238384Sjkim *       b_k  ...  b_2  b_1  b_0,
150238384Sjkim *
151238384Sjkim *     of a nonnegative integer (b_k in {0, 1}), rewrite it in digits 0, 1, -1
152238384Sjkim *     by using bit-wise subtraction as follows:
153238384Sjkim *
154238384Sjkim *        b_k b_(k-1)  ...  b_2  b_1  b_0
155238384Sjkim *      -     b_k      ...  b_3  b_2  b_1  b_0
156238384Sjkim *       -------------------------------------
157238384Sjkim *        s_k b_(k-1)  ...  s_3  s_2  s_1  s_0
158238384Sjkim *
159238384Sjkim *     A left-shift followed by subtraction of the original value yields a new
160238384Sjkim *     representation of the same value, using signed bits s_i = b_(i+1) - b_i.
161238384Sjkim *     This representation from Booth's paper has since appeared in the
162238384Sjkim *     literature under a variety of different names including "reversed binary
163238384Sjkim *     form", "alternating greedy expansion", "mutual opposite form", and
164238384Sjkim *     "sign-alternating {+-1}-representation".
165238384Sjkim *
166238384Sjkim *     An interesting property is that among the nonzero bits, values 1 and -1
167238384Sjkim *     strictly alternate.
168238384Sjkim *
169238384Sjkim * (2) Various window schemes can be applied to the Booth representation of
170238384Sjkim *     integers: for example, right-to-left sliding windows yield the wNAF
171238384Sjkim *     (a signed-digit encoding independently discovered by various researchers
172238384Sjkim *     in the 1990s), and left-to-right sliding windows yield a left-to-right
173238384Sjkim *     equivalent of the wNAF (independently discovered by various researchers
174238384Sjkim *     around 2004).
175238384Sjkim *
176238384Sjkim * To prevent leaking information through side channels in point multiplication,
177238384Sjkim * we need to recode the given integer into a regular pattern: sliding windows
178238384Sjkim * as in wNAFs won't do, we need their fixed-window equivalent -- which is a few
179238384Sjkim * decades older: we'll be using the so-called "modified Booth encoding" due to
180238384Sjkim * MacSorley ("High-speed arithmetic in binary computers", Proc. IRE, vol. 49
181238384Sjkim * (1961), pp. 67-91), in a radix-2^5 setting.  That is, we always combine five
182238384Sjkim * signed bits into a signed digit:
183238384Sjkim *
184238384Sjkim *       s_(4j + 4) s_(4j + 3) s_(4j + 2) s_(4j + 1) s_(4j)
185238384Sjkim *
186238384Sjkim * The sign-alternating property implies that the resulting digit values are
187238384Sjkim * integers from -16 to 16.
188238384Sjkim *
189238384Sjkim * Of course, we don't actually need to compute the signed digits s_i as an
190238384Sjkim * intermediate step (that's just a nice way to see how this scheme relates
191238384Sjkim * to the wNAF): a direct computation obtains the recoded digit from the
192238384Sjkim * six bits b_(4j + 4) ... b_(4j - 1).
193238384Sjkim *
194238384Sjkim * This function takes those five bits as an integer (0 .. 63), writing the
195238384Sjkim * recoded digit to *sign (0 for positive, 1 for negative) and *digit (absolute
196238384Sjkim * value, in the range 0 .. 8).  Note that this integer essentially provides the
197238384Sjkim * input bits "shifted to the left" by one position: for example, the input to
198238384Sjkim * compute the least significant recoded digit, given that there's no bit b_-1,
199238384Sjkim * has to be b_4 b_3 b_2 b_1 b_0 0.
200238384Sjkim *
201238384Sjkim */
202280304Sjkimvoid ec_GFp_nistp_recode_scalar_bits(unsigned char *sign,
203280304Sjkim                                     unsigned char *digit, unsigned char in)
204280304Sjkim{
205280304Sjkim    unsigned char s, d;
206238384Sjkim
207280304Sjkim    s = ~((in >> 5) - 1);       /* sets all bits to MSB(in), 'in' seen as
208280304Sjkim                                 * 6-bit value */
209280304Sjkim    d = (1 << 6) - in - 1;
210280304Sjkim    d = (d & s) | (in & ~s);
211280304Sjkim    d = (d >> 1) + (d & 1);
212238384Sjkim
213280304Sjkim    *sign = s & 1;
214280304Sjkim    *digit = d;
215280304Sjkim}
216238384Sjkim#else
217280304Sjkimstatic void *dummy = &dummy;
218238384Sjkim#endif
219