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