Clean up EC_POINT to byte conversions.
With the allocations and BN_CTX gone, ECDH and point2oct are much, much
shorter.
Bug: 242
Change-Id: I3421822e94100f7eb2f5f2373df7fb3b3311365e
Reviewed-on: https://boringssl-review.googlesource.com/c/33071
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/ecdh_extra/ecdh_extra.c b/crypto/ecdh_extra/ecdh_extra.c
index eb321f7..1e08099 100644
--- a/crypto/ecdh_extra/ecdh_extra.c
+++ b/crypto/ecdh_extra/ecdh_extra.c
@@ -69,7 +69,6 @@
#include <limits.h>
#include <string.h>
-#include <openssl/bn.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -78,10 +77,10 @@
#include "../internal.h"
-int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
+int ECDH_compute_key(void *out, size_t out_len, const EC_POINT *pub_key,
const EC_KEY *priv_key,
void *(*kdf)(const void *in, size_t inlen, void *out,
- size_t *outlen)) {
+ size_t *out_len)) {
if (priv_key->priv_key == NULL) {
OPENSSL_PUT_ERROR(ECDH, ECDH_R_NO_PRIVATE_VALUE);
return -1;
@@ -93,74 +92,33 @@
return -1;
}
- BN_CTX *ctx = BN_CTX_new();
- if (ctx == NULL) {
+ EC_RAW_POINT shared_point;
+ uint8_t buf[EC_MAX_BYTES];
+ size_t buf_len;
+ if (!ec_point_mul_scalar(group, &shared_point, NULL, &pub_key->raw, priv) ||
+ !ec_point_get_affine_coordinate_bytes(group, buf, NULL, &buf_len,
+ sizeof(buf), &shared_point)) {
+ OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE);
return -1;
}
- BN_CTX_start(ctx);
-
- int ret = -1;
- size_t buflen = 0;
- uint8_t *buf = NULL;
-
- EC_POINT *tmp = EC_POINT_new(group);
- if (tmp == NULL) {
- OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (!ec_point_mul_scalar(group, &tmp->raw, NULL, &pub_key->raw, priv)) {
- OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE);
- goto err;
- }
-
- BIGNUM *x = BN_CTX_get(ctx);
- if (!x) {
- OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, NULL, ctx)) {
- OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE);
- goto err;
- }
-
- buflen = (EC_GROUP_get_degree(group) + 7) / 8;
- buf = OPENSSL_malloc(buflen);
- if (buf == NULL) {
- OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (!BN_bn2bin_padded(buf, buflen, x)) {
- OPENSSL_PUT_ERROR(ECDH, ERR_R_INTERNAL_ERROR);
- goto err;
- }
if (kdf != NULL) {
- if (kdf(buf, buflen, out, &outlen) == NULL) {
+ if (kdf(buf, buf_len, out, &out_len) == NULL) {
OPENSSL_PUT_ERROR(ECDH, ECDH_R_KDF_FAILED);
- goto err;
+ return -1;
}
} else {
// no KDF, just copy as much as we can
- if (buflen < outlen) {
- outlen = buflen;
+ if (buf_len < out_len) {
+ out_len = buf_len;
}
- OPENSSL_memcpy(out, buf, outlen);
+ OPENSSL_memcpy(out, buf, out_len);
}
- if (outlen > INT_MAX) {
+ if (out_len > INT_MAX) {
OPENSSL_PUT_ERROR(ECDH, ERR_R_OVERFLOW);
- goto err;
+ return -1;
}
- ret = (int)outlen;
-
-err:
- OPENSSL_free(buf);
- EC_POINT_free(tmp);
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- return ret;
+ return (int)out_len;
}
diff --git a/crypto/fipsmodule/ec/ec.c b/crypto/fipsmodule/ec/ec.c
index 717e054..bd0662a 100644
--- a/crypto/fipsmodule/ec/ec.c
+++ b/crypto/fipsmodule/ec/ec.c
@@ -973,6 +973,37 @@
return 1;
}
+int ec_point_get_affine_coordinate_bytes(const EC_GROUP *group, uint8_t *out_x,
+ uint8_t *out_y, size_t *out_len,
+ size_t max_out,
+ const EC_RAW_POINT *p) {
+ size_t len = BN_num_bytes(&group->field);
+ assert(len <= EC_MAX_BYTES);
+ if (max_out < len) {
+ OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ EC_FELEM x, y;
+ if (!group->meth->point_get_affine_coordinates(
+ group, p, out_x == NULL ? NULL : &x, out_y == NULL ? NULL : &y)) {
+ return 0;
+ }
+
+ if (out_x != NULL) {
+ for (size_t i = 0; i < len; i++) {
+ out_x[i] = x.bytes[len - i - 1];
+ }
+ }
+ if (out_y != NULL) {
+ for (size_t i = 0; i < len; i++) {
+ out_y[i] = y.bytes[len - i - 1];
+ }
+ }
+ *out_len = len;
+ return 1;
+}
+
void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {}
const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) {
diff --git a/crypto/fipsmodule/ec/internal.h b/crypto/fipsmodule/ec/internal.h
index a34ae98..d78d719 100644
--- a/crypto/fipsmodule/ec/internal.h
+++ b/crypto/fipsmodule/ec/internal.h
@@ -354,6 +354,17 @@
int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
const EC_RAW_POINT *p);
+// ec_point_get_affine_coordinate_bytes writes |p|'s affine coordinates to
+// |out_x| and |out_y|, each of which must have at must |max_out| bytes. It sets
+// |*out_len| to the number of bytes written in each buffer. Coordinates are
+// written big-endian and zero-padded to the size of the field.
+//
+// Either of |out_x| or |out_y| may be NULL to omit that coordinate. This
+// function returns one on success and zero on failure.
+int ec_point_get_affine_coordinate_bytes(const EC_GROUP *group, uint8_t *out_x,
+ uint8_t *out_y, size_t *out_len,
+ size_t max_out, const EC_RAW_POINT *p);
+
// ec_field_element_to_scalar reduces |r| modulo |group->order|. |r| must
// previously have been reduced modulo |group->field|.
int ec_field_element_to_scalar(const EC_GROUP *group, BIGNUM *r);
diff --git a/crypto/fipsmodule/ec/oct.c b/crypto/fipsmodule/ec/oct.c
index 19e17a7..04b1f2c 100644
--- a/crypto/fipsmodule/ec/oct.c
+++ b/crypto/fipsmodule/ec/oct.c
@@ -74,22 +74,18 @@
static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
- const EC_POINT *point,
+ const EC_RAW_POINT *point,
point_conversion_form_t form,
- uint8_t *buf, size_t len, BN_CTX *ctx) {
- size_t ret = 0;
- BN_CTX *new_ctx = NULL;
- int used_ctx = 0;
-
- if ((form != POINT_CONVERSION_COMPRESSED) &&
- (form != POINT_CONVERSION_UNCOMPRESSED)) {
+ uint8_t *buf, size_t len) {
+ if (form != POINT_CONVERSION_COMPRESSED &&
+ form != POINT_CONVERSION_UNCOMPRESSED) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM);
- goto err;
+ return 0;
}
- if (EC_POINT_is_at_infinity(group, point)) {
+ if (ec_GFp_simple_is_at_infinity(group, point)) {
OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
- goto err;
+ return 0;
}
const size_t field_len = BN_num_bytes(&group->field);
@@ -103,64 +99,31 @@
if (buf != NULL) {
if (len < output_len) {
OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
- goto err;
+ return 0;
}
- if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL) {
- goto err;
- }
+ uint8_t y_buf[EC_MAX_BYTES];
+ size_t field_len_out;
+ if (!ec_point_get_affine_coordinate_bytes(
+ group, buf + 1 /* x */,
+ form == POINT_CONVERSION_COMPRESSED ? y_buf : buf + 1 + field_len,
+ &field_len_out, field_len, point)) {
+ return 0;
}
- BN_CTX_start(ctx);
- used_ctx = 1;
- BIGNUM *x = BN_CTX_get(ctx);
- BIGNUM *y = BN_CTX_get(ctx);
- if (y == NULL) {
- goto err;
+ if (field_len_out != field_len) {
+ OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
+ return 0;
}
- if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) {
- goto err;
- }
-
- if ((form == POINT_CONVERSION_COMPRESSED) &&
- BN_is_odd(y)) {
- buf[0] = form + 1;
+ if (form == POINT_CONVERSION_COMPRESSED) {
+ buf[0] = form + (y_buf[field_len - 1] & 1);
} else {
buf[0] = form;
}
- size_t i = 1;
-
- if (!BN_bn2bin_padded(buf + i, field_len, x)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- i += field_len;
-
- if (form == POINT_CONVERSION_UNCOMPRESSED) {
- if (!BN_bn2bin_padded(buf + i, field_len, y)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- i += field_len;
- }
-
- if (i != output_len) {
- OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
- goto err;
- }
}
- ret = output_len;
-
-err:
- if (used_ctx) {
- BN_CTX_end(ctx);
- }
- BN_CTX_free(new_ctx);
- return ret;
+ return output_len;
}
static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
@@ -263,7 +226,7 @@
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
- return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx);
+ return ec_GFp_simple_point2oct(group, &point->raw, form, buf, len);
}
int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
diff --git a/crypto/fipsmodule/ecdh/ecdh.c b/crypto/fipsmodule/ecdh/ecdh.c
index 19d12c9..b9dc237 100644
--- a/crypto/fipsmodule/ecdh/ecdh.c
+++ b/crypto/fipsmodule/ecdh/ecdh.c
@@ -66,10 +66,8 @@
#include <openssl/ecdh.h>
-#include <limits.h>
#include <string.h>
-#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/ec_key.h>
#include <openssl/err.h>
@@ -92,50 +90,15 @@
return 0;
}
- BN_CTX *ctx = BN_CTX_new();
- if (ctx == NULL) {
+ EC_RAW_POINT shared_point;
+ uint8_t buf[EC_MAX_BYTES];
+ size_t buflen;
+ if (!ec_point_mul_scalar(group, &shared_point, NULL, &pub_key->raw, priv) ||
+ !ec_point_get_affine_coordinate_bytes(group, buf, NULL, &buflen,
+ sizeof(buf), &shared_point)) {
+ OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE);
return 0;
}
- BN_CTX_start(ctx);
-
- int ret = 0;
- size_t buflen = 0;
- uint8_t *buf = NULL;
-
- EC_POINT *shared_point = EC_POINT_new(group);
- if (shared_point == NULL) {
- OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (!ec_point_mul_scalar(group, &shared_point->raw, NULL, &pub_key->raw,
- priv)) {
- OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE);
- goto err;
- }
-
- BIGNUM *x = BN_CTX_get(ctx);
- if (!x) {
- OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (!EC_POINT_get_affine_coordinates_GFp(group, shared_point, x, NULL, ctx)) {
- OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE);
- goto err;
- }
-
- buflen = (EC_GROUP_get_degree(group) + 7) / 8;
- buf = OPENSSL_malloc(buflen);
- if (buf == NULL) {
- OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (!BN_bn2bin_padded(buf, buflen, x)) {
- OPENSSL_PUT_ERROR(ECDH, ERR_R_INTERNAL_ERROR);
- goto err;
- }
switch (out_len) {
case SHA224_DIGEST_LENGTH:
@@ -152,15 +115,8 @@
break;
default:
OPENSSL_PUT_ERROR(ECDH, ECDH_R_UNKNOWN_DIGEST_LENGTH);
- goto err;
+ return 0;
}
- ret = 1;
-
-err:
- OPENSSL_free(buf);
- EC_POINT_free(shared_point);
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- return ret;
+ return 1;
}