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>
This commit is contained in:
parent
c93ab63a53
commit
5279ef5769
@ -69,7 +69,6 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <openssl/bn.h>
|
|
||||||
#include <openssl/digest.h>
|
#include <openssl/digest.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/mem.h>
|
#include <openssl/mem.h>
|
||||||
@ -78,10 +77,10 @@
|
|||||||
#include "../internal.h"
|
#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,
|
const EC_KEY *priv_key,
|
||||||
void *(*kdf)(const void *in, size_t inlen, void *out,
|
void *(*kdf)(const void *in, size_t inlen, void *out,
|
||||||
size_t *outlen)) {
|
size_t *out_len)) {
|
||||||
if (priv_key->priv_key == NULL) {
|
if (priv_key->priv_key == NULL) {
|
||||||
OPENSSL_PUT_ERROR(ECDH, ECDH_R_NO_PRIVATE_VALUE);
|
OPENSSL_PUT_ERROR(ECDH, ECDH_R_NO_PRIVATE_VALUE);
|
||||||
return -1;
|
return -1;
|
||||||
@ -93,74 +92,33 @@ int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BN_CTX *ctx = BN_CTX_new();
|
EC_RAW_POINT shared_point;
|
||||||
if (ctx == NULL) {
|
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;
|
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 != 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);
|
OPENSSL_PUT_ERROR(ECDH, ECDH_R_KDF_FAILED);
|
||||||
goto err;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// no KDF, just copy as much as we can
|
// no KDF, just copy as much as we can
|
||||||
if (buflen < outlen) {
|
if (buf_len < out_len) {
|
||||||
outlen = buflen;
|
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);
|
OPENSSL_PUT_ERROR(ECDH, ERR_R_OVERFLOW);
|
||||||
goto err;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = (int)outlen;
|
return (int)out_len;
|
||||||
|
|
||||||
err:
|
|
||||||
OPENSSL_free(buf);
|
|
||||||
EC_POINT_free(tmp);
|
|
||||||
BN_CTX_end(ctx);
|
|
||||||
BN_CTX_free(ctx);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
@ -973,6 +973,37 @@ int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
|
|||||||
return 1;
|
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) {}
|
void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {}
|
||||||
|
|
||||||
const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) {
|
const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) {
|
||||||
|
@ -354,6 +354,17 @@ int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p,
|
|||||||
int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
|
int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
|
||||||
const EC_RAW_POINT *p);
|
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
|
// ec_field_element_to_scalar reduces |r| modulo |group->order|. |r| must
|
||||||
// previously have been reduced modulo |group->field|.
|
// previously have been reduced modulo |group->field|.
|
||||||
int ec_field_element_to_scalar(const EC_GROUP *group, BIGNUM *r);
|
int ec_field_element_to_scalar(const EC_GROUP *group, BIGNUM *r);
|
||||||
|
@ -74,22 +74,18 @@
|
|||||||
|
|
||||||
|
|
||||||
static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
|
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,
|
point_conversion_form_t form,
|
||||||
uint8_t *buf, size_t len, BN_CTX *ctx) {
|
uint8_t *buf, size_t len) {
|
||||||
size_t ret = 0;
|
if (form != POINT_CONVERSION_COMPRESSED &&
|
||||||
BN_CTX *new_ctx = NULL;
|
form != POINT_CONVERSION_UNCOMPRESSED) {
|
||||||
int used_ctx = 0;
|
|
||||||
|
|
||||||
if ((form != POINT_CONVERSION_COMPRESSED) &&
|
|
||||||
(form != POINT_CONVERSION_UNCOMPRESSED)) {
|
|
||||||
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM);
|
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);
|
OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
|
||||||
goto err;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t field_len = BN_num_bytes(&group->field);
|
const size_t field_len = BN_num_bytes(&group->field);
|
||||||
@ -103,64 +99,31 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
|
|||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
if (len < output_len) {
|
if (len < output_len) {
|
||||||
OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
|
OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
|
||||||
goto err;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx == NULL) {
|
uint8_t y_buf[EC_MAX_BYTES];
|
||||||
ctx = new_ctx = BN_CTX_new();
|
size_t field_len_out;
|
||||||
if (ctx == NULL) {
|
if (!ec_point_get_affine_coordinate_bytes(
|
||||||
goto err;
|
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);
|
if (field_len_out != field_len) {
|
||||||
used_ctx = 1;
|
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
|
||||||
BIGNUM *x = BN_CTX_get(ctx);
|
return 0;
|
||||||
BIGNUM *y = BN_CTX_get(ctx);
|
|
||||||
if (y == NULL) {
|
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) {
|
if (form == POINT_CONVERSION_COMPRESSED) {
|
||||||
goto err;
|
buf[0] = form + (y_buf[field_len - 1] & 1);
|
||||||
}
|
|
||||||
|
|
||||||
if ((form == POINT_CONVERSION_COMPRESSED) &&
|
|
||||||
BN_is_odd(y)) {
|
|
||||||
buf[0] = form + 1;
|
|
||||||
} else {
|
} else {
|
||||||
buf[0] = form;
|
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;
|
return output_len;
|
||||||
|
|
||||||
err:
|
|
||||||
if (used_ctx) {
|
|
||||||
BN_CTX_end(ctx);
|
|
||||||
}
|
|
||||||
BN_CTX_free(new_ctx);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
|
static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
|
||||||
@ -263,7 +226,7 @@ size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
|
|||||||
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
|
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
|
||||||
return 0;
|
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,
|
int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
|
||||||
|
@ -66,10 +66,8 @@
|
|||||||
|
|
||||||
#include <openssl/ecdh.h>
|
#include <openssl/ecdh.h>
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <openssl/bn.h>
|
|
||||||
#include <openssl/ec.h>
|
#include <openssl/ec.h>
|
||||||
#include <openssl/ec_key.h>
|
#include <openssl/ec_key.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
@ -92,50 +90,15 @@ int ECDH_compute_key_fips(uint8_t *out, size_t out_len, const EC_POINT *pub_key,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BN_CTX *ctx = BN_CTX_new();
|
EC_RAW_POINT shared_point;
|
||||||
if (ctx == NULL) {
|
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;
|
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) {
|
switch (out_len) {
|
||||||
case SHA224_DIGEST_LENGTH:
|
case SHA224_DIGEST_LENGTH:
|
||||||
@ -152,15 +115,8 @@ int ECDH_compute_key_fips(uint8_t *out, size_t out_len, const EC_POINT *pub_key,
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
OPENSSL_PUT_ERROR(ECDH, ECDH_R_UNKNOWN_DIGEST_LENGTH);
|
OPENSSL_PUT_ERROR(ECDH, ECDH_R_UNKNOWN_DIGEST_LENGTH);
|
||||||
goto err;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 1;
|
return 1;
|
||||||
|
|
||||||
err:
|
|
||||||
OPENSSL_free(buf);
|
|
||||||
EC_POINT_free(shared_point);
|
|
||||||
BN_CTX_end(ctx);
|
|
||||||
BN_CTX_free(ctx);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user