diff options
author | tb <> | 2024-10-22 21:06:16 +0000 |
---|---|---|
committer | tb <> | 2024-10-22 21:06:16 +0000 |
commit | 0e8f02da5cba6c145d528b1887147781392b4d70 (patch) | |
tree | 3ac82763626783e1abca600aac6de1ce68b05723 /src | |
parent | ce4cdd7bfccc5f813dee8ea16e06ced908ec63e1 (diff) | |
download | openbsd-0e8f02da5cba6c145d528b1887147781392b4d70.tar.gz openbsd-0e8f02da5cba6c145d528b1887147781392b4d70.tar.bz2 openbsd-0e8f02da5cba6c145d528b1887147781392b4d70.zip |
Start cleaning up oct2point and point2oct
The SEC 1 standard defines various ways of encoding an elliptic curve
point as ASN.1 octet string. It's also used for the public key, which
isn't an octet string but a bit string for whatever historic reason.
The public API is incomplete and inconvenient, so we need to jump
through a few hoops to support it and to preserve our own sanity.
Split a small helper function out of ec_GFp_simple_point2oct() that
checks that a uint8_t represents a valid point conversion form. It
supports exactly the four possible variants and helps translating
from point_conversion_form_t at the API boundary.
Reject the form for the point at infinity since the function has
historically done that even for the case that the point actually is
the point at infinity.
ok jsing
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libcrypto/ec/ecp_oct.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/src/lib/libcrypto/ec/ecp_oct.c b/src/lib/libcrypto/ec/ecp_oct.c index 133704bd7f..9646e44499 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.22 2024/10/22 12:09:57 tb Exp $ */ | 1 | /* $OpenBSD: ecp_oct.c,v 1.23 2024/10/22 21:06:16 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. |
@@ -63,6 +63,7 @@ | |||
63 | */ | 63 | */ |
64 | 64 | ||
65 | #include <stddef.h> | 65 | #include <stddef.h> |
66 | #include <stdint.h> | ||
66 | 67 | ||
67 | #include <openssl/bn.h> | 68 | #include <openssl/bn.h> |
68 | #include <openssl/ec.h> | 69 | #include <openssl/ec.h> |
@@ -182,17 +183,52 @@ ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, | |||
182 | return ret; | 183 | return ret; |
183 | } | 184 | } |
184 | 185 | ||
186 | /* | ||
187 | * Only the last three bits of the leading octet of a point should be set. | ||
188 | * Bits 3 and 2 encode the conversion form for all points except the point | ||
189 | * at infinity. In compressed and hybrid form bit 1 indicates if the even | ||
190 | * or the odd solution of the quadratic equation for y should be used. | ||
191 | * | ||
192 | * The public point_conversion_t enum lacks the point at infinity, so we | ||
193 | * ignore it except at the API boundary. | ||
194 | */ | ||
195 | |||
196 | #define EC_OCT_YBIT 0x01 | ||
197 | |||
198 | #define EC_OCT_POINT_AT_INFINITY 0x00 | ||
199 | #define EC_OCT_POINT_COMPRESSED 0x02 | ||
200 | #define EC_OCT_POINT_UNCOMPRESSED 0x04 | ||
201 | #define EC_OCT_POINT_HYBRID 0x06 | ||
202 | #define EC_OCT_POINT_CONVERSION_MASK 0x06 | ||
203 | |||
204 | static int | ||
205 | ec_oct_conversion_form_is_valid(uint8_t form) | ||
206 | { | ||
207 | return (form & EC_OCT_POINT_CONVERSION_MASK) == form; | ||
208 | } | ||
209 | |||
185 | size_t | 210 | size_t |
186 | ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, | 211 | ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, |
187 | point_conversion_form_t form, unsigned char *buf, size_t len, BN_CTX *ctx) | 212 | point_conversion_form_t conversion_form, unsigned char *buf, size_t len, |
213 | BN_CTX *ctx) | ||
188 | { | 214 | { |
215 | uint8_t form; | ||
189 | BIGNUM *x, *y; | 216 | BIGNUM *x, *y; |
190 | size_t field_len, i, skip; | 217 | size_t field_len, i, skip; |
191 | size_t ret = 0; | 218 | size_t ret = 0; |
192 | 219 | ||
193 | if (form != POINT_CONVERSION_COMPRESSED && | 220 | if (conversion_form > UINT8_MAX) { |
194 | form != POINT_CONVERSION_UNCOMPRESSED && | 221 | ECerror(EC_R_INVALID_FORM); |
195 | form != POINT_CONVERSION_HYBRID) { | 222 | return 0; |
223 | } | ||
224 | |||
225 | form = conversion_form; | ||
226 | |||
227 | /* | ||
228 | * Established behavior is to reject a request for the form 0 for the | ||
229 | * point at infinity even if it is valid. | ||
230 | */ | ||
231 | if (form == 0 || !ec_oct_conversion_form_is_valid(form)) { | ||
196 | ECerror(EC_R_INVALID_FORM); | 232 | ECerror(EC_R_INVALID_FORM); |
197 | return 0; | 233 | return 0; |
198 | } | 234 | } |