]> granicus.if.org Git - esp-idf/commitdiff
wpa_supplicant: Implement BIGNUM and ECC crypto wrapper apis for ESP using mbedtls
authorSagar Bijwe <sagar@espressif.com>
Fri, 31 Aug 2018 13:55:48 +0000 (19:25 +0530)
committerSagar Bijwe <sagar@espressif.com>
Wed, 19 Sep 2018 05:40:28 +0000 (11:10 +0530)
components/mbedtls/test/test_mbedtls_mpi.c
components/wpa_supplicant/CMakeLists.txt
components/wpa_supplicant/component.mk
components/wpa_supplicant/include/crypto/crypto.h
components/wpa_supplicant/src/crypto/crypto_mbedtls.c [new file with mode: 0644]
components/wpa_supplicant/test/component.mk [new file with mode: 0644]
components/wpa_supplicant/test/test_crypto.c [new file with mode: 0644]

index 515f9d30587075c9275d1f6468cd2dc73f63f173..ade0fdb6b8bfa82cdb7a7fa9eb63b7ae3f5859d2 100644 (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]")
index 8564f1ba0289e3ac09eb93924cf97cb5ac74ca1a..c8be031a7b8e24ab5acb17e6d01f38e33732890a 100644 (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
     )
index ae73ccf12634be46dd9a6ea2bc2bcab81de09bbb..f4a57ef7e21f7e5a8a500403b5d79c23e85905cf 100644 (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
index bccb6fed7ff01b3cf0286865ecd3279c13f667d4..f6b7b2f2c49ee76a798a51ac7ae30f20a7a1d967 100644 (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 */
diff --git a/components/wpa_supplicant/src/crypto/crypto_mbedtls.c b/components/wpa_supplicant/src/crypto/crypto_mbedtls.c
new file mode 100644 (file)
index 0000000..835af1d
--- /dev/null
@@ -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 */
diff --git a/components/wpa_supplicant/test/component.mk b/components/wpa_supplicant/test/component.mk
new file mode 100644 (file)
index 0000000..5dd172b
--- /dev/null
@@ -0,0 +1,5 @@
+#
+#Component Makefile
+#
+
+COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
diff --git a/components/wpa_supplicant/test/test_crypto.c b/components/wpa_supplicant/test/test_crypto.c
new file mode 100644 (file)
index 0000000..e8f8d05
--- /dev/null
@@ -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);
+
+    }
+
+}
+