wpa_supplicant: Implement BIGNUM and ECC crypto wrapper apis for ESP using mbedtls

This commit is contained in:
Sagar Bijwe 2018-08-31 19:25:48 +05:30
parent df215d2f02
commit 112244bac4
7 changed files with 1520 additions and 1 deletions

View File

@ -140,6 +140,11 @@ static void test_bignum_modexp(const char *z_str, const char *x_str, const char
mbedtls_mpi_write_string(&Z, 16, z_buf, sizeof(z_buf)-1, &z_buf_len);
TEST_ASSERT_EQUAL_STRING_MESSAGE(z_str, z_buf, "mbedtls_mpi_exp_mod incorrect");
mbedtls_mpi_free(&Z);
mbedtls_mpi_free(&X);
mbedtls_mpi_free(&Y);
mbedtls_mpi_free(&M);
}
TEST_CASE("test MPI modexp", "[bignum]")

View File

@ -6,6 +6,7 @@ set(COMPONENT_SRCS "port/os_xtensa.c"
"src/crypto/aes-unwrap.c"
"src/crypto/aes-wrap.c"
"src/crypto/bignum.c"
"src/crypto/crypto_mbedtls.c"
"src/crypto/crypto_internal-cipher.c"
"src/crypto/crypto_internal-modexp.c"
"src/crypto/crypto_internal-rsa.c"
@ -94,4 +95,5 @@ component_compile_definitions(
USE_WPS_TASK
ESPRESSIF_USE
ESP32_WORKAROUND
CONFIG_ECC
)

View File

@ -1,4 +1,4 @@
COMPONENT_ADD_INCLUDEDIRS := include port/include
COMPONENT_SRCDIRS := src/crypto port src/fast_crypto src/wpa2/eap_peer src/wpa2/tls src/wpa2/utils src/wps
CFLAGS += -DEMBEDDED_SUPP -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_MSCHAPv2 -DEAP_TTLS -DEAP_TLS -DEAP_PEAP -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -D__ets__ -Wno-strict-aliasing
CFLAGS += -DEMBEDDED_SUPP -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_MSCHAPv2 -DEAP_TTLS -DEAP_TLS -DEAP_PEAP -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -D__ets__ -DCONFIG_ECC -Wno-strict-aliasing

View File

@ -606,4 +606,363 @@ int __must_check fast_crypto_mod_exp(const uint8_t *base, size_t base_len,
int rc4_skip(const u8 *key, size_t keylen, size_t skip,
u8 *data, size_t data_len);
/**
* crypto_get_random - Generate cryptographically strong pseudy-random bytes
* @buf: Buffer for data
* @len: Number of bytes to generate
* Returns: 0 on success, -1 on failure
*
* If the PRNG does not have enough entropy to ensure unpredictable byte
* sequence, this functions must return -1.
*/
int crypto_get_random(void *buf, size_t len);
/**
* struct crypto_bignum - bignum
*
* Internal data structure for bignum implementation. The contents is specific
* to the used crypto library.
*/
struct crypto_bignum;
/**
* crypto_bignum_init - Allocate memory for bignum
* Returns: Pointer to allocated bignum or %NULL on failure
*/
struct crypto_bignum * crypto_bignum_init(void);
/**
* crypto_bignum_init_set - Allocate memory for bignum and set the value
* @buf: Buffer with unsigned binary value
* @len: Length of buf in octets
* Returns: Pointer to allocated bignum or %NULL on failure
*/
struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len);
/**
* crypto_bignum_deinit - Free bignum
* @n: Bignum from crypto_bignum_init() or crypto_bignum_init_set()
* @clear: Whether to clear the value from memory
*/
void crypto_bignum_deinit(struct crypto_bignum *n, int clear);
/**
* crypto_bignum_to_bin - Set binary buffer to unsigned bignum
* @a: Bignum
* @buf: Buffer for the binary number
* @len: Length of @buf in octets
* @padlen: Length in octets to pad the result to or 0 to indicate no padding
* Returns: Number of octets written on success, -1 on failure
*/
int crypto_bignum_to_bin(const struct crypto_bignum *a,
u8 *buf, size_t buflen, size_t padlen);
/**
* crypto_bignum_add - c = a + b
* @a: Bignum
* @b: Bignum
* @c: Bignum; used to store the result of a + b
* Returns: 0 on success, -1 on failure
*/
int crypto_bignum_add(const struct crypto_bignum *a,
const struct crypto_bignum *b,
struct crypto_bignum *c);
/**
* crypto_bignum_mod - c = a % b
* @a: Bignum
* @b: Bignum
* @c: Bignum; used to store the result of a % b
* Returns: 0 on success, -1 on failure
*/
int crypto_bignum_mod(const struct crypto_bignum *a,
const struct crypto_bignum *b,
struct crypto_bignum *c);
/**
* crypto_bignum_exptmod - Modular exponentiation: d = a^b (mod c)
* @a: Bignum; base
* @b: Bignum; exponent
* @c: Bignum; modulus
* @d: Bignum; used to store the result of a^b (mod c)
* Returns: 0 on success, -1 on failure
*/
int crypto_bignum_exptmod(const struct crypto_bignum *a,
const struct crypto_bignum *b,
const struct crypto_bignum *c,
struct crypto_bignum *d);
/**
* crypto_bignum_inverse - Inverse a bignum so that a * c = 1 (mod b)
* @a: Bignum
* @b: Bignum
* @c: Bignum; used to store the result
* Returns: 0 on success, -1 on failure
*/
int crypto_bignum_inverse(const struct crypto_bignum *a,
const struct crypto_bignum *b,
struct crypto_bignum *c);
/**
* crypto_bignum_sub - c = a - b
* @a: Bignum
* @b: Bignum
* @c: Bignum; used to store the result of a - b
* Returns: 0 on success, -1 on failure
*/
int crypto_bignum_sub(const struct crypto_bignum *a,
const struct crypto_bignum *b,
struct crypto_bignum *c);
/**
* crypto_bignum_div - c = a / b
* @a: Bignum
* @b: Bignum
* @c: Bignum; used to store the result of a / b
* Returns: 0 on success, -1 on failure
*/
int crypto_bignum_div(const struct crypto_bignum *a,
const struct crypto_bignum *b,
struct crypto_bignum *c);
/**
* crypto_bignum_mulmod - d = a * b (mod c)
* @a: Bignum
* @b: Bignum
* @c: Bignum
* @d: Bignum; used to store the result of (a * b) % c
* Returns: 0 on success, -1 on failure
*/
int crypto_bignum_mulmod(const struct crypto_bignum *a,
const struct crypto_bignum *b,
const struct crypto_bignum *c,
struct crypto_bignum *d);
/**
* crypto_bignum_cmp - Compare two bignums
* @a: Bignum
* @b: Bignum
* Returns: -1 if a < b, 0 if a == b, or 1 if a > b
*/
int crypto_bignum_cmp(const struct crypto_bignum *a,
const struct crypto_bignum *b);
/**
* crypto_bignum_bits - Get size of a bignum in bits
* @a: Bignum
* Returns: Number of bits in the bignum
*/
int crypto_bignum_bits(const struct crypto_bignum *a);
/**
* crypto_bignum_is_zero - Is the given bignum zero
* @a: Bignum
* Returns: 1 if @a is zero or 0 if not
*/
int crypto_bignum_is_zero(const struct crypto_bignum *a);
/**
* crypto_bignum_is_one - Is the given bignum one
* @a: Bignum
* Returns: 1 if @a is one or 0 if not
*/
int crypto_bignum_is_one(const struct crypto_bignum *a);
/**
* crypto_bignum_legendre - Compute the Legendre symbol (a/p)
* @a: Bignum
* @p: Bignum
* Returns: Legendre symbol -1,0,1 on success; -2 on calculation failure
*/
int crypto_bignum_legendre(const struct crypto_bignum *a,
const struct crypto_bignum *p);
/**
* struct crypto_ec - Elliptic curve context
*
* Internal data structure for EC implementation. The contents is specific
* to the used crypto library.
*/
struct crypto_ec;
/**
* crypto_ec_init - Initialize elliptic curve context
* @group: Identifying number for the ECC group (IANA "Group Description"
* attribute registrty for RFC 2409)
* Returns: Pointer to EC context or %NULL on failure
*/
struct crypto_ec * crypto_ec_init(int group);
/**
* crypto_ec_deinit - Deinitialize elliptic curve context
* @e: EC context from crypto_ec_init()
*/
void crypto_ec_deinit(struct crypto_ec *e);
/**
* crypto_ec_prime_len - Get length of the prime in octets
* @e: EC context from crypto_ec_init()
* Returns: Length of the prime defining the group
*/
size_t crypto_ec_prime_len(struct crypto_ec *e);
/**
* crypto_ec_prime_len_bits - Get length of the prime in bits
* @e: EC context from crypto_ec_init()
* Returns: Length of the prime defining the group in bits
*/
size_t crypto_ec_prime_len_bits(struct crypto_ec *e);
/**
* crypto_ec_get_prime - Get prime defining an EC group
* @e: EC context from crypto_ec_init()
* Returns: Prime (bignum) defining the group
*/
const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e);
/**
* crypto_ec_get_order - Get order of an EC group
* @e: EC context from crypto_ec_init()
* Returns: Order (bignum) of the group
*/
const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e);
/**
* struct crypto_ec_point - Elliptic curve point
*
* Internal data structure for EC implementation to represent a point. The
* contents is specific to the used crypto library.
*/
struct crypto_ec_point;
/**
* crypto_ec_point_init - Initialize data for an EC point
* @e: EC context from crypto_ec_init()
* Returns: Pointer to EC point data or %NULL on failure
*/
struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e);
/**
* crypto_ec_point_deinit - Deinitialize EC point data
* @p: EC point data from crypto_ec_point_init()
* @clear: Whether to clear the EC point value from memory
*/
void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear);
/**
* crypto_ec_point_to_bin - Write EC point value as binary data
* @e: EC context from crypto_ec_init()
* @p: EC point data from crypto_ec_point_init()
* @x: Buffer for writing the binary data for x coordinate or %NULL if not used
* @y: Buffer for writing the binary data for y coordinate or %NULL if not used
* Returns: 0 on success, -1 on failure
*
* This function can be used to write an EC point as binary data in a format
* that has the x and y coordinates in big endian byte order fields padded to
* the length of the prime defining the group.
*/
int crypto_ec_point_to_bin(struct crypto_ec *e,
const struct crypto_ec_point *point, u8 *x, u8 *y);
/**
* crypto_ec_point_from_bin - Create EC point from binary data
* @e: EC context from crypto_ec_init()
* @val: Binary data to read the EC point from
* Returns: Pointer to EC point data or %NULL on failure
*
* This function readers x and y coordinates of the EC point from the provided
* buffer assuming the values are in big endian byte order with fields padded to
* the length of the prime defining the group.
*/
struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
const u8 *val);
/**
* crypto_bignum_add - c = a + b
* @e: EC context from crypto_ec_init()
* @a: Bignum
* @b: Bignum
* @c: Bignum; used to store the result of a + b
* Returns: 0 on success, -1 on failure
*/
int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
const struct crypto_ec_point *b,
struct crypto_ec_point *c);
/**
* crypto_bignum_mul - res = b * p
* @e: EC context from crypto_ec_init()
* @p: EC point
* @b: Bignum
* @res: EC point; used to store the result of b * p
* Returns: 0 on success, -1 on failure
*/
int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
const struct crypto_bignum *b,
struct crypto_ec_point *res);
/**
* crypto_ec_point_invert - Compute inverse of an EC point
* @e: EC context from crypto_ec_init()
* @p: EC point to invert (and result of the operation)
* Returns: 0 on success, -1 on failure
*/
int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p);
/**
* crypto_ec_point_solve_y_coord - Solve y coordinate for an x coordinate
* @e: EC context from crypto_ec_init()
* @p: EC point to use for the returning the result
* @x: x coordinate
* @y_bit: y-bit (0 or 1) for selecting the y value to use
* Returns: 0 on success, -1 on failure
*/
int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
struct crypto_ec_point *p,
const struct crypto_bignum *x, int y_bit);
/**
* crypto_ec_point_compute_y_sqr - Compute y^2 = x^3 + ax + b
* @e: EC context from crypto_ec_init()
* @x: x coordinate
* Returns: y^2 on success, %NULL failure
*/
struct crypto_bignum *
crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
const struct crypto_bignum *x);
/**
* crypto_ec_point_is_at_infinity - Check whether EC point is neutral element
* @e: EC context from crypto_ec_init()
* @p: EC point
* Returns: 1 if the specified EC point is the neutral element of the group or
* 0 if not
*/
int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
const struct crypto_ec_point *p);
/**
* crypto_ec_point_is_on_curve - Check whether EC point is on curve
* @e: EC context from crypto_ec_init()
* @p: EC point
* Returns: 1 if the specified EC point is on the curve or 0 if not
*/
int crypto_ec_point_is_on_curve(struct crypto_ec *e,
const struct crypto_ec_point *p);
/**
* crypto_ec_point_cmp - Compare two EC points
* @e: EC context from crypto_ec_init()
* @a: EC point
* @b: EC point
* Returns: 0 on equal, non-zero otherwise
*/
int crypto_ec_point_cmp(const struct crypto_ec *e,
const struct crypto_ec_point *a,
const struct crypto_ec_point *b);
#endif /* CRYPTO_H */

View File

@ -0,0 +1,603 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// 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
// http://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.
#include "crypto/includes.h"
#include "crypto/common.h"
#include "crypto/crypto.h"
#include "mbedtls/ecp.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#ifdef ESP_PLATFORM
#include "esp_system.h"
#include "mbedtls/bignum.h"
#endif
#define IANA_SECP256R1 19
#ifdef ESP_PLATFORM
int crypto_get_random(void *buf, size_t len)
{
if (!buf) {
return -1;
}
esp_fill_random(buf, len);
return 0;
}
#endif
struct crypto_bignum *crypto_bignum_init(void)
{
mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi));
if (bn == NULL) {
return NULL;
}
mbedtls_mpi_init(bn);
return (struct crypto_bignum *)bn;
}
struct crypto_bignum *crypto_bignum_init_set(const u8 *buf, size_t len)
{
int ret = 0;
mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi));
if (bn == NULL) {
return NULL;
}
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(bn, buf, len));
return (struct crypto_bignum *) bn;
cleanup:
os_free(bn);
return NULL;
}
void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
{
mbedtls_mpi_free((mbedtls_mpi *)n);
os_free((mbedtls_mpi *)n);
}
int crypto_bignum_to_bin(const struct crypto_bignum *a,
u8 *buf, size_t buflen, size_t padlen)
{
int num_bytes, offset;
if (padlen > buflen) {
return -1;
}
num_bytes = mbedtls_mpi_size((mbedtls_mpi *) a);
if ((size_t) num_bytes > buflen) {
return -1;
}
if (padlen > (size_t) num_bytes) {
offset = padlen - num_bytes;
} else {
offset = 0;
}
os_memset(buf, 0, offset);
mbedtls_mpi_write_binary((mbedtls_mpi *) a, buf + offset, mbedtls_mpi_size((mbedtls_mpi *)a) );
return num_bytes + offset;
}
int crypto_bignum_add(const struct crypto_bignum *a,
const struct crypto_bignum *b,
struct crypto_bignum *c)
{
return mbedtls_mpi_add_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
-1 : 0;
}
int crypto_bignum_mod(const struct crypto_bignum *a,
const struct crypto_bignum *b,
struct crypto_bignum *c)
{
return mbedtls_mpi_mod_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ? -1 : 0;
}
int crypto_bignum_exptmod(const struct crypto_bignum *a,
const struct crypto_bignum *b,
const struct crypto_bignum *c,
struct crypto_bignum *d)
{
return mbedtls_mpi_exp_mod((mbedtls_mpi *) d, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b, (const mbedtls_mpi *) c, NULL) ? -1 : 0;
}
int crypto_bignum_inverse(const struct crypto_bignum *a,
const struct crypto_bignum *b,
struct crypto_bignum *c)
{
return mbedtls_mpi_inv_mod((mbedtls_mpi *) c, (const mbedtls_mpi *) a,
(const mbedtls_mpi *) b) ? -1 : 0;
}
int crypto_bignum_sub(const struct crypto_bignum *a,
const struct crypto_bignum *b,
struct crypto_bignum *c)
{
return mbedtls_mpi_sub_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
-1 : 0;
}
int crypto_bignum_div(const struct crypto_bignum *a,
const struct crypto_bignum *b,
struct crypto_bignum *c)
{
return mbedtls_mpi_div_mpi((mbedtls_mpi *) c, NULL, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
-1 : 0;
}
int crypto_bignum_mulmod(const struct crypto_bignum *a,
const struct crypto_bignum *b,
const struct crypto_bignum *c,
struct crypto_bignum *d)
{
int res;
#if ALLOW_EVEN_MOD // Must enable this macro if c is even.
mbedtls_mpi temp;
mbedtls_mpi_init(&temp);
res = mbedtls_mpi_mul_mpi(&temp, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b);
if (res) {
return -1;
}
res = mbedtls_mpi_mod_mpi((mbedtls_mpi *) d, &temp, (mbedtls_mpi *) c);
mbedtls_mpi_free(&temp);
#else
// Works with odd modulus only, but it is faster with HW acceleration
res = esp_mpi_mul_mpi_mod((mbedtls_mpi *) d, (mbedtls_mpi *) a, (mbedtls_mpi *) b, (mbedtls_mpi *) c);
#endif
return res ? -1 : 0;
}
int crypto_bignum_cmp(const struct crypto_bignum *a,
const struct crypto_bignum *b)
{
return mbedtls_mpi_cmp_mpi((const mbedtls_mpi *) a, (const mbedtls_mpi *) b);
}
int crypto_bignum_bits(const struct crypto_bignum *a)
{
return mbedtls_mpi_bitlen((const mbedtls_mpi *) a);
}
int crypto_bignum_is_zero(const struct crypto_bignum *a)
{
return (mbedtls_mpi_cmp_int((const mbedtls_mpi *) a, 0) == 0);
}
int crypto_bignum_is_one(const struct crypto_bignum *a)
{
return (mbedtls_mpi_cmp_int((const mbedtls_mpi *) a, 1) == 0);
}
int crypto_bignum_legendre(const struct crypto_bignum *a,
const struct crypto_bignum *p)
{
mbedtls_mpi exp, tmp;
int res = -2, ret;
mbedtls_mpi_init(&exp);
mbedtls_mpi_init(&tmp);
/* exp = (p-1) / 2 */
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&exp, (const mbedtls_mpi *) p, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&exp, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&tmp, (const mbedtls_mpi *) a, &exp, (const mbedtls_mpi *) p, NULL));
if (mbedtls_mpi_cmp_int(&tmp, 1) == 0) {
res = 1;
} else if (mbedtls_mpi_cmp_int(&tmp, 0) == 0
/* The below check is workaround for the case where HW
* does not behave properly for X ^ A mod M when X is
* power of M. Instead of returning value 0, value M is
* returned.*/
|| mbedtls_mpi_cmp_mpi(&tmp, (const mbedtls_mpi *)p) == 0) {
res = 0;
} else {
res = -1;
}
cleanup:
mbedtls_mpi_free(&tmp);
mbedtls_mpi_free(&exp);
return res;
}
#ifdef CONFIG_ECC
struct crypto_ec {
mbedtls_ecp_group group;
};
struct crypto_ec *crypto_ec_init(int group)
{
struct crypto_ec *e;
mbedtls_ecp_group_id grp_id;
/* IANA registry to mbedtls internal mapping*/
switch (group) {
case IANA_SECP256R1:
/* For now just support NIST-P256.
* This is of type "short Weierstrass".
*/
grp_id = MBEDTLS_ECP_DP_SECP256R1;
break;
default:
return NULL;
}
e = os_zalloc(sizeof(*e));
if (e == NULL) {
return NULL;
}
mbedtls_ecp_group_init( &e->group );
if (mbedtls_ecp_group_load(&e->group, grp_id)) {
crypto_ec_deinit(e);
e = NULL;
}
return e;
}
void crypto_ec_deinit(struct crypto_ec *e)
{
if (e == NULL) {
return;
}
mbedtls_ecp_group_free( &e->group );
os_free(e);
}
struct crypto_ec_point *crypto_ec_point_init(struct crypto_ec *e)
{
mbedtls_ecp_point *pt;
if (e == NULL) {
return NULL;
}
pt = os_zalloc(sizeof(mbedtls_ecp_point));
if( pt == NULL) {
return NULL;
}
mbedtls_ecp_point_init(pt);
return (struct crypto_ec_point *) pt;
}
size_t crypto_ec_prime_len(struct crypto_ec *e)
{
return mbedtls_mpi_size(&e->group.P);
}
size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
{
return mbedtls_mpi_bitlen(&e->group.P);
}
const struct crypto_bignum *crypto_ec_get_prime(struct crypto_ec *e)
{
return (const struct crypto_bignum *) &e->group.P;
}
const struct crypto_bignum *crypto_ec_get_order(struct crypto_ec *e)
{
return (const struct crypto_bignum *) &e->group.N;
}
void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
{
mbedtls_ecp_point_free((mbedtls_ecp_point *) p);
os_free(p);
}
int crypto_ec_point_to_bin(struct crypto_ec *e,
const struct crypto_ec_point *point, u8 *x, u8 *y)
{
int len = mbedtls_mpi_size(&e->group.P);
if (x) {
if(crypto_bignum_to_bin((struct crypto_bignum *) & ((mbedtls_ecp_point *) point)->X,
x, len, len) < 0) {
return -1;
}
}
if (y) {
if(crypto_bignum_to_bin((struct crypto_bignum *) & ((mbedtls_ecp_point *) point)->Y,
y, len, len) < 0) {
return -1;
}
}
return 0;
}
struct crypto_ec_point *crypto_ec_point_from_bin(struct crypto_ec *e,
const u8 *val)
{
mbedtls_ecp_point *pt;
int len, ret;
if (e == NULL) {
return NULL;
}
len = mbedtls_mpi_size(&e->group.P);
pt = os_zalloc(sizeof(mbedtls_ecp_point));
mbedtls_ecp_point_init(pt);
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->X, val, len));
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->Y, val + len, len));
MBEDTLS_MPI_CHK(mbedtls_mpi_lset((&pt->Z), 1));
return (struct crypto_ec_point *) pt;
cleanup:
mbedtls_ecp_point_free(pt);
os_free(pt);
return NULL;
}
int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
const struct crypto_ec_point *b,
struct crypto_ec_point *c)
{
int ret;
mbedtls_mpi one;
mbedtls_mpi_init(&one);
MBEDTLS_MPI_CHK(mbedtls_mpi_lset( &one, 1 ));
MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&e->group, (mbedtls_ecp_point *) c, &one, (const mbedtls_ecp_point *)a , &one, (const mbedtls_ecp_point *)b));
cleanup:
mbedtls_mpi_free(&one);
return ret ? -1 : 0;
}
int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
const struct crypto_bignum *b,
struct crypto_ec_point *res)
{
int ret;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_init(&entropy);
MBEDTLS_MPI_CHK(mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
NULL, 0));
MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&e->group,
(mbedtls_ecp_point *) res,
(const mbedtls_mpi *)b,
(const mbedtls_ecp_point *)p,
mbedtls_ctr_drbg_random,
&ctr_drbg));
cleanup:
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
return ret ? -1 : 0;
}
/* Currently mbedtls does not have any function for inverse
* This function calculates inverse of a point.
* Set R = -P
*/
static int ecp_opp( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point *P)
{
int ret = 0;
/* Copy */
if (R != P) {
MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P));
}
/* In-place opposite */
if (mbedtls_mpi_cmp_int( &R->Y, 0) != 0) {
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&R->Y, &grp->P, &R->Y));
}
cleanup:
return ( ret );
}
int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
{
return ecp_opp(&e->group, (mbedtls_ecp_point *) p, (mbedtls_ecp_point *) p) ? -1 : 0;
}
int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
struct crypto_ec_point *p,
const struct crypto_bignum *x, int y_bit)
{
mbedtls_mpi temp;
mbedtls_mpi *y_sqr, *y;
mbedtls_mpi_init(&temp);
int ret = 0;
y = &((mbedtls_ecp_point *)p)->Y;
/* Faster way to find sqrt
* Works only with curves having prime p
* such that p 3 (mod 4)
* y_ = (y2 ^ ((p+1)/4)) mod p
*
* if y_bit: y = p-y_
* else y = y_`
*/
y_sqr = (mbedtls_mpi *) crypto_ec_point_compute_y_sqr(e, x);
if (y_sqr) {
MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&temp, &e->group.P, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(&temp, NULL, &temp, 4));
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(y, y_sqr, &temp, &e->group.P, NULL));
if (y_bit) {
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(y, &e->group.P, y));
}
} else {
ret = 1;
}
cleanup:
mbedtls_mpi_free(&temp);
mbedtls_mpi_free(y_sqr);
os_free(y_sqr);
return ret ? -1 : 0;
}
struct crypto_bignum *
crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
const struct crypto_bignum *x)
{
mbedtls_mpi temp, temp2, num;
int ret = 0;
mbedtls_mpi *y_sqr = os_zalloc(sizeof(mbedtls_mpi));
if (y_sqr == NULL) {
return NULL;
}
mbedtls_mpi_init(&temp);
mbedtls_mpi_init(&temp2);
mbedtls_mpi_init(&num);
mbedtls_mpi_init(y_sqr);
/* y^2 = x^3 + ax + b mod P*/
/* mbedtls does not have mod-add or mod-mul apis.
*
*/
/* Calculate x^3 mod P*/
MBEDTLS_MPI_CHK(mbedtls_mpi_lset( &num, 3));
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&temp, (const mbedtls_mpi *) x, &num, &e->group.P, NULL));
/* Calculate ax mod P*/
MBEDTLS_MPI_CHK(mbedtls_mpi_lset( &num, -3));
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&temp2, (const mbedtls_mpi *) x, &num));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&temp2, &temp2, &e->group.P));
/* Calculate ax + b mod P. Note that b is already < P*/
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&temp2, &temp2, &e->group.B));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&temp2, &temp2, &e->group.P));
/* Calculate x^3 + ax + b mod P*/
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&temp2, &temp2, &temp));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(y_sqr, &temp2, &e->group.P));
cleanup:
mbedtls_mpi_free(&temp);
mbedtls_mpi_free(&temp2);
mbedtls_mpi_free(&num);
if (ret) {
mbedtls_mpi_free(y_sqr);
os_free(y_sqr);
return NULL;
} else {
return (struct crypto_bignum *) y_sqr;
}
}
int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
const struct crypto_ec_point *p)
{
return mbedtls_ecp_is_zero((mbedtls_ecp_point *) p);
}
int crypto_ec_point_is_on_curve(struct crypto_ec *e,
const struct crypto_ec_point *p)
{
mbedtls_mpi y_sqr_lhs, *y_sqr_rhs = NULL, two;
int ret = 0, on_curve = 0;
mbedtls_mpi_init(&y_sqr_lhs);
mbedtls_mpi_init(&two);
/* Calculate y^2 mod P*/
MBEDTLS_MPI_CHK(mbedtls_mpi_lset( &two, 2));
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&y_sqr_lhs, &((const mbedtls_ecp_point *)p)->Y , &two, &e->group.P, NULL));
y_sqr_rhs = (mbedtls_mpi *) crypto_ec_point_compute_y_sqr(e, (const struct crypto_bignum *) & ((const mbedtls_ecp_point *)p)->X);
if (y_sqr_rhs && (mbedtls_mpi_cmp_mpi(y_sqr_rhs, &y_sqr_lhs) == 0)) {
on_curve = 1;
}
cleanup:
mbedtls_mpi_free(&y_sqr_lhs);
mbedtls_mpi_free(y_sqr_rhs);
os_free(y_sqr_rhs);
return (ret == 0) && (on_curve == 1);
}
int crypto_ec_point_cmp(const struct crypto_ec *e,
const struct crypto_ec_point *a,
const struct crypto_ec_point *b)
{
return mbedtls_ecp_point_cmp((const mbedtls_ecp_point *) a,
(const mbedtls_ecp_point *) b);
}
#endif /* CONFIG_ECC */

View File

@ -0,0 +1,5 @@
#
#Component Makefile
#
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

View File

@ -0,0 +1,545 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// 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
// http://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.
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#include "unity.h"
#include <string.h>
#include "crypto/crypto.h"
#include "mbedtls/ecp.h"
typedef struct crypto_bignum crypto_bignum;
TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]")
{
{
uint8_t buf[32], buf2[32];
/* BN - Init & Deinit*/
crypto_bignum *bn = crypto_bignum_init();
crypto_bignum_deinit(bn, 1);
/* BN - Binary to bignum & bignum to binary*/
TEST_ASSERT(!crypto_get_random(buf, 32));
bn = crypto_bignum_init_set(buf, 32);
TEST_ASSERT_NOT_NULL(bn);
TEST_ASSERT(crypto_bignum_to_bin(bn, buf2, 32, 0) == 32);
TEST_ASSERT(!memcmp(buf, buf2, 32));
crypto_bignum_deinit(bn, 1);
}
{ /** BN summation*/
uint8_t buf1[32], buf2[32], buf3[32], buf4[32];
crypto_bignum *bn1, *bn2, *sum;
uint8_t count;
sum = crypto_bignum_init();
for (count = 0; count < 32; count++) {
buf1[count] = 0x11;
buf2[count] = 0x22;
buf3[count] = 0x33; //expected result
buf4[count] = 0x0; //Calculated result
}
bn1 = crypto_bignum_init_set(buf1, 32);
TEST_ASSERT_NOT_NULL(bn1);
bn2 = crypto_bignum_init_set(buf2, 32);
TEST_ASSERT_NOT_NULL(bn2);
TEST_ASSERT(crypto_bignum_add(bn1, bn2, sum) == 0);
TEST_ASSERT(crypto_bignum_to_bin(sum, buf4, 32, 0) == 32);
TEST_ASSERT(!memcmp(buf3, buf4, 32));
crypto_bignum_deinit(bn1, 1);
crypto_bignum_deinit(bn2, 1);
crypto_bignum_deinit(sum, 1);
}
{ /** BN mod*/
uint8_t buf1[32], buf2[32], buf3[32], buf4[32];
crypto_bignum *bn1, *bn2, *mod;
uint8_t count;
mod = crypto_bignum_init();
for (count = 0; count < 32; count++) {
buf1[count] = 0x33;
buf2[count] = 0x22;
buf3[count] = 0x11; //expected result
buf4[count] = 0x0; //Calculated result
}
bn1 = crypto_bignum_init_set(buf1, 32);
TEST_ASSERT_NOT_NULL(bn1);
bn2 = crypto_bignum_init_set(buf2, 32);
TEST_ASSERT_NOT_NULL(bn2);
TEST_ASSERT(crypto_bignum_mod(bn1, bn2, mod) == 0);
TEST_ASSERT(crypto_bignum_to_bin(mod, buf4, 32, 0) == 32);
TEST_ASSERT(!memcmp(buf3, buf4, 32));
crypto_bignum_deinit(bn1, 1);
crypto_bignum_deinit(bn2, 1);
crypto_bignum_deinit(mod, 1);
}
{ /** BN sub*/
uint8_t buf1[32], buf2[32], buf3[32], buf4[32];
crypto_bignum *bn1, *bn2, *sub;
uint8_t count;
sub = crypto_bignum_init();
for (count = 0; count < 32; count++) {
buf1[count] = 0x44;
buf2[count] = 0x11;
buf3[count] = 0x33; //expected result
buf4[count] = 0x0; //Calculated result
}
bn1 = crypto_bignum_init_set(buf1, 32);
TEST_ASSERT_NOT_NULL(bn1);
bn2 = crypto_bignum_init_set(buf2, 32);
TEST_ASSERT_NOT_NULL(bn2);
TEST_ASSERT(crypto_bignum_sub(bn1, bn2, sub) == 0);
TEST_ASSERT(crypto_bignum_to_bin(sub, buf4, 32, 0) == 32);
TEST_ASSERT(!memcmp(buf3, buf4, 32));
crypto_bignum_deinit(bn1, 1);
crypto_bignum_deinit(bn2, 1);
crypto_bignum_deinit(sub, 1);
}
{ /** BN div*/
uint8_t buf1[32], buf2[32], buf3[32], buf4[32];
crypto_bignum *bn1, *bn2, *div;
uint8_t count;
div = crypto_bignum_init();
for (count = 0; count < 32; count++) {
buf1[count] = 0x44;
buf2[count] = 0x22;
buf3[count] = count ? 0 : 0x2; //expected result
buf4[count] = 0x0; //Calculated result
}
bn1 = crypto_bignum_init_set(buf1, 32);
TEST_ASSERT_NOT_NULL(bn1);
bn2 = crypto_bignum_init_set(buf2, 32);
TEST_ASSERT_NOT_NULL(bn2);
TEST_ASSERT(crypto_bignum_div(bn1, bn2, div) == 0);
TEST_ASSERT(crypto_bignum_to_bin(div, buf4, 32, 0) == 1);
TEST_ASSERT(!memcmp(buf3, buf4, 1));
crypto_bignum_deinit(bn1, 1);
crypto_bignum_deinit(bn2, 1);
crypto_bignum_deinit(div, 1);
}
{ /** BN mul mod*/
uint8_t buf1[32], buf2[32], buf3[32], buf4[32], buf5[32];
crypto_bignum *bn1, *bn2, *bn3, *mulmod;
uint8_t count;
for (count = 0; count < 32; count++) {
buf1[count] = 0x22;
buf2[count] = 0x11;
buf3[count] = (count < 4) ? 0x21 : 0;
buf4[count] = (count < 4) ? 0x14 : 0;
buf5[count] = 0;
}
mulmod = crypto_bignum_init();
bn1 = crypto_bignum_init_set(buf1, 32);
TEST_ASSERT_NOT_NULL(bn1);
bn2 = crypto_bignum_init_set(buf2, 32);
TEST_ASSERT_NOT_NULL(bn2);
bn3 = crypto_bignum_init_set(buf3, 4);
TEST_ASSERT_NOT_NULL(bn3);
TEST_ASSERT(crypto_bignum_mulmod(bn1, bn2, bn3, mulmod) == 0);
TEST_ASSERT(crypto_bignum_to_bin(mulmod, buf5, 32, 0) == 4);
TEST_ASSERT(!memcmp(buf5, buf4, 4));
crypto_bignum_deinit(bn1, 1);
crypto_bignum_deinit(bn2, 1);
crypto_bignum_deinit(bn3, 1);
crypto_bignum_deinit(mulmod, 1);
}
{ /** BN exp mod*/
uint8_t buf1[32], buf2[32], buf3[32], buf4[32], buf5[32];
crypto_bignum *bn1, *bn2, *bn3, *expmod;
uint8_t count;
expmod = crypto_bignum_init();
for (count = 0; count < 32; count++) {
buf1[count] = 0x22;
buf2[count] = (count >= 30) ? 0x11 : 0;
buf3[count] = (count >= 31) ? 0xE9 : 0;
buf4[count] = count ? 0 : 0x62;
buf5[count] = 0;
}
bn1 = crypto_bignum_init_set(buf1, 32);
TEST_ASSERT_NOT_NULL(bn1);
bn2 = crypto_bignum_init_set(buf2, 32);
TEST_ASSERT_NOT_NULL(bn2);
bn3 = crypto_bignum_init_set(buf3, 32);
TEST_ASSERT_NOT_NULL(bn3);
TEST_ASSERT(crypto_bignum_exptmod(bn1, bn2, bn3, expmod) == 0);
TEST_ASSERT(crypto_bignum_to_bin(expmod, buf5, 32, 0) == 1);
TEST_ASSERT(!memcmp(buf5, buf4, 1));
crypto_bignum_deinit(bn1, 1);
crypto_bignum_deinit(bn2, 1);
crypto_bignum_deinit(bn3, 1);
crypto_bignum_deinit(expmod, 1);
}
{ /** BN Legendre symbol test*/
uint8_t buf1[32], buf2[32];
crypto_bignum *bn1, *bn2;
buf1[0] = 0xf;
buf2[0] = 0x11;
bn1 = crypto_bignum_init_set(buf1, 1);
TEST_ASSERT_NOT_NULL(bn1);
bn2 = crypto_bignum_init_set(buf2, 1);
TEST_ASSERT_NOT_NULL(bn2);
TEST_ASSERT(crypto_bignum_legendre(bn1, bn2) == 1);
crypto_bignum_deinit(bn1, 1);
buf1[0] = 0xa;
bn1 = crypto_bignum_init_set(buf1, 1);
TEST_ASSERT_NOT_NULL(bn1);
TEST_ASSERT(crypto_bignum_legendre(bn1, bn2) == -1);
crypto_bignum_deinit(bn1, 1);
buf1[0] = 0x11;
bn1 = crypto_bignum_init_set(buf1, 1);
TEST_ASSERT_NOT_NULL(bn1);
TEST_ASSERT(crypto_bignum_legendre(bn1, bn2) == 0);
crypto_bignum_deinit(bn1, 1);
crypto_bignum_deinit(bn2, 1);
}
}
/*
* Conversion macros for embedded constants:
* build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2
*/
#if defined(MBEDTLS_HAVE_INT32)
#define BYTES_TO_T_UINT_4( a, b, c, d ) \
( (mbedtls_mpi_uint) a << 0 ) | \
( (mbedtls_mpi_uint) b << 8 ) | \
( (mbedtls_mpi_uint) c << 16 ) | \
( (mbedtls_mpi_uint) d << 24 )
#define BYTES_TO_T_UINT_2( a, b ) \
BYTES_TO_T_UINT_4( a, b, 0, 0 )
#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
BYTES_TO_T_UINT_4( a, b, c, d ), \
BYTES_TO_T_UINT_4( e, f, g, h )
#else /* 64-bits */
#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
( (mbedtls_mpi_uint) a << 0 ) | \
( (mbedtls_mpi_uint) b << 8 ) | \
( (mbedtls_mpi_uint) c << 16 ) | \
( (mbedtls_mpi_uint) d << 24 ) | \
( (mbedtls_mpi_uint) e << 32 ) | \
( (mbedtls_mpi_uint) f << 40 ) | \
( (mbedtls_mpi_uint) g << 48 ) | \
( (mbedtls_mpi_uint) h << 56 )
#define BYTES_TO_T_UINT_4( a, b, c, d ) \
BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 )
#define BYTES_TO_T_UINT_2( a, b ) \
BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 )
#endif /* bits in mbedtls_mpi_uint */
/*
* Create an MPI from embedded constants
* (assumes len is an exact multiple of sizeof mbedtls_mpi_uint)
* Allocate a new memory as well so that it can be freed.
*/
static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len )
{
X->s = 1;
X->n = len / sizeof( mbedtls_mpi_uint );
X->p = os_zalloc(len);
memcpy(X->p, (void *)p, len);
}
TEST_CASE("Test crypto lib ECC apis", "[wpa_crypto]")
{
static const mbedtls_mpi_uint secp256r1_gx[] = {
BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ),
BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ),
BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ),
BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ),
};
static const mbedtls_mpi_uint secp256r1_gy[] = {
BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ),
BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ),
BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ),
BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ),
};
{
/* Check init and deinit APIs*/
struct crypto_ec *e = crypto_ec_init(19);
struct crypto_ec_point *pt = crypto_ec_point_init(e);
crypto_ec_point_deinit(pt, 1);
crypto_ec_deinit(e);
}
{
uint8_t pt1[64], pt2[64];
struct crypto_ec *e = crypto_ec_init(19);
struct crypto_ec_point *p;
TEST_ASSERT_NOT_NULL(e);
/* Note this is just testing coversion & not whether point is
* in the group or not*/
TEST_ASSERT(!crypto_get_random(pt1, 64));
p = crypto_ec_point_from_bin(e, pt1);
TEST_ASSERT(crypto_ec_prime_len(e) == 32);
TEST_ASSERT(crypto_ec_point_to_bin(e, p, pt2, &pt2[32]) == 0);
TEST_ASSERT(!memcmp(pt1, pt2, sizeof(pt1)));
crypto_ec_point_deinit(p, 1);
crypto_ec_deinit(e);
}
{
/* Check addition and multiplication APIs
* yield the same answer.
*/
struct crypto_ec *e = crypto_ec_init(19);
struct crypto_ec_point *p = crypto_ec_point_init(e);
struct crypto_ec_point *q = crypto_ec_point_init(e);
struct crypto_ec_point *r = crypto_ec_point_init(e);
mbedtls_mpi num;
TEST_ASSERT_NOT_NULL(e);
TEST_ASSERT_NOT_NULL(p);
TEST_ASSERT_NOT_NULL(q);
TEST_ASSERT_NOT_NULL(r);
mbedtls_mpi_init( &num );
mbedtls_mpi_lset( &num, 3 );
ecp_mpi_load(& ((mbedtls_ecp_point *)p)->X, secp256r1_gx, sizeof(secp256r1_gx));
ecp_mpi_load(& ((mbedtls_ecp_point *)p)->Y, secp256r1_gy, sizeof(secp256r1_gy));
mbedtls_mpi_lset((&((mbedtls_ecp_point *)p)->Z), 1);
TEST_ASSERT(crypto_ec_point_mul(e, p, (crypto_bignum *) &num, q) == 0); //q = 3p
TEST_ASSERT(crypto_ec_point_add(e, p, p, r) == 0);
TEST_ASSERT(crypto_ec_point_add(e, p, r, r) == 0);
TEST_ASSERT(crypto_ec_point_cmp(e, q, r) == 0);
mbedtls_mpi_free( &num );
crypto_ec_point_deinit(p, 1);
crypto_ec_point_deinit(q, 1);
crypto_ec_point_deinit(r, 1);
crypto_ec_deinit(e);
}
{
/* Generate a point using generator and take its inverse
* Check that adding point to inverse yields identity
*/
struct crypto_ec *e = crypto_ec_init(19);
struct crypto_ec_point *p = crypto_ec_point_init(e);
struct crypto_ec_point *q = crypto_ec_point_init(e);
struct crypto_ec_point *r = crypto_ec_point_init(e);
mbedtls_mpi num;
TEST_ASSERT_NOT_NULL(e);
TEST_ASSERT_NOT_NULL(p);
TEST_ASSERT_NOT_NULL(q);
TEST_ASSERT_NOT_NULL(r);
mbedtls_mpi_init( &num );
mbedtls_mpi_lset( &num, 100 );
ecp_mpi_load(& ((mbedtls_ecp_point *)p)->X, secp256r1_gx, sizeof(secp256r1_gx));
ecp_mpi_load(& ((mbedtls_ecp_point *)p)->Y, secp256r1_gy, sizeof(secp256r1_gy));
mbedtls_mpi_lset((&((mbedtls_ecp_point *)p)->Z), 1);
TEST_ASSERT(crypto_ec_point_mul(e, p, (crypto_bignum *) &num, q) == 0);
TEST_ASSERT(crypto_ec_point_mul(e, p, (crypto_bignum *) &num, r) == 0);
TEST_ASSERT(crypto_ec_point_invert(e, r) == 0);
TEST_ASSERT(crypto_ec_point_add(e, q, r, r) == 0);
TEST_ASSERT(crypto_ec_point_is_at_infinity(e, r));
mbedtls_mpi_free( &num );
crypto_ec_point_deinit(p, 1);
crypto_ec_point_deinit(q, 1);
crypto_ec_point_deinit(r, 1);
crypto_ec_deinit(e);
}
{
/* Check y_sqr calculations and other dependent APIs */
struct crypto_ec *e = crypto_ec_init(19);
struct crypto_ec_point *p = crypto_ec_point_init(e);
struct crypto_ec_point *q = crypto_ec_point_init(e);
mbedtls_mpi num;
TEST_ASSERT_NOT_NULL(e);
TEST_ASSERT_NOT_NULL(p);
TEST_ASSERT_NOT_NULL(q);
mbedtls_mpi_init( &num );
mbedtls_mpi_lset( &num, 50 );
ecp_mpi_load(& ((mbedtls_ecp_point *)p)->X, secp256r1_gx, sizeof(secp256r1_gx));
ecp_mpi_load(& ((mbedtls_ecp_point *)p)->Y, secp256r1_gy, sizeof(secp256r1_gy));
mbedtls_mpi_lset((&((mbedtls_ecp_point *)p)->Z), 1);
/* Generator should always be on the curve*/
TEST_ASSERT(crypto_ec_point_is_on_curve(e, p));
/* Any point generated using generated should also be on the same curve*/
TEST_ASSERT(crypto_ec_point_mul(e, p, (crypto_bignum *) &num, q) == 0);
TEST_ASSERT(crypto_ec_point_is_on_curve(e, q));
mbedtls_mpi_free( &num );
crypto_ec_point_deinit(p, 1);
crypto_ec_point_deinit(q, 1);
crypto_ec_deinit(e);
}
{
/* crypto_ec_point_solve_y_coord APIs*/
struct crypto_ec *e = crypto_ec_init(19);
struct crypto_ec_point *p = crypto_ec_point_init(e);
struct crypto_ec_point *q = crypto_ec_point_init(e);
struct crypto_ec_point *r = crypto_ec_point_init(e);
mbedtls_mpi num;
TEST_ASSERT_NOT_NULL(e);
TEST_ASSERT_NOT_NULL(p);
TEST_ASSERT_NOT_NULL(q);
TEST_ASSERT_NOT_NULL(r);
mbedtls_mpi_init( &num );
mbedtls_mpi_lset( &num, 50 );
ecp_mpi_load(& ((mbedtls_ecp_point *)p)->X, secp256r1_gx, sizeof(secp256r1_gx));
ecp_mpi_load(& ((mbedtls_ecp_point *)p)->Y, secp256r1_gy, sizeof(secp256r1_gy));
mbedtls_mpi_lset((&((mbedtls_ecp_point *)p)->Z), 1);
mbedtls_mpi_copy(&((mbedtls_ecp_point *)q)->X, &((mbedtls_ecp_point *)p)->X);
mbedtls_mpi_copy(&((mbedtls_ecp_point *)r)->X, &((mbedtls_ecp_point *)p)->X);
mbedtls_mpi_lset((&((mbedtls_ecp_point *)q)->Z), 1);
mbedtls_mpi_lset((&((mbedtls_ecp_point *)r)->Z), 1);
TEST_ASSERT(crypto_ec_point_solve_y_coord(e, q, (crypto_bignum *) & ((mbedtls_ecp_point *)q)->X, 0) == 0);
TEST_ASSERT(crypto_ec_point_is_on_curve(e, q));
TEST_ASSERT(crypto_ec_point_solve_y_coord(e, r, (crypto_bignum *) & ((mbedtls_ecp_point *)q)->X, 1) == 0);
TEST_ASSERT(crypto_ec_point_is_on_curve(e, r));
TEST_ASSERT((crypto_ec_point_cmp(e, p, q) == 0) || (crypto_ec_point_cmp(e, p, r) == 0));
/* The two roots should be inverse of one another*/
TEST_ASSERT(crypto_ec_point_add(e, q, r, r) == 0);
TEST_ASSERT(crypto_ec_point_is_at_infinity(e, r));
mbedtls_mpi_free( &num );
crypto_ec_point_deinit(p, 1);
crypto_ec_point_deinit(q, 1);
crypto_ec_point_deinit(r, 1);
crypto_ec_deinit(e);
}
}