From 5c4620113ab7012317816371f38e45e4cefa0af0 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 27 Jan 2022 12:22:40 +0100 Subject: [PATCH] Kobo/WifiDialog: use PBKDF2-SHA1 passwords On older Kobos like the Kobo Mini, wpa_supplicant accepts ASCII passwords, newer models require a PBKDF2-SHA1 digest. This is implemented using libcrypto (OpenSSL). --- NEWS.txt | 1 + build/kobo.mk | 4 +- build/libutil.mk | 1 + doc/build.rst | 1 + ide/provisioning/install-debian-packages.sh | 1 + src/Kobo/WPASupplicant.hpp | 2 +- src/Kobo/WifiDialog.cpp | 17 +++++- src/util/HexFormat.cxx | 43 ++++++++++++++ src/util/HexFormat.hxx | 64 +++++++++++++++++++++ 9 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 src/util/HexFormat.cxx create mode 100644 src/util/HexFormat.hxx diff --git a/NEWS.txt b/NEWS.txt index c3e55579387..0bfa57a3d06 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -9,6 +9,7 @@ Version 7.23 - not yet released - fix broken button text background - add OTG support (serial, sound, net) for Clara HD - fix "Network failure" in Wifi dialog + - support Wifi on Clara HD Version 7.22 - 2022/01/14 * user interface diff --git a/build/kobo.mk b/build/kobo.mk index 16a07f3d3b4..1b77f8e140d 100644 --- a/build/kobo.mk +++ b/build/kobo.mk @@ -1,3 +1,5 @@ +$(eval $(call pkg-config-library,LIBCRYPTO,libcrypto)) + KOBO_MENU_SOURCES = \ $(SRC)/Version.cpp \ $(SRC)/Asset.cpp \ @@ -37,7 +39,7 @@ KOBO_MENU_SOURCES = \ $(SRC)/Kobo/WifiDialog.cpp \ $(SRC)/Kobo/FakeSymbols.cpp \ $(SRC)/Kobo/KoboMenu.cpp -KOBO_MENU_DEPENDS = WIDGET FORM SCREEN EVENT RESOURCE ASYNC LIBNET OS IO THREAD MATH UTIL +KOBO_MENU_DEPENDS = WIDGET FORM SCREEN EVENT RESOURCE ASYNC LIBNET OS IO THREAD MATH UTIL LIBCRYPTO KOBO_MENU_STRIP = y $(eval $(call link-program,KoboMenu,KOBO_MENU)) diff --git a/build/libutil.mk b/build/libutil.mk index 247d6bb0529..ed5e4c2501d 100644 --- a/build/libutil.mk +++ b/build/libutil.mk @@ -13,6 +13,7 @@ UTIL_SOURCES = \ $(UTIL_SRC_DIR)/TruncateString.cpp \ $(UTIL_SRC_DIR)/EscapeBackslash.cpp \ $(UTIL_SRC_DIR)/ExtractParameters.cpp \ + $(UTIL_SRC_DIR)/HexFormat.cxx \ $(UTIL_SRC_DIR)/ConvertString.cpp \ $(UTIL_SRC_DIR)/StaticString.cxx \ $(UTIL_SRC_DIR)/StringBuilder.cxx \ diff --git a/doc/build.rst b/doc/build.rst index 4e72af95a6f..00d533b917f 100644 --- a/doc/build.rst +++ b/doc/build.rst @@ -133,6 +133,7 @@ The following command installs these on Debian:: libtiff5-dev libgeotiff-dev \ libc-ares-dev \ libcurl4-openssl-dev \ + libssl-dev \ libc-ares-dev \ liblua5.4-dev \ libxml-parser-perl \ diff --git a/ide/provisioning/install-debian-packages.sh b/ide/provisioning/install-debian-packages.sh index a02cb081750..da29a4258f4 100755 --- a/ide/provisioning/install-debian-packages.sh +++ b/ide/provisioning/install-debian-packages.sh @@ -38,6 +38,7 @@ apt-get install ${APTOPTS[*]} make g++ \ libfreetype6-dev \ libpng-dev libjpeg-dev \ libtiff5-dev libgeotiff-dev \ + libssl-dev \ libcurl4-openssl-dev \ libc-ares-dev \ liblua5.4-dev \ diff --git a/src/Kobo/WPASupplicant.hpp b/src/Kobo/WPASupplicant.hpp index 89f216a1936..5827fb539a4 100644 --- a/src/Kobo/WPASupplicant.hpp +++ b/src/Kobo/WPASupplicant.hpp @@ -126,7 +126,7 @@ class WPASupplicant { } void SetNetworkPSK(unsigned id, const char *psk) { - SetNetworkString(id, "psk", psk); + SetNetworkID(id, "psk", psk); } void SelectNetwork(unsigned id); diff --git a/src/Kobo/WifiDialog.cpp b/src/Kobo/WifiDialog.cpp index 3036f907aa3..4533eb01bb2 100644 --- a/src/Kobo/WifiDialog.cpp +++ b/src/Kobo/WifiDialog.cpp @@ -36,6 +36,13 @@ Copyright_License { #include "WPASupplicant.hpp" #include "net/IPv4Address.hxx" #include "ui/event/PeriodicTimer.hpp" +#include "util/HexFormat.hxx" + +/* workaround because OpenSSL has a typedef called "UI", which clashes + with our "UI" namespace */ +#define UI OPENSSL_UI +#include // for PKCS5_PBKDF2_HMAC_SHA1() +#undef UI class WifiListWidget final : public ListWidget { @@ -216,8 +223,16 @@ WifiConnect(enum WifiSecurity security, WPASupplicant &wpa_supplicant, const cha wpa_supplicant.SetNetworkSSID(id, ssid); if (security == WPA_SECURITY) { + std::array pmk; + PKCS5_PBKDF2_HMAC_SHA1(psk, strlen(psk), + (const unsigned char *)ssid, strlen(ssid), + 4096, + pmk.size(), pmk.data()); + + std::array hex; + *HexFormat(hex.data(), {pmk.data(), pmk.size()}) = 0; - wpa_supplicant.SetNetworkPSK(id, psk); + wpa_supplicant.SetNetworkPSK(id, hex.data()); } else if (security == WEP_SECURITY) { wpa_supplicant.SetNetworkID(id, "key_mgmt", "NONE"); diff --git a/src/util/HexFormat.cxx b/src/util/HexFormat.cxx new file mode 100644 index 00000000000..1a048eb23d2 --- /dev/null +++ b/src/util/HexFormat.cxx @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2018 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "HexFormat.hxx" + +#include + +char * +HexFormat(char *dest, ConstBuffer src) noexcept +{ + for (auto i : src) { + sprintf(dest, "%02x", i); + dest += 2; + } + + return dest; +} diff --git a/src/util/HexFormat.hxx b/src/util/HexFormat.hxx new file mode 100644 index 00000000000..93f5127bd8c --- /dev/null +++ b/src/util/HexFormat.hxx @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2018 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HEX_FORMAT_HXX +#define HEX_FORMAT_HXX + +#include "ConstBuffer.hxx" +#include "StringBuffer.hxx" + +#include +#include + +/** + * Format the given byte sequence into a null-terminated hexadecimal + * string. + * + * @param dest the destination buffer; must be large enough to hold + * all hex digits plus the null terminator + * @return a pointer to the generated null terminator + */ +char * +HexFormat(char *dest, ConstBuffer src) noexcept; + +/** + * Like HexFormat(), but return a #StringBuffer with exactly the + * required size. + */ +template +[[gnu::pure]] +auto +HexFormatBuffer(const uint8_t *src) noexcept +{ + StringBuffer dest; + HexFormat(dest.data(), {src, size}); + return dest; +} + +#endif