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]")
"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"
USE_WPS_TASK
ESPRESSIF_USE
ESP32_WORKAROUND
+ CONFIG_ECC
)
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
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 */
--- /dev/null
+// 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 */
--- /dev/null
+#
+#Component Makefile
+#
+
+COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
--- /dev/null
+// 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);
+
+ }
+
+}
+