diff options
-rw-r--r-- | src/lib/libcrypto/ec/ec2_oct.c | 66 |
1 files changed, 49 insertions, 17 deletions
diff --git a/src/lib/libcrypto/ec/ec2_oct.c b/src/lib/libcrypto/ec/ec2_oct.c index 5f7f7e3c99..9cd1dddfa1 100644 --- a/src/lib/libcrypto/ec/ec2_oct.c +++ b/src/lib/libcrypto/ec/ec2_oct.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ec2_oct.c,v 1.12 2020/12/04 08:55:30 tb Exp $ */ | 1 | /* $OpenBSD: ec2_oct.c,v 1.13 2021/04/19 17:06:37 tb Exp $ */ |
2 | /* ==================================================================== | 2 | /* ==================================================================== |
3 | * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. | 3 | * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. |
4 | * | 4 | * |
@@ -280,10 +280,11 @@ ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, | |||
280 | } | 280 | } |
281 | 281 | ||
282 | 282 | ||
283 | /* Converts an octet string representation to an EC_POINT. | 283 | /* |
284 | * Converts an octet string representation to an EC_POINT. | ||
284 | * Note that the simple implementation only uses affine coordinates. | 285 | * Note that the simple implementation only uses affine coordinates. |
285 | */ | 286 | */ |
286 | int | 287 | int |
287 | ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, | 288 | ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, |
288 | const unsigned char *buf, size_t len, BN_CTX *ctx) | 289 | const unsigned char *buf, size_t len, BN_CTX *ctx) |
289 | { | 290 | { |
@@ -298,19 +299,35 @@ ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, | |||
298 | ECerror(EC_R_BUFFER_TOO_SMALL); | 299 | ECerror(EC_R_BUFFER_TOO_SMALL); |
299 | return 0; | 300 | return 0; |
300 | } | 301 | } |
301 | form = buf[0]; | 302 | |
302 | y_bit = form & 1; | 303 | /* |
303 | form = form & ~1U; | 304 | * The first octet is the point conversion octet PC, see X9.62, page 4 |
304 | if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) && | 305 | * and section 4.4.2. It must be: |
305 | (form != POINT_CONVERSION_UNCOMPRESSED) && | 306 | * 0x00 for the point at infinity |
306 | (form != POINT_CONVERSION_HYBRID)) { | 307 | * 0x02 or 0x03 for compressed form |
308 | * 0x04 for uncompressed form | ||
309 | * 0x06 or 0x07 for hybrid form. | ||
310 | * For compressed or hybrid forms, we store the last bit of buf[0] as | ||
311 | * y_bit and clear it from buf[0] so as to obtain a POINT_CONVERSION_*. | ||
312 | * We error if buf[0] contains any but the above values. | ||
313 | */ | ||
314 | y_bit = buf[0] & 1; | ||
315 | form = buf[0] & ~1U; | ||
316 | |||
317 | if (form != 0 && form != POINT_CONVERSION_COMPRESSED && | ||
318 | form != POINT_CONVERSION_UNCOMPRESSED && | ||
319 | form != POINT_CONVERSION_HYBRID) { | ||
307 | ECerror(EC_R_INVALID_ENCODING); | 320 | ECerror(EC_R_INVALID_ENCODING); |
308 | return 0; | 321 | return 0; |
309 | } | 322 | } |
310 | if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) { | 323 | if (form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) { |
311 | ECerror(EC_R_INVALID_ENCODING); | 324 | if (y_bit != 0) { |
312 | return 0; | 325 | ECerror(EC_R_INVALID_ENCODING); |
326 | return 0; | ||
327 | } | ||
313 | } | 328 | } |
329 | |||
330 | /* The point at infinity is represented by a single zero octet. */ | ||
314 | if (form == 0) { | 331 | if (form == 0) { |
315 | if (len != 1) { | 332 | if (len != 1) { |
316 | ECerror(EC_R_INVALID_ENCODING); | 333 | ECerror(EC_R_INVALID_ENCODING); |
@@ -318,6 +335,7 @@ ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, | |||
318 | } | 335 | } |
319 | return EC_POINT_set_to_infinity(group, point); | 336 | return EC_POINT_set_to_infinity(group, point); |
320 | } | 337 | } |
338 | |||
321 | field_len = (EC_GROUP_get_degree(group) + 7) / 8; | 339 | field_len = (EC_GROUP_get_degree(group) + 7) / 8; |
322 | enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : | 340 | enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : |
323 | 1 + 2 * field_len; | 341 | 1 + 2 * field_len; |
@@ -326,6 +344,7 @@ ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, | |||
326 | ECerror(EC_R_INVALID_ENCODING); | 344 | ECerror(EC_R_INVALID_ENCODING); |
327 | return 0; | 345 | return 0; |
328 | } | 346 | } |
347 | |||
329 | if (ctx == NULL) { | 348 | if (ctx == NULL) { |
330 | ctx = new_ctx = BN_CTX_new(); | 349 | ctx = new_ctx = BN_CTX_new(); |
331 | if (ctx == NULL) | 350 | if (ctx == NULL) |
@@ -360,11 +379,24 @@ ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, | |||
360 | goto err; | 379 | goto err; |
361 | } | 380 | } |
362 | if (form == POINT_CONVERSION_HYBRID) { | 381 | if (form == POINT_CONVERSION_HYBRID) { |
363 | if (!group->meth->field_div(group, yxi, y, x, ctx)) | 382 | /* |
364 | goto err; | 383 | * Check that the form in the encoding was set |
365 | if (y_bit != BN_is_odd(yxi)) { | 384 | * correctly according to X9.62 4.4.2.a, 4(c), |
366 | ECerror(EC_R_INVALID_ENCODING); | 385 | * see also first paragraph of X9.62 4.4.1.b. |
367 | goto err; | 386 | */ |
387 | if (BN_is_zero(x)) { | ||
388 | if (y_bit != 0) { | ||
389 | ECerror(EC_R_INVALID_ENCODING); | ||
390 | goto err; | ||
391 | } | ||
392 | } else { | ||
393 | if (!group->meth->field_div(group, yxi, y, x, | ||
394 | ctx)) | ||
395 | goto err; | ||
396 | if (y_bit != BN_is_odd(yxi)) { | ||
397 | ECerror(EC_R_INVALID_ENCODING); | ||
398 | goto err; | ||
399 | } | ||
368 | } | 400 | } |
369 | } | 401 | } |
370 | /* | 402 | /* |