summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec/ec_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/ec/ec_lib.c')
-rw-r--r--src/lib/libcrypto/ec/ec_lib.c89
1 files changed, 81 insertions, 8 deletions
diff --git a/src/lib/libcrypto/ec/ec_lib.c b/src/lib/libcrypto/ec/ec_lib.c
index ed51582146..a8b74ce89d 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.109 2025/01/11 14:38:57 tb Exp $ */ 1/* $OpenBSD: ec_lib.c,v 1.110 2025/01/11 15:02:42 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 */
@@ -1026,8 +1026,9 @@ LCRYPTO_ALIAS(EC_POINT_get_affine_coordinates_GFp);
1026 1026
1027int 1027int
1028EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point, 1028EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
1029 const BIGNUM *x, int y_bit, BN_CTX *ctx_in) 1029 const BIGNUM *in_x, int y_bit, BN_CTX *ctx_in)
1030{ 1030{
1031 BIGNUM *p, *a, *b, *w, *x, *y;
1031 BN_CTX *ctx; 1032 BN_CTX *ctx;
1032 int ret = 0; 1033 int ret = 0;
1033 1034
@@ -1036,18 +1037,90 @@ EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
1036 if (ctx == NULL) 1037 if (ctx == NULL)
1037 goto err; 1038 goto err;
1038 1039
1039 if (group->meth->point_set_compressed_coordinates == NULL) { 1040 y_bit = (y_bit != 0);
1040 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1041
1042 BN_CTX_start(ctx);
1043
1044 if ((p = BN_CTX_get(ctx)) == NULL)
1045 goto err;
1046 if ((a = BN_CTX_get(ctx)) == NULL)
1047 goto err;
1048 if ((b = BN_CTX_get(ctx)) == NULL)
1049 goto err;
1050 if ((w = BN_CTX_get(ctx)) == NULL)
1051 goto err;
1052 if ((x = BN_CTX_get(ctx)) == NULL)
1053 goto err;
1054 if ((y = BN_CTX_get(ctx)) == NULL)
1055 goto err;
1056
1057 /*
1058 * Weierstrass equation: y^2 = x^3 + ax + b, so y is one of the
1059 * square roots of x^3 + ax + b. The y-bit indicates which one.
1060 */
1061
1062 if (!EC_GROUP_get_curve(group, p, a, b, ctx))
1063 goto err;
1064
1065 /* XXX - should we not insist on 0 <= x < p instead? */
1066 if (!BN_nnmod(x, in_x, p, ctx))
1067 goto err;
1068
1069 /* y = x^3 */
1070 if (!BN_mod_sqr(y, x, p, ctx))
1071 goto err;
1072 if (!BN_mod_mul(y, y, x, p, ctx))
1073 goto err;
1074
1075 /* y += ax */
1076 if (group->a_is_minus3) {
1077 if (!BN_mod_lshift1_quick(w, x, p))
1078 goto err;
1079 if (!BN_mod_add_quick(w, w, x, p))
1080 goto err;
1081 if (!BN_mod_sub_quick(y, y, w, p))
1082 goto err;
1083 } else {
1084 if (!BN_mod_mul(w, a, x, p, ctx))
1085 goto err;
1086 if (!BN_mod_add_quick(y, y, w, p))
1087 goto err;
1088 }
1089
1090 /* y += b */
1091 if (!BN_mod_add_quick(y, y, b, p))
1092 goto err;
1093
1094 if (!BN_mod_sqrt(y, y, p, ctx)) {
1095 ECerror(EC_R_INVALID_COMPRESSED_POINT);
1041 goto err; 1096 goto err;
1042 } 1097 }
1043 if (group->meth != point->meth) { 1098
1044 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1099 if (y_bit == BN_is_odd(y))
1100 goto done;
1101
1102 if (BN_is_zero(y)) {
1103 ECerror(EC_R_INVALID_COMPRESSION_BIT);
1045 goto err; 1104 goto err;
1046 } 1105 }
1047 ret = group->meth->point_set_compressed_coordinates(group, point, 1106 if (!BN_usub(y, p, y))
1048 x, y_bit, ctx); 1107 goto err;
1108
1109 if (y_bit != BN_is_odd(y)) {
1110 /* Can only happen if p is even and should not be reachable. */
1111 ECerror(ERR_R_INTERNAL_ERROR);
1112 goto err;
1113 }
1114
1115 done:
1116 if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
1117 goto err;
1118
1119 ret = 1;
1049 1120
1050 err: 1121 err:
1122 BN_CTX_end(ctx);
1123
1051 if (ctx != ctx_in) 1124 if (ctx != ctx_in)
1052 BN_CTX_free(ctx); 1125 BN_CTX_free(ctx);
1053 1126