summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec/ec2_smpl.c
diff options
context:
space:
mode:
authordjm <>2012-10-13 21:25:14 +0000
committerdjm <>2012-10-13 21:25:14 +0000
commit93723b50b639d8dc717bc1bf463fd46e1b321239 (patch)
tree281e0a29ae8f87a8c47fbd4deaa1f3d48b8cc5c1 /src/lib/libcrypto/ec/ec2_smpl.c
parent65e72ac55a6405783db7a12d7e35a7561d46005b (diff)
downloadopenbsd-93723b50b639d8dc717bc1bf463fd46e1b321239.tar.gz
openbsd-93723b50b639d8dc717bc1bf463fd46e1b321239.tar.bz2
openbsd-93723b50b639d8dc717bc1bf463fd46e1b321239.zip
resolve conflicts
Diffstat (limited to 'src/lib/libcrypto/ec/ec2_smpl.c')
-rw-r--r--src/lib/libcrypto/ec/ec2_smpl.c351
1 files changed, 14 insertions, 337 deletions
diff --git a/src/lib/libcrypto/ec/ec2_smpl.c b/src/lib/libcrypto/ec/ec2_smpl.c
index 03deae6674..e0e59c7d82 100644
--- a/src/lib/libcrypto/ec/ec2_smpl.c
+++ b/src/lib/libcrypto/ec/ec2_smpl.c
@@ -71,10 +71,20 @@
71 71
72#include "ec_lcl.h" 72#include "ec_lcl.h"
73 73
74#ifndef OPENSSL_NO_EC2M
75
76#ifdef OPENSSL_FIPS
77#include <openssl/fips.h>
78#endif
79
74 80
75const EC_METHOD *EC_GF2m_simple_method(void) 81const EC_METHOD *EC_GF2m_simple_method(void)
76 { 82 {
83#ifdef OPENSSL_FIPS
84 return fips_ec_gf2m_simple_method();
85#else
77 static const EC_METHOD ret = { 86 static const EC_METHOD ret = {
87 EC_FLAGS_DEFAULT_OCT,
78 NID_X9_62_characteristic_two_field, 88 NID_X9_62_characteristic_two_field,
79 ec_GF2m_simple_group_init, 89 ec_GF2m_simple_group_init,
80 ec_GF2m_simple_group_finish, 90 ec_GF2m_simple_group_finish,
@@ -93,9 +103,7 @@ const EC_METHOD *EC_GF2m_simple_method(void)
93 0 /* get_Jprojective_coordinates_GFp */, 103 0 /* get_Jprojective_coordinates_GFp */,
94 ec_GF2m_simple_point_set_affine_coordinates, 104 ec_GF2m_simple_point_set_affine_coordinates,
95 ec_GF2m_simple_point_get_affine_coordinates, 105 ec_GF2m_simple_point_get_affine_coordinates,
96 ec_GF2m_simple_set_compressed_coordinates, 106 0,0,0,
97 ec_GF2m_simple_point2oct,
98 ec_GF2m_simple_oct2point,
99 ec_GF2m_simple_add, 107 ec_GF2m_simple_add,
100 ec_GF2m_simple_dbl, 108 ec_GF2m_simple_dbl,
101 ec_GF2m_simple_invert, 109 ec_GF2m_simple_invert,
@@ -118,6 +126,7 @@ const EC_METHOD *EC_GF2m_simple_method(void)
118 0 /* field_set_to_one */ }; 126 0 /* field_set_to_one */ };
119 127
120 return &ret; 128 return &ret;
129#endif
121 } 130 }
122 131
123 132
@@ -405,340 +414,6 @@ int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_
405 return ret; 414 return ret;
406 } 415 }
407 416
408
409/* Calculates and sets the affine coordinates of an EC_POINT from the given
410 * compressed coordinates. Uses algorithm 2.3.4 of SEC 1.
411 * Note that the simple implementation only uses affine coordinates.
412 *
413 * The method is from the following publication:
414 *
415 * Harper, Menezes, Vanstone:
416 * "Public-Key Cryptosystems with Very Small Key Lengths",
417 * EUROCRYPT '92, Springer-Verlag LNCS 658,
418 * published February 1993
419 *
420 * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
421 * the same method, but claim no priority date earlier than July 29, 1994
422 * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
423 */
424int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
425 const BIGNUM *x_, int y_bit, BN_CTX *ctx)
426 {
427 BN_CTX *new_ctx = NULL;
428 BIGNUM *tmp, *x, *y, *z;
429 int ret = 0, z0;
430
431 /* clear error queue */
432 ERR_clear_error();
433
434 if (ctx == NULL)
435 {
436 ctx = new_ctx = BN_CTX_new();
437 if (ctx == NULL)
438 return 0;
439 }
440
441 y_bit = (y_bit != 0) ? 1 : 0;
442
443 BN_CTX_start(ctx);
444 tmp = BN_CTX_get(ctx);
445 x = BN_CTX_get(ctx);
446 y = BN_CTX_get(ctx);
447 z = BN_CTX_get(ctx);
448 if (z == NULL) goto err;
449
450 if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err;
451 if (BN_is_zero(x))
452 {
453 if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err;
454 }
455 else
456 {
457 if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err;
458 if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err;
459 if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err;
460 if (!BN_GF2m_add(tmp, x, tmp)) goto err;
461 if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx))
462 {
463 unsigned long err = ERR_peek_last_error();
464
465 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION)
466 {
467 ERR_clear_error();
468 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
469 }
470 else
471 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
472 goto err;
473 }
474 z0 = (BN_is_odd(z)) ? 1 : 0;
475 if (!group->meth->field_mul(group, y, x, z, ctx)) goto err;
476 if (z0 != y_bit)
477 {
478 if (!BN_GF2m_add(y, y, x)) goto err;
479 }
480 }
481
482 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
483
484 ret = 1;
485
486 err:
487 BN_CTX_end(ctx);
488 if (new_ctx != NULL)
489 BN_CTX_free(new_ctx);
490 return ret;
491 }
492
493
494/* Converts an EC_POINT to an octet string.
495 * If buf is NULL, the encoded length will be returned.
496 * If the length len of buf is smaller than required an error will be returned.
497 */
498size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
499 unsigned char *buf, size_t len, BN_CTX *ctx)
500 {
501 size_t ret;
502 BN_CTX *new_ctx = NULL;
503 int used_ctx = 0;
504 BIGNUM *x, *y, *yxi;
505 size_t field_len, i, skip;
506
507 if ((form != POINT_CONVERSION_COMPRESSED)
508 && (form != POINT_CONVERSION_UNCOMPRESSED)
509 && (form != POINT_CONVERSION_HYBRID))
510 {
511 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
512 goto err;
513 }
514
515 if (EC_POINT_is_at_infinity(group, point))
516 {
517 /* encodes to a single 0 octet */
518 if (buf != NULL)
519 {
520 if (len < 1)
521 {
522 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
523 return 0;
524 }
525 buf[0] = 0;
526 }
527 return 1;
528 }
529
530
531 /* ret := required output buffer length */
532 field_len = (EC_GROUP_get_degree(group) + 7) / 8;
533 ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
534
535 /* if 'buf' is NULL, just return required length */
536 if (buf != NULL)
537 {
538 if (len < ret)
539 {
540 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
541 goto err;
542 }
543
544 if (ctx == NULL)
545 {
546 ctx = new_ctx = BN_CTX_new();
547 if (ctx == NULL)
548 return 0;
549 }
550
551 BN_CTX_start(ctx);
552 used_ctx = 1;
553 x = BN_CTX_get(ctx);
554 y = BN_CTX_get(ctx);
555 yxi = BN_CTX_get(ctx);
556 if (yxi == NULL) goto err;
557
558 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
559
560 buf[0] = form;
561 if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
562 {
563 if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
564 if (BN_is_odd(yxi)) buf[0]++;
565 }
566
567 i = 1;
568
569 skip = field_len - BN_num_bytes(x);
570 if (skip > field_len)
571 {
572 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
573 goto err;
574 }
575 while (skip > 0)
576 {
577 buf[i++] = 0;
578 skip--;
579 }
580 skip = BN_bn2bin(x, buf + i);
581 i += skip;
582 if (i != 1 + field_len)
583 {
584 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
585 goto err;
586 }
587
588 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
589 {
590 skip = field_len - BN_num_bytes(y);
591 if (skip > field_len)
592 {
593 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
594 goto err;
595 }
596 while (skip > 0)
597 {
598 buf[i++] = 0;
599 skip--;
600 }
601 skip = BN_bn2bin(y, buf + i);
602 i += skip;
603 }
604
605 if (i != ret)
606 {
607 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
608 goto err;
609 }
610 }
611
612 if (used_ctx)
613 BN_CTX_end(ctx);
614 if (new_ctx != NULL)
615 BN_CTX_free(new_ctx);
616 return ret;
617
618 err:
619 if (used_ctx)
620 BN_CTX_end(ctx);
621 if (new_ctx != NULL)
622 BN_CTX_free(new_ctx);
623 return 0;
624 }
625
626
627/* Converts an octet string representation to an EC_POINT.
628 * Note that the simple implementation only uses affine coordinates.
629 */
630int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
631 const unsigned char *buf, size_t len, BN_CTX *ctx)
632 {
633 point_conversion_form_t form;
634 int y_bit;
635 BN_CTX *new_ctx = NULL;
636 BIGNUM *x, *y, *yxi;
637 size_t field_len, enc_len;
638 int ret = 0;
639
640 if (len == 0)
641 {
642 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
643 return 0;
644 }
645 form = buf[0];
646 y_bit = form & 1;
647 form = form & ~1U;
648 if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
649 && (form != POINT_CONVERSION_UNCOMPRESSED)
650 && (form != POINT_CONVERSION_HYBRID))
651 {
652 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
653 return 0;
654 }
655 if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
656 {
657 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
658 return 0;
659 }
660
661 if (form == 0)
662 {
663 if (len != 1)
664 {
665 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
666 return 0;
667 }
668
669 return EC_POINT_set_to_infinity(group, point);
670 }
671
672 field_len = (EC_GROUP_get_degree(group) + 7) / 8;
673 enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
674
675 if (len != enc_len)
676 {
677 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
678 return 0;
679 }
680
681 if (ctx == NULL)
682 {
683 ctx = new_ctx = BN_CTX_new();
684 if (ctx == NULL)
685 return 0;
686 }
687
688 BN_CTX_start(ctx);
689 x = BN_CTX_get(ctx);
690 y = BN_CTX_get(ctx);
691 yxi = BN_CTX_get(ctx);
692 if (yxi == NULL) goto err;
693
694 if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
695 if (BN_ucmp(x, &group->field) >= 0)
696 {
697 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
698 goto err;
699 }
700
701 if (form == POINT_CONVERSION_COMPRESSED)
702 {
703 if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
704 }
705 else
706 {
707 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
708 if (BN_ucmp(y, &group->field) >= 0)
709 {
710 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
711 goto err;
712 }
713 if (form == POINT_CONVERSION_HYBRID)
714 {
715 if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
716 if (y_bit != BN_is_odd(yxi))
717 {
718 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
719 goto err;
720 }
721 }
722
723 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
724 }
725
726 if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
727 {
728 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
729 goto err;
730 }
731
732 ret = 1;
733
734 err:
735 BN_CTX_end(ctx);
736 if (new_ctx != NULL)
737 BN_CTX_free(new_ctx);
738 return ret;
739 }
740
741
742/* Computes a + b and stores the result in r. r could be a or b, a could be b. 417/* Computes a + b and stores the result in r. r could be a or b, a could be b.
743 * Uses algorithm A.10.2 of IEEE P1363. 418 * Uses algorithm A.10.2 of IEEE P1363.
744 */ 419 */
@@ -1040,3 +715,5 @@ int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
1040 { 715 {
1041 return BN_GF2m_mod_div(r, a, b, &group->field, ctx); 716 return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
1042 } 717 }
718
719#endif