/src/openssl30/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 | 51.5k | { | 
| 216 | 51.5k |     unsigned char s, d; | 
| 217 |  |  | 
| 218 | 51.5k |     s = ~((in >> 5) - 1);       /* sets all bits to MSB(in), 'in' seen as | 
| 219 |  |                                  * 6-bit value */ | 
| 220 | 51.5k |     d = (1 << 6) - in - 1; | 
| 221 | 51.5k |     d = (d & s) | (in & ~s); | 
| 222 | 51.5k |     d = (d >> 1) + (d & 1); | 
| 223 |  |  | 
| 224 | 51.5k |     *sign = s & 1; | 
| 225 | 51.5k |     *digit = d; | 
| 226 | 51.5k | } |