summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2024-10-22 21:06:16 +0000
committertb <>2024-10-22 21:06:16 +0000
commit0e8f02da5cba6c145d528b1887147781392b4d70 (patch)
tree3ac82763626783e1abca600aac6de1ce68b05723 /src
parentce4cdd7bfccc5f813dee8ea16e06ced908ec63e1 (diff)
downloadopenbsd-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.c46
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
204static int
205ec_oct_conversion_form_is_valid(uint8_t form)
206{
207 return (form & EC_OCT_POINT_CONVERSION_MASK) == form;
208}
209
185size_t 210size_t
186ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, 211ec_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 }