diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libcrypto/ec/ecp_oct.c | 143 |
1 files changed, 86 insertions, 57 deletions
diff --git a/src/lib/libcrypto/ec/ecp_oct.c b/src/lib/libcrypto/ec/ecp_oct.c index 9646e44499..aa5a3906d1 100644 --- a/src/lib/libcrypto/ec/ecp_oct.c +++ b/src/lib/libcrypto/ec/ecp_oct.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: ecp_oct.c,v 1.23 2024/10/22 21:06:16 tb Exp $ */ | 1 | /* $OpenBSD: ecp_oct.c,v 1.24 2024/10/22 21:08:49 tb Exp $ */ |
| 2 | /* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de> | 2 | /* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de> |
| 3 | * for the OpenSSL project. | 3 | * for the OpenSSL project. |
| 4 | * Includes code written by Bodo Moeller for the OpenSSL project. | 4 | * Includes code written by Bodo Moeller for the OpenSSL project. |
| @@ -71,6 +71,8 @@ | |||
| 71 | 71 | ||
| 72 | #include "ec_local.h" | 72 | #include "ec_local.h" |
| 73 | 73 | ||
| 74 | #include "bytestring.h" | ||
| 75 | |||
| 74 | int | 76 | int |
| 75 | ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, | 77 | ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, |
| 76 | EC_POINT *point, const BIGNUM *x_, int y_bit, BN_CTX *ctx) | 78 | EC_POINT *point, const BIGNUM *x_, int y_bit, BN_CTX *ctx) |
| @@ -207,6 +209,67 @@ ec_oct_conversion_form_is_valid(uint8_t form) | |||
| 207 | return (form & EC_OCT_POINT_CONVERSION_MASK) == form; | 209 | return (form & EC_OCT_POINT_CONVERSION_MASK) == form; |
| 208 | } | 210 | } |
| 209 | 211 | ||
| 212 | /* Nonzero y-bit only makes sense with compressed or hybrid encoding. */ | ||
| 213 | static int | ||
| 214 | ec_oct_nonzero_ybit_allowed(uint8_t form) | ||
| 215 | { | ||
| 216 | return form == EC_OCT_POINT_COMPRESSED || form == EC_OCT_POINT_HYBRID; | ||
| 217 | } | ||
| 218 | |||
| 219 | static int | ||
| 220 | ec_oct_get_leading_octet_cbs(CBS *cbs, uint8_t *out_form, int *out_ybit) | ||
| 221 | { | ||
| 222 | uint8_t octet; | ||
| 223 | |||
| 224 | if (!CBS_get_u8(cbs, &octet)) { | ||
| 225 | ECerror(EC_R_BUFFER_TOO_SMALL); | ||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | *out_ybit = octet & EC_OCT_YBIT; | ||
| 230 | *out_form = octet & ~EC_OCT_YBIT; | ||
| 231 | |||
| 232 | if (!ec_oct_conversion_form_is_valid(*out_form)) { | ||
| 233 | ECerror(EC_R_INVALID_ENCODING); | ||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | |||
| 237 | if (*out_ybit != 0 && !ec_oct_nonzero_ybit_allowed(*out_form)) { | ||
| 238 | ECerror(EC_R_INVALID_ENCODING); | ||
| 239 | return 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | return 1; | ||
| 243 | } | ||
| 244 | |||
| 245 | static int | ||
| 246 | ec_oct_field_element_is_valid(const EC_GROUP *group, const BIGNUM *bn) | ||
| 247 | { | ||
| 248 | /* Ensure bn is in the range [0, field). */ | ||
| 249 | return !BN_is_negative(bn) && BN_cmp(&group->field, bn) > 0; | ||
| 250 | } | ||
| 251 | |||
| 252 | static int | ||
| 253 | ec_oct_get_field_element_cbs(CBS *cbs, const EC_GROUP *group, BIGNUM *bn) | ||
| 254 | { | ||
| 255 | CBS field_element; | ||
| 256 | |||
| 257 | if (!CBS_get_bytes(cbs, &field_element, BN_num_bytes(&group->field))) { | ||
| 258 | ECerror(EC_R_INVALID_ENCODING); | ||
| 259 | return 0; | ||
| 260 | } | ||
| 261 | if (!BN_bin2bn(CBS_data(&field_element), CBS_len(&field_element), bn)) { | ||
| 262 | ECerror(ERR_R_MALLOC_FAILURE); | ||
| 263 | return 0; | ||
| 264 | } | ||
| 265 | if (!ec_oct_field_element_is_valid(group, bn)) { | ||
| 266 | ECerror(EC_R_BIGNUM_OUT_OF_RANGE); | ||
| 267 | return 0; | ||
| 268 | } | ||
| 269 | |||
| 270 | return 1; | ||
| 271 | } | ||
| 272 | |||
| 210 | size_t | 273 | size_t |
| 211 | ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, | 274 | ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, |
| 212 | point_conversion_form_t conversion_form, unsigned char *buf, size_t len, | 275 | point_conversion_form_t conversion_form, unsigned char *buf, size_t len, |
| @@ -317,44 +380,13 @@ int | |||
| 317 | ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, | 380 | ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, |
| 318 | const unsigned char *buf, size_t len, BN_CTX *ctx) | 381 | const unsigned char *buf, size_t len, BN_CTX *ctx) |
| 319 | { | 382 | { |
| 320 | point_conversion_form_t form; | 383 | CBS cbs; |
| 321 | int y_bit; | 384 | uint8_t form; |
| 385 | int ybit; | ||
| 322 | BIGNUM *x, *y; | 386 | BIGNUM *x, *y; |
| 323 | size_t field_len, enc_len; | ||
| 324 | int ret = 0; | 387 | int ret = 0; |
| 325 | 388 | ||
| 326 | if (len == 0) { | 389 | CBS_init(&cbs, buf, len); |
| 327 | ECerror(EC_R_BUFFER_TOO_SMALL); | ||
| 328 | return 0; | ||
| 329 | } | ||
| 330 | form = buf[0]; | ||
| 331 | y_bit = form & 1; | ||
| 332 | form = form & ~1U; | ||
| 333 | if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) | ||
| 334 | && (form != POINT_CONVERSION_UNCOMPRESSED) | ||
| 335 | && (form != POINT_CONVERSION_HYBRID)) { | ||
| 336 | ECerror(EC_R_INVALID_ENCODING); | ||
| 337 | return 0; | ||
| 338 | } | ||
| 339 | if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) { | ||
| 340 | ECerror(EC_R_INVALID_ENCODING); | ||
| 341 | return 0; | ||
| 342 | } | ||
| 343 | if (form == 0) { | ||
| 344 | if (len != 1) { | ||
| 345 | ECerror(EC_R_INVALID_ENCODING); | ||
| 346 | return 0; | ||
| 347 | } | ||
| 348 | return EC_POINT_set_to_infinity(group, point); | ||
| 349 | } | ||
| 350 | field_len = BN_num_bytes(&group->field); | ||
| 351 | enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; | ||
| 352 | |||
| 353 | if (len != enc_len) { | ||
| 354 | ECerror(EC_R_INVALID_ENCODING); | ||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | BN_CTX_start(ctx); | 390 | BN_CTX_start(ctx); |
| 359 | 391 | ||
| 360 | if ((x = BN_CTX_get(ctx)) == NULL) | 392 | if ((x = BN_CTX_get(ctx)) == NULL) |
| @@ -362,40 +394,37 @@ ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, | |||
| 362 | if ((y = BN_CTX_get(ctx)) == NULL) | 394 | if ((y = BN_CTX_get(ctx)) == NULL) |
| 363 | goto err; | 395 | goto err; |
| 364 | 396 | ||
| 365 | if (!BN_bin2bn(buf + 1, field_len, x)) | 397 | if (!ec_oct_get_leading_octet_cbs(&cbs, &form, &ybit)) |
| 366 | goto err; | ||
| 367 | if (BN_ucmp(x, &group->field) >= 0) { | ||
| 368 | ECerror(EC_R_INVALID_ENCODING); | ||
| 369 | goto err; | 398 | goto err; |
| 370 | } | 399 | |
| 371 | if (form == POINT_CONVERSION_COMPRESSED) { | 400 | if (form == EC_OCT_POINT_AT_INFINITY) { |
| 372 | /* | 401 | if (!EC_POINT_set_to_infinity(group, point)) |
| 373 | * EC_POINT_set_compressed_coordinates checks that the point | 402 | goto err; |
| 374 | * is on the curve as required by X9.62. | 403 | } else if (form == EC_OCT_POINT_COMPRESSED) { |
| 375 | */ | 404 | if (!ec_oct_get_field_element_cbs(&cbs, group, x)) |
| 376 | if (!EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx)) | 405 | goto err; |
| 406 | if (!EC_POINT_set_compressed_coordinates(group, point, x, ybit, ctx)) | ||
| 377 | goto err; | 407 | goto err; |
| 378 | } else { | 408 | } else { |
| 379 | if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) | 409 | if (!ec_oct_get_field_element_cbs(&cbs, group, x)) |
| 380 | goto err; | 410 | goto err; |
| 381 | if (BN_ucmp(y, &group->field) >= 0) { | 411 | if (!ec_oct_get_field_element_cbs(&cbs, group, y)) |
| 382 | ECerror(EC_R_INVALID_ENCODING); | ||
| 383 | goto err; | 412 | goto err; |
| 384 | } | 413 | if (form == EC_OCT_POINT_HYBRID) { |
| 385 | if (form == POINT_CONVERSION_HYBRID) { | 414 | if (ybit != BN_is_odd(y)) { |
| 386 | if (y_bit != BN_is_odd(y)) { | ||
| 387 | ECerror(EC_R_INVALID_ENCODING); | 415 | ECerror(EC_R_INVALID_ENCODING); |
| 388 | goto err; | 416 | goto err; |
| 389 | } | 417 | } |
| 390 | } | 418 | } |
| 391 | /* | ||
| 392 | * EC_POINT_set_affine_coordinates checks that the point is | ||
| 393 | * on the curve as required by X9.62. | ||
| 394 | */ | ||
| 395 | if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx)) | 419 | if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx)) |
| 396 | goto err; | 420 | goto err; |
| 397 | } | 421 | } |
| 398 | 422 | ||
| 423 | if (CBS_len(&cbs) > 0) { | ||
| 424 | ECerror(EC_R_INVALID_ENCODING); | ||
| 425 | goto err; | ||
| 426 | } | ||
| 427 | |||
| 399 | ret = 1; | 428 | ret = 1; |
| 400 | 429 | ||
| 401 | err: | 430 | err: |
