summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2024-11-02 09:21:04 +0000
committertb <>2024-11-02 09:21:04 +0000
commit48bac334008e8da0a46268db5e831bad09c7a1ed (patch)
tree21c0cdcf944a9def5acf5c52f126ad2b8e696828 /src
parent31a7069580c5c1283d698f07f552c4dd435a4c2b (diff)
downloadopenbsd-48bac334008e8da0a46268db5e831bad09c7a1ed.tar.gz
openbsd-48bac334008e8da0a46268db5e831bad09c7a1ed.tar.bz2
openbsd-48bac334008e8da0a46268db5e831bad09c7a1ed.zip
Rewrite/clean up ec_GFp_simple_set_compressed_coordinates()
The biggest change here is that the computation is now performed in the Montgomery domain if we have a Montgomery curve. This avoids constant checking whether need to use plain field operations or whether we can use curve-specific ones. Use a few better variable names and stop attempting to figure out whether the operation failed due to an error in BN_mod_sqrt() or a bad point. All in all this only shaves off 10 lines, but it is astounding what a few tweaks can do to code that looked like Rome in 455 AD. with/ok jsing
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/ec/ecp_oct.c110
1 files changed, 48 insertions, 62 deletions
diff --git a/src/lib/libcrypto/ec/ecp_oct.c b/src/lib/libcrypto/ec/ecp_oct.c
index 6daab41870..85467a4143 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.31 2024/10/31 05:47:37 tb Exp $ */ 1/* $OpenBSD: ecp_oct.c,v 1.32 2024/11/02 09:21:04 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.
@@ -72,21 +72,17 @@
72 72
73int 73int
74ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, 74ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
75 EC_POINT *point, const BIGNUM *x_, int y_bit, BN_CTX *ctx) 75 EC_POINT *point, const BIGNUM *in_x, int y_bit, BN_CTX *ctx)
76{ 76{
77 BIGNUM *tmp1, *tmp2, *x, *y; 77 const BIGNUM *p = &group->field, *a = &group->a, *b = &group->b;
78 BIGNUM *w, *x, *y;
78 int ret = 0; 79 int ret = 0;
79 80
80 /* clear error queue */
81 ERR_clear_error();
82
83 y_bit = (y_bit != 0); 81 y_bit = (y_bit != 0);
84 82
85 BN_CTX_start(ctx); 83 BN_CTX_start(ctx);
86 84
87 if ((tmp1 = BN_CTX_get(ctx)) == NULL) 85 if ((w = BN_CTX_get(ctx)) == NULL)
88 goto err;
89 if ((tmp2 = BN_CTX_get(ctx)) == NULL)
90 goto err; 86 goto err;
91 if ((x = BN_CTX_get(ctx)) == NULL) 87 if ((x = BN_CTX_get(ctx)) == NULL)
92 goto err; 88 goto err;
@@ -94,83 +90,73 @@ ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
94 goto err; 90 goto err;
95 91
96 /* 92 /*
97 * Recover y. We have a Weierstrass equation y^2 = x^3 + a*x + b, so 93 * Weierstrass equation: y^2 = x^3 + ax + b, so y is one of the
98 * y is one of the square roots of x^3 + a*x + b. 94 * square roots of x^3 + ax + b. The y-bit indicates which one.
99 */ 95 */
100 96
101 /* tmp1 := x^3 */ 97 /* XXX - should we not insist on 0 <= x < p instead? */
102 if (!BN_nnmod(x, x_, &group->field, ctx)) 98 if (!BN_nnmod(x, in_x, p, ctx))
103 goto err; 99 goto err;
104 if (group->meth->field_decode == NULL) { 100
105 /* field_{sqr,mul} work on standard representation */ 101 if (group->meth->field_encode != NULL) {
106 if (!group->meth->field_sqr(group, tmp2, x_, ctx)) 102 if (!group->meth->field_encode(group, x, x, ctx))
107 goto err;
108 if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx))
109 goto err;
110 } else {
111 if (!BN_mod_sqr(tmp2, x_, &group->field, ctx))
112 goto err;
113 if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx))
114 goto err; 103 goto err;
115 } 104 }
116 105
117 /* tmp1 := tmp1 + a*x */ 106 /* y = x^3 */
107 if (!group->meth->field_sqr(group, y, x, ctx))
108 goto err;
109 if (!group->meth->field_mul(group, y, y, x, ctx))
110 goto err;
111
112 /* y += ax */
118 if (group->a_is_minus3) { 113 if (group->a_is_minus3) {
119 if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) 114 if (!BN_mod_lshift1_quick(w, x, p))
120 goto err; 115 goto err;
121 if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) 116 if (!BN_mod_add_quick(w, w, x, p))
122 goto err; 117 goto err;
123 if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) 118 if (!BN_mod_sub_quick(y, y, w, p))
124 goto err; 119 goto err;
125 } else { 120 } else {
126 if (group->meth->field_decode) { 121 if (!group->meth->field_mul(group, w, a, x, ctx))
127 if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) 122 goto err;
128 goto err; 123 if (!BN_mod_add_quick(y, y, w, p))
129 if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx))
130 goto err;
131 } else {
132 /* field_mul works on standard representation */
133 if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx))
134 goto err;
135 }
136
137 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field))
138 goto err; 124 goto err;
139 } 125 }
140 126
141 /* tmp1 := tmp1 + b */ 127 /* y += b */
128 if (!BN_mod_add_quick(y, y, b, p))
129 goto err;
130
142 if (group->meth->field_decode != NULL) { 131 if (group->meth->field_decode != NULL) {
143 if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) 132 if (!group->meth->field_decode(group, x, x, ctx))
144 goto err; 133 goto err;
145 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) 134 if (!group->meth->field_decode(group, y, y, ctx))
146 goto err;
147 } else {
148 if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field))
149 goto err; 135 goto err;
150 } 136 }
151 137
152 if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) { 138 if (!BN_mod_sqrt(y, y, p, ctx)) {
153 unsigned long err = ERR_peek_last_error(); 139 ECerror(EC_R_INVALID_COMPRESSED_POINT);
140 goto err;
141 }
142
143 if (y_bit == BN_is_odd(y))
144 goto done;
154 145
155 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) { 146 if (BN_is_zero(y)) {
156 ERR_clear_error(); 147 ECerror(EC_R_INVALID_COMPRESSION_BIT);
157 ECerror(EC_R_INVALID_COMPRESSED_POINT);
158 } else
159 ECerror(ERR_R_BN_LIB);
160 goto err; 148 goto err;
161 } 149 }
150 if (!BN_usub(y, &group->field, y))
151 goto err;
152
162 if (y_bit != BN_is_odd(y)) { 153 if (y_bit != BN_is_odd(y)) {
163 if (BN_is_zero(y)) { 154 /* Can only happen if p is even and should not be reachable. */
164 ECerror(EC_R_INVALID_COMPRESSION_BIT); 155 ECerror(ERR_R_INTERNAL_ERROR);
165 goto err; 156 goto err;
166 }
167 if (!BN_usub(y, &group->field, y))
168 goto err;
169 if (y_bit != BN_is_odd(y)) {
170 ECerror(ERR_R_INTERNAL_ERROR);
171 goto err;
172 }
173 } 157 }
158
159 done:
174 if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx)) 160 if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
175 goto err; 161 goto err;
176 162