diff --git a/Makefile.am b/Makefile.am index f91fb3c7..51cc5c56 100644 --- a/Makefile.am +++ b/Makefile.am @@ -193,7 +193,6 @@ src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h \ src/adhoc.h src/adhoc.c \ src/sae.h src/sae.c \ src/nl80211util.h src/nl80211util.c \ - src/ecdh.h src/ecdh.c \ src/owe.h src/owe.c \ $(eap_sources) \ $(builtin_sources) @@ -308,7 +307,7 @@ unit_tests = unit/test-cmac-aes \ unit/test-crypto unit/test-eapol unit/test-mpdu \ unit/test-ie unit/test-ssid-to-utf8 unit/test-ssid-security \ unit/test-arc4 unit/test-wsc unit/test-eap-mschapv2 \ - unit/test-eap-sim unit/test-ecc unit/test-sae unit/test-ecdh + unit/test-eap-sim unit/test-ecc unit/test-sae if CLIENT unit_tests += unit/test-client @@ -443,12 +442,6 @@ unit_test_sae_SOURCES = unit/test-sae.c \ src/ecc.h src/ecc.c unit_test_sae_LDADD = $(ell_ldadd) -unit_test_ecdh_SOURCES = unit/test-ecdh.c \ - src/ecdh.h src/ecdh.c \ - src/ecc.h src/ecc.c -unit_test_ecdh_LDADD = $(ell_ldadd) -unit_test_ecdh_LDFLAGS = -Wl,-wrap,l_getrandom - TESTS = $(unit_tests) manual_pages = doc/iwmon.1 diff --git a/src/ecdh.c b/src/ecdh.c deleted file mode 100644 index b6601b08..00000000 --- a/src/ecdh.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * - * Wireless daemon for Linux - * - * Copyright (C) 2018 Intel Corporation. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include - -#include "ecdh.h" -#include "ecc.h" - -static struct ecc_point p256_generator = CURVE_G_32; -static uint64_t p256_prime[4] = CURVE_P_32; -/* - * IETF - Compact representation of an elliptic curve point: - * https://tools.ietf.org/id/draft-jivsov-ecc-compact-00.xml - * - * "min(y,p-y) can be calculated with the help of the pre-calculated value - * p2=(p-1)/2. min(y,p-y) is y if y 64) - return false; - - while (!compliant && iter++ < ECDH_MAX_ITERATIONS) { - if (!l_getrandom(private, priv_len)) - return false; - - /* private * G(x,y) = public key */ - ecc_point_mult(&pub, &p256_generator, - (uint64_t *)private, NULL, - vli_num_bits((uint64_t *)private)); - - /* ensure public key is compliant */ - if (vli_cmp(pub.y, p2) >= 0) { - compliant = true; - break; - } - } - - if (!compliant) { - l_error("could not generate a compliant public key pair"); - return false; - } - - memcpy(public, &pub, pub_len); - - return true; -} - -/* - * IETF draft-jivsov-ecc-compact-00 Section 4.1 - * Encoding and decoding of an elliptic curve point - * ... - * Decoding: - * Given the compact representation of Q, return canonical representation - * of Q=(x,y) as follows: - * 1. y' = sqrt( x^3 + a*x + b ), where y'>0 - * 2. y = min(y',p-y') - * 3. Q=(x,y) is the canonical representation of the point - */ -static bool decode_point(const uint64_t *x, struct ecc_point *point) -{ - uint64_t y_min[4]; - - if (!ecc_compute_y(y_min, (uint64_t *)x)) - return false; - - if (vli_cmp(y_min, p2) >= 0) - vli_mod_sub(point->y, p256_prime, y_min, p256_prime); - else - memcpy(point->y, y_min, 32); - - memcpy(point->x, x, 32); - - return true; -} - -bool ecdh_generate_shared_secret(const void *private, const void *other_public, - size_t pub_len, void *secret, - size_t secret_len) -{ - struct ecc_point product; - struct ecc_point public; - uint64_t z[4]; - uint64_t x[4]; - - if (secret_len > 32) - return false; - - /* - * TODO: Once other ECC groups are added this will need to be modified - * to check for 1/2 the full public key lengths - */ - if (pub_len == 32) { - /* - * Only half the public key was given, the remainder (Y) must - * be decoded. - */ - memcpy(x, other_public, 32); - - if (!decode_point(x, &public)) { - l_error("could not decode compressed public key"); - return false; - } - } else if (pub_len == 64) { - memcpy(&public, other_public, 64); - } else { - l_error("unsupported public key length %zu", pub_len); - return false; - } - - if (!l_getrandom(z, sizeof(z))) - return false; - - ecc_point_mult(&product, &public, (uint64_t *)private, z, - vli_num_bits(private)); - - memcpy(secret, product.x, secret_len); - - return true; -} diff --git a/unit/test-ecdh.c b/unit/test-ecdh.c deleted file mode 100644 index d7a0a1a7..00000000 --- a/unit/test-ecdh.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * - * Wireless daemon for Linux - * - * Copyright (C) 2018 Intel Corporation. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "src/ecdh.h" -#include "src/ecc.h" - -static bool use_real_getrandom = true; - -bool __wrap_l_getrandom(void *buf, size_t len); -bool __real_l_getrandom(void *buf, size_t len); - -bool __wrap_l_getrandom(void *buf, size_t len) -{ - static const uint8_t random_buf[] = { 0x75, 0xc5, 0xfe, 0x3e, 0x53, - 0xcc, 0x33, 0x33, 0x64, 0xea, - 0xdd, 0xa1, 0xe6, 0x62, 0x7a, - 0xb1, 0x98, 0xa7, 0xa0, 0x1e, - 0xac, 0x4b, 0x1d, 0xb8, 0x71, - 0x5b, 0x1d, 0x00, 0x36, 0xd0, - 0x0f, 0xde }; - - if (use_real_getrandom) - return __real_l_getrandom(buf, len); - - memcpy(buf, random_buf, len); - - return true; -} - -/* - * Tests the most basic case. Generate two full public keys and use to create - * two identical shared secrets. - */ -static void test_basic(const void *data) -{ - uint8_t private1[32]; - uint8_t private2[32]; - - uint8_t public1[64]; - uint8_t public2[64]; - - uint8_t secret1[32]; - uint8_t secret2[32]; - - assert(ecdh_generate_key_pair(private1, 32, public1, 64)); - assert(ecdh_generate_key_pair(private2, 32, public2, 64)); - - assert(ecdh_generate_shared_secret(private1, public2, 64, secret1, 32)); - assert(ecdh_generate_shared_secret(private2, public1, 64, secret2, 32)); - - assert(!memcmp(secret1, secret2, 32)); -} - -/* - * Tests public key compliance. When generating the public keys, only specify - * half their length (32). This requires ECDH to compute the remainder of the - * public key when generating the shared secret. - */ -static void test_compliant_key(const void *data) -{ - uint8_t private1[32]; - uint8_t private2[32]; - - uint8_t public1[32]; - uint8_t public2[32]; - - uint8_t secret1[32]; - uint8_t secret2[32]; - - assert(ecdh_generate_key_pair(private1, 32, public1, 32)); - assert(ecdh_generate_key_pair(private2, 32, public2, 32)); - - assert(ecdh_generate_shared_secret(private1, public2, 32, secret1, 32)); - assert(ecdh_generate_shared_secret(private2, public1, 32, secret2, 32)); - - assert(!memcmp(secret1, secret2, 32)); -} - -/* - * Test vector from RFC 5114 - 256-bit Random ECP Group - */ -static void test_vectors(const void *data) -{ - uint64_t a_secret[4] = { 0x867B7291D507A3AFull, 0x3FAF432A5ABCE59Eull, - 0xE96A8E337A128499ull, 0x814264145F2F56F2ull }; - struct ecc_point a_public = { - .x = { 0x5E8D3B4BA83AEB15ull, 0x7165BE50BC42AE4Aull, - 0xC9B5A8D4160D09E9ull, 0x2AF502F3BE8952F2ull }, - .y = { 0xC0F5015ECE5EFD85ull, 0x6795BD4BFF6E6DE3ull, - 0x8681A0F9872D79D5ull, 0xEB0FAF4CA986C4D3ull } - }; - uint64_t b_secret[4] = { 0xEE1B593761CF7F41ull, 0x19CE6BCCAD562B8Eull, - 0xDB95A200CC0AB26Aull, 0x2CE1788EC197E096ull }; - struct ecc_point b_public = { - .x = { 0xB3AB0715F6CE51B0ull, 0xAE06AAEA279FA775ull, - 0x5346E8DE6C2C8646ull, 0xB120DE4AA3649279ull }, - .y = { 0x85C34DDE5708B2B6ull, 0x3727027092A84113ull, - 0xD8EC685FA3F071D8ull, 0x9F1B7EECE20D7B5Eull } - }; - uint64_t shared_secret[4] = { 0x7F80D21C820C2788ull, - 0xF5811E9DC8EC8EEAull, - 0x93310412D19A08F1ull, - 0xDD0F5396219D1EA3ull }; - - uint64_t a_shared[4]; - uint64_t b_shared[4]; - - use_real_getrandom = false; - - assert(ecdh_generate_shared_secret(a_secret, (const void *)&b_public, - 64, a_shared, 32)); - assert(ecdh_generate_shared_secret(b_secret, (const void *)&a_public, - 64, b_shared, 32)); - - assert(!memcmp(a_shared, shared_secret, 32)); - assert(!memcmp(b_shared, shared_secret, 32)); - - use_real_getrandom = true; -} - -int main(int argc, char *argv[]) -{ - l_test_init(&argc, &argv); - - if (l_getrandom_is_supported()) { - l_test_add("ECDH Basic", test_basic, NULL); - l_test_add("ECDH Compliant key", test_compliant_key, NULL); - } - - l_test_add("ECDH test vector", test_vectors, NULL); - - return l_test_run(); -}