in source/ecc.c [194:283]
int aws_der_decoder_load_ecc_key_pair(
struct aws_der_decoder *decoder,
struct aws_byte_cursor *out_public_x_coor,
struct aws_byte_cursor *out_public_y_coor,
struct aws_byte_cursor *out_private_d,
enum aws_ecc_curve_name *out_curve_name) {
AWS_ZERO_STRUCT(*out_public_x_coor);
AWS_ZERO_STRUCT(*out_public_y_coor);
AWS_ZERO_STRUCT(*out_private_d);
/* we could have private key or a public key, or a full pair. */
struct aws_byte_cursor pair_part_1;
AWS_ZERO_STRUCT(pair_part_1);
struct aws_byte_cursor pair_part_2;
AWS_ZERO_STRUCT(pair_part_2);
bool curve_name_recognized = false;
/* work with this pointer and move it to the next after using it. We need
* to know which curve we're dealing with before we can figure out which is which. */
struct aws_byte_cursor *current_part = &pair_part_1;
while (aws_der_decoder_next(decoder)) {
enum aws_der_type type = aws_der_decoder_tlv_type(decoder);
if (type == AWS_DER_OBJECT_IDENTIFIER) {
struct aws_byte_cursor oid;
AWS_ZERO_STRUCT(oid);
aws_der_decoder_tlv_blob(decoder, &oid);
/* There can be other OID's so just look for one that is the curve. */
if (!aws_ecc_curve_name_from_oid(&oid, out_curve_name)) {
curve_name_recognized = true;
}
continue;
}
/* you'd think we'd get some type hints on which key this is, but it's not consistent
* as far as I can tell. */
if (type == AWS_DER_BIT_STRING || type == AWS_DER_OCTET_STRING) {
aws_der_decoder_tlv_string(decoder, current_part);
current_part = &pair_part_2;
}
}
if (!curve_name_recognized) {
return aws_raise_error(AWS_ERROR_CAL_UNKNOWN_OBJECT_IDENTIFIER);
}
size_t key_coordinate_size = aws_ecc_key_coordinate_byte_size_from_curve_name(*out_curve_name);
struct aws_byte_cursor *private_key = NULL;
struct aws_byte_cursor *public_key = NULL;
size_t public_key_blob_size = key_coordinate_size * 2 + 1;
if (pair_part_1.ptr && pair_part_1.len) {
if (pair_part_1.len == key_coordinate_size) {
private_key = &pair_part_1;
} else if (pair_part_1.len == public_key_blob_size) {
public_key = &pair_part_1;
}
}
if (pair_part_2.ptr && pair_part_2.len) {
if (pair_part_2.len == key_coordinate_size) {
private_key = &pair_part_2;
} else if (pair_part_2.len == public_key_blob_size) {
public_key = &pair_part_2;
}
}
if (!private_key && !public_key) {
return aws_raise_error(AWS_ERROR_CAL_MISSING_REQUIRED_KEY_COMPONENT);
}
if (private_key) {
*out_private_d = *private_key;
}
if (public_key) {
aws_byte_cursor_advance(public_key, 1);
*out_public_x_coor = *public_key;
out_public_x_coor->len = key_coordinate_size;
out_public_y_coor->ptr = public_key->ptr + key_coordinate_size;
out_public_y_coor->len = key_coordinate_size;
}
return AWS_OP_SUCCESS;
}