diff options
| author | tb <> | 2025-01-05 16:07:08 +0000 |
|---|---|---|
| committer | tb <> | 2025-01-05 16:07:08 +0000 |
| commit | 26c9248a10bd0d95f47397e21bc2f056e53e19c8 (patch) | |
| tree | 01052cd554006bd8d0b366164df08e22b7dd6d57 /src/lib/libcrypto/ec/ec_lib.c | |
| parent | 7d80fee84377d3dd9365558712de411fc7f8356b (diff) | |
| download | openbsd-26c9248a10bd0d95f47397e21bc2f056e53e19c8.tar.gz openbsd-26c9248a10bd0d95f47397e21bc2f056e53e19c8.tar.bz2 openbsd-26c9248a10bd0d95f47397e21bc2f056e53e19c8.zip | |
Move BIGNUMs in EC_GROUP and EC_POINT to the heap
The only way to get an EC_GROUP or an EC_POINT is by calling the relevant
_new() function and to get rid of it, something must call _free(). Thus we
can establish the invariant that every group has Weierstrass coefficients
p, a, b as well as order and cofactor hanging off it. Similarly, Every
point has allocated BIGNUMs for its Jacobian projective coordinates.
Unfortunately, a group has the generator as an optional component in
addition to seed and montgomery context/one (where optionality makes
more sense).
This is a mostly mechanical diff and only drops a few silly comments and
a couple of unnecessary NULL checks since in our part of the wrold the
word invariant has a meaning.
This should also appease Coverity who likes to throw fits at calling
BN_free() for BIGNUM on the stack (yes, this is actually a thing).
ok jsing
Diffstat (limited to 'src/lib/libcrypto/ec/ec_lib.c')
| -rw-r--r-- | src/lib/libcrypto/ec/ec_lib.c | 97 |
1 files changed, 58 insertions, 39 deletions
diff --git a/src/lib/libcrypto/ec/ec_lib.c b/src/lib/libcrypto/ec/ec_lib.c index 89d26e1177..d961ad0ee4 100644 --- a/src/lib/libcrypto/ec/ec_lib.c +++ b/src/lib/libcrypto/ec/ec_lib.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: ec_lib.c,v 1.93 2025/01/01 10:01:31 tb Exp $ */ | 1 | /* $OpenBSD: ec_lib.c,v 1.94 2025/01/05 16:07:08 tb Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Originally written by Bodo Moeller for the OpenSSL project. | 3 | * Originally written by Bodo Moeller for the OpenSSL project. |
| 4 | */ | 4 | */ |
| @@ -94,6 +94,23 @@ EC_GROUP_new(const EC_METHOD *meth) | |||
| 94 | group->asn1_flag = OPENSSL_EC_NAMED_CURVE; | 94 | group->asn1_flag = OPENSSL_EC_NAMED_CURVE; |
| 95 | group->asn1_form = POINT_CONVERSION_UNCOMPRESSED; | 95 | group->asn1_form = POINT_CONVERSION_UNCOMPRESSED; |
| 96 | 96 | ||
| 97 | if ((group->p = BN_new()) == NULL) | ||
| 98 | goto err; | ||
| 99 | if ((group->a = BN_new()) == NULL) | ||
| 100 | goto err; | ||
| 101 | if ((group->b = BN_new()) == NULL) | ||
| 102 | goto err; | ||
| 103 | |||
| 104 | if ((group->order = BN_new()) == NULL) | ||
| 105 | goto err; | ||
| 106 | if ((group->cofactor = BN_new()) == NULL) | ||
| 107 | goto err; | ||
| 108 | |||
| 109 | /* | ||
| 110 | * generator and seed are optional. mont_ctx, mont_one are only for | ||
| 111 | * curves using EC_GFp_mont_method() | ||
| 112 | */ | ||
| 113 | |||
| 97 | return group; | 114 | return group; |
| 98 | 115 | ||
| 99 | err: | 116 | err: |
| @@ -109,16 +126,16 @@ EC_GROUP_free(EC_GROUP *group) | |||
| 109 | if (group == NULL) | 126 | if (group == NULL) |
| 110 | return; | 127 | return; |
| 111 | 128 | ||
| 112 | BN_free(&group->p); | 129 | BN_free(group->p); |
| 113 | BN_free(&group->a); | 130 | BN_free(group->a); |
| 114 | BN_free(&group->b); | 131 | BN_free(group->b); |
| 115 | 132 | ||
| 116 | BN_MONT_CTX_free(group->mont_ctx); | 133 | BN_MONT_CTX_free(group->mont_ctx); |
| 117 | BN_free(group->mont_one); | 134 | BN_free(group->mont_one); |
| 118 | 135 | ||
| 119 | EC_POINT_free(group->generator); | 136 | EC_POINT_free(group->generator); |
| 120 | BN_free(&group->order); | 137 | BN_free(group->order); |
| 121 | BN_free(&group->cofactor); | 138 | BN_free(group->cofactor); |
| 122 | 139 | ||
| 123 | freezero(group->seed, group->seed_len); | 140 | freezero(group->seed, group->seed_len); |
| 124 | freezero(group, sizeof *group); | 141 | freezero(group, sizeof *group); |
| @@ -152,14 +169,14 @@ EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) | |||
| 152 | EC_POINT_free(dest->generator); | 169 | EC_POINT_free(dest->generator); |
| 153 | dest->generator = NULL; | 170 | dest->generator = NULL; |
| 154 | if (src->generator != NULL) { | 171 | if (src->generator != NULL) { |
| 155 | if (!EC_GROUP_set_generator(dest, src->generator, &src->order, | 172 | if (!EC_GROUP_set_generator(dest, src->generator, src->order, |
| 156 | &src->cofactor)) | 173 | src->cofactor)) |
| 157 | return 0; | 174 | return 0; |
| 158 | } else { | 175 | } else { |
| 159 | /* XXX - should do the sanity checks as in set_generator() */ | 176 | /* XXX - should do the sanity checks as in set_generator() */ |
| 160 | if (!bn_copy(&dest->order, &src->order)) | 177 | if (!bn_copy(dest->order, src->order)) |
| 161 | return 0; | 178 | return 0; |
| 162 | if (!bn_copy(&dest->cofactor, &src->cofactor)) | 179 | if (!bn_copy(dest->cofactor, src->cofactor)) |
| 163 | return 0; | 180 | return 0; |
| 164 | } | 181 | } |
| 165 | 182 | ||
| @@ -241,7 +258,7 @@ ec_set_cofactor(EC_GROUP *group, const BIGNUM *in_cofactor) | |||
| 241 | BIGNUM *cofactor; | 258 | BIGNUM *cofactor; |
| 242 | int ret = 0; | 259 | int ret = 0; |
| 243 | 260 | ||
| 244 | BN_zero(&group->cofactor); | 261 | BN_zero(group->cofactor); |
| 245 | 262 | ||
| 246 | if ((ctx = BN_CTX_new()) == NULL) | 263 | if ((ctx = BN_CTX_new()) == NULL) |
| 247 | goto err; | 264 | goto err; |
| @@ -269,7 +286,7 @@ ec_set_cofactor(EC_GROUP *group, const BIGNUM *in_cofactor) | |||
| 269 | * If the cofactor is too large, we cannot guess it and default to zero. | 286 | * If the cofactor is too large, we cannot guess it and default to zero. |
| 270 | * The RHS of below is a strict overestimate of log(4 * sqrt(p)). | 287 | * The RHS of below is a strict overestimate of log(4 * sqrt(p)). |
| 271 | */ | 288 | */ |
| 272 | if (BN_num_bits(&group->order) <= (BN_num_bits(&group->p) + 1) / 2 + 3) | 289 | if (BN_num_bits(group->order) <= (BN_num_bits(group->p) + 1) / 2 + 3) |
| 273 | goto done; | 290 | goto done; |
| 274 | 291 | ||
| 275 | /* | 292 | /* |
| @@ -278,26 +295,26 @@ ec_set_cofactor(EC_GROUP *group, const BIGNUM *in_cofactor) | |||
| 278 | */ | 295 | */ |
| 279 | 296 | ||
| 280 | /* h = n/2 */ | 297 | /* h = n/2 */ |
| 281 | if (!BN_rshift1(cofactor, &group->order)) | 298 | if (!BN_rshift1(cofactor, group->order)) |
| 282 | goto err; | 299 | goto err; |
| 283 | /* h = 1 + n/2 */ | 300 | /* h = 1 + n/2 */ |
| 284 | if (!BN_add_word(cofactor, 1)) | 301 | if (!BN_add_word(cofactor, 1)) |
| 285 | goto err; | 302 | goto err; |
| 286 | /* h = p + 1 + n/2 */ | 303 | /* h = p + 1 + n/2 */ |
| 287 | if (!BN_add(cofactor, cofactor, &group->p)) | 304 | if (!BN_add(cofactor, cofactor, group->p)) |
| 288 | goto err; | 305 | goto err; |
| 289 | /* h = (p + 1 + n/2) / n */ | 306 | /* h = (p + 1 + n/2) / n */ |
| 290 | if (!BN_div_ct(cofactor, NULL, cofactor, &group->order, ctx)) | 307 | if (!BN_div_ct(cofactor, NULL, cofactor, group->order, ctx)) |
| 291 | goto err; | 308 | goto err; |
| 292 | 309 | ||
| 293 | done: | 310 | done: |
| 294 | /* Use Hasse's theorem to bound the cofactor. */ | 311 | /* Use Hasse's theorem to bound the cofactor. */ |
| 295 | if (BN_num_bits(cofactor) > BN_num_bits(&group->p) + 1) { | 312 | if (BN_num_bits(cofactor) > BN_num_bits(group->p) + 1) { |
| 296 | ECerror(EC_R_INVALID_GROUP_ORDER); | 313 | ECerror(EC_R_INVALID_GROUP_ORDER); |
| 297 | goto err; | 314 | goto err; |
| 298 | } | 315 | } |
| 299 | 316 | ||
| 300 | if (!bn_copy(&group->cofactor, cofactor)) | 317 | if (!bn_copy(group->cofactor, cofactor)) |
| 301 | goto err; | 318 | goto err; |
| 302 | 319 | ||
| 303 | ret = 1; | 320 | ret = 1; |
| @@ -319,7 +336,7 @@ EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, | |||
| 319 | } | 336 | } |
| 320 | 337 | ||
| 321 | /* Require p >= 1. */ | 338 | /* Require p >= 1. */ |
| 322 | if (BN_is_zero(&group->p) || BN_is_negative(&group->p)) { | 339 | if (BN_is_zero(group->p) || BN_is_negative(group->p)) { |
| 323 | ECerror(EC_R_INVALID_FIELD); | 340 | ECerror(EC_R_INVALID_FIELD); |
| 324 | return 0; | 341 | return 0; |
| 325 | } | 342 | } |
| @@ -329,7 +346,7 @@ EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, | |||
| 329 | * than the field cardinality due to Hasse's theorem. | 346 | * than the field cardinality due to Hasse's theorem. |
| 330 | */ | 347 | */ |
| 331 | if (order == NULL || BN_cmp(order, BN_value_one()) <= 0 || | 348 | if (order == NULL || BN_cmp(order, BN_value_one()) <= 0 || |
| 332 | BN_num_bits(order) > BN_num_bits(&group->p) + 1) { | 349 | BN_num_bits(order) > BN_num_bits(group->p) + 1) { |
| 333 | ECerror(EC_R_INVALID_GROUP_ORDER); | 350 | ECerror(EC_R_INVALID_GROUP_ORDER); |
| 334 | return 0; | 351 | return 0; |
| 335 | } | 352 | } |
| @@ -342,7 +359,7 @@ EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, | |||
| 342 | if (!EC_POINT_copy(group->generator, generator)) | 359 | if (!EC_POINT_copy(group->generator, generator)) |
| 343 | return 0; | 360 | return 0; |
| 344 | 361 | ||
| 345 | if (!bn_copy(&group->order, order)) | 362 | if (!bn_copy(group->order, order)) |
| 346 | return 0; | 363 | return 0; |
| 347 | 364 | ||
| 348 | if (!ec_set_cofactor(group, cofactor)) | 365 | if (!ec_set_cofactor(group, cofactor)) |
| @@ -362,7 +379,7 @@ LCRYPTO_ALIAS(EC_GROUP_get0_generator); | |||
| 362 | int | 379 | int |
| 363 | EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) | 380 | EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) |
| 364 | { | 381 | { |
| 365 | if (!bn_copy(order, &group->order)) | 382 | if (!bn_copy(order, group->order)) |
| 366 | return 0; | 383 | return 0; |
| 367 | 384 | ||
| 368 | return !BN_is_zero(order); | 385 | return !BN_is_zero(order); |
| @@ -372,7 +389,7 @@ LCRYPTO_ALIAS(EC_GROUP_get_order); | |||
| 372 | const BIGNUM * | 389 | const BIGNUM * |
| 373 | EC_GROUP_get0_order(const EC_GROUP *group) | 390 | EC_GROUP_get0_order(const EC_GROUP *group) |
| 374 | { | 391 | { |
| 375 | return &group->order; | 392 | return group->order; |
| 376 | } | 393 | } |
| 377 | 394 | ||
| 378 | int | 395 | int |
| @@ -385,17 +402,17 @@ LCRYPTO_ALIAS(EC_GROUP_order_bits); | |||
| 385 | int | 402 | int |
| 386 | EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) | 403 | EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) |
| 387 | { | 404 | { |
| 388 | if (!bn_copy(cofactor, &group->cofactor)) | 405 | if (!bn_copy(cofactor, group->cofactor)) |
| 389 | return 0; | 406 | return 0; |
| 390 | 407 | ||
| 391 | return !BN_is_zero(&group->cofactor); | 408 | return !BN_is_zero(group->cofactor); |
| 392 | } | 409 | } |
| 393 | LCRYPTO_ALIAS(EC_GROUP_get_cofactor); | 410 | LCRYPTO_ALIAS(EC_GROUP_get_cofactor); |
| 394 | 411 | ||
| 395 | const BIGNUM * | 412 | const BIGNUM * |
| 396 | EC_GROUP_get0_cofactor(const EC_GROUP *group) | 413 | EC_GROUP_get0_cofactor(const EC_GROUP *group) |
| 397 | { | 414 | { |
| 398 | return &group->cofactor; | 415 | return group->cofactor; |
| 399 | } | 416 | } |
| 400 | 417 | ||
| 401 | void | 418 | void |
| @@ -784,6 +801,13 @@ EC_POINT_new(const EC_GROUP *group) | |||
| 784 | goto err; | 801 | goto err; |
| 785 | } | 802 | } |
| 786 | 803 | ||
| 804 | if ((point->X = BN_new()) == NULL) | ||
| 805 | goto err; | ||
| 806 | if ((point->Y = BN_new()) == NULL) | ||
| 807 | goto err; | ||
| 808 | if ((point->Z = BN_new()) == NULL) | ||
| 809 | goto err; | ||
| 810 | |||
| 787 | point->meth = group->meth; | 811 | point->meth = group->meth; |
| 788 | 812 | ||
| 789 | return point; | 813 | return point; |
| @@ -801,9 +825,9 @@ EC_POINT_free(EC_POINT *point) | |||
| 801 | if (point == NULL) | 825 | if (point == NULL) |
| 802 | return; | 826 | return; |
| 803 | 827 | ||
| 804 | BN_free(&point->X); | 828 | BN_free(point->X); |
| 805 | BN_free(&point->Y); | 829 | BN_free(point->Y); |
| 806 | BN_free(&point->Z); | 830 | BN_free(point->Z); |
| 807 | 831 | ||
| 808 | freezero(point, sizeof *point); | 832 | freezero(point, sizeof *point); |
| 809 | } | 833 | } |
| @@ -826,11 +850,11 @@ EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) | |||
| 826 | if (dest == src) | 850 | if (dest == src) |
| 827 | return 1; | 851 | return 1; |
| 828 | 852 | ||
| 829 | if (!bn_copy(&dest->X, &src->X)) | 853 | if (!bn_copy(dest->X, src->X)) |
| 830 | return 0; | 854 | return 0; |
| 831 | if (!bn_copy(&dest->Y, &src->Y)) | 855 | if (!bn_copy(dest->Y, src->Y)) |
| 832 | return 0; | 856 | return 0; |
| 833 | if (!bn_copy(&dest->Z, &src->Z)) | 857 | if (!bn_copy(dest->Z, src->Z)) |
| 834 | return 0; | 858 | return 0; |
| 835 | dest->Z_is_one = src->Z_is_one; | 859 | dest->Z_is_one = src->Z_is_one; |
| 836 | 860 | ||
| @@ -876,7 +900,7 @@ EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) | |||
| 876 | return 0; | 900 | return 0; |
| 877 | } | 901 | } |
| 878 | 902 | ||
| 879 | BN_zero(&point->Z); | 903 | BN_zero(point->Z); |
| 880 | point->Z_is_one = 0; | 904 | point->Z_is_one = 0; |
| 881 | 905 | ||
| 882 | return 1; | 906 | return 1; |
| @@ -1193,7 +1217,7 @@ EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) | |||
| 1193 | return 0; | 1217 | return 0; |
| 1194 | } | 1218 | } |
| 1195 | 1219 | ||
| 1196 | return BN_is_zero(&point->Z); | 1220 | return BN_is_zero(point->Z); |
| 1197 | } | 1221 | } |
| 1198 | LCRYPTO_ALIAS(EC_POINT_is_at_infinity); | 1222 | LCRYPTO_ALIAS(EC_POINT_is_at_infinity); |
| 1199 | 1223 | ||
| @@ -1440,10 +1464,5 @@ LCRYPTO_ALIAS(EC_GROUP_have_precompute_mult); | |||
| 1440 | int | 1464 | int |
| 1441 | ec_group_simple_order_bits(const EC_GROUP *group) | 1465 | ec_group_simple_order_bits(const EC_GROUP *group) |
| 1442 | { | 1466 | { |
| 1443 | /* XXX change group->order to a pointer? */ | 1467 | return BN_num_bits(group->order); |
| 1444 | #if 0 | ||
| 1445 | if (group->order == NULL) | ||
| 1446 | return 0; | ||
| 1447 | #endif | ||
| 1448 | return BN_num_bits(&group->order); | ||
| 1449 | } | 1468 | } |
