| // Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. |
| // Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_EC_INTERNAL_H |
| #define OPENSSL_HEADER_CRYPTO_FIPSMODULE_EC_INTERNAL_H |
| |
| #include <openssl/base.h> |
| |
| #include <assert.h> |
| |
| #include <openssl/bn.h> |
| #include <openssl/ec.h> |
| #include <openssl/ex_data.h> |
| |
| #include "../../mem_internal.h" |
| #include "../bn/internal.h" |
| |
| |
| DECLARE_OPAQUE_STRUCT(ec_key_st, ECKey) |
| |
| BSSL_NAMESPACE_BEGIN |
| |
| // EC internals. |
| |
| |
| // Cap the size of all field elements and scalars, including custom curves, to |
| // 66 bytes, large enough to fit secp521r1 and brainpoolP512r1, which appear to |
| // be the largest fields anyone plausibly uses. |
| #define EC_MAX_BYTES 66 |
| #define EC_MAX_WORDS ((EC_MAX_BYTES + BN_BYTES - 1) / BN_BYTES) |
| #define EC_MAX_COMPRESSED (EC_MAX_BYTES + 1) |
| #define EC_MAX_UNCOMPRESSED (2 * EC_MAX_BYTES + 1) |
| |
| static_assert(EC_MAX_WORDS <= BN_SMALL_MAX_WORDS, |
| "bn_*_small functions not usable"); |
| |
| |
| // Scalars. |
| |
| // An EC_SCALAR is an integer fully reduced modulo the order. Only the first |
| // `order->width` words are used. An `EC_SCALAR` is specific to an `EC_GROUP` |
| // and must not be mixed between groups. |
| typedef struct { |
| BN_ULONG words[EC_MAX_WORDS]; |
| } EC_SCALAR; |
| |
| // ec_bignum_to_scalar converts `in` to an `EC_SCALAR` and writes it to |
| // `*out`. It returns one on success and zero if `in` is out of range. |
| int ec_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out, |
| const BIGNUM *in); |
| |
| // ec_scalar_to_bytes serializes `in` as a big-endian bytestring to `out` and |
| // sets `*out_len` to the number of bytes written. The number of bytes written |
| // is `BN_num_bytes(&group->order)`, which is at most `EC_MAX_BYTES`. |
| void ec_scalar_to_bytes(const EC_GROUP *group, uint8_t *out, size_t *out_len, |
| const EC_SCALAR *in); |
| |
| // ec_scalar_from_bytes deserializes `in` and stores the resulting scalar over |
| // group `group` to `out`. It returns one on success and zero if `in` is |
| // invalid. |
| int ec_scalar_from_bytes(const EC_GROUP *group, EC_SCALAR *out, |
| const uint8_t *in, size_t len); |
| |
| // ec_scalar_reduce sets `out` to `words`, reduced modulo the group order. |
| // `words` must be less than order^2. `num` must be at most twice the width of |
| // group order. This function treats `words` as secret. |
| void ec_scalar_reduce(const EC_GROUP *group, EC_SCALAR *out, |
| const BN_ULONG *words, size_t num); |
| |
| // ec_random_nonzero_scalar sets `out` to a uniformly selected random value from |
| // zero to `group->order` - 1. It returns one on success and zero on error. |
| int ec_random_scalar(const EC_GROUP *group, EC_SCALAR *out, |
| const uint8_t additional_data[32]); |
| |
| // ec_random_nonzero_scalar sets `out` to a uniformly selected random value from |
| // 1 to `group->order` - 1. It returns one on success and zero on error. |
| int ec_random_nonzero_scalar(const EC_GROUP *group, EC_SCALAR *out, |
| const uint8_t additional_data[32]); |
| |
| // ec_scalar_equal_vartime returns one if `a` and `b` are equal and zero |
| // otherwise. Both values are treated as public. |
| int ec_scalar_equal_vartime(const EC_GROUP *group, const EC_SCALAR *a, |
| const EC_SCALAR *b); |
| |
| // ec_scalar_is_zero returns one if `a` is zero and zero otherwise. |
| int ec_scalar_is_zero(const EC_GROUP *group, const EC_SCALAR *a); |
| |
| // ec_scalar_add sets `r` to `a` + `b`. |
| void ec_scalar_add(const EC_GROUP *group, EC_SCALAR *r, const EC_SCALAR *a, |
| const EC_SCALAR *b); |
| |
| // ec_scalar_sub sets `r` to `a` - `b`. |
| void ec_scalar_sub(const EC_GROUP *group, EC_SCALAR *r, const EC_SCALAR *a, |
| const EC_SCALAR *b); |
| |
| // ec_scalar_neg sets `r` to -`a`. |
| void ec_scalar_neg(const EC_GROUP *group, EC_SCALAR *r, const EC_SCALAR *a); |
| |
| // ec_scalar_to_montgomery sets `r` to `a` in Montgomery form. |
| void ec_scalar_to_montgomery(const EC_GROUP *group, EC_SCALAR *r, |
| const EC_SCALAR *a); |
| |
| // ec_scalar_to_montgomery sets `r` to `a` converted from Montgomery form. |
| void ec_scalar_from_montgomery(const EC_GROUP *group, EC_SCALAR *r, |
| const EC_SCALAR *a); |
| |
| // ec_scalar_mul_montgomery sets `r` to `a` * `b` where inputs and outputs are |
| // in Montgomery form. |
| void ec_scalar_mul_montgomery(const EC_GROUP *group, EC_SCALAR *r, |
| const EC_SCALAR *a, const EC_SCALAR *b); |
| |
| // ec_scalar_inv0_montgomery sets `r` to `a`^-1 where inputs and outputs are in |
| // Montgomery form. If `a` is zero, `r` is set to zero. |
| void ec_scalar_inv0_montgomery(const EC_GROUP *group, EC_SCALAR *r, |
| const EC_SCALAR *a); |
| |
| // ec_scalar_to_montgomery_inv_vartime sets `r` to `a`^-1 R. That is, it takes |
| // in `a` not in Montgomery form and computes the inverse in Montgomery form. It |
| // returns one on success and zero if `a` has no inverse. This function assumes |
| // `a` is public and may leak information about it via timing. |
| // |
| // Note this is not the same operation as `ec_scalar_inv0_montgomery`. |
| int ec_scalar_to_montgomery_inv_vartime(const EC_GROUP *group, EC_SCALAR *r, |
| const EC_SCALAR *a); |
| |
| // ec_scalar_select, in constant time, sets `out` to `a` if `mask` is all ones |
| // and `b` if `mask` is all zeros. |
| void ec_scalar_select(const EC_GROUP *group, EC_SCALAR *out, BN_ULONG mask, |
| const EC_SCALAR *a, const EC_SCALAR *b); |
| |
| |
| // Field elements. |
| |
| // An EC_FELEM represents a field element. Only the first `field->width` words |
| // are used. An `EC_FELEM` is specific to an `EC_GROUP` and must not be mixed |
| // between groups. Unless otherwise stated, all inputs and outputs are in |
| // Montgomery form. |
| typedef struct { |
| BN_ULONG words[EC_MAX_WORDS]; |
| } EC_FELEM; |
| |
| // ec_felem_one returns one in `group`'s field. |
| const EC_FELEM *ec_felem_one(const EC_GROUP *group); |
| |
| // ec_bignum_to_felem converts `in` to an `EC_FELEM`. It returns one on success |
| // and zero if `in` is out of range. |
| int ec_bignum_to_felem(const EC_GROUP *group, EC_FELEM *out, const BIGNUM *in); |
| |
| // ec_felem_to_bignum converts `in` to a `BIGNUM`. It returns one on success and |
| // zero on allocation failure. |
| int ec_felem_to_bignum(const EC_GROUP *group, BIGNUM *out, const EC_FELEM *in); |
| |
| // ec_felem_to_bytes serializes `in` as a big-endian bytestring to `out` and |
| // sets `*out_len` to the number of bytes written. The number of bytes written |
| // is `BN_num_bytes(&group->order)`, which is at most `EC_MAX_BYTES`. |
| void ec_felem_to_bytes(const EC_GROUP *group, uint8_t *out, size_t *out_len, |
| const EC_FELEM *in); |
| |
| // ec_felem_from_bytes deserializes `in` and stores the resulting field element |
| // to `out`. It returns one on success and zero if `in` is invalid. |
| int ec_felem_from_bytes(const EC_GROUP *group, EC_FELEM *out, const uint8_t *in, |
| size_t len); |
| |
| // ec_felem_neg sets `out` to -`a`. |
| void ec_felem_neg(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a); |
| |
| // ec_felem_add sets `out` to `a` + `b`. |
| void ec_felem_add(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a, |
| const EC_FELEM *b); |
| |
| // ec_felem_add sets `out` to `a` - `b`. |
| void ec_felem_sub(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a, |
| const EC_FELEM *b); |
| |
| // ec_felem_non_zero_mask returns all ones if `a` is non-zero and all zeros |
| // otherwise. |
| BN_ULONG ec_felem_non_zero_mask(const EC_GROUP *group, const EC_FELEM *a); |
| |
| // ec_felem_select, in constant time, sets `out` to `a` if `mask` is all ones |
| // and `b` if `mask` is all zeros. |
| void ec_felem_select(const EC_GROUP *group, EC_FELEM *out, BN_ULONG mask, |
| const EC_FELEM *a, const EC_FELEM *b); |
| |
| // ec_felem_equal returns one if `a` and `b` are equal and zero otherwise. |
| int ec_felem_equal(const EC_GROUP *group, const EC_FELEM *a, const EC_FELEM *b); |
| |
| // ec_felem_mul sets `out` to `a` * `b`. |
| void ec_felem_mul(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a, |
| const EC_FELEM *b); |
| |
| // ec_felem_sqr sets `out` to `a`^2. |
| void ec_felem_sqr(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a); |
| |
| // ec_felem_to_montgomery sets `out` to `a` converted to Montgomery form. |
| void ec_felem_to_montgomery(const EC_GROUP *group, EC_FELEM *out, |
| const EC_FELEM *a); |
| |
| // ec_felem_from_montgomery sets `out` to `a` converted from Montgomery form. |
| void ec_felem_from_montgomery(const EC_GROUP *group, EC_FELEM *out, |
| const EC_FELEM *a); |
| |
| // ec_felem_reduce sets `out` to `words`, reduced modulo the field size, p. |
| // `words` must be less than p^2. `num` must be at most twice the width of p. |
| // This function treats `words` as secret. |
| void ec_felem_reduce(const EC_GROUP *group, EC_FELEM *out, |
| const BN_ULONG *words, size_t num); |
| |
| // ec_felem_exp sets `out` to `a`^`exp`. It treats `a` is secret but `exp` as |
| // public. |
| // |
| // TODO(crbug.com/42290435): hash-to-curve uses this as part of computing a |
| // square root, which is what compressed coordinates ultimately needs to avoid |
| // `BIGNUM`. Can we unify this a bit? By generalizing to arbitrary |
| // exponentiation, we also miss an opportunity to use a specialized addition |
| // chain. We also miss our specialized field arithmetic for P-256. |
| void ec_felem_exp(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a, |
| const BN_ULONG *exp, size_t num_exp); |
| |
| |
| // Points. |
| // |
| // Points may represented in affine coordinates as `EC_AFFINE` or Jacobian |
| // coordinates as `EC_JACOBIAN`. Affine coordinates directly represent a |
| // point on the curve, but point addition over affine coordinates requires |
| // costly field inversions, so arithmetic is done in Jacobian coordinates. |
| // Converting from affine to Jacobian is cheap, while converting from Jacobian |
| // to affine costs a field inversion. (Jacobian coordinates amortize the field |
| // inversions needed in a sequence of point operations.) |
| |
| // An EC_JACOBIAN represents an elliptic curve point in Jacobian coordinates. |
| // Unlike `EC_POINT`, it is a plain struct which can be stack-allocated and |
| // needs no cleanup. It is specific to an `EC_GROUP` and must not be mixed |
| // between groups. |
| typedef struct { |
| // X, Y, and Z are Jacobian projective coordinates. They represent |
| // (X/Z^2, Y/Z^3) if Z != 0 and the point at infinity otherwise. |
| EC_FELEM X, Y, Z; |
| } EC_JACOBIAN; |
| |
| // An EC_AFFINE represents an elliptic curve point in affine coordinates. |
| // coordinates. Note the point at infinity cannot be represented in affine |
| // coordinates. |
| typedef struct { |
| EC_FELEM X, Y; |
| } EC_AFFINE; |
| |
| // ec_affine_to_jacobian converts `p` to Jacobian form and writes the result to |
| // `*out`. This operation is very cheap and only costs a few copies. |
| void ec_affine_to_jacobian(const EC_GROUP *group, EC_JACOBIAN *out, |
| const EC_AFFINE *p); |
| |
| // ec_jacobian_to_affine converts `p` to affine form and writes the result to |
| // `*out`. It returns one on success and zero if `p` was the point at infinity. |
| // This operation performs a field inversion and should only be done once per |
| // point. |
| // |
| // If only extracting the x-coordinate, use `ec_get_x_coordinate_*` which is |
| // slightly faster. |
| int ec_jacobian_to_affine(const EC_GROUP *group, EC_AFFINE *out, |
| const EC_JACOBIAN *p); |
| |
| // ec_jacobian_to_affine_batch converts `num` points in `in` from Jacobian |
| // coordinates to affine coordinates and writes the results to `out`. It returns |
| // one on success and zero if any of the input points were infinity. |
| // |
| // This function is not implemented for all curves. Add implementations as |
| // needed. |
| int ec_jacobian_to_affine_batch(const EC_GROUP *group, EC_AFFINE *out, |
| const EC_JACOBIAN *in, size_t num); |
| |
| // ec_point_set_affine_coordinates sets `out`'s to a point with affine |
| // coordinates `x` and `y`. It returns one if the point is on the curve and |
| // zero otherwise. If the point is not on the curve, the value of `out` is |
| // undefined. |
| int ec_point_set_affine_coordinates(const EC_GROUP *group, EC_AFFINE *out, |
| const EC_FELEM *x, const EC_FELEM *y); |
| |
| // ec_point_mul_no_self_test does the same as `EC_POINT_mul`, but doesn't try to |
| // run the self-test first. This is for use in the self tests themselves, to |
| // prevent an infinite loop. |
| int ec_point_mul_no_self_test(const EC_GROUP *group, EC_POINT *r, |
| const BIGNUM *g_scalar, const EC_POINT *p, |
| const BIGNUM *p_scalar, BN_CTX *ctx); |
| |
| // ec_point_mul_scalar sets `r` to `p` * `scalar`. Both inputs are considered |
| // secret. |
| int ec_point_mul_scalar(const EC_GROUP *group, EC_JACOBIAN *r, |
| const EC_JACOBIAN *p, const EC_SCALAR *scalar); |
| |
| // ec_point_mul_scalar_base sets `r` to generator * `scalar`. `scalar` is |
| // treated as secret. |
| int ec_point_mul_scalar_base(const EC_GROUP *group, EC_JACOBIAN *r, |
| const EC_SCALAR *scalar); |
| |
| // ec_point_mul_scalar_batch sets `r` to `p0` * `scalar0` + `p1` * `scalar1` + |
| // `p2` * `scalar2`. `p2` may be NULL to skip that term. |
| // |
| // The inputs are treated as secret, however, this function leaks information |
| // about whether intermediate computations add a point to itself. Callers must |
| // ensure that discrete logs between `p0`, `p1`, and `p2` are uniformly |
| // distributed and independent of the scalars, which should be uniformly |
| // selected and not under the attackers control. This ensures the doubling case |
| // will occur with negligible probability. |
| // |
| // This function is not implemented for all curves. Add implementations as |
| // needed. |
| // |
| // TODO(davidben): This function does not use base point tables. For now, it is |
| // only used with the generic `EC_GFp_mont_method` implementation which has |
| // none. If generalizing to tuned curves, this may be useful. However, we still |
| // must double up to the least efficient input, so precomputed tables can only |
| // save table setup and allow a wider window size. |
| int ec_point_mul_scalar_batch(const EC_GROUP *group, EC_JACOBIAN *r, |
| const EC_JACOBIAN *p0, const EC_SCALAR *scalar0, |
| const EC_JACOBIAN *p1, const EC_SCALAR *scalar1, |
| const EC_JACOBIAN *p2, const EC_SCALAR *scalar2); |
| |
| #define EC_MONT_PRECOMP_COMB_SIZE 5 |
| |
| // An `EC_PRECOMP` stores precomputed information about a point, to optimize |
| // repeated multiplications involving it. It is a union so different |
| // `EC_METHOD`s can store different information in it. |
| typedef union { |
| EC_AFFINE comb[(1 << EC_MONT_PRECOMP_COMB_SIZE) - 1]; |
| } EC_PRECOMP; |
| |
| // ec_init_precomp precomputes multiples of `p` and writes the result to `out`. |
| // It returns one on success and zero on error. The resulting table may be used |
| // with `ec_point_mul_scalar_precomp`. This function will fail if `p` is the |
| // point at infinity. |
| // |
| // This function is not implemented for all curves. Add implementations as |
| // needed. |
| int ec_init_precomp(const EC_GROUP *group, EC_PRECOMP *out, |
| const EC_JACOBIAN *p); |
| |
| // ec_point_mul_scalar_precomp sets `r` to `p0` * `scalar0` + `p1` * `scalar1` + |
| // `p2` * `scalar2`. `p1` or `p2` may be NULL to skip the corresponding term. |
| // The points are represented as `EC_PRECOMP` and must be initialized with |
| // `ec_init_precomp`. This function runs faster than `ec_point_mul_scalar_batch` |
| // but requires setup work per input point, so it is only appropriate for points |
| // which are used frequently. |
| // |
| // The inputs are treated as secret, however, this function leaks information |
| // about whether intermediate computations add a point to itself. Callers must |
| // ensure that discrete logs between `p0`, `p1`, and `p2` are uniformly |
| // distributed and independent of the scalars, which should be uniformly |
| // selected and not under the attackers control. This ensures the doubling case |
| // will occur with negligible probability. |
| // |
| // This function is not implemented for all curves. Add implementations as |
| // needed. |
| // |
| // TODO(davidben): This function does not use base point tables. For now, it is |
| // only used with the generic `EC_GFp_mont_method` implementation which has |
| // none. If generalizing to tuned curves, we should add a parameter for the base |
| // point and arrange for the generic implementation to have base point tables |
| // available. |
| int ec_point_mul_scalar_precomp(const EC_GROUP *group, EC_JACOBIAN *r, |
| const EC_PRECOMP *p0, const EC_SCALAR *scalar0, |
| const EC_PRECOMP *p1, const EC_SCALAR *scalar1, |
| const EC_PRECOMP *p2, const EC_SCALAR *scalar2); |
| |
| // ec_point_mul_scalar_public sets `r` to |
| // generator * `g_scalar` + `p` * `p_scalar`. It assumes that the inputs are |
| // public so there is no concern about leaking their values through timing. |
| int ec_point_mul_scalar_public(const EC_GROUP *group, EC_JACOBIAN *r, |
| const EC_SCALAR *g_scalar, const EC_JACOBIAN *p, |
| const EC_SCALAR *p_scalar); |
| |
| // ec_point_mul_scalar_public_batch sets `r` to the sum of generator * |
| // `g_scalar` and `points[i]` * `scalars[i]` where `points` and `scalars` have |
| // `num` elements. It assumes that the inputs are public so there is no concern |
| // about leaking their values through timing. `g_scalar` may be NULL to skip |
| // that term. |
| // |
| // This function is not implemented for all curves. Add implementations as |
| // needed. |
| int ec_point_mul_scalar_public_batch(const EC_GROUP *group, EC_JACOBIAN *r, |
| const EC_SCALAR *g_scalar, |
| const EC_JACOBIAN *points, |
| const EC_SCALAR *scalars, size_t num); |
| |
| // ec_point_select, in constant time, sets `out` to `a` if `mask` is all ones |
| // and `b` if `mask` is all zeros. |
| void ec_point_select(const EC_GROUP *group, EC_JACOBIAN *out, BN_ULONG mask, |
| const EC_JACOBIAN *a, const EC_JACOBIAN *b); |
| |
| // ec_affine_select behaves like `ec_point_select` but acts on affine points. |
| void ec_affine_select(const EC_GROUP *group, EC_AFFINE *out, BN_ULONG mask, |
| const EC_AFFINE *a, const EC_AFFINE *b); |
| |
| // ec_precomp_select behaves like `ec_point_select` but acts on `EC_PRECOMP`. |
| void ec_precomp_select(const EC_GROUP *group, EC_PRECOMP *out, BN_ULONG mask, |
| const EC_PRECOMP *a, const EC_PRECOMP *b); |
| |
| // ec_cmp_x_coordinate compares the x (affine) coordinate of `p`, mod the group |
| // order, with `r`. It returns one if the values match and zero if `p` is the |
| // point at infinity of the values do not match. `p` is treated as public. |
| int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_JACOBIAN *p, |
| const EC_SCALAR *r); |
| |
| // ec_get_x_coordinate_as_scalar sets `*out` to `p`'s x-coordinate, modulo |
| // `group->order`. It returns one on success and zero if `p` is the point at |
| // infinity. |
| int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out, |
| const EC_JACOBIAN *p); |
| |
| // ec_get_x_coordinate_as_bytes writes `p`'s affine x-coordinate to `out`, which |
| // must have at must `max_out` bytes. It sets `*out_len` to the number of bytes |
| // written. The value is written big-endian and zero-padded to the size of the |
| // field. This function returns one on success and zero on failure. |
| int ec_get_x_coordinate_as_bytes(const EC_GROUP *group, uint8_t *out, |
| size_t *out_len, size_t max_out, |
| const EC_JACOBIAN *p); |
| |
| // ec_point_byte_len returns the number of bytes in the byte representation of |
| // a non-infinity point in `group`, encoded according to `form`, or zero if |
| // `form` is invalid. |
| size_t ec_point_byte_len(const EC_GROUP *group, point_conversion_form_t form); |
| |
| // ec_point_to_bytes encodes `point` according to `form` and writes the result |
| // `buf`. It returns the size of the output on success or zero on error. At most |
| // `max_out` bytes will be written. The buffer should be at least |
| // `ec_point_byte_len` long to guarantee success. |
| size_t ec_point_to_bytes(const EC_GROUP *group, const EC_AFFINE *point, |
| point_conversion_form_t form, uint8_t *buf, |
| size_t max_out); |
| |
| // ec_point_from_uncompressed parses `in` as a point in uncompressed form and |
| // sets the result to `out`. It returns one on success and zero if the input was |
| // invalid. |
| int ec_point_from_uncompressed(const EC_GROUP *group, EC_AFFINE *out, |
| const uint8_t *in, size_t len); |
| |
| // ec_set_to_safe_point sets `out` to an arbitrary point on `group`, either the |
| // generator or the point at infinity. This is used to guard against callers of |
| // external APIs not checking the return value. |
| void ec_set_to_safe_point(const EC_GROUP *group, EC_JACOBIAN *out); |
| |
| // ec_affine_jacobian_equal returns one if `a` and `b` represent the same point |
| // and zero otherwise. It treats both inputs as secret. |
| int ec_affine_jacobian_equal(const EC_GROUP *group, const EC_AFFINE *a, |
| const EC_JACOBIAN *b); |
| |
| BSSL_NAMESPACE_END |
| |
| // Implementation details. |
| |
| struct ec_method_st { |
| // point_get_affine_coordinates sets `*x` and `*y` to the affine coordinates |
| // of `p`. Either `x` or `y` may be NULL to omit it. It returns one on success |
| // and zero if `p` is the point at infinity. It leaks whether `p` was the |
| // point at infinity, but otherwise treats `p` as secret. |
| int (*point_get_affine_coordinates)(const EC_GROUP *, |
| const bssl::EC_JACOBIAN *p, |
| bssl::EC_FELEM *x, bssl::EC_FELEM *y); |
| |
| // jacobian_to_affine_batch implements `ec_jacobian_to_affine_batch`. |
| int (*jacobian_to_affine_batch)(const EC_GROUP *group, bssl::EC_AFFINE *out, |
| const bssl::EC_JACOBIAN *in, size_t num); |
| |
| // add sets `r` to `a` + `b`. |
| void (*add)(const EC_GROUP *group, bssl::EC_JACOBIAN *r, |
| const bssl::EC_JACOBIAN *a, const bssl::EC_JACOBIAN *b); |
| // dbl sets `r` to `a` + `a`. |
| void (*dbl)(const EC_GROUP *group, bssl::EC_JACOBIAN *r, |
| const bssl::EC_JACOBIAN *a); |
| |
| // mul sets `r` to `scalar`*`p`. |
| void (*mul)(const EC_GROUP *group, bssl::EC_JACOBIAN *r, |
| const bssl::EC_JACOBIAN *p, const bssl::EC_SCALAR *scalar); |
| // mul_base sets `r` to `scalar`*generator. |
| void (*mul_base)(const EC_GROUP *group, bssl::EC_JACOBIAN *r, |
| const bssl::EC_SCALAR *scalar); |
| // mul_batch implements `ec_mul_scalar_batch`. |
| void (*mul_batch)(const EC_GROUP *group, bssl::EC_JACOBIAN *r, |
| const bssl::EC_JACOBIAN *p0, const bssl::EC_SCALAR *scalar0, |
| const bssl::EC_JACOBIAN *p1, const bssl::EC_SCALAR *scalar1, |
| const bssl::EC_JACOBIAN *p2, |
| const bssl::EC_SCALAR *scalar2); |
| // mul_public sets `r` to `g_scalar`*generator + `p_scalar`*`p`. It assumes |
| // that the inputs are public so there is no concern about leaking their |
| // values through timing. |
| // |
| // This function may be omitted if `mul_public_batch` is provided. |
| void (*mul_public)(const EC_GROUP *group, bssl::EC_JACOBIAN *r, |
| const bssl::EC_SCALAR *g_scalar, |
| const bssl::EC_JACOBIAN *p, |
| const bssl::EC_SCALAR *p_scalar); |
| // mul_public_batch implements `ec_point_mul_scalar_public_batch`. |
| int (*mul_public_batch)(const EC_GROUP *group, bssl::EC_JACOBIAN *r, |
| const bssl::EC_SCALAR *g_scalar, |
| const bssl::EC_JACOBIAN *points, |
| const bssl::EC_SCALAR *scalars, size_t num); |
| |
| // init_precomp implements `ec_init_precomp`. |
| int (*init_precomp)(const EC_GROUP *group, bssl::EC_PRECOMP *out, |
| const bssl::EC_JACOBIAN *p); |
| // mul_precomp implements `ec_point_mul_scalar_precomp`. |
| void (*mul_precomp)(const EC_GROUP *group, bssl::EC_JACOBIAN *r, |
| const bssl::EC_PRECOMP *p0, |
| const bssl::EC_SCALAR *scalar0, |
| const bssl::EC_PRECOMP *p1, |
| const bssl::EC_SCALAR *scalar1, |
| const bssl::EC_PRECOMP *p2, |
| const bssl::EC_SCALAR *scalar2); |
| |
| // scalar_inv0_montgomery implements `ec_scalar_inv0_montgomery`. |
| void (*scalar_inv0_montgomery)(const EC_GROUP *group, bssl::EC_SCALAR *out, |
| const bssl::EC_SCALAR *in); |
| |
| // scalar_to_montgomery_inv_vartime implements |
| // `ec_scalar_to_montgomery_inv_vartime`. |
| int (*scalar_to_montgomery_inv_vartime)(const EC_GROUP *group, |
| bssl::EC_SCALAR *out, |
| const bssl::EC_SCALAR *in); |
| |
| // cmp_x_coordinate compares the x (affine) coordinate of `p`, mod the group |
| // order, with `r`. It returns one if the values match and zero if `p` is the |
| // point at infinity of the values do not match. |
| int (*cmp_x_coordinate)(const EC_GROUP *group, const bssl::EC_JACOBIAN *p, |
| const bssl::EC_SCALAR *r); |
| } /* EC_METHOD */; |
| |
| BSSL_NAMESPACE_BEGIN |
| |
| const EC_METHOD *EC_GFp_mont_method(); |
| |
| BSSL_NAMESPACE_END |
| |
| struct ec_point_st { |
| // group is an owning reference to `group`, unless this is |
| // `group->generator`. |
| EC_GROUP *group; |
| // raw is the group-specific point data. Functions that take `EC_POINT` |
| // typically check consistency with `EC_GROUP` while functions that take |
| // `EC_JACOBIAN` do not. Thus accesses to this field should be externally |
| // checked for consistency. |
| bssl::EC_JACOBIAN raw; |
| } /* EC_POINT */; |
| |
| struct ec_group_st { |
| const EC_METHOD *meth; |
| |
| // Unlike all other `EC_POINT`s, `generator` does not own `generator->group` |
| // to avoid a reference cycle. Additionally, Z is guaranteed to be one, so X |
| // and Y are suitable for use as an `EC_AFFINE`. Before `has_order` is set, Z |
| // is one, but X and Y are uninitialized. |
| EC_POINT generator; |
| |
| BN_MONT_CTX order; |
| BN_MONT_CTX field; |
| |
| bssl::EC_FELEM a, b; // Curve coefficients. |
| |
| // comment is a human-readable string describing the curve. |
| const char *comment; |
| |
| // curve_name is the optional NID for named curve. |
| // |
| // If curve_name is NID_undef, the actual type is ECCustomGroup and the |
| // refcount must be respected when allocating/freeing. |
| int curve_name; |
| |
| uint8_t oid[9]; |
| uint8_t oid_len; |
| |
| // a_is_minus3 is one if `a` is -3 mod `field` and zero otherwise. Point |
| // arithmetic is optimized for -3. |
| int a_is_minus3; |
| |
| // has_order is one if `generator` and `order` have been initialized. |
| int has_order; |
| |
| // field_greater_than_order is one if `field` is greater than `order` and zero |
| // otherwise. |
| int field_greater_than_order; |
| } /* EC_GROUP */; |
| |
| BSSL_NAMESPACE_BEGIN |
| |
| class ECCustomGroup : public ec_group_st, public RefCounted<ECCustomGroup> { |
| public: |
| explicit ECCustomGroup(const EC_METHOD *meth); |
| |
| private: |
| ~ECCustomGroup(); |
| friend RefCounted; |
| }; |
| |
| EC_GROUP *ec_group_new(const EC_METHOD *meth, const BIGNUM *p, const BIGNUM *a, |
| const BIGNUM *b, BN_CTX *ctx); |
| |
| void ec_GFp_mont_mul(const EC_GROUP *group, EC_JACOBIAN *r, |
| const EC_JACOBIAN *p, const EC_SCALAR *scalar); |
| void ec_GFp_mont_mul_base(const EC_GROUP *group, EC_JACOBIAN *r, |
| const EC_SCALAR *scalar); |
| void ec_GFp_mont_mul_batch(const EC_GROUP *group, EC_JACOBIAN *r, |
| const EC_JACOBIAN *p0, const EC_SCALAR *scalar0, |
| const EC_JACOBIAN *p1, const EC_SCALAR *scalar1, |
| const EC_JACOBIAN *p2, const EC_SCALAR *scalar2); |
| int ec_GFp_mont_init_precomp(const EC_GROUP *group, EC_PRECOMP *out, |
| const EC_JACOBIAN *p); |
| void ec_GFp_mont_mul_precomp(const EC_GROUP *group, EC_JACOBIAN *r, |
| const EC_PRECOMP *p0, const EC_SCALAR *scalar0, |
| const EC_PRECOMP *p1, const EC_SCALAR *scalar1, |
| const EC_PRECOMP *p2, const EC_SCALAR *scalar2); |
| |
| // ec_compute_wNAF writes the modified width-(w+1) Non-Adjacent Form (wNAF) of |
| // `scalar` to `out`. `out` must have room for `bits` + 1 elements, each of |
| // which will be either zero or odd with an absolute value less than 2^w |
| // satisfying |
| // scalar = \sum_j out[j]*2^j |
| // where at most one of any w+1 consecutive digits is non-zero |
| // with the exception that the most significant digit may be only |
| // w-1 zeros away from that next non-zero digit. |
| void ec_compute_wNAF(const EC_GROUP *group, int8_t *out, |
| const EC_SCALAR *scalar, size_t bits, int w); |
| |
| int ec_GFp_mont_mul_public_batch(const EC_GROUP *group, EC_JACOBIAN *r, |
| const EC_SCALAR *g_scalar, |
| const EC_JACOBIAN *points, |
| const EC_SCALAR *scalars, size_t num); |
| |
| // method functions in simple.c |
| int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, |
| const BIGNUM *b, BN_CTX *); |
| int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, |
| BIGNUM *b); |
| void ec_GFp_simple_point_init(EC_JACOBIAN *); |
| void ec_GFp_simple_point_copy(EC_JACOBIAN *, const EC_JACOBIAN *); |
| void ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_JACOBIAN *); |
| void ec_GFp_mont_add(const EC_GROUP *, EC_JACOBIAN *r, const EC_JACOBIAN *a, |
| const EC_JACOBIAN *b); |
| void ec_GFp_mont_dbl(const EC_GROUP *, EC_JACOBIAN *r, const EC_JACOBIAN *a); |
| void ec_GFp_simple_invert(const EC_GROUP *, EC_JACOBIAN *); |
| int ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_JACOBIAN *); |
| int ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_JACOBIAN *); |
| int ec_GFp_simple_points_equal(const EC_GROUP *, const EC_JACOBIAN *a, |
| const EC_JACOBIAN *b); |
| void ec_simple_scalar_inv0_montgomery(const EC_GROUP *group, EC_SCALAR *r, |
| const EC_SCALAR *a); |
| |
| int ec_simple_scalar_to_montgomery_inv_vartime(const EC_GROUP *group, |
| EC_SCALAR *r, |
| const EC_SCALAR *a); |
| |
| int ec_GFp_simple_cmp_x_coordinate(const EC_GROUP *group, const EC_JACOBIAN *p, |
| const EC_SCALAR *r); |
| |
| void ec_GFp_nistp_recode_scalar_bits(crypto_word_t *sign, crypto_word_t *digit, |
| crypto_word_t in); |
| |
| const EC_METHOD *EC_GFp_nistp256_method(); |
| |
| // EC_GFp_nistz256_method is a GFp method using montgomery multiplication, with |
| // x86-64 optimized P256. See http://eprint.iacr.org/2013/816. |
| const EC_METHOD *EC_GFp_nistz256_method(); |
| |
| // An EC_WRAPPED_SCALAR is an `EC_SCALAR` with a parallel `BIGNUM` |
| // representation. It exists to support the `EC_KEY_get0_private_key` API. |
| typedef struct { |
| BIGNUM bignum; |
| EC_SCALAR scalar; |
| } EC_WRAPPED_SCALAR; |
| |
| class ECKey : public ec_key_st, public RefCounted<ECKey> { |
| public: |
| explicit ECKey(const ENGINE *engine); |
| |
| EC_GROUP *group = nullptr; |
| |
| // Ideally `pub_key` would be an `EC_AFFINE` so serializing it does not pay an |
| // inversion each time, but the `EC_KEY_get0_public_key` API implies public |
| // keys are stored in an `EC_POINT`-compatible form. |
| EC_POINT *pub_key = nullptr; |
| bssl::EC_WRAPPED_SCALAR *priv_key = nullptr; |
| |
| unsigned int enc_flag = 0; |
| point_conversion_form_t conv_form = POINT_CONVERSION_UNCOMPRESSED; |
| |
| ECDSA_METHOD *ecdsa_meth = nullptr; |
| |
| CRYPTO_EX_DATA ex_data = {}; |
| |
| private: |
| ~ECKey(); |
| friend RefCounted; |
| } /* EC_KEY */; |
| |
| BSSL_NAMESPACE_END |
| |
| |
| #endif // OPENSSL_HEADER_CRYPTO_FIPSMODULE_EC_INTERNAL_H |