int aws_der_decoder_load_ecc_key_pair()

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;
}