aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_ecc.c
diff options
context:
space:
mode:
authororivej <orivej@yandex-team.ru>2022-02-10 16:44:49 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:44:49 +0300
commit718c552901d703c502ccbefdfc3c9028d608b947 (patch)
tree46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_ecc.c
parente9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff)
downloadydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_ecc.c')
-rw-r--r--contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_ecc.c748
1 files changed, 374 insertions, 374 deletions
diff --git a/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_ecc.c b/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_ecc.c
index 14be8c3df5..153bcd5f4e 100644
--- a/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_ecc.c
+++ b/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_ecc.c
@@ -1,374 +1,374 @@
-/**
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0.
- */
-#include <aws/cal/private/ecc.h>
-
-#include <aws/cal/cal.h>
-#include <aws/cal/private/der.h>
-
-#include <openssl/bn.h>
-#include <openssl/ec.h>
-#include <openssl/ecdsa.h>
-#include <openssl/obj_mac.h>
-
-struct libcrypto_ecc_key {
- struct aws_ecc_key_pair key_pair;
- EC_KEY *ec_key;
-};
-
-static int s_curve_name_to_nid(enum aws_ecc_curve_name curve_name) {
- switch (curve_name) {
- case AWS_CAL_ECDSA_P256:
- return NID_X9_62_prime256v1;
- case AWS_CAL_ECDSA_P384:
- return NID_secp384r1;
- }
-
- AWS_FATAL_ASSERT(!"Unsupported elliptic curve name");
- return -1;
-}
-
-static void s_key_pair_destroy(struct aws_ecc_key_pair *key_pair) {
-
- if (key_pair) {
- aws_byte_buf_clean_up(&key_pair->pub_x);
- aws_byte_buf_clean_up(&key_pair->pub_y);
- aws_byte_buf_clean_up_secure(&key_pair->priv_d);
-
- struct libcrypto_ecc_key *key_impl = key_pair->impl;
-
- if (key_impl->ec_key) {
- EC_KEY_free(key_impl->ec_key);
- }
- aws_mem_release(key_pair->allocator, key_pair);
- }
-}
-
-static int s_sign_payload(
- const struct aws_ecc_key_pair *key_pair,
- const struct aws_byte_cursor *hash,
- struct aws_byte_buf *signature_output) {
- struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl;
-
- unsigned int signature_size = signature_output->capacity - signature_output->len;
- int ret_val = ECDSA_sign(
- 0,
- hash->ptr,
- hash->len,
- signature_output->buffer + signature_output->len,
- &signature_size,
- libcrypto_key_pair->ec_key);
- signature_output->len += signature_size;
-
- return ret_val == 1 ? AWS_OP_SUCCESS : aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
-}
-
-static int s_verify_payload(
- const struct aws_ecc_key_pair *key_pair,
- const struct aws_byte_cursor *hash,
- const struct aws_byte_cursor *signature) {
- struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl;
-
- return ECDSA_verify(0, hash->ptr, hash->len, signature->ptr, signature->len, libcrypto_key_pair->ec_key) == 1
- ? AWS_OP_SUCCESS
- : aws_raise_error(AWS_ERROR_CAL_SIGNATURE_VALIDATION_FAILED);
-}
-
-static size_t s_signature_length(const struct aws_ecc_key_pair *key_pair) {
- struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl;
-
- return ECDSA_size(libcrypto_key_pair->ec_key);
-}
-
-static int s_fill_in_public_key_info(
- struct libcrypto_ecc_key *libcrypto_key_pair,
- const EC_GROUP *group,
- const EC_POINT *pub_key_point) {
- BIGNUM *big_num_x = BN_new();
- BIGNUM *big_num_y = BN_new();
-
- int ret_val = AWS_OP_ERR;
-
- if (EC_POINT_get_affine_coordinates_GFp(group, pub_key_point, big_num_x, big_num_y, NULL) != 1) {
- aws_raise_error(AWS_ERROR_INVALID_STATE);
- goto clean_up;
- }
-
- size_t x_coor_size = BN_num_bytes(big_num_x);
- size_t y_coor_size = BN_num_bytes(big_num_y);
-
- if (aws_byte_buf_init(&libcrypto_key_pair->key_pair.pub_x, libcrypto_key_pair->key_pair.allocator, x_coor_size)) {
- goto clean_up;
- }
-
- if (aws_byte_buf_init(&libcrypto_key_pair->key_pair.pub_y, libcrypto_key_pair->key_pair.allocator, y_coor_size)) {
- goto clean_up;
- }
-
- BN_bn2bin(big_num_x, libcrypto_key_pair->key_pair.pub_x.buffer);
- BN_bn2bin(big_num_y, libcrypto_key_pair->key_pair.pub_y.buffer);
-
- libcrypto_key_pair->key_pair.pub_x.len = x_coor_size;
- libcrypto_key_pair->key_pair.pub_y.len = y_coor_size;
-
- ret_val = AWS_OP_SUCCESS;
-
-clean_up:
- BN_free(big_num_x);
- BN_free(big_num_y);
-
- return ret_val;
-}
-
-static int s_derive_public_key(struct aws_ecc_key_pair *key_pair) {
- struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl;
-
- if (!libcrypto_key_pair->key_pair.priv_d.buffer) {
- return aws_raise_error(AWS_ERROR_INVALID_STATE);
- }
-
- /* we already have a public key. */
- if (libcrypto_key_pair->key_pair.pub_x.len) {
- return AWS_OP_SUCCESS;
- }
-
- BIGNUM *priv_key_num =
- BN_bin2bn(libcrypto_key_pair->key_pair.priv_d.buffer, libcrypto_key_pair->key_pair.priv_d.len, NULL);
-
- const EC_GROUP *group = EC_KEY_get0_group(libcrypto_key_pair->ec_key);
- EC_POINT *point = EC_POINT_new(group);
-
- EC_POINT_mul(group, point, priv_key_num, NULL, NULL, NULL);
- BN_free(priv_key_num);
-
- EC_KEY_set_public_key(libcrypto_key_pair->ec_key, point);
- int ret_val = s_fill_in_public_key_info(libcrypto_key_pair, group, point);
- EC_POINT_free(point);
- return ret_val;
-}
-
-static struct aws_ecc_key_pair_vtable vtable = {
- .sign_message = s_sign_payload,
- .verify_signature = s_verify_payload,
- .derive_pub_key = s_derive_public_key,
- .signature_length = s_signature_length,
- .destroy = s_key_pair_destroy,
-};
-
-struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_private_key(
- struct aws_allocator *allocator,
- enum aws_ecc_curve_name curve_name,
- const struct aws_byte_cursor *priv_key) {
-
- size_t key_length = aws_ecc_key_coordinate_byte_size_from_curve_name(curve_name);
- if (priv_key->len != key_length) {
- aws_raise_error(AWS_ERROR_CAL_INVALID_KEY_LENGTH_FOR_ALGORITHM);
- return NULL;
- }
-
- struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key));
-
- key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name));
- key_impl->key_pair.curve_name = curve_name;
- key_impl->key_pair.allocator = allocator;
- key_impl->key_pair.vtable = &vtable;
- key_impl->key_pair.impl = key_impl;
- aws_atomic_init_int(&key_impl->key_pair.ref_count, 1);
- aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.priv_d, allocator, *priv_key);
-
- BIGNUM *priv_key_num = BN_bin2bn(key_impl->key_pair.priv_d.buffer, key_impl->key_pair.priv_d.len, NULL);
- if (!EC_KEY_set_private_key(key_impl->ec_key, priv_key_num)) {
- aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
- BN_free(priv_key_num);
- s_key_pair_destroy(&key_impl->key_pair);
- return NULL;
- }
- BN_free(priv_key_num);
- return &key_impl->key_pair;
-}
-
-struct aws_ecc_key_pair *aws_ecc_key_pair_new_generate_random(
- struct aws_allocator *allocator,
- enum aws_ecc_curve_name curve_name) {
- struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key));
-
- key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name));
- key_impl->key_pair.curve_name = curve_name;
- key_impl->key_pair.allocator = allocator;
- key_impl->key_pair.vtable = &vtable;
- key_impl->key_pair.impl = key_impl;
- aws_atomic_init_int(&key_impl->key_pair.ref_count, 1);
-
- if (EC_KEY_generate_key(key_impl->ec_key) != 1) {
- goto error;
- }
-
- const EC_POINT *pub_key_point = EC_KEY_get0_public_key(key_impl->ec_key);
- const EC_GROUP *group = EC_KEY_get0_group(key_impl->ec_key);
-
- const BIGNUM *private_key_num = EC_KEY_get0_private_key(key_impl->ec_key);
- size_t priv_key_size = BN_num_bytes(private_key_num);
- if (aws_byte_buf_init(&key_impl->key_pair.priv_d, allocator, priv_key_size)) {
- goto error;
- }
-
- BN_bn2bin(private_key_num, key_impl->key_pair.priv_d.buffer);
- key_impl->key_pair.priv_d.len = priv_key_size;
-
- if (!s_fill_in_public_key_info(key_impl, group, pub_key_point)) {
- return &key_impl->key_pair;
- }
-
-error:
- s_key_pair_destroy(&key_impl->key_pair);
- return NULL;
-}
-
-struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_public_key(
- struct aws_allocator *allocator,
- enum aws_ecc_curve_name curve_name,
- const struct aws_byte_cursor *public_key_x,
- const struct aws_byte_cursor *public_key_y) {
- struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key));
- BIGNUM *pub_x_num = NULL;
- BIGNUM *pub_y_num = NULL;
- EC_POINT *point = NULL;
-
- if (!key_impl) {
- return NULL;
- }
-
- key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name));
- key_impl->key_pair.curve_name = curve_name;
- key_impl->key_pair.allocator = allocator;
- key_impl->key_pair.vtable = &vtable;
- key_impl->key_pair.impl = key_impl;
- aws_atomic_init_int(&key_impl->key_pair.ref_count, 1);
-
- if (aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.pub_x, allocator, *public_key_x)) {
- s_key_pair_destroy(&key_impl->key_pair);
- return NULL;
- }
-
- if (aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.pub_y, allocator, *public_key_y)) {
- s_key_pair_destroy(&key_impl->key_pair);
- return NULL;
- }
-
- pub_x_num = BN_bin2bn(public_key_x->ptr, public_key_x->len, NULL);
- pub_y_num = BN_bin2bn(public_key_y->ptr, public_key_y->len, NULL);
-
- const EC_GROUP *group = EC_KEY_get0_group(key_impl->ec_key);
- point = EC_POINT_new(group);
-
- if (EC_POINT_set_affine_coordinates_GFp(group, point, pub_x_num, pub_y_num, NULL) != 1) {
- goto error;
- }
-
- if (EC_KEY_set_public_key(key_impl->ec_key, point) != 1) {
- goto error;
- }
-
- EC_POINT_free(point);
- BN_free(pub_x_num);
- BN_free(pub_y_num);
-
- return &key_impl->key_pair;
-
-error:
- if (point) {
- EC_POINT_free(point);
- }
-
- if (pub_x_num) {
- BN_free(pub_x_num);
- }
-
- if (pub_y_num) {
- BN_free(pub_y_num);
- }
-
- s_key_pair_destroy(&key_impl->key_pair);
-
- return NULL;
-}
-
-struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_asn1(
- struct aws_allocator *allocator,
- const struct aws_byte_cursor *encoded_keys) {
-
- struct aws_ecc_key_pair *key = NULL;
- struct aws_der_decoder *decoder = aws_der_decoder_new(allocator, *encoded_keys);
-
- if (!decoder) {
- return NULL;
- }
-
- struct aws_byte_cursor pub_x;
- struct aws_byte_cursor pub_y;
- struct aws_byte_cursor priv_d;
-
- enum aws_ecc_curve_name curve_name;
- if (aws_der_decoder_load_ecc_key_pair(decoder, &pub_x, &pub_y, &priv_d, &curve_name)) {
- goto error;
- }
-
- if (priv_d.ptr) {
- struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key));
- key_impl->key_pair.curve_name = curve_name;
- /* as awkward as it seems, there's not a great way to manually set the public key, so let openssl just parse
- * the der document manually now that we know what parts are what. */
- if (!d2i_ECPrivateKey(&key_impl->ec_key, (const unsigned char **)&encoded_keys->ptr, encoded_keys->len)) {
- aws_mem_release(allocator, key_impl);
- aws_raise_error(AWS_ERROR_CAL_MISSING_REQUIRED_KEY_COMPONENT);
- goto error;
- }
-
- key_impl->key_pair.allocator = allocator;
- key_impl->key_pair.vtable = &vtable;
- key_impl->key_pair.impl = key_impl;
- aws_atomic_init_int(&key_impl->key_pair.ref_count, 1);
- key = &key_impl->key_pair;
-
- struct aws_byte_buf temp_buf;
- AWS_ZERO_STRUCT(temp_buf);
-
- if (pub_x.ptr) {
- temp_buf = aws_byte_buf_from_array(pub_x.ptr, pub_x.len);
- if (aws_byte_buf_init_copy(&key->pub_x, allocator, &temp_buf)) {
- goto error;
- }
- }
-
- if (pub_y.ptr) {
- temp_buf = aws_byte_buf_from_array(pub_y.ptr, pub_y.len);
- if (aws_byte_buf_init_copy(&key->pub_y, allocator, &temp_buf)) {
- goto error;
- }
- }
-
- if (priv_d.ptr) {
- temp_buf = aws_byte_buf_from_array(priv_d.ptr, priv_d.len);
- if (aws_byte_buf_init_copy(&key->priv_d, allocator, &temp_buf)) {
- goto error;
- }
- }
-
- } else {
- key = aws_ecc_key_pair_new_from_public_key(allocator, curve_name, &pub_x, &pub_y);
-
- if (!key) {
- goto error;
- }
- }
-
- aws_der_decoder_destroy(decoder);
- return key;
-
-error:
- aws_der_decoder_destroy(decoder);
- s_key_pair_destroy(key);
-
- return NULL;
-}
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+#include <aws/cal/private/ecc.h>
+
+#include <aws/cal/cal.h>
+#include <aws/cal/private/der.h>
+
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/obj_mac.h>
+
+struct libcrypto_ecc_key {
+ struct aws_ecc_key_pair key_pair;
+ EC_KEY *ec_key;
+};
+
+static int s_curve_name_to_nid(enum aws_ecc_curve_name curve_name) {
+ switch (curve_name) {
+ case AWS_CAL_ECDSA_P256:
+ return NID_X9_62_prime256v1;
+ case AWS_CAL_ECDSA_P384:
+ return NID_secp384r1;
+ }
+
+ AWS_FATAL_ASSERT(!"Unsupported elliptic curve name");
+ return -1;
+}
+
+static void s_key_pair_destroy(struct aws_ecc_key_pair *key_pair) {
+
+ if (key_pair) {
+ aws_byte_buf_clean_up(&key_pair->pub_x);
+ aws_byte_buf_clean_up(&key_pair->pub_y);
+ aws_byte_buf_clean_up_secure(&key_pair->priv_d);
+
+ struct libcrypto_ecc_key *key_impl = key_pair->impl;
+
+ if (key_impl->ec_key) {
+ EC_KEY_free(key_impl->ec_key);
+ }
+ aws_mem_release(key_pair->allocator, key_pair);
+ }
+}
+
+static int s_sign_payload(
+ const struct aws_ecc_key_pair *key_pair,
+ const struct aws_byte_cursor *hash,
+ struct aws_byte_buf *signature_output) {
+ struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl;
+
+ unsigned int signature_size = signature_output->capacity - signature_output->len;
+ int ret_val = ECDSA_sign(
+ 0,
+ hash->ptr,
+ hash->len,
+ signature_output->buffer + signature_output->len,
+ &signature_size,
+ libcrypto_key_pair->ec_key);
+ signature_output->len += signature_size;
+
+ return ret_val == 1 ? AWS_OP_SUCCESS : aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
+}
+
+static int s_verify_payload(
+ const struct aws_ecc_key_pair *key_pair,
+ const struct aws_byte_cursor *hash,
+ const struct aws_byte_cursor *signature) {
+ struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl;
+
+ return ECDSA_verify(0, hash->ptr, hash->len, signature->ptr, signature->len, libcrypto_key_pair->ec_key) == 1
+ ? AWS_OP_SUCCESS
+ : aws_raise_error(AWS_ERROR_CAL_SIGNATURE_VALIDATION_FAILED);
+}
+
+static size_t s_signature_length(const struct aws_ecc_key_pair *key_pair) {
+ struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl;
+
+ return ECDSA_size(libcrypto_key_pair->ec_key);
+}
+
+static int s_fill_in_public_key_info(
+ struct libcrypto_ecc_key *libcrypto_key_pair,
+ const EC_GROUP *group,
+ const EC_POINT *pub_key_point) {
+ BIGNUM *big_num_x = BN_new();
+ BIGNUM *big_num_y = BN_new();
+
+ int ret_val = AWS_OP_ERR;
+
+ if (EC_POINT_get_affine_coordinates_GFp(group, pub_key_point, big_num_x, big_num_y, NULL) != 1) {
+ aws_raise_error(AWS_ERROR_INVALID_STATE);
+ goto clean_up;
+ }
+
+ size_t x_coor_size = BN_num_bytes(big_num_x);
+ size_t y_coor_size = BN_num_bytes(big_num_y);
+
+ if (aws_byte_buf_init(&libcrypto_key_pair->key_pair.pub_x, libcrypto_key_pair->key_pair.allocator, x_coor_size)) {
+ goto clean_up;
+ }
+
+ if (aws_byte_buf_init(&libcrypto_key_pair->key_pair.pub_y, libcrypto_key_pair->key_pair.allocator, y_coor_size)) {
+ goto clean_up;
+ }
+
+ BN_bn2bin(big_num_x, libcrypto_key_pair->key_pair.pub_x.buffer);
+ BN_bn2bin(big_num_y, libcrypto_key_pair->key_pair.pub_y.buffer);
+
+ libcrypto_key_pair->key_pair.pub_x.len = x_coor_size;
+ libcrypto_key_pair->key_pair.pub_y.len = y_coor_size;
+
+ ret_val = AWS_OP_SUCCESS;
+
+clean_up:
+ BN_free(big_num_x);
+ BN_free(big_num_y);
+
+ return ret_val;
+}
+
+static int s_derive_public_key(struct aws_ecc_key_pair *key_pair) {
+ struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl;
+
+ if (!libcrypto_key_pair->key_pair.priv_d.buffer) {
+ return aws_raise_error(AWS_ERROR_INVALID_STATE);
+ }
+
+ /* we already have a public key. */
+ if (libcrypto_key_pair->key_pair.pub_x.len) {
+ return AWS_OP_SUCCESS;
+ }
+
+ BIGNUM *priv_key_num =
+ BN_bin2bn(libcrypto_key_pair->key_pair.priv_d.buffer, libcrypto_key_pair->key_pair.priv_d.len, NULL);
+
+ const EC_GROUP *group = EC_KEY_get0_group(libcrypto_key_pair->ec_key);
+ EC_POINT *point = EC_POINT_new(group);
+
+ EC_POINT_mul(group, point, priv_key_num, NULL, NULL, NULL);
+ BN_free(priv_key_num);
+
+ EC_KEY_set_public_key(libcrypto_key_pair->ec_key, point);
+ int ret_val = s_fill_in_public_key_info(libcrypto_key_pair, group, point);
+ EC_POINT_free(point);
+ return ret_val;
+}
+
+static struct aws_ecc_key_pair_vtable vtable = {
+ .sign_message = s_sign_payload,
+ .verify_signature = s_verify_payload,
+ .derive_pub_key = s_derive_public_key,
+ .signature_length = s_signature_length,
+ .destroy = s_key_pair_destroy,
+};
+
+struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_private_key(
+ struct aws_allocator *allocator,
+ enum aws_ecc_curve_name curve_name,
+ const struct aws_byte_cursor *priv_key) {
+
+ size_t key_length = aws_ecc_key_coordinate_byte_size_from_curve_name(curve_name);
+ if (priv_key->len != key_length) {
+ aws_raise_error(AWS_ERROR_CAL_INVALID_KEY_LENGTH_FOR_ALGORITHM);
+ return NULL;
+ }
+
+ struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key));
+
+ key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name));
+ key_impl->key_pair.curve_name = curve_name;
+ key_impl->key_pair.allocator = allocator;
+ key_impl->key_pair.vtable = &vtable;
+ key_impl->key_pair.impl = key_impl;
+ aws_atomic_init_int(&key_impl->key_pair.ref_count, 1);
+ aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.priv_d, allocator, *priv_key);
+
+ BIGNUM *priv_key_num = BN_bin2bn(key_impl->key_pair.priv_d.buffer, key_impl->key_pair.priv_d.len, NULL);
+ if (!EC_KEY_set_private_key(key_impl->ec_key, priv_key_num)) {
+ aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
+ BN_free(priv_key_num);
+ s_key_pair_destroy(&key_impl->key_pair);
+ return NULL;
+ }
+ BN_free(priv_key_num);
+ return &key_impl->key_pair;
+}
+
+struct aws_ecc_key_pair *aws_ecc_key_pair_new_generate_random(
+ struct aws_allocator *allocator,
+ enum aws_ecc_curve_name curve_name) {
+ struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key));
+
+ key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name));
+ key_impl->key_pair.curve_name = curve_name;
+ key_impl->key_pair.allocator = allocator;
+ key_impl->key_pair.vtable = &vtable;
+ key_impl->key_pair.impl = key_impl;
+ aws_atomic_init_int(&key_impl->key_pair.ref_count, 1);
+
+ if (EC_KEY_generate_key(key_impl->ec_key) != 1) {
+ goto error;
+ }
+
+ const EC_POINT *pub_key_point = EC_KEY_get0_public_key(key_impl->ec_key);
+ const EC_GROUP *group = EC_KEY_get0_group(key_impl->ec_key);
+
+ const BIGNUM *private_key_num = EC_KEY_get0_private_key(key_impl->ec_key);
+ size_t priv_key_size = BN_num_bytes(private_key_num);
+ if (aws_byte_buf_init(&key_impl->key_pair.priv_d, allocator, priv_key_size)) {
+ goto error;
+ }
+
+ BN_bn2bin(private_key_num, key_impl->key_pair.priv_d.buffer);
+ key_impl->key_pair.priv_d.len = priv_key_size;
+
+ if (!s_fill_in_public_key_info(key_impl, group, pub_key_point)) {
+ return &key_impl->key_pair;
+ }
+
+error:
+ s_key_pair_destroy(&key_impl->key_pair);
+ return NULL;
+}
+
+struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_public_key(
+ struct aws_allocator *allocator,
+ enum aws_ecc_curve_name curve_name,
+ const struct aws_byte_cursor *public_key_x,
+ const struct aws_byte_cursor *public_key_y) {
+ struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key));
+ BIGNUM *pub_x_num = NULL;
+ BIGNUM *pub_y_num = NULL;
+ EC_POINT *point = NULL;
+
+ if (!key_impl) {
+ return NULL;
+ }
+
+ key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name));
+ key_impl->key_pair.curve_name = curve_name;
+ key_impl->key_pair.allocator = allocator;
+ key_impl->key_pair.vtable = &vtable;
+ key_impl->key_pair.impl = key_impl;
+ aws_atomic_init_int(&key_impl->key_pair.ref_count, 1);
+
+ if (aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.pub_x, allocator, *public_key_x)) {
+ s_key_pair_destroy(&key_impl->key_pair);
+ return NULL;
+ }
+
+ if (aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.pub_y, allocator, *public_key_y)) {
+ s_key_pair_destroy(&key_impl->key_pair);
+ return NULL;
+ }
+
+ pub_x_num = BN_bin2bn(public_key_x->ptr, public_key_x->len, NULL);
+ pub_y_num = BN_bin2bn(public_key_y->ptr, public_key_y->len, NULL);
+
+ const EC_GROUP *group = EC_KEY_get0_group(key_impl->ec_key);
+ point = EC_POINT_new(group);
+
+ if (EC_POINT_set_affine_coordinates_GFp(group, point, pub_x_num, pub_y_num, NULL) != 1) {
+ goto error;
+ }
+
+ if (EC_KEY_set_public_key(key_impl->ec_key, point) != 1) {
+ goto error;
+ }
+
+ EC_POINT_free(point);
+ BN_free(pub_x_num);
+ BN_free(pub_y_num);
+
+ return &key_impl->key_pair;
+
+error:
+ if (point) {
+ EC_POINT_free(point);
+ }
+
+ if (pub_x_num) {
+ BN_free(pub_x_num);
+ }
+
+ if (pub_y_num) {
+ BN_free(pub_y_num);
+ }
+
+ s_key_pair_destroy(&key_impl->key_pair);
+
+ return NULL;
+}
+
+struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_asn1(
+ struct aws_allocator *allocator,
+ const struct aws_byte_cursor *encoded_keys) {
+
+ struct aws_ecc_key_pair *key = NULL;
+ struct aws_der_decoder *decoder = aws_der_decoder_new(allocator, *encoded_keys);
+
+ if (!decoder) {
+ return NULL;
+ }
+
+ struct aws_byte_cursor pub_x;
+ struct aws_byte_cursor pub_y;
+ struct aws_byte_cursor priv_d;
+
+ enum aws_ecc_curve_name curve_name;
+ if (aws_der_decoder_load_ecc_key_pair(decoder, &pub_x, &pub_y, &priv_d, &curve_name)) {
+ goto error;
+ }
+
+ if (priv_d.ptr) {
+ struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key));
+ key_impl->key_pair.curve_name = curve_name;
+ /* as awkward as it seems, there's not a great way to manually set the public key, so let openssl just parse
+ * the der document manually now that we know what parts are what. */
+ if (!d2i_ECPrivateKey(&key_impl->ec_key, (const unsigned char **)&encoded_keys->ptr, encoded_keys->len)) {
+ aws_mem_release(allocator, key_impl);
+ aws_raise_error(AWS_ERROR_CAL_MISSING_REQUIRED_KEY_COMPONENT);
+ goto error;
+ }
+
+ key_impl->key_pair.allocator = allocator;
+ key_impl->key_pair.vtable = &vtable;
+ key_impl->key_pair.impl = key_impl;
+ aws_atomic_init_int(&key_impl->key_pair.ref_count, 1);
+ key = &key_impl->key_pair;
+
+ struct aws_byte_buf temp_buf;
+ AWS_ZERO_STRUCT(temp_buf);
+
+ if (pub_x.ptr) {
+ temp_buf = aws_byte_buf_from_array(pub_x.ptr, pub_x.len);
+ if (aws_byte_buf_init_copy(&key->pub_x, allocator, &temp_buf)) {
+ goto error;
+ }
+ }
+
+ if (pub_y.ptr) {
+ temp_buf = aws_byte_buf_from_array(pub_y.ptr, pub_y.len);
+ if (aws_byte_buf_init_copy(&key->pub_y, allocator, &temp_buf)) {
+ goto error;
+ }
+ }
+
+ if (priv_d.ptr) {
+ temp_buf = aws_byte_buf_from_array(priv_d.ptr, priv_d.len);
+ if (aws_byte_buf_init_copy(&key->priv_d, allocator, &temp_buf)) {
+ goto error;
+ }
+ }
+
+ } else {
+ key = aws_ecc_key_pair_new_from_public_key(allocator, curve_name, &pub_x, &pub_y);
+
+ if (!key) {
+ goto error;
+ }
+ }
+
+ aws_der_decoder_destroy(decoder);
+ return key;
+
+error:
+ aws_der_decoder_destroy(decoder);
+ s_key_pair_destroy(key);
+
+ return NULL;
+}