summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2024-10-22 21:10:45 +0000
committertb <>2024-10-22 21:10:45 +0000
commit2ecb80a0db01a12008dcf47db9a6f3f5862966ec (patch)
treecc5e766b146756db1f49d72144c1639f3fe3572d /src
parent9c7b8e21b0aef7b0d224cd59cdc95557a81f289f (diff)
downloadopenbsd-2ecb80a0db01a12008dcf47db9a6f3f5862966ec.tar.gz
openbsd-2ecb80a0db01a12008dcf47db9a6f3f5862966ec.tar.bz2
openbsd-2ecb80a0db01a12008dcf47db9a6f3f5862966ec.zip
Rewrite ec_GFp_simple_point2oct() using CBB
Factor ad-hoc inline code into helper functions. Use CBB and BN_bn2binpad() instead of batshit crazy skip loops and pointer banging. With all this done, the function becomes relatively streamlined and pretty much symmetric with the new oct2point() implementation. ok jsing
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/ec/ecp_oct.c153
1 files changed, 90 insertions, 63 deletions
diff --git a/src/lib/libcrypto/ec/ecp_oct.c b/src/lib/libcrypto/ec/ecp_oct.c
index aa5a3906d1..0a66a5cd48 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.24 2024/10/22 21:08:49 tb Exp $ */ 1/* $OpenBSD: ecp_oct.c,v 1.25 2024/10/22 21:10:45 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.
@@ -217,6 +217,15 @@ ec_oct_nonzero_ybit_allowed(uint8_t form)
217} 217}
218 218
219static int 219static int
220ec_oct_add_leading_octet_cbb(CBB *cbb, uint8_t form, int ybit)
221{
222 if (ec_oct_nonzero_ybit_allowed(form) && ybit != 0)
223 form |= EC_OCT_YBIT;
224
225 return CBB_add_u8(cbb, form);
226}
227
228static int
220ec_oct_get_leading_octet_cbs(CBS *cbs, uint8_t *out_form, int *out_ybit) 229ec_oct_get_leading_octet_cbs(CBS *cbs, uint8_t *out_form, int *out_ybit)
221{ 230{
222 uint8_t octet; 231 uint8_t octet;
@@ -243,6 +252,25 @@ ec_oct_get_leading_octet_cbs(CBS *cbs, uint8_t *out_form, int *out_ybit)
243} 252}
244 253
245static int 254static int
255ec_oct_encoded_length(const EC_GROUP *group, uint8_t form, size_t *out_len)
256{
257 switch (form) {
258 case EC_OCT_POINT_AT_INFINITY:
259 *out_len = 1;
260 return 1;
261 case EC_OCT_POINT_COMPRESSED:
262 *out_len = 1 + BN_num_bytes(&group->field);
263 return 1;
264 case EC_OCT_POINT_UNCOMPRESSED:
265 case EC_OCT_POINT_HYBRID:
266 *out_len = 1 + 2 * BN_num_bytes(&group->field);
267 return 1;
268 default:
269 return 0;
270 }
271}
272
273static int
246ec_oct_field_element_is_valid(const EC_GROUP *group, const BIGNUM *bn) 274ec_oct_field_element_is_valid(const EC_GROUP *group, const BIGNUM *bn)
247{ 275{
248 /* Ensure bn is in the range [0, field). */ 276 /* Ensure bn is in the range [0, field). */
@@ -250,6 +278,28 @@ ec_oct_field_element_is_valid(const EC_GROUP *group, const BIGNUM *bn)
250} 278}
251 279
252static int 280static int
281ec_oct_add_field_element_cbb(CBB *cbb, const EC_GROUP *group, const BIGNUM *bn)
282{
283 uint8_t *buf = NULL;
284 int buf_len = BN_num_bytes(&group->field);
285
286 if (!ec_oct_field_element_is_valid(group, bn)) {
287 ECerror(EC_R_BIGNUM_OUT_OF_RANGE);
288 return 0;
289 }
290 if (!CBB_add_space(cbb, &buf, buf_len)) {
291 ECerror(ERR_R_MALLOC_FAILURE);
292 return 0;
293 }
294 if (BN_bn2binpad(bn, buf, buf_len) != buf_len) {
295 ECerror(ERR_R_MALLOC_FAILURE);
296 return 0;
297 }
298
299 return 1;
300}
301
302static int
253ec_oct_get_field_element_cbs(CBS *cbs, const EC_GROUP *group, BIGNUM *bn) 303ec_oct_get_field_element_cbs(CBS *cbs, const EC_GROUP *group, BIGNUM *bn)
254{ 304{
255 CBS field_element; 305 CBS field_element;
@@ -275,9 +325,10 @@ ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
275 point_conversion_form_t conversion_form, unsigned char *buf, size_t len, 325 point_conversion_form_t conversion_form, unsigned char *buf, size_t len,
276 BN_CTX *ctx) 326 BN_CTX *ctx)
277{ 327{
328 CBB cbb;
278 uint8_t form; 329 uint8_t form;
279 BIGNUM *x, *y; 330 BIGNUM *x, *y;
280 size_t field_len, i, skip; 331 size_t encoded_length;
281 size_t ret = 0; 332 size_t ret = 0;
282 333
283 if (conversion_form > UINT8_MAX) { 334 if (conversion_form > UINT8_MAX) {
@@ -296,82 +347,58 @@ ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
296 return 0; 347 return 0;
297 } 348 }
298 349
299 if (EC_POINT_is_at_infinity(group, point) > 0) { 350 if (EC_POINT_is_at_infinity(group, point))
300 /* encodes to a single 0 octet */ 351 form = EC_OCT_POINT_AT_INFINITY;
301 if (buf != NULL) { 352
302 if (len < 1) { 353 if (!ec_oct_encoded_length(group, form, &encoded_length)) {
303 ECerror(EC_R_BUFFER_TOO_SMALL); 354 ECerror(EC_R_INVALID_FORM);
304 return 0; 355 return 0;
305 }
306 buf[0] = 0;
307 }
308 return 1;
309 } 356 }
310 357
311 /* ret := required output buffer length */ 358 if (buf == NULL)
312 field_len = BN_num_bytes(&group->field); 359 return encoded_length;
313 ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; 360
361 if (len < encoded_length) {
362 ECerror(EC_R_BUFFER_TOO_SMALL);
363 return 0;
364 }
314 365
366 CBB_init_fixed(&cbb, buf, len);
315 BN_CTX_start(ctx); 367 BN_CTX_start(ctx);
316 368
317 /* if 'buf' is NULL, just return required length */ 369 if ((x = BN_CTX_get(ctx)) == NULL)
318 if (buf != NULL) { 370 goto err;
319 if (len < ret) { 371 if ((y = BN_CTX_get(ctx)) == NULL)
320 ECerror(EC_R_BUFFER_TOO_SMALL); 372 goto err;
321 goto err; 373 if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
322 } 374 goto err;
375
376 if (!ec_oct_add_leading_octet_cbb(&cbb, form, BN_is_odd(y)))
377 goto err;
323 378
324 if ((x = BN_CTX_get(ctx)) == NULL) 379 if (form == EC_OCT_POINT_AT_INFINITY) {
380 /* Encoded in leading octet. */;
381 } else if (form == EC_OCT_POINT_COMPRESSED) {
382 if (!ec_oct_add_field_element_cbb(&cbb, group, x))
325 goto err; 383 goto err;
326 if ((y = BN_CTX_get(ctx)) == NULL) 384 } else {
385 if (!ec_oct_add_field_element_cbb(&cbb, group, x))
327 goto err; 386 goto err;
328 387 if (!ec_oct_add_field_element_cbb(&cbb, group, y))
329 if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
330 goto err; 388 goto err;
389 }
331 390
332 if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y)) 391 if (!CBB_finish(&cbb, NULL, &ret))
333 buf[0] = form + 1; 392 goto err;
334 else
335 buf[0] = form;
336
337 i = 1;
338 393
339 skip = field_len - BN_num_bytes(x); 394 if (ret != encoded_length) {
340 if (skip > field_len) { 395 ret = 0;
341 ECerror(ERR_R_INTERNAL_ERROR); 396 goto err;
342 goto err;
343 }
344 while (skip > 0) {
345 buf[i++] = 0;
346 skip--;
347 }
348 skip = BN_bn2bin(x, buf + i);
349 i += skip;
350 if (i != 1 + field_len) {
351 ECerror(ERR_R_INTERNAL_ERROR);
352 goto err;
353 }
354 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID) {
355 skip = field_len - BN_num_bytes(y);
356 if (skip > field_len) {
357 ECerror(ERR_R_INTERNAL_ERROR);
358 goto err;
359 }
360 while (skip > 0) {
361 buf[i++] = 0;
362 skip--;
363 }
364 skip = BN_bn2bin(y, buf + i);
365 i += skip;
366 }
367 if (i != ret) {
368 ECerror(ERR_R_INTERNAL_ERROR);
369 goto err;
370 }
371 } 397 }
372 398
373 err: 399 err:
374 BN_CTX_end(ctx); 400 BN_CTX_end(ctx);
401 CBB_cleanup(&cbb);
375 402
376 return ret; 403 return ret;
377} 404}