Switch ssl_ecdh to C++.
The EC_POINT munging is sufficiently heavy on the goto err that I went
ahead and tidied it up.
Bug: 132
Change-Id: I7a3b3b3f166e39e4559acec834dd8e1ea9ac8620
Reviewed-on: https://boringssl-review.googlesource.com/17747
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/include/openssl/bn.h b/include/openssl/bn.h
index 5ebdade..0d2068f 100644
--- a/include/openssl/bn.h
+++ b/include/openssl/bn.h
@@ -938,6 +938,7 @@
#if defined(__cplusplus)
} /* extern C */
+#if !defined(OPENSSL_NO_CXX)
extern "C++" {
namespace bssl {
@@ -946,9 +947,22 @@
BORINGSSL_MAKE_DELETER(BN_CTX, BN_CTX_free)
BORINGSSL_MAKE_DELETER(BN_MONT_CTX, BN_MONT_CTX_free)
+class BN_CTXScope {
+ public:
+ BN_CTXScope(BN_CTX *ctx) : ctx_(ctx) { BN_CTX_start(ctx_); }
+ ~BN_CTXScope() { BN_CTX_end(ctx_); }
+
+ private:
+ BN_CTX *ctx_;
+
+ BN_CTXScope(BN_CTXScope &) = delete;
+ BN_CTXScope &operator=(BN_CTXScope &) = delete;
+};
+
} // namespace bssl
} /* extern C++ */
+#endif
#endif
diff --git a/ssl/CMakeLists.txt b/ssl/CMakeLists.txt
index 1f60ebe..c7b4a3b 100644
--- a/ssl/CMakeLists.txt
+++ b/ssl/CMakeLists.txt
@@ -21,7 +21,7 @@
ssl_buffer.cc
ssl_cert.cc
ssl_cipher.cc
- ssl_ecdh.c
+ ssl_ecdh.cc
ssl_file.c
ssl_lib.c
ssl_privkey.c
diff --git a/ssl/ssl_ecdh.c b/ssl/ssl_ecdh.cc
similarity index 80%
rename from ssl/ssl_ecdh.c
rename to ssl/ssl_ecdh.cc
index 49652f2..fa1cbe9 100644
--- a/ssl/ssl_ecdh.c
+++ b/ssl/ssl_ecdh.cc
@@ -37,49 +37,35 @@
}
static int ssl_ec_point_offer(SSL_ECDH_CTX *ctx, CBB *out) {
- assert(ctx->data == NULL);
- BIGNUM *private_key = BN_new();
- if (private_key == NULL) {
- return 0;
- }
- ctx->data = private_key;
-
/* Set up a shared |BN_CTX| for all operations. */
- BN_CTX *bn_ctx = BN_CTX_new();
- if (bn_ctx == NULL) {
+ bssl::UniquePtr<BN_CTX> bn_ctx(BN_CTX_new());
+ if (!bn_ctx) {
return 0;
}
- BN_CTX_start(bn_ctx);
-
- int ret = 0;
- EC_POINT *public_key = NULL;
- EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid);
- if (group == NULL) {
- goto err;
- }
+ bssl::BN_CTXScope scope(bn_ctx.get());
/* Generate a private key. */
- if (!BN_rand_range_ex(private_key, 1, EC_GROUP_get0_order(group))) {
- goto err;
+ bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(ctx->method->nid));
+ bssl::UniquePtr<BIGNUM> private_key(BN_new());
+ if (!group || !private_key ||
+ !BN_rand_range_ex(private_key.get(), 1,
+ EC_GROUP_get0_order(group.get()))) {
+ return 0;
}
/* Compute the corresponding public key and serialize it. */
- public_key = EC_POINT_new(group);
- if (public_key == NULL ||
- !EC_POINT_mul(group, public_key, private_key, NULL, NULL, bn_ctx) ||
- !EC_POINT_point2cbb(out, group, public_key, POINT_CONVERSION_UNCOMPRESSED,
- bn_ctx)) {
- goto err;
+ bssl::UniquePtr<EC_POINT> public_key(EC_POINT_new(group.get()));
+ if (!public_key ||
+ !EC_POINT_mul(group.get(), public_key.get(), private_key.get(), NULL,
+ NULL, bn_ctx.get()) ||
+ !EC_POINT_point2cbb(out, group.get(), public_key.get(),
+ POINT_CONVERSION_UNCOMPRESSED, bn_ctx.get())) {
+ return 0;
}
- ret = 1;
-
-err:
- EC_GROUP_free(group);
- EC_POINT_free(public_key);
- BN_CTX_end(bn_ctx);
- BN_CTX_free(bn_ctx);
- return ret;
+ assert(ctx->data == NULL);
+ ctx->data = private_key.release();
+ return 1;
}
static int ssl_ec_point_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
@@ -90,59 +76,48 @@
*out_alert = SSL_AD_INTERNAL_ERROR;
/* Set up a shared |BN_CTX| for all operations. */
- BN_CTX *bn_ctx = BN_CTX_new();
- if (bn_ctx == NULL) {
+ bssl::UniquePtr<BN_CTX> bn_ctx(BN_CTX_new());
+ if (!bn_ctx) {
return 0;
}
- BN_CTX_start(bn_ctx);
+ bssl::BN_CTXScope scope(bn_ctx.get());
- int ret = 0;
- EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid);
- EC_POINT *peer_point = NULL, *result = NULL;
- uint8_t *secret = NULL;
- if (group == NULL) {
- goto err;
+ bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(ctx->method->nid));
+ if (!group) {
+ return 0;
+ }
+
+ bssl::UniquePtr<EC_POINT> peer_point(EC_POINT_new(group.get()));
+ bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group.get()));
+ BIGNUM *x = BN_CTX_get(bn_ctx.get());
+ if (!peer_point || !result || !x) {
+ return 0;
+ }
+
+ if (!EC_POINT_oct2point(group.get(), peer_point.get(), peer_key, peer_key_len,
+ bn_ctx.get())) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
}
/* Compute the x-coordinate of |peer_key| * |private_key|. */
- peer_point = EC_POINT_new(group);
- result = EC_POINT_new(group);
- if (peer_point == NULL || result == NULL) {
- goto err;
- }
- BIGNUM *x = BN_CTX_get(bn_ctx);
- if (x == NULL) {
- goto err;
- }
- if (!EC_POINT_oct2point(group, peer_point, peer_key, peer_key_len, bn_ctx)) {
- *out_alert = SSL_AD_DECODE_ERROR;
- goto err;
- }
- if (!EC_POINT_mul(group, result, NULL, peer_point, private_key, bn_ctx) ||
- !EC_POINT_get_affine_coordinates_GFp(group, result, x, NULL, bn_ctx)) {
- goto err;
+ if (!EC_POINT_mul(group.get(), result.get(), NULL, peer_point.get(),
+ private_key, bn_ctx.get()) ||
+ !EC_POINT_get_affine_coordinates_GFp(group.get(), result.get(), x, NULL,
+ bn_ctx.get())) {
+ return 0;
}
/* Encode the x-coordinate left-padded with zeros. */
- size_t secret_len = (EC_GROUP_get_degree(group) + 7) / 8;
- secret = OPENSSL_malloc(secret_len);
- if (secret == NULL || !BN_bn2bin_padded(secret, secret_len, x)) {
- goto err;
+ size_t secret_len = (EC_GROUP_get_degree(group.get()) + 7) / 8;
+ bssl::UniquePtr<uint8_t> secret((uint8_t *)OPENSSL_malloc(secret_len));
+ if (!secret || !BN_bn2bin_padded(secret.get(), secret_len, x)) {
+ return 0;
}
- *out_secret = secret;
+ *out_secret = secret.release();
*out_secret_len = secret_len;
- secret = NULL;
- ret = 1;
-
-err:
- EC_GROUP_free(group);
- EC_POINT_free(peer_point);
- EC_POINT_free(result);
- BN_CTX_end(bn_ctx);
- BN_CTX_free(bn_ctx);
- OPENSSL_free(secret);
- return ret;
+ return 1;
}
static int ssl_ec_point_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
@@ -187,7 +162,7 @@
assert(ctx->data != NULL);
*out_alert = SSL_AD_INTERNAL_ERROR;
- uint8_t *secret = OPENSSL_malloc(32);
+ uint8_t *secret = (uint8_t *)OPENSSL_malloc(32);
if (secret == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;