/src/openssl30/crypto/ec/ec2_smpl.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. | 
| 3 |  |  * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved | 
| 4 |  |  * | 
| 5 |  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | 
| 6 |  |  * this file except in compliance with the License.  You can obtain a copy | 
| 7 |  |  * in the file LICENSE in the source distribution or at | 
| 8 |  |  * https://www.openssl.org/source/license.html | 
| 9 |  |  */ | 
| 10 |  |  | 
| 11 |  | /* | 
| 12 |  |  * ECDSA low level APIs are deprecated for public use, but still ok for | 
| 13 |  |  * internal use. | 
| 14 |  |  */ | 
| 15 |  | #include "internal/deprecated.h" | 
| 16 |  |  | 
| 17 |  | #include <openssl/err.h> | 
| 18 |  |  | 
| 19 |  | #include "crypto/bn.h" | 
| 20 |  | #include "ec_local.h" | 
| 21 |  |  | 
| 22 |  | #ifndef OPENSSL_NO_EC2M | 
| 23 |  |  | 
| 24 |  | /* | 
| 25 |  |  * Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members | 
| 26 |  |  * are handled by EC_GROUP_new. | 
| 27 |  |  */ | 
| 28 |  | int ossl_ec_GF2m_simple_group_init(EC_GROUP *group) | 
| 29 | 140k | { | 
| 30 | 140k |     group->field = BN_new(); | 
| 31 | 140k |     group->a = BN_new(); | 
| 32 | 140k |     group->b = BN_new(); | 
| 33 |  |  | 
| 34 | 140k |     if (group->field == NULL || group->a == NULL || group->b == NULL) { | 
| 35 | 0 |         BN_free(group->field); | 
| 36 | 0 |         BN_free(group->a); | 
| 37 | 0 |         BN_free(group->b); | 
| 38 | 0 |         return 0; | 
| 39 | 0 |     } | 
| 40 | 140k |     return 1; | 
| 41 | 140k | } | 
| 42 |  |  | 
| 43 |  | /* | 
| 44 |  |  * Free a GF(2^m)-based EC_GROUP structure. Note that all other members are | 
| 45 |  |  * handled by EC_GROUP_free. | 
| 46 |  |  */ | 
| 47 |  | void ossl_ec_GF2m_simple_group_finish(EC_GROUP *group) | 
| 48 | 140k | { | 
| 49 | 140k |     BN_free(group->field); | 
| 50 | 140k |     BN_free(group->a); | 
| 51 | 140k |     BN_free(group->b); | 
| 52 | 140k | } | 
| 53 |  |  | 
| 54 |  | /* | 
| 55 |  |  * Clear and free a GF(2^m)-based EC_GROUP structure. Note that all other | 
| 56 |  |  * members are handled by EC_GROUP_clear_free. | 
| 57 |  |  */ | 
| 58 |  | void ossl_ec_GF2m_simple_group_clear_finish(EC_GROUP *group) | 
| 59 | 0 | { | 
| 60 | 0 |     BN_clear_free(group->field); | 
| 61 | 0 |     BN_clear_free(group->a); | 
| 62 | 0 |     BN_clear_free(group->b); | 
| 63 | 0 |     group->poly[0] = 0; | 
| 64 | 0 |     group->poly[1] = 0; | 
| 65 | 0 |     group->poly[2] = 0; | 
| 66 | 0 |     group->poly[3] = 0; | 
| 67 | 0 |     group->poly[4] = 0; | 
| 68 | 0 |     group->poly[5] = -1; | 
| 69 | 0 | } | 
| 70 |  |  | 
| 71 |  | /* | 
| 72 |  |  * Copy a GF(2^m)-based EC_GROUP structure. Note that all other members are | 
| 73 |  |  * handled by EC_GROUP_copy. | 
| 74 |  |  */ | 
| 75 |  | int ossl_ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) | 
| 76 | 69.7k | { | 
| 77 | 69.7k |     if (!BN_copy(dest->field, src->field)) | 
| 78 | 0 |         return 0; | 
| 79 | 69.7k |     if (!BN_copy(dest->a, src->a)) | 
| 80 | 0 |         return 0; | 
| 81 | 69.7k |     if (!BN_copy(dest->b, src->b)) | 
| 82 | 0 |         return 0; | 
| 83 | 69.7k |     dest->poly[0] = src->poly[0]; | 
| 84 | 69.7k |     dest->poly[1] = src->poly[1]; | 
| 85 | 69.7k |     dest->poly[2] = src->poly[2]; | 
| 86 | 69.7k |     dest->poly[3] = src->poly[3]; | 
| 87 | 69.7k |     dest->poly[4] = src->poly[4]; | 
| 88 | 69.7k |     dest->poly[5] = src->poly[5]; | 
| 89 | 69.7k |     if (bn_wexpand(dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == | 
| 90 | 69.7k |         NULL) | 
| 91 | 0 |         return 0; | 
| 92 | 69.7k |     if (bn_wexpand(dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == | 
| 93 | 69.7k |         NULL) | 
| 94 | 0 |         return 0; | 
| 95 | 69.7k |     bn_set_all_zero(dest->a); | 
| 96 | 69.7k |     bn_set_all_zero(dest->b); | 
| 97 | 69.7k |     return 1; | 
| 98 | 69.7k | } | 
| 99 |  |  | 
| 100 |  | /* Set the curve parameters of an EC_GROUP structure. */ | 
| 101 |  | int ossl_ec_GF2m_simple_group_set_curve(EC_GROUP *group, | 
| 102 |  |                                         const BIGNUM *p, const BIGNUM *a, | 
| 103 |  |                                         const BIGNUM *b, BN_CTX *ctx) | 
| 104 | 70.9k | { | 
| 105 | 70.9k |     int ret = 0, i; | 
| 106 |  |  | 
| 107 |  |     /* group->field */ | 
| 108 | 70.9k |     if (!BN_copy(group->field, p)) | 
| 109 | 0 |         goto err; | 
| 110 | 70.9k |     i = BN_GF2m_poly2arr(group->field, group->poly, 6) - 1; | 
| 111 | 70.9k |     if ((i != 5) && (i != 3)) { | 
| 112 | 0 |         ERR_raise(ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD); | 
| 113 | 0 |         goto err; | 
| 114 | 0 |     } | 
| 115 |  |  | 
| 116 |  |     /* group->a */ | 
| 117 | 70.9k |     if (!BN_GF2m_mod_arr(group->a, a, group->poly)) | 
| 118 | 0 |         goto err; | 
| 119 | 70.9k |     if (bn_wexpand(group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) | 
| 120 | 70.9k |         == NULL) | 
| 121 | 0 |         goto err; | 
| 122 | 70.9k |     bn_set_all_zero(group->a); | 
| 123 |  |  | 
| 124 |  |     /* group->b */ | 
| 125 | 70.9k |     if (!BN_GF2m_mod_arr(group->b, b, group->poly)) | 
| 126 | 0 |         goto err; | 
| 127 | 70.9k |     if (bn_wexpand(group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) | 
| 128 | 70.9k |         == NULL) | 
| 129 | 0 |         goto err; | 
| 130 | 70.9k |     bn_set_all_zero(group->b); | 
| 131 |  |  | 
| 132 | 70.9k |     ret = 1; | 
| 133 | 70.9k |  err: | 
| 134 | 70.9k |     return ret; | 
| 135 | 70.9k | } | 
| 136 |  |  | 
| 137 |  | /* | 
| 138 |  |  * Get the curve parameters of an EC_GROUP structure. If p, a, or b are NULL | 
| 139 |  |  * then there values will not be set but the method will return with success. | 
| 140 |  |  */ | 
| 141 |  | int ossl_ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, | 
| 142 |  |                                         BIGNUM *a, BIGNUM *b, BN_CTX *ctx) | 
| 143 | 624 | { | 
| 144 | 624 |     int ret = 0; | 
| 145 |  |  | 
| 146 | 624 |     if (p != NULL) { | 
| 147 | 624 |         if (!BN_copy(p, group->field)) | 
| 148 | 0 |             return 0; | 
| 149 | 624 |     } | 
| 150 |  |  | 
| 151 | 624 |     if (a != NULL) { | 
| 152 | 624 |         if (!BN_copy(a, group->a)) | 
| 153 | 0 |             goto err; | 
| 154 | 624 |     } | 
| 155 |  |  | 
| 156 | 624 |     if (b != NULL) { | 
| 157 | 624 |         if (!BN_copy(b, group->b)) | 
| 158 | 0 |             goto err; | 
| 159 | 624 |     } | 
| 160 |  |  | 
| 161 | 624 |     ret = 1; | 
| 162 |  |  | 
| 163 | 624 |  err: | 
| 164 | 624 |     return ret; | 
| 165 | 624 | } | 
| 166 |  |  | 
| 167 |  | /* | 
| 168 |  |  * Gets the degree of the field.  For a curve over GF(2^m) this is the value | 
| 169 |  |  * m. | 
| 170 |  |  */ | 
| 171 |  | int ossl_ec_GF2m_simple_group_get_degree(const EC_GROUP *group) | 
| 172 | 97.5k | { | 
| 173 | 97.5k |     return BN_num_bits(group->field) - 1; | 
| 174 | 97.5k | } | 
| 175 |  |  | 
| 176 |  | /* | 
| 177 |  |  * Checks the discriminant of the curve. y^2 + x*y = x^3 + a*x^2 + b is an | 
| 178 |  |  * elliptic curve <=> b != 0 (mod p) | 
| 179 |  |  */ | 
| 180 |  | int ossl_ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, | 
| 181 |  |                                                  BN_CTX *ctx) | 
| 182 | 312 | { | 
| 183 | 312 |     int ret = 0; | 
| 184 | 312 |     BIGNUM *b; | 
| 185 | 312 | #ifndef FIPS_MODULE | 
| 186 | 312 |     BN_CTX *new_ctx = NULL; | 
| 187 |  |  | 
| 188 | 312 |     if (ctx == NULL) { | 
| 189 | 0 |         ctx = new_ctx = BN_CTX_new(); | 
| 190 | 0 |         if (ctx == NULL) { | 
| 191 | 0 |             ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); | 
| 192 | 0 |             goto err; | 
| 193 | 0 |         } | 
| 194 | 0 |     } | 
| 195 | 312 | #endif | 
| 196 | 312 |     BN_CTX_start(ctx); | 
| 197 | 312 |     b = BN_CTX_get(ctx); | 
| 198 | 312 |     if (b == NULL) | 
| 199 | 0 |         goto err; | 
| 200 |  |  | 
| 201 | 312 |     if (!BN_GF2m_mod_arr(b, group->b, group->poly)) | 
| 202 | 0 |         goto err; | 
| 203 |  |  | 
| 204 |  |     /* | 
| 205 |  |      * check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic | 
| 206 |  |      * curve <=> b != 0 (mod p) | 
| 207 |  |      */ | 
| 208 | 312 |     if (BN_is_zero(b)) | 
| 209 | 0 |         goto err; | 
| 210 |  |  | 
| 211 | 312 |     ret = 1; | 
| 212 |  |  | 
| 213 | 312 |  err: | 
| 214 | 312 |     BN_CTX_end(ctx); | 
| 215 | 312 | #ifndef FIPS_MODULE | 
| 216 | 312 |     BN_CTX_free(new_ctx); | 
| 217 | 312 | #endif | 
| 218 | 312 |     return ret; | 
| 219 | 312 | } | 
| 220 |  |  | 
| 221 |  | /* Initializes an EC_POINT. */ | 
| 222 |  | int ossl_ec_GF2m_simple_point_init(EC_POINT *point) | 
| 223 | 288k | { | 
| 224 | 288k |     point->X = BN_new(); | 
| 225 | 288k |     point->Y = BN_new(); | 
| 226 | 288k |     point->Z = BN_new(); | 
| 227 |  |  | 
| 228 | 288k |     if (point->X == NULL || point->Y == NULL || point->Z == NULL) { | 
| 229 | 0 |         BN_free(point->X); | 
| 230 | 0 |         BN_free(point->Y); | 
| 231 | 0 |         BN_free(point->Z); | 
| 232 | 0 |         return 0; | 
| 233 | 0 |     } | 
| 234 | 288k |     return 1; | 
| 235 | 288k | } | 
| 236 |  |  | 
| 237 |  | /* Frees an EC_POINT. */ | 
| 238 |  | void ossl_ec_GF2m_simple_point_finish(EC_POINT *point) | 
| 239 | 286k | { | 
| 240 | 286k |     BN_free(point->X); | 
| 241 | 286k |     BN_free(point->Y); | 
| 242 | 286k |     BN_free(point->Z); | 
| 243 | 286k | } | 
| 244 |  |  | 
| 245 |  | /* Clears and frees an EC_POINT. */ | 
| 246 |  | void ossl_ec_GF2m_simple_point_clear_finish(EC_POINT *point) | 
| 247 | 2.28k | { | 
| 248 | 2.28k |     BN_clear_free(point->X); | 
| 249 | 2.28k |     BN_clear_free(point->Y); | 
| 250 | 2.28k |     BN_clear_free(point->Z); | 
| 251 | 2.28k |     point->Z_is_one = 0; | 
| 252 | 2.28k | } | 
| 253 |  |  | 
| 254 |  | /* | 
| 255 |  |  * Copy the contents of one EC_POINT into another.  Assumes dest is | 
| 256 |  |  * initialized. | 
| 257 |  |  */ | 
| 258 |  | int ossl_ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src) | 
| 259 | 143k | { | 
| 260 | 143k |     if (!BN_copy(dest->X, src->X)) | 
| 261 | 0 |         return 0; | 
| 262 | 143k |     if (!BN_copy(dest->Y, src->Y)) | 
| 263 | 0 |         return 0; | 
| 264 | 143k |     if (!BN_copy(dest->Z, src->Z)) | 
| 265 | 0 |         return 0; | 
| 266 | 143k |     dest->Z_is_one = src->Z_is_one; | 
| 267 | 143k |     dest->curve_name = src->curve_name; | 
| 268 |  |  | 
| 269 | 143k |     return 1; | 
| 270 | 143k | } | 
| 271 |  |  | 
| 272 |  | /* | 
| 273 |  |  * Set an EC_POINT to the point at infinity. A point at infinity is | 
| 274 |  |  * represented by having Z=0. | 
| 275 |  |  */ | 
| 276 |  | int ossl_ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, | 
| 277 |  |                                               EC_POINT *point) | 
| 278 | 15.3k | { | 
| 279 | 15.3k |     point->Z_is_one = 0; | 
| 280 | 15.3k |     BN_zero(point->Z); | 
| 281 | 15.3k |     return 1; | 
| 282 | 15.3k | } | 
| 283 |  |  | 
| 284 |  | /* | 
| 285 |  |  * Set the coordinates of an EC_POINT using affine coordinates. Note that | 
| 286 |  |  * the simple implementation only uses affine coordinates. | 
| 287 |  |  */ | 
| 288 |  | int ossl_ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, | 
| 289 |  |                                                      EC_POINT *point, | 
| 290 |  |                                                      const BIGNUM *x, | 
| 291 |  |                                                      const BIGNUM *y, | 
| 292 |  |                                                      BN_CTX *ctx) | 
| 293 | 105k | { | 
| 294 | 105k |     int ret = 0; | 
| 295 | 105k |     if (x == NULL || y == NULL) { | 
| 296 | 0 |         ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); | 
| 297 | 0 |         return 0; | 
| 298 | 0 |     } | 
| 299 |  |  | 
| 300 | 105k |     if (!BN_copy(point->X, x)) | 
| 301 | 0 |         goto err; | 
| 302 | 105k |     BN_set_negative(point->X, 0); | 
| 303 | 105k |     if (!BN_copy(point->Y, y)) | 
| 304 | 0 |         goto err; | 
| 305 | 105k |     BN_set_negative(point->Y, 0); | 
| 306 | 105k |     if (!BN_copy(point->Z, BN_value_one())) | 
| 307 | 0 |         goto err; | 
| 308 | 105k |     BN_set_negative(point->Z, 0); | 
| 309 | 105k |     point->Z_is_one = 1; | 
| 310 | 105k |     ret = 1; | 
| 311 |  |  | 
| 312 | 105k |  err: | 
| 313 | 105k |     return ret; | 
| 314 | 105k | } | 
| 315 |  |  | 
| 316 |  | /* | 
| 317 |  |  * Gets the affine coordinates of an EC_POINT. Note that the simple | 
| 318 |  |  * implementation only uses affine coordinates. | 
| 319 |  |  */ | 
| 320 |  | int ossl_ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, | 
| 321 |  |                                                      const EC_POINT *point, | 
| 322 |  |                                                      BIGNUM *x, BIGNUM *y, | 
| 323 |  |                                                      BN_CTX *ctx) | 
| 324 | 1.59k | { | 
| 325 | 1.59k |     int ret = 0; | 
| 326 |  |  | 
| 327 | 1.59k |     if (EC_POINT_is_at_infinity(group, point)) { | 
| 328 | 0 |         ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY); | 
| 329 | 0 |         return 0; | 
| 330 | 0 |     } | 
| 331 |  |  | 
| 332 | 1.59k |     if (BN_cmp(point->Z, BN_value_one())) { | 
| 333 | 0 |         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); | 
| 334 | 0 |         return 0; | 
| 335 | 0 |     } | 
| 336 | 1.59k |     if (x != NULL) { | 
| 337 | 1.59k |         if (!BN_copy(x, point->X)) | 
| 338 | 0 |             goto err; | 
| 339 | 1.59k |         BN_set_negative(x, 0); | 
| 340 | 1.59k |     } | 
| 341 | 1.59k |     if (y != NULL) { | 
| 342 | 1.54k |         if (!BN_copy(y, point->Y)) | 
| 343 | 0 |             goto err; | 
| 344 | 1.54k |         BN_set_negative(y, 0); | 
| 345 | 1.54k |     } | 
| 346 | 1.59k |     ret = 1; | 
| 347 |  |  | 
| 348 | 1.59k |  err: | 
| 349 | 1.59k |     return ret; | 
| 350 | 1.59k | } | 
| 351 |  |  | 
| 352 |  | /* | 
| 353 |  |  * Computes a + b and stores the result in r.  r could be a or b, a could be | 
| 354 |  |  * b. Uses algorithm A.10.2 of IEEE P1363. | 
| 355 |  |  */ | 
| 356 |  | int ossl_ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, | 
| 357 |  |                             const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) | 
| 358 | 55 | { | 
| 359 | 55 |     BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t; | 
| 360 | 55 |     int ret = 0; | 
| 361 | 55 | #ifndef FIPS_MODULE | 
| 362 | 55 |     BN_CTX *new_ctx = NULL; | 
| 363 | 55 | #endif | 
| 364 |  |  | 
| 365 | 55 |     if (EC_POINT_is_at_infinity(group, a)) { | 
| 366 | 0 |         if (!EC_POINT_copy(r, b)) | 
| 367 | 0 |             return 0; | 
| 368 | 0 |         return 1; | 
| 369 | 0 |     } | 
| 370 |  |  | 
| 371 | 55 |     if (EC_POINT_is_at_infinity(group, b)) { | 
| 372 | 0 |         if (!EC_POINT_copy(r, a)) | 
| 373 | 0 |             return 0; | 
| 374 | 0 |         return 1; | 
| 375 | 0 |     } | 
| 376 |  |  | 
| 377 | 55 | #ifndef FIPS_MODULE | 
| 378 | 55 |     if (ctx == NULL) { | 
| 379 | 0 |         ctx = new_ctx = BN_CTX_new(); | 
| 380 | 0 |         if (ctx == NULL) | 
| 381 | 0 |             return 0; | 
| 382 | 0 |     } | 
| 383 | 55 | #endif | 
| 384 |  |  | 
| 385 | 55 |     BN_CTX_start(ctx); | 
| 386 | 55 |     x0 = BN_CTX_get(ctx); | 
| 387 | 55 |     y0 = BN_CTX_get(ctx); | 
| 388 | 55 |     x1 = BN_CTX_get(ctx); | 
| 389 | 55 |     y1 = BN_CTX_get(ctx); | 
| 390 | 55 |     x2 = BN_CTX_get(ctx); | 
| 391 | 55 |     y2 = BN_CTX_get(ctx); | 
| 392 | 55 |     s = BN_CTX_get(ctx); | 
| 393 | 55 |     t = BN_CTX_get(ctx); | 
| 394 | 55 |     if (t == NULL) | 
| 395 | 0 |         goto err; | 
| 396 |  |  | 
| 397 | 55 |     if (a->Z_is_one) { | 
| 398 | 55 |         if (!BN_copy(x0, a->X)) | 
| 399 | 0 |             goto err; | 
| 400 | 55 |         if (!BN_copy(y0, a->Y)) | 
| 401 | 0 |             goto err; | 
| 402 | 55 |     } else { | 
| 403 | 0 |         if (!EC_POINT_get_affine_coordinates(group, a, x0, y0, ctx)) | 
| 404 | 0 |             goto err; | 
| 405 | 0 |     } | 
| 406 | 55 |     if (b->Z_is_one) { | 
| 407 | 55 |         if (!BN_copy(x1, b->X)) | 
| 408 | 0 |             goto err; | 
| 409 | 55 |         if (!BN_copy(y1, b->Y)) | 
| 410 | 0 |             goto err; | 
| 411 | 55 |     } else { | 
| 412 | 0 |         if (!EC_POINT_get_affine_coordinates(group, b, x1, y1, ctx)) | 
| 413 | 0 |             goto err; | 
| 414 | 0 |     } | 
| 415 |  |  | 
| 416 | 55 |     if (BN_GF2m_cmp(x0, x1)) { | 
| 417 | 55 |         if (!BN_GF2m_add(t, x0, x1)) | 
| 418 | 0 |             goto err; | 
| 419 | 55 |         if (!BN_GF2m_add(s, y0, y1)) | 
| 420 | 0 |             goto err; | 
| 421 | 55 |         if (!group->meth->field_div(group, s, s, t, ctx)) | 
| 422 | 0 |             goto err; | 
| 423 | 55 |         if (!group->meth->field_sqr(group, x2, s, ctx)) | 
| 424 | 0 |             goto err; | 
| 425 | 55 |         if (!BN_GF2m_add(x2, x2, group->a)) | 
| 426 | 0 |             goto err; | 
| 427 | 55 |         if (!BN_GF2m_add(x2, x2, s)) | 
| 428 | 0 |             goto err; | 
| 429 | 55 |         if (!BN_GF2m_add(x2, x2, t)) | 
| 430 | 0 |             goto err; | 
| 431 | 55 |     } else { | 
| 432 | 0 |         if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) { | 
| 433 | 0 |             if (!EC_POINT_set_to_infinity(group, r)) | 
| 434 | 0 |                 goto err; | 
| 435 | 0 |             ret = 1; | 
| 436 | 0 |             goto err; | 
| 437 | 0 |         } | 
| 438 | 0 |         if (!group->meth->field_div(group, s, y1, x1, ctx)) | 
| 439 | 0 |             goto err; | 
| 440 | 0 |         if (!BN_GF2m_add(s, s, x1)) | 
| 441 | 0 |             goto err; | 
| 442 |  |  | 
| 443 | 0 |         if (!group->meth->field_sqr(group, x2, s, ctx)) | 
| 444 | 0 |             goto err; | 
| 445 | 0 |         if (!BN_GF2m_add(x2, x2, s)) | 
| 446 | 0 |             goto err; | 
| 447 | 0 |         if (!BN_GF2m_add(x2, x2, group->a)) | 
| 448 | 0 |             goto err; | 
| 449 | 0 |     } | 
| 450 |  |  | 
| 451 | 55 |     if (!BN_GF2m_add(y2, x1, x2)) | 
| 452 | 0 |         goto err; | 
| 453 | 55 |     if (!group->meth->field_mul(group, y2, y2, s, ctx)) | 
| 454 | 0 |         goto err; | 
| 455 | 55 |     if (!BN_GF2m_add(y2, y2, x2)) | 
| 456 | 0 |         goto err; | 
| 457 | 55 |     if (!BN_GF2m_add(y2, y2, y1)) | 
| 458 | 0 |         goto err; | 
| 459 |  |  | 
| 460 | 55 |     if (!EC_POINT_set_affine_coordinates(group, r, x2, y2, ctx)) | 
| 461 | 0 |         goto err; | 
| 462 |  |  | 
| 463 | 55 |     ret = 1; | 
| 464 |  |  | 
| 465 | 55 |  err: | 
| 466 | 55 |     BN_CTX_end(ctx); | 
| 467 | 55 | #ifndef FIPS_MODULE | 
| 468 | 55 |     BN_CTX_free(new_ctx); | 
| 469 | 55 | #endif | 
| 470 | 55 |     return ret; | 
| 471 | 55 | } | 
| 472 |  |  | 
| 473 |  | /* | 
| 474 |  |  * Computes 2 * a and stores the result in r.  r could be a. Uses algorithm | 
| 475 |  |  * A.10.2 of IEEE P1363. | 
| 476 |  |  */ | 
| 477 |  | int ossl_ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, | 
| 478 |  |                             const EC_POINT *a, BN_CTX *ctx) | 
| 479 | 0 | { | 
| 480 | 0 |     return ossl_ec_GF2m_simple_add(group, r, a, a, ctx); | 
| 481 | 0 | } | 
| 482 |  |  | 
| 483 |  | int ossl_ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, | 
| 484 |  |                                BN_CTX *ctx) | 
| 485 | 14 | { | 
| 486 | 14 |     if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y)) | 
| 487 |  |         /* point is its own inverse */ | 
| 488 | 2 |         return 1; | 
| 489 |  |  | 
| 490 | 12 |     if (group->meth->make_affine == NULL | 
| 491 | 12 |         || !group->meth->make_affine(group, point, ctx)) | 
| 492 | 0 |         return 0; | 
| 493 | 12 |     return BN_GF2m_add(point->Y, point->X, point->Y); | 
| 494 | 12 | } | 
| 495 |  |  | 
| 496 |  | /* Indicates whether the given point is the point at infinity. */ | 
| 497 |  | int ossl_ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, | 
| 498 |  |                                        const EC_POINT *point) | 
| 499 | 115k | { | 
| 500 | 115k |     return BN_is_zero(point->Z); | 
| 501 | 115k | } | 
| 502 |  |  | 
| 503 |  | /*- | 
| 504 |  |  * Determines whether the given EC_POINT is an actual point on the curve defined | 
| 505 |  |  * in the EC_GROUP.  A point is valid if it satisfies the Weierstrass equation: | 
| 506 |  |  *      y^2 + x*y = x^3 + a*x^2 + b. | 
| 507 |  |  */ | 
| 508 |  | int ossl_ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, | 
| 509 |  |                                     BN_CTX *ctx) | 
| 510 | 106k | { | 
| 511 | 106k |     int ret = -1; | 
| 512 | 106k |     BIGNUM *lh, *y2; | 
| 513 | 106k |     int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, | 
| 514 | 106k |                       const BIGNUM *, BN_CTX *); | 
| 515 | 106k |     int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); | 
| 516 | 106k | #ifndef FIPS_MODULE | 
| 517 | 106k |     BN_CTX *new_ctx = NULL; | 
| 518 | 106k | #endif | 
| 519 |  |  | 
| 520 | 106k |     if (EC_POINT_is_at_infinity(group, point)) | 
| 521 | 0 |         return 1; | 
| 522 |  |  | 
| 523 | 106k |     field_mul = group->meth->field_mul; | 
| 524 | 106k |     field_sqr = group->meth->field_sqr; | 
| 525 |  |  | 
| 526 |  |     /* only support affine coordinates */ | 
| 527 | 106k |     if (!point->Z_is_one) | 
| 528 | 0 |         return -1; | 
| 529 |  |  | 
| 530 | 106k | #ifndef FIPS_MODULE | 
| 531 | 106k |     if (ctx == NULL) { | 
| 532 | 0 |         ctx = new_ctx = BN_CTX_new(); | 
| 533 | 0 |         if (ctx == NULL) | 
| 534 | 0 |             return -1; | 
| 535 | 0 |     } | 
| 536 | 106k | #endif | 
| 537 |  |  | 
| 538 | 106k |     BN_CTX_start(ctx); | 
| 539 | 106k |     y2 = BN_CTX_get(ctx); | 
| 540 | 106k |     lh = BN_CTX_get(ctx); | 
| 541 | 106k |     if (lh == NULL) | 
| 542 | 0 |         goto err; | 
| 543 |  |  | 
| 544 |  |     /*- | 
| 545 |  |      * We have a curve defined by a Weierstrass equation | 
| 546 |  |      *      y^2 + x*y = x^3 + a*x^2 + b. | 
| 547 |  |      *  <=> x^3 + a*x^2 + x*y + b + y^2 = 0 | 
| 548 |  |      *  <=> ((x + a) * x + y ) * x + b + y^2 = 0 | 
| 549 |  |      */ | 
| 550 | 106k |     if (!BN_GF2m_add(lh, point->X, group->a)) | 
| 551 | 0 |         goto err; | 
| 552 | 106k |     if (!field_mul(group, lh, lh, point->X, ctx)) | 
| 553 | 0 |         goto err; | 
| 554 | 106k |     if (!BN_GF2m_add(lh, lh, point->Y)) | 
| 555 | 0 |         goto err; | 
| 556 | 106k |     if (!field_mul(group, lh, lh, point->X, ctx)) | 
| 557 | 0 |         goto err; | 
| 558 | 106k |     if (!BN_GF2m_add(lh, lh, group->b)) | 
| 559 | 0 |         goto err; | 
| 560 | 106k |     if (!field_sqr(group, y2, point->Y, ctx)) | 
| 561 | 0 |         goto err; | 
| 562 | 106k |     if (!BN_GF2m_add(lh, lh, y2)) | 
| 563 | 0 |         goto err; | 
| 564 | 106k |     ret = BN_is_zero(lh); | 
| 565 |  |  | 
| 566 | 106k |  err: | 
| 567 | 106k |     BN_CTX_end(ctx); | 
| 568 | 106k | #ifndef FIPS_MODULE | 
| 569 | 106k |     BN_CTX_free(new_ctx); | 
| 570 | 106k | #endif | 
| 571 | 106k |     return ret; | 
| 572 | 106k | } | 
| 573 |  |  | 
| 574 |  | /*- | 
| 575 |  |  * Indicates whether two points are equal. | 
| 576 |  |  * Return values: | 
| 577 |  |  *  -1   error | 
| 578 |  |  *   0   equal (in affine coordinates) | 
| 579 |  |  *   1   not equal | 
| 580 |  |  */ | 
| 581 |  | int ossl_ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, | 
| 582 |  |                             const EC_POINT *b, BN_CTX *ctx) | 
| 583 | 726 | { | 
| 584 | 726 |     BIGNUM *aX, *aY, *bX, *bY; | 
| 585 | 726 |     int ret = -1; | 
| 586 | 726 | #ifndef FIPS_MODULE | 
| 587 | 726 |     BN_CTX *new_ctx = NULL; | 
| 588 | 726 | #endif | 
| 589 |  |  | 
| 590 | 726 |     if (EC_POINT_is_at_infinity(group, a)) { | 
| 591 | 23 |         return EC_POINT_is_at_infinity(group, b) ? 0 : 1; | 
| 592 | 23 |     } | 
| 593 |  |  | 
| 594 | 703 |     if (EC_POINT_is_at_infinity(group, b)) | 
| 595 | 0 |         return 1; | 
| 596 |  |  | 
| 597 | 703 |     if (a->Z_is_one && b->Z_is_one) { | 
| 598 | 703 |         return ((BN_cmp(a->X, b->X) == 0) && BN_cmp(a->Y, b->Y) == 0) ? 0 : 1; | 
| 599 | 703 |     } | 
| 600 |  |  | 
| 601 | 0 | #ifndef FIPS_MODULE | 
| 602 | 0 |     if (ctx == NULL) { | 
| 603 | 0 |         ctx = new_ctx = BN_CTX_new(); | 
| 604 | 0 |         if (ctx == NULL) | 
| 605 | 0 |             return -1; | 
| 606 | 0 |     } | 
| 607 | 0 | #endif | 
| 608 |  |  | 
| 609 | 0 |     BN_CTX_start(ctx); | 
| 610 | 0 |     aX = BN_CTX_get(ctx); | 
| 611 | 0 |     aY = BN_CTX_get(ctx); | 
| 612 | 0 |     bX = BN_CTX_get(ctx); | 
| 613 | 0 |     bY = BN_CTX_get(ctx); | 
| 614 | 0 |     if (bY == NULL) | 
| 615 | 0 |         goto err; | 
| 616 |  |  | 
| 617 | 0 |     if (!EC_POINT_get_affine_coordinates(group, a, aX, aY, ctx)) | 
| 618 | 0 |         goto err; | 
| 619 | 0 |     if (!EC_POINT_get_affine_coordinates(group, b, bX, bY, ctx)) | 
| 620 | 0 |         goto err; | 
| 621 | 0 |     ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1; | 
| 622 |  | 
 | 
| 623 | 0 |  err: | 
| 624 | 0 |     BN_CTX_end(ctx); | 
| 625 | 0 | #ifndef FIPS_MODULE | 
| 626 | 0 |     BN_CTX_free(new_ctx); | 
| 627 | 0 | #endif | 
| 628 | 0 |     return ret; | 
| 629 | 0 | } | 
| 630 |  |  | 
| 631 |  | /* Forces the given EC_POINT to internally use affine coordinates. */ | 
| 632 |  | int ossl_ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, | 
| 633 |  |                                     BN_CTX *ctx) | 
| 634 | 12 | { | 
| 635 | 12 |     BIGNUM *x, *y; | 
| 636 | 12 |     int ret = 0; | 
| 637 | 12 | #ifndef FIPS_MODULE | 
| 638 | 12 |     BN_CTX *new_ctx = NULL; | 
| 639 | 12 | #endif | 
| 640 |  |  | 
| 641 | 12 |     if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) | 
| 642 | 12 |         return 1; | 
| 643 |  |  | 
| 644 | 0 | #ifndef FIPS_MODULE | 
| 645 | 0 |     if (ctx == NULL) { | 
| 646 | 0 |         ctx = new_ctx = BN_CTX_new(); | 
| 647 | 0 |         if (ctx == NULL) | 
| 648 | 0 |             return 0; | 
| 649 | 0 |     } | 
| 650 | 0 | #endif | 
| 651 |  |  | 
| 652 | 0 |     BN_CTX_start(ctx); | 
| 653 | 0 |     x = BN_CTX_get(ctx); | 
| 654 | 0 |     y = BN_CTX_get(ctx); | 
| 655 | 0 |     if (y == NULL) | 
| 656 | 0 |         goto err; | 
| 657 |  |  | 
| 658 | 0 |     if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx)) | 
| 659 | 0 |         goto err; | 
| 660 | 0 |     if (!BN_copy(point->X, x)) | 
| 661 | 0 |         goto err; | 
| 662 | 0 |     if (!BN_copy(point->Y, y)) | 
| 663 | 0 |         goto err; | 
| 664 | 0 |     if (!BN_one(point->Z)) | 
| 665 | 0 |         goto err; | 
| 666 | 0 |     point->Z_is_one = 1; | 
| 667 |  | 
 | 
| 668 | 0 |     ret = 1; | 
| 669 |  | 
 | 
| 670 | 0 |  err: | 
| 671 | 0 |     BN_CTX_end(ctx); | 
| 672 | 0 | #ifndef FIPS_MODULE | 
| 673 | 0 |     BN_CTX_free(new_ctx); | 
| 674 | 0 | #endif | 
| 675 | 0 |     return ret; | 
| 676 | 0 | } | 
| 677 |  |  | 
| 678 |  | /* | 
| 679 |  |  * Forces each of the EC_POINTs in the given array to use affine coordinates. | 
| 680 |  |  */ | 
| 681 |  | int ossl_ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, | 
| 682 |  |                                            EC_POINT *points[], BN_CTX *ctx) | 
| 683 | 0 | { | 
| 684 | 0 |     size_t i; | 
| 685 |  | 
 | 
| 686 | 0 |     for (i = 0; i < num; i++) { | 
| 687 | 0 |         if (!group->meth->make_affine(group, points[i], ctx)) | 
| 688 | 0 |             return 0; | 
| 689 | 0 |     } | 
| 690 |  |  | 
| 691 | 0 |     return 1; | 
| 692 | 0 | } | 
| 693 |  |  | 
| 694 |  | /* Wrapper to simple binary polynomial field multiplication implementation. */ | 
| 695 |  | int ossl_ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, | 
| 696 |  |                                   const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) | 
| 697 | 3.45M | { | 
| 698 | 3.45M |     return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx); | 
| 699 | 3.45M | } | 
| 700 |  |  | 
| 701 |  | /* Wrapper to simple binary polynomial field squaring implementation. */ | 
| 702 |  | int ossl_ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, | 
| 703 |  |                                   const BIGNUM *a, BN_CTX *ctx) | 
| 704 | 2.81M | { | 
| 705 | 2.81M |     return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx); | 
| 706 | 2.81M | } | 
| 707 |  |  | 
| 708 |  | /* Wrapper to simple binary polynomial field division implementation. */ | 
| 709 |  | int ossl_ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, | 
| 710 |  |                                   const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) | 
| 711 | 40.9k | { | 
| 712 | 40.9k |     return BN_GF2m_mod_div(r, a, b, group->field, ctx); | 
| 713 | 40.9k | } | 
| 714 |  |  | 
| 715 |  | /*- | 
| 716 |  |  * Lopez-Dahab ladder, pre step. | 
| 717 |  |  * See e.g. "Guide to ECC" Alg 3.40. | 
| 718 |  |  * Modified to blind s and r independently. | 
| 719 |  |  * s:= p, r := 2p | 
| 720 |  |  */ | 
| 721 |  | static | 
| 722 |  | int ec_GF2m_simple_ladder_pre(const EC_GROUP *group, | 
| 723 |  |                               EC_POINT *r, EC_POINT *s, | 
| 724 |  |                               EC_POINT *p, BN_CTX *ctx) | 
| 725 | 2.54k | { | 
| 726 |  |     /* if p is not affine, something is wrong */ | 
| 727 | 2.54k |     if (p->Z_is_one == 0) | 
| 728 | 0 |         return 0; | 
| 729 |  |  | 
| 730 |  |     /* s blinding: make sure lambda (s->Z here) is not zero */ | 
| 731 | 2.54k |     do { | 
| 732 | 2.54k |         if (!BN_priv_rand_ex(s->Z, BN_num_bits(group->field) - 1, | 
| 733 | 2.54k |                              BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, ctx)) { | 
| 734 | 0 |             ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); | 
| 735 | 0 |             return 0; | 
| 736 | 0 |         } | 
| 737 | 2.54k |     } while (BN_is_zero(s->Z)); | 
| 738 |  |  | 
| 739 |  |     /* if field_encode defined convert between representations */ | 
| 740 | 2.54k |     if ((group->meth->field_encode != NULL | 
| 741 | 2.54k |          && !group->meth->field_encode(group, s->Z, s->Z, ctx)) | 
| 742 | 2.54k |         || !group->meth->field_mul(group, s->X, p->X, s->Z, ctx)) | 
| 743 | 0 |         return 0; | 
| 744 |  |  | 
| 745 |  |     /* r blinding: make sure lambda (r->Y here for storage) is not zero */ | 
| 746 | 2.54k |     do { | 
| 747 | 2.54k |         if (!BN_priv_rand_ex(r->Y, BN_num_bits(group->field) - 1, | 
| 748 | 2.54k |                              BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, ctx)) { | 
| 749 | 0 |             ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); | 
| 750 | 0 |             return 0; | 
| 751 | 0 |         } | 
| 752 | 2.54k |     } while (BN_is_zero(r->Y)); | 
| 753 |  |  | 
| 754 | 2.54k |     if ((group->meth->field_encode != NULL | 
| 755 | 2.54k |          && !group->meth->field_encode(group, r->Y, r->Y, ctx)) | 
| 756 | 2.54k |         || !group->meth->field_sqr(group, r->Z, p->X, ctx) | 
| 757 | 2.54k |         || !group->meth->field_sqr(group, r->X, r->Z, ctx) | 
| 758 | 2.54k |         || !BN_GF2m_add(r->X, r->X, group->b) | 
| 759 | 2.54k |         || !group->meth->field_mul(group, r->Z, r->Z, r->Y, ctx) | 
| 760 | 2.54k |         || !group->meth->field_mul(group, r->X, r->X, r->Y, ctx)) | 
| 761 | 0 |         return 0; | 
| 762 |  |  | 
| 763 | 2.54k |     s->Z_is_one = 0; | 
| 764 | 2.54k |     r->Z_is_one = 0; | 
| 765 |  |  | 
| 766 | 2.54k |     return 1; | 
| 767 | 2.54k | } | 
| 768 |  |  | 
| 769 |  | /*- | 
| 770 |  |  * Ladder step: differential addition-and-doubling, mixed Lopez-Dahab coords. | 
| 771 |  |  * http://www.hyperelliptic.org/EFD/g12o/auto-code/shortw/xz/ladder/mladd-2003-s.op3 | 
| 772 |  |  * s := r + s, r := 2r | 
| 773 |  |  */ | 
| 774 |  | static | 
| 775 |  | int ec_GF2m_simple_ladder_step(const EC_GROUP *group, | 
| 776 |  |                                EC_POINT *r, EC_POINT *s, | 
| 777 |  |                                EC_POINT *p, BN_CTX *ctx) | 
| 778 | 591k | { | 
| 779 | 591k |     if (!group->meth->field_mul(group, r->Y, r->Z, s->X, ctx) | 
| 780 | 591k |         || !group->meth->field_mul(group, s->X, r->X, s->Z, ctx) | 
| 781 | 591k |         || !group->meth->field_sqr(group, s->Y, r->Z, ctx) | 
| 782 | 591k |         || !group->meth->field_sqr(group, r->Z, r->X, ctx) | 
| 783 | 591k |         || !BN_GF2m_add(s->Z, r->Y, s->X) | 
| 784 | 591k |         || !group->meth->field_sqr(group, s->Z, s->Z, ctx) | 
| 785 | 591k |         || !group->meth->field_mul(group, s->X, r->Y, s->X, ctx) | 
| 786 | 591k |         || !group->meth->field_mul(group, r->Y, s->Z, p->X, ctx) | 
| 787 | 591k |         || !BN_GF2m_add(s->X, s->X, r->Y) | 
| 788 | 591k |         || !group->meth->field_sqr(group, r->Y, r->Z, ctx) | 
| 789 | 591k |         || !group->meth->field_mul(group, r->Z, r->Z, s->Y, ctx) | 
| 790 | 591k |         || !group->meth->field_sqr(group, s->Y, s->Y, ctx) | 
| 791 | 591k |         || !group->meth->field_mul(group, s->Y, s->Y, group->b, ctx) | 
| 792 | 591k |         || !BN_GF2m_add(r->X, r->Y, s->Y)) | 
| 793 | 0 |         return 0; | 
| 794 |  |  | 
| 795 | 591k |     return 1; | 
| 796 | 591k | } | 
| 797 |  |  | 
| 798 |  | /*- | 
| 799 |  |  * Recover affine (x,y) result from Lopez-Dahab r and s, affine p. | 
| 800 |  |  * See e.g. "Fast Multiplication on Elliptic Curves over GF(2**m) | 
| 801 |  |  * without Precomputation" (Lopez and Dahab, CHES 1999), | 
| 802 |  |  * Appendix Alg Mxy. | 
| 803 |  |  */ | 
| 804 |  | static | 
| 805 |  | int ec_GF2m_simple_ladder_post(const EC_GROUP *group, | 
| 806 |  |                                EC_POINT *r, EC_POINT *s, | 
| 807 |  |                                EC_POINT *p, BN_CTX *ctx) | 
| 808 | 2.54k | { | 
| 809 | 2.54k |     int ret = 0; | 
| 810 | 2.54k |     BIGNUM *t0, *t1, *t2 = NULL; | 
| 811 |  |  | 
| 812 | 2.54k |     if (BN_is_zero(r->Z)) | 
| 813 | 836 |         return EC_POINT_set_to_infinity(group, r); | 
| 814 |  |  | 
| 815 | 1.70k |     if (BN_is_zero(s->Z)) { | 
| 816 | 14 |         if (!EC_POINT_copy(r, p) | 
| 817 | 14 |             || !EC_POINT_invert(group, r, ctx)) { | 
| 818 | 0 |             ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); | 
| 819 | 0 |             return 0; | 
| 820 | 0 |         } | 
| 821 | 14 |         return 1; | 
| 822 | 14 |     } | 
| 823 |  |  | 
| 824 | 1.69k |     BN_CTX_start(ctx); | 
| 825 | 1.69k |     t0 = BN_CTX_get(ctx); | 
| 826 | 1.69k |     t1 = BN_CTX_get(ctx); | 
| 827 | 1.69k |     t2 = BN_CTX_get(ctx); | 
| 828 | 1.69k |     if (t2 == NULL) { | 
| 829 | 0 |         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); | 
| 830 | 0 |         goto err; | 
| 831 | 0 |     } | 
| 832 |  |  | 
| 833 | 1.69k |     if (!group->meth->field_mul(group, t0, r->Z, s->Z, ctx) | 
| 834 | 1.69k |         || !group->meth->field_mul(group, t1, p->X, r->Z, ctx) | 
| 835 | 1.69k |         || !BN_GF2m_add(t1, r->X, t1) | 
| 836 | 1.69k |         || !group->meth->field_mul(group, t2, p->X, s->Z, ctx) | 
| 837 | 1.69k |         || !group->meth->field_mul(group, r->Z, r->X, t2, ctx) | 
| 838 | 1.69k |         || !BN_GF2m_add(t2, t2, s->X) | 
| 839 | 1.69k |         || !group->meth->field_mul(group, t1, t1, t2, ctx) | 
| 840 | 1.69k |         || !group->meth->field_sqr(group, t2, p->X, ctx) | 
| 841 | 1.69k |         || !BN_GF2m_add(t2, p->Y, t2) | 
| 842 | 1.69k |         || !group->meth->field_mul(group, t2, t2, t0, ctx) | 
| 843 | 1.69k |         || !BN_GF2m_add(t1, t2, t1) | 
| 844 | 1.69k |         || !group->meth->field_mul(group, t2, p->X, t0, ctx) | 
| 845 | 1.69k |         || !group->meth->field_inv(group, t2, t2, ctx) | 
| 846 | 1.69k |         || !group->meth->field_mul(group, t1, t1, t2, ctx) | 
| 847 | 1.69k |         || !group->meth->field_mul(group, r->X, r->Z, t2, ctx) | 
| 848 | 1.69k |         || !BN_GF2m_add(t2, p->X, r->X) | 
| 849 | 1.69k |         || !group->meth->field_mul(group, t2, t2, t1, ctx) | 
| 850 | 1.69k |         || !BN_GF2m_add(r->Y, p->Y, t2) | 
| 851 | 1.69k |         || !BN_one(r->Z)) | 
| 852 | 0 |         goto err; | 
| 853 |  |  | 
| 854 | 1.69k |     r->Z_is_one = 1; | 
| 855 |  |  | 
| 856 |  |     /* GF(2^m) field elements should always have BIGNUM::neg = 0 */ | 
| 857 | 1.69k |     BN_set_negative(r->X, 0); | 
| 858 | 1.69k |     BN_set_negative(r->Y, 0); | 
| 859 |  |  | 
| 860 | 1.69k |     ret = 1; | 
| 861 |  |  | 
| 862 | 1.69k |  err: | 
| 863 | 1.69k |     BN_CTX_end(ctx); | 
| 864 | 1.69k |     return ret; | 
| 865 | 1.69k | } | 
| 866 |  |  | 
| 867 |  | static | 
| 868 |  | int ec_GF2m_simple_points_mul(const EC_GROUP *group, EC_POINT *r, | 
| 869 |  |                               const BIGNUM *scalar, size_t num, | 
| 870 |  |                               const EC_POINT *points[], | 
| 871 |  |                               const BIGNUM *scalars[], | 
| 872 |  |                               BN_CTX *ctx) | 
| 873 | 2.49k | { | 
| 874 | 2.49k |     int ret = 0; | 
| 875 | 2.49k |     EC_POINT *t = NULL; | 
| 876 |  |  | 
| 877 |  |     /*- | 
| 878 |  |      * We limit use of the ladder only to the following cases: | 
| 879 |  |      * - r := scalar * G | 
| 880 |  |      *   Fixed point mul: scalar != NULL && num == 0; | 
| 881 |  |      * - r := scalars[0] * points[0] | 
| 882 |  |      *   Variable point mul: scalar == NULL && num == 1; | 
| 883 |  |      * - r := scalar * G + scalars[0] * points[0] | 
| 884 |  |      *   used, e.g., in ECDSA verification: scalar != NULL && num == 1 | 
| 885 |  |      * | 
| 886 |  |      * In any other case (num > 1) we use the default wNAF implementation. | 
| 887 |  |      * | 
| 888 |  |      * We also let the default implementation handle degenerate cases like group | 
| 889 |  |      * order or cofactor set to 0. | 
| 890 |  |      */ | 
| 891 | 2.49k |     if (num > 1 || BN_is_zero(group->order) || BN_is_zero(group->cofactor)) | 
| 892 | 0 |         return ossl_ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); | 
| 893 |  |  | 
| 894 | 2.49k |     if (scalar != NULL && num == 0) | 
| 895 |  |         /* Fixed point multiplication */ | 
| 896 | 1.92k |         return ossl_ec_scalar_mul_ladder(group, r, scalar, NULL, ctx); | 
| 897 |  |  | 
| 898 | 563 |     if (scalar == NULL && num == 1) | 
| 899 |  |         /* Variable point multiplication */ | 
| 900 | 508 |         return ossl_ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx); | 
| 901 |  |  | 
| 902 |  |     /*- | 
| 903 |  |      * Double point multiplication: | 
| 904 |  |      *  r := scalar * G + scalars[0] * points[0] | 
| 905 |  |      */ | 
| 906 |  |  | 
| 907 | 55 |     if ((t = EC_POINT_new(group)) == NULL) { | 
| 908 | 0 |         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); | 
| 909 | 0 |         return 0; | 
| 910 | 0 |     } | 
| 911 |  |  | 
| 912 | 55 |     if (!ossl_ec_scalar_mul_ladder(group, t, scalar, NULL, ctx) | 
| 913 | 55 |         || !ossl_ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx) | 
| 914 | 55 |         || !EC_POINT_add(group, r, t, r, ctx)) | 
| 915 | 0 |         goto err; | 
| 916 |  |  | 
| 917 | 55 |     ret = 1; | 
| 918 |  |  | 
| 919 | 55 |  err: | 
| 920 | 55 |     EC_POINT_free(t); | 
| 921 | 55 |     return ret; | 
| 922 | 55 | } | 
| 923 |  |  | 
| 924 |  | /*- | 
| 925 |  |  * Computes the multiplicative inverse of a in GF(2^m), storing the result in r. | 
| 926 |  |  * If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error. | 
| 927 |  |  * SCA hardening is with blinding: BN_GF2m_mod_inv does that. | 
| 928 |  |  */ | 
| 929 |  | static int ec_GF2m_simple_field_inv(const EC_GROUP *group, BIGNUM *r, | 
| 930 |  |                                     const BIGNUM *a, BN_CTX *ctx) | 
| 931 | 1.69k | { | 
| 932 | 1.69k |     int ret; | 
| 933 |  |  | 
| 934 | 1.69k |     if (!(ret = BN_GF2m_mod_inv(r, a, group->field, ctx))) | 
| 935 | 1.69k |         ERR_raise(ERR_LIB_EC, EC_R_CANNOT_INVERT); | 
| 936 | 1.69k |     return ret; | 
| 937 | 1.69k | } | 
| 938 |  |  | 
| 939 |  | const EC_METHOD *EC_GF2m_simple_method(void) | 
| 940 | 94.2k | { | 
| 941 | 94.2k |     static const EC_METHOD ret = { | 
| 942 | 94.2k |         EC_FLAGS_DEFAULT_OCT, | 
| 943 | 94.2k |         NID_X9_62_characteristic_two_field, | 
| 944 | 94.2k |         ossl_ec_GF2m_simple_group_init, | 
| 945 | 94.2k |         ossl_ec_GF2m_simple_group_finish, | 
| 946 | 94.2k |         ossl_ec_GF2m_simple_group_clear_finish, | 
| 947 | 94.2k |         ossl_ec_GF2m_simple_group_copy, | 
| 948 | 94.2k |         ossl_ec_GF2m_simple_group_set_curve, | 
| 949 | 94.2k |         ossl_ec_GF2m_simple_group_get_curve, | 
| 950 | 94.2k |         ossl_ec_GF2m_simple_group_get_degree, | 
| 951 | 94.2k |         ossl_ec_group_simple_order_bits, | 
| 952 | 94.2k |         ossl_ec_GF2m_simple_group_check_discriminant, | 
| 953 | 94.2k |         ossl_ec_GF2m_simple_point_init, | 
| 954 | 94.2k |         ossl_ec_GF2m_simple_point_finish, | 
| 955 | 94.2k |         ossl_ec_GF2m_simple_point_clear_finish, | 
| 956 | 94.2k |         ossl_ec_GF2m_simple_point_copy, | 
| 957 | 94.2k |         ossl_ec_GF2m_simple_point_set_to_infinity, | 
| 958 | 94.2k |         ossl_ec_GF2m_simple_point_set_affine_coordinates, | 
| 959 | 94.2k |         ossl_ec_GF2m_simple_point_get_affine_coordinates, | 
| 960 | 94.2k |         0, /* point_set_compressed_coordinates */ | 
| 961 | 94.2k |         0, /* point2oct */ | 
| 962 | 94.2k |         0, /* oct2point */ | 
| 963 | 94.2k |         ossl_ec_GF2m_simple_add, | 
| 964 | 94.2k |         ossl_ec_GF2m_simple_dbl, | 
| 965 | 94.2k |         ossl_ec_GF2m_simple_invert, | 
| 966 | 94.2k |         ossl_ec_GF2m_simple_is_at_infinity, | 
| 967 | 94.2k |         ossl_ec_GF2m_simple_is_on_curve, | 
| 968 | 94.2k |         ossl_ec_GF2m_simple_cmp, | 
| 969 | 94.2k |         ossl_ec_GF2m_simple_make_affine, | 
| 970 | 94.2k |         ossl_ec_GF2m_simple_points_make_affine, | 
| 971 | 94.2k |         ec_GF2m_simple_points_mul, | 
| 972 | 94.2k |         0, /* precompute_mult */ | 
| 973 | 94.2k |         0, /* have_precompute_mult */ | 
| 974 | 94.2k |         ossl_ec_GF2m_simple_field_mul, | 
| 975 | 94.2k |         ossl_ec_GF2m_simple_field_sqr, | 
| 976 | 94.2k |         ossl_ec_GF2m_simple_field_div, | 
| 977 | 94.2k |         ec_GF2m_simple_field_inv, | 
| 978 | 94.2k |         0, /* field_encode */ | 
| 979 | 94.2k |         0, /* field_decode */ | 
| 980 | 94.2k |         0, /* field_set_to_one */ | 
| 981 | 94.2k |         ossl_ec_key_simple_priv2oct, | 
| 982 | 94.2k |         ossl_ec_key_simple_oct2priv, | 
| 983 | 94.2k |         0, /* set private */ | 
| 984 | 94.2k |         ossl_ec_key_simple_generate_key, | 
| 985 | 94.2k |         ossl_ec_key_simple_check_key, | 
| 986 | 94.2k |         ossl_ec_key_simple_generate_public_key, | 
| 987 | 94.2k |         0, /* keycopy */ | 
| 988 | 94.2k |         0, /* keyfinish */ | 
| 989 | 94.2k |         ossl_ecdh_simple_compute_key, | 
| 990 | 94.2k |         ossl_ecdsa_simple_sign_setup, | 
| 991 | 94.2k |         ossl_ecdsa_simple_sign_sig, | 
| 992 | 94.2k |         ossl_ecdsa_simple_verify_sig, | 
| 993 | 94.2k |         0, /* field_inverse_mod_ord */ | 
| 994 | 94.2k |         0, /* blind_coordinates */ | 
| 995 | 94.2k |         ec_GF2m_simple_ladder_pre, | 
| 996 | 94.2k |         ec_GF2m_simple_ladder_step, | 
| 997 | 94.2k |         ec_GF2m_simple_ladder_post | 
| 998 | 94.2k |     }; | 
| 999 |  |  | 
| 1000 | 94.2k |     return &ret; | 
| 1001 | 94.2k | } | 
| 1002 |  |  | 
| 1003 |  | #endif |