diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
commit | 718c552901d703c502ccbefdfc3c9028d608b947 (patch) | |
tree | 46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_ecc.c | |
parent | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff) | |
download | ydb-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.c | 748 |
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; +} |