diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/README b/IDE/Renesas/e2studio/RX72NEnvisionKit/README new file mode 100644 index 0000000000..331debab13 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/README @@ -0,0 +1,155 @@ +----------------------------------------------------- +0. 初めに +----------------------------------------------------- + +このドキュメントではE2Studio上でwolfsslを含んだテストアプリケーションを作成する手順を示します。 + +このREADMEが含まれているフォルダには + 1.smc    ---スマートコンフィギュレータ用プロジェクトが格納されているフォルダです + 2.test    ---テストアプリケーション用プロジェクトが格納されているフォルダです + 3.wolfssl  ---テストアプリケーションにリンクされて使用されるwolfsslライブラリ用プロジェクトが格納されているフォルダです + 4.common   ---設定ファイル等が格納されたフォルダです + +フォルダが存在しています。 + +------------------------------------- +1.プロジェクトのインポート +------------------------------------- + +e2studioを起動したら、プロジェクト・エクスプローラー画面を表示させ、"ファイル"メニュー > ”ファイル・システムからプロジェクトを開く...”を選択し、 +プロジェクトインポートダイアログを表示させます。 + +ディレクトリボタンを押して、上記の1~3のフォルダの3プロジェクトをインポートしてください。 + +------------------------------------- +2.smcプロジェクトでソースファイルを生成させる +------------------------------------- + +smcプロジェクトにはsmc.scfgファイルが既に用意してあります。 +このファイルをダブルクリックするとスマートコンフィギュレータパースペクティブが開き、複数のタブを含んだ設定ページが表示されます。 +概要タブに現在選択されているコンポーネントがバージョンとともにリストアップされています。 +これらはテストアプリケーションの実行に必要なものが設定済みとなっています。 +ボード情報、クロック設定などもRX72N EnvisionKitに合わせて設定済みです。 + +設定が必要な個所は、 +コンポーネントタブで r_t4_rx コンポーネントの設定を表示させます。ここで、次のプロパティの値 +#IP address for ch0,when DHCP disable. + +として、RX72N EnvisionKitに設定するIPv4アドレスを皆さんの環境に合った値に設定してください。 +ここだけが設定が必要な個所です。 + +設定を保存し、画面右上のソースファイル生成ボタンを押してソースファイルを生成させてください。 + +------------------------------------- +3.testプロジェクトに生成させたソースファイルをコピーする +------------------------------------- + +e2studioのプロジェクト・エクスプローラー画面のtestプロジェクトのフォルダを展開すると、 +srcフォルダがあります。このフォルダに、smcプロジェクトフォルダ内のsrc/smc_genをコピーしてください。 + +------------------------------------- +4.testプロジェクトの動作を選択する +------------------------------------- + +テストアプリケーションは、暗号化テスト、ベンチマーク、TLSクライアント、TLSサーバーの +4種類の動作を選択できます。選択は、common/user_settings.hの +定義文のいずれか一つを有効化することで行います。 + +------------------------------------- +5.wolfsslプロジェクト、testプロジェクトをビルドする +------------------------------------- + +ビルド前に必ず上記4の設定が終わっていることを確認してください。 +ビルドはwolfssl,testの順に行います。 + +------------------------------------- +6.エミュレータを使ってtestアプリケーションを実行する +------------------------------------- + +エミュレータとターゲットボードとPCをケーブルで接続したら、すでに、test HardwareDebug.launchが用意してありますから +e2studioのメニュー”実行” >”デバッグ”を選択してデバッグを開始してください。 + +お手持ちのエミュレータが異なる場合はデバッグ構成を変更して上記ファイルを更新してください。 + +デバッグパースペクティブ表示になったら、e2studioのメニュー”Renesas Views” > ”デバッグ” > "Renesas Debug Virtual Console"を選択して +デバッグコンソール画面を表示してください。 testアプリケーション実行時の経過、結果等の表示がこのコンソールに出力されます。 + + +================================================================================= + +----------------------------------------------------- +0. About this document +----------------------------------------------------- + +This document will show you how to create a test application containing wolfssl on E2Studio. + +The folder that contains this README has: + 1.smc --- the folder where the smart configurator project is stored. + 2.test --- the folder where the test application project is stored + 3.wolfssl --- the folder where the project for the wolfssl library used by the test application is stored. + 4.common --- the folder where the configuration files etc. are stored + + +------------------------------------- +1. Import projects +------------------------------------- + +After starting e2studio, display the project explorer screen, +select "File" menu> "Open project from file system...", +Display the project import dialog. + +Press the directory button and import the 3 projects in the folders 1 to 3 above. + +------------------------------------- +2. Generate source files in smc project +------------------------------------- + +The smc.scfg file is already prepared in the smc project. +Double-clicking on this file will open the Smart Configurator perspective, +displaying a configuration page with multiple tabs. +The components currently selected in the Overview tab are listed along with their version. +These are already set up to run the test application. +Board information and clock settings are already set according to RX72N EnvisionKit. + +The points that need to be set are +Display the r_t4_rx component settings in the component tab. Where the value of the following property +#IP address for ch0,when DHCP disable. + +Then, set the IPv4 address set in RX72N EnvisionKit to a value that suits your environment. +This is the only place that needs to be set. + +Save the settings and press the source file generation button at the top right of the screen to generate the source file. + +------------------------------------- +3. Copy the source files generated in the test project +------------------------------------- + +When you expand the test project folder on the e2studio Project Explorer screen, +There is a src folder. Copy src/smc_gen in the smc project folder to test/src folder. + +------------------------------------- +4. Select the behavior of the test project +------------------------------------- + +Test applications include encryption test, benchmark, TLS client, TLS server +You can select four types of operation. +This is done by activating one of those commented definition statements in common/user_settings.h. + +------------------------------------- +5. Build wolfssl project, test project +------------------------------------- + +Make sure that the above settings are completed before building. +Build in order of wolfssl and test. + +------------------------------------- +6. Run the test application using the emulator +------------------------------------- + +After connecting the emulator, target board and PC with a cable, test HardwareDebug.launch is already prepared. +Select "Run"> "Debug" in e2 studio to start debugging. + +If the emulator you have is different, change the debug configuration and update the above file. + +When the debug perspective is displayed, select the e2 studio menu "Renesas Views"> "Debug"> "Renesas Debug Virtual Console" +Display the debug console screen. The progress and results of the test application execution are output to this console. diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/common/strings.h b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/strings.h new file mode 100644 index 0000000000..fd2cf86e6a --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/strings.h @@ -0,0 +1,22 @@ +/* strings.h + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +int strncasecmp(const char *s1, const char * s2, unsigned int sz); diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/common/unistd.h b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/unistd.h new file mode 100644 index 0000000000..d91dd47903 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/unistd.h @@ -0,0 +1,22 @@ +/* unistd.h + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* DUMMY Header */ diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/common/user_settings.h b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/user_settings.h new file mode 100644 index 0000000000..bcc83bdb76 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/user_settings.h @@ -0,0 +1,181 @@ +/* user_settings.h + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*-- Renesas MCU type --------------------------------------------------------- + * + * + *----------------------------------------------------------------------------*/ +/*#define WOLFSSL_RENESAS_RX65N*/ + #define WOLFSSL_RENESAS_RX72N + + +/*-- Renesas TSIP usage and its version --------------------------------------- + * + * "WOLFSSL_RENESAS_TSIP" definition makes wolfSSL to use H/W acceleration + * for cipher operations. + * TSIP definition asks to have its version number. + * "WOLFSSL_RENESAS_TSIP_VER" takes following value: + * 106: TSIPv1.06 + * 109: TSIPv1.09 + * + *----------------------------------------------------------------------------*/ + #define WOLFSSL_RENESAS_TSIP + #define WOLFSSL_RENESAS_TSIP_VER 109 + + +/*-- TLS version definitions -------------------------------------------------- + * + * wolfSSL supports TLSv1.2 by default. In case you want your system supports + * TLSv1.3, uncomment line below. + * + *----------------------------------------------------------------------------*/ +/*#define WOLFSSL_TLS13*/ + + +/*-- Operating System related definitions -------------------------------------- + * + * In case any real-time OS is used, define its name(e.g. FREERTOS). + * Otherwise, define "SINGLE_THREADED". They are exclusive each other. + * + *----------------------------------------------------------------------------*/ + #define SINGLE_THREADED +/*#define FREERTOS*/ + + +/*-- Cipher related definitions ----------------------------------------------- + * + * + *----------------------------------------------------------------------------*/ + + #define NO_DEV_RANDOM + #define USE_CERT_BUFFERS_2048 + #define WOLFSSL_DH_CONST + #define HAVE_TLS_EXTENSIONS + + #define HAVE_AESGCM + #define HAVE_AES_CBC + #define WOLFSSL_SHA512 + + #define HAVE_SUPPORTED_CURVES + #define HAVE_ECC + #define HAVE_CURVE25519 + #define CURVE25519_SMALL + #define HAVE_ED25519 + + #define WOLFSSL_STATIC_RSA + + +/*-- Misc definitions --------------------------------------------------------- + * + * + *----------------------------------------------------------------------------*/ + #define SIZEOF_LONG_LONG 8 + +#if !defined(min) + #define min(data1, data2) _builtin_min(data1, data2) +#endif + + /* + * -- "NO_ASN_TIME" macro is to avoid certificate expiration validation -- + * + * Note. In your actual products, do not forget to comment-out + * "NO_ASN_TIME" macro. And prepare time function to get calender time, + * otherwise, certificate expiration validation will not work. + */ + /*#define NO_ASN_TIME*/ + + #define NO_MAIN_DRIVER + #define BENCH_EMBEDDED + #define NO_WOLFSSL_DIR + #define WOLFSSL_NO_CURRDIR + #define NO_FILESYSTEM + #define WOLFSSL_LOG_PRINTF + #define WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MAX + #define WOLFSSL_SMALL_STACK + #define NO_WRITEV + #define WOLFSSL_USER_IO + + #define WOLFSSL_USER_CURRTIME + #define USER_TIME + #define XTIME time + #define USE_WOLF_SUSECONDS_T + #define USE_WOLF_TIMEVAL_T + + #define WOLFSSL_USER_CURRTIME /* for benchmark */ + #define WC_RSA_BLINDING + #define TFM_TIMING_RESISTANT + #define ECC_TIMING_RESISTANT + +/*-- Debugging options ------------------------------------------------------ + * + * "DEBUG_WOLFSSL" definition enables log to output into stdout. + * Note: wolfSSL_Debugging_ON() must be called just after wolfSSL_Init(). + *----------------------------------------------------------------------------*/ + +/*#define DEBUG_WOLFSSL*/ + +/*-- Definitions for functionality negation ----------------------------------- + * + * + *----------------------------------------------------------------------------*/ + +/*#define NO_RENESAS_TSIP_CRYPT*/ +/*#define NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION*/ + + +/*-- Consistency checking between definitions --------------------------------- + * + * + *----------------------------------------------------------------------------*/ + +/*-- TSIP TLS specific definitions --*/ +#if defined(WOLFSSL_RENESAS_TSIP) + #if !defined(WOLFSSL_RENESAS_TSIP_VER) + #error "WOLFSSL_RENESAS_TSIP_VER is required to be defined and have value" + #endif +#endif + +/*-- Complementary definitions ------------------------------------------------ + * + * + *----------------------------------------------------------------------------*/ + +#if defined(WOLFSSL_RENESAS_TSIP) + + #if !defined(NO_RENESAS_TSIP_CRYPT) + #define WOLFSSL_RENESAS_TSIP_CRYPT + #define WOLFSSL_RENESAS_TSIP_TLS + #define WOLFSSL_RENESAS_TSIP_TLS_AES_CRYPT + #endif + +#else + #define OPENSSL_EXTRA + #define WOLFSSL_GENSEED_FORTEST /* Warning: define your own seed gen */ +#endif + + +/*-- TLS version and required definitions --*/ +#if defined(WOLFSSL_TLS13) + #define HAVE_FFDHE_2048 + #define HAVE_HKDF + #define WC_RSA_PSS +#endif diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/common/wolfssl_dummy.c b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/wolfssl_dummy.c new file mode 100644 index 0000000000..8fa6340b45 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/wolfssl_dummy.c @@ -0,0 +1,41 @@ +/* wolfssl_dummy.c + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +typedef unsigned long time_t; + +#define YEAR 2020 +#define MON 7 + +static int tick = 0; + +time_t time(time_t *t) +{ + return ((YEAR-1970)*365+30*MON)*24*60*60 + tick++; +} + +#include +int strncasecmp(const char *s1, const char * s2, unsigned int sz) +{ + for( ; sz>0; sz--) + if(toupper(s1++) != toupper(s2++)) + return 1; + return 0; +} diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/include.am b/IDE/Renesas/e2studio/RX72NEnvisionKit/include.am new file mode 100644 index 0000000000..1b59192e70 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/include.am @@ -0,0 +1,23 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/README +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/wolfssl/.cproject +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/wolfssl/.project +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/test/.cproject +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/test/.project +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/test/test_HardwareDebug.launch +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/test_main.c +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.c +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.h +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_client.c +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_server.c +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolfssl_demo.h +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/common/wolfssl_dummy.c +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/common/strings.h +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/common/unistd.h +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/common/user_settings.h +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/smc/.cproject +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/smc/.project +EXTRA_DIST+= IDE/Renesas/e2studio/RX72NEnvisionKit/smc/smc.scfg \ No newline at end of file diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/smc/.cproject b/IDE/Renesas/e2studio/RX72NEnvisionKit/smc/.cproject new file mode 100644 index 0000000000..bd4b162235 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/smc/.cproject @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/smc/.project b/IDE/Renesas/e2studio/RX72NEnvisionKit/smc/.project new file mode 100644 index 0000000000..eb9d9de48c --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/smc/.project @@ -0,0 +1,31 @@ + + + smc + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + com.renesas.cdt.managedbuild.renesas.misrachecker.builder + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/smc/smc.scfg b/IDE/Renesas/e2studio/RX72NEnvisionKit/smc/smc.scfg new file mode 100644 index 0000000000..aae3bb2e31 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/smc/smc.scfg @@ -0,0 +1,859 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/.cproject b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/.cproject new file mode 100644 index 0000000000..266d7d6f04 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/.cproject @@ -0,0 +1,508 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/.project b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/.project new file mode 100644 index 0000000000..0a68066534 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/.project @@ -0,0 +1,59 @@ + + + test + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + com.renesas.cdt.managedbuild.renesas.misrachecker.builder + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + src/benchmark.c + 1 + $%7BPARENT-5-PROJECT_LOC%7D/wolfcrypt/benchmark/benchmark.c + + + src/benchmark.h + 1 + $%7BPARENT-5-PROJECT_LOC%7D/wolfcrypt/benchmark/benchmark.h + + + src/test.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/test/test.c + + + src/wolfssl_dummy.c + 1 + $%7BPARENT-1-PROJECT_LOC%7D/common/wolfssl_dummy.c + + + + + copy_PARENT + $%7BPARENT-3-ECLIPSE_HOME%7D/workspace/wolfssl + + + diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.c b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.c new file mode 100644 index 0000000000..6dfac9811f --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.c @@ -0,0 +1,126 @@ +/* key_data.c + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#include "key_data.h" + +/*------------------------------------------------------------------------- + TSIP v1.09 +--------------------------------------------------------------------------*/ +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && (WOLFSSL_RENESAS_TSIP_VER >=109) + +/* Key type of the encrypted user_public_key 0: RSA-2048 2: ECDSA-P256*/ +const uint32_t encrypted_user_key_type = 0; + +const st_key_block_data_t g_key_block_data = +{ + /* uint8_t encrypted_provisioning_key[R_TSIP_AES_CBC_IV_BYTE_SIZE * 2]; */ + { + 0xD8, 0xB3, 0xA7, 0xDB, 0xD1, 0x5E, 0x44, 0x24, 0x00, 0xDA, 0xEB, 0xB3, 0x33, 0xE1, 0x49, 0xAF, + 0x4B, 0xAC, 0xC5, 0xF5, 0xC8, 0xD5, 0xAC, 0x12, 0x7F, 0xF7, 0x58, 0xAE, 0x59, 0xFE, 0xFB, 0x32 + }, + /* uint8_t iv[R_TSIP_AES_CBC_IV_BYTE_SIZE]; */ + { + 0xF6, 0xA9, 0x83, 0x5A, 0xA1, 0x65, 0x1D, 0x28, 0xC8, 0x1A, 0xA6, 0x9D, 0x34, 0xB2, 0x4D, 0x92 + }, + /* uint8_t encrypted_user_rsa2048_ne_key[R_TSIP_RSA2048_NE_KEY_BYTE_SIZE + 16]; */ + { + 0xC1, 0xB7, 0xCC, 0x99, 0x0A, 0xC8, 0x3E, 0xAB, 0x74, 0x35, 0x9D, 0x1C, 0x81, 0x32, 0x72, 0xA7, + 0xA8, 0x0D, 0xBA, 0x1B, 0x35, 0x42, 0x2F, 0x7B, 0xB4, 0x1C, 0x86, 0x81, 0xC4, 0xFA, 0xD9, 0x65, + 0xCE, 0x8A, 0x70, 0x1A, 0x28, 0x09, 0x72, 0xC0, 0x4F, 0x7A, 0x4A, 0xC7, 0xE6, 0x21, 0x65, 0x6E, + 0xEB, 0x11, 0x45, 0x23, 0x35, 0xC0, 0x0F, 0x1D, 0x48, 0xC6, 0x8A, 0x1C, 0x27, 0x70, 0xA6, 0x26, + 0xD0, 0x49, 0xCD, 0x42, 0x8D, 0x65, 0x2F, 0xFC, 0x32, 0x12, 0x6F, 0xE6, 0x61, 0xB6, 0x2F, 0xD9, + 0xA7, 0xC3, 0xB0, 0x3A, 0x4F, 0x58, 0xFD, 0x1E, 0x8E, 0xDE, 0x5C, 0xD4, 0xF3, 0x4E, 0xF7, 0x45, + 0x01, 0xDC, 0x39, 0x38, 0x15, 0x37, 0x8A, 0xFD, 0x59, 0x1A, 0x6C, 0x04, 0x55, 0x31, 0x56, 0x14, + 0x07, 0x71, 0x9A, 0x19, 0x81, 0x7F, 0x69, 0x88, 0xD7, 0xD5, 0xBE, 0xB4, 0x95, 0x83, 0xC5, 0x35, + 0xA8, 0xDE, 0x65, 0x5E, 0x95, 0xBB, 0xE3, 0x9C, 0x81, 0x4C, 0x8B, 0x18, 0x4C, 0xEA, 0x12, 0xEE, + 0xF3, 0x98, 0x68, 0x35, 0xC8, 0xA5, 0x69, 0x6F, 0x71, 0x8C, 0xAA, 0xB5, 0x3F, 0xF7, 0x3C, 0x10, + 0xC0, 0xD4, 0x46, 0x4D, 0xD0, 0x56, 0xDB, 0x7F, 0xC1, 0x52, 0xE0, 0x06, 0xD8, 0xB9, 0x5E, 0x41, + 0x43, 0x0E, 0xBB, 0xCD, 0x5C, 0x4D, 0x02, 0x37, 0xD1, 0xFD, 0x88, 0xCB, 0x49, 0xC3, 0x51, 0x0C, + 0x8A, 0x17, 0x71, 0xFE, 0x97, 0x8F, 0xF6, 0x65, 0xFC, 0xF8, 0xB4, 0xC2, 0x65, 0x4B, 0x5B, 0x74, + 0x4B, 0xFF, 0x35, 0xE9, 0x33, 0x3A, 0xBE, 0xDF, 0x23, 0x4F, 0xDB, 0x3F, 0x94, 0x6F, 0x34, 0x21, + 0x76, 0x14, 0xAF, 0x2B, 0x96, 0x62, 0xA5, 0x52, 0x80, 0xB9, 0x36, 0x7E, 0x25, 0xAF, 0xB6, 0x75, + 0xE5, 0x79, 0x8E, 0xE8, 0x67, 0xE4, 0xDD, 0x4B, 0x3D, 0xB2, 0x7F, 0xAF, 0x32, 0xC5, 0xF5, 0x1B, + 0x90, 0x0E, 0x41, 0x97, 0x5D, 0xFD, 0xC1, 0x9A, 0xA1, 0xF9, 0x57, 0xF1, 0x21, 0x94, 0xF9, 0x31, + 0xC9, 0xC7, 0x16, 0xAA, 0xD8, 0xE9, 0x78, 0x03, 0xAD, 0xEF, 0x3E, 0x98, 0x1F, 0x32, 0x3D, 0x8E + }, + /* uint8_t encrypted_user_update_key[R_TSIP_AES256_KEY_BYTE_SIZE + 16]; */ + { + 0x70, 0xA8, 0xB5, 0x63, 0xE9, 0xC2, 0xA0, 0xFC, 0xE5, 0xA5, 0x4D, 0x94, 0x6E, 0x69, 0xE8, 0x94, + 0xAC, 0xE6, 0x68, 0x7C, 0xB2, 0xB9, 0xDC, 0xCF, 0x69, 0xBC, 0xE6, 0xB9, 0x8C, 0xDA, 0x72, 0x5C, + 0x62, 0xE9, 0xB9, 0xC1, 0xB4, 0xC7, 0x60, 0x21, 0xAE, 0x1B, 0x52, 0x25, 0x06, 0x8A, 0x91, 0xA1 + }, + +}; +/* ./ca-cert.der.sign, */ +const unsigned char ca_cert_sig[] = +{ +0x04,0x1C,0x4C,0x29,0x93,0x38,0x78,0x72,0x32,0x55,0x90,0x4F,0xA7,0x43,0xC8,0x00, +0x98,0x75,0xC8,0x62,0x37,0xEC,0x8F,0xAD,0x8F,0x98,0x04,0x5B,0xC9,0x50,0xD2,0xE3, +0xC3,0x89,0x21,0xC7,0xF4,0x43,0x27,0xFB,0xC0,0x7A,0x17,0x45,0x5C,0x10,0x23,0x1B, +0xC0,0x63,0x2F,0x61,0xE5,0xEE,0x0B,0x89,0xF2,0x6E,0x6B,0x49,0xFB,0xD4,0xB5,0x89, +0xED,0xB4,0x7F,0x70,0xA0,0x68,0x44,0x6F,0xE6,0x15,0x0F,0x0C,0x78,0x9D,0x4C,0xBD, +0x1C,0x24,0x50,0xAE,0xD2,0xB4,0x53,0xA5,0x7C,0x5F,0x5D,0x8C,0x8C,0x37,0xAB,0x72, +0x61,0x83,0x39,0xDD,0x76,0x86,0xB4,0xEC,0xCF,0x57,0x35,0xC4,0x56,0x6B,0x45,0xCE, +0x4C,0x06,0x35,0xBE,0xF2,0x95,0x5A,0x37,0x43,0x15,0x7F,0x42,0x3A,0xBA,0x90,0xE7, +0x01,0x37,0x10,0x46,0x5B,0x65,0x7D,0x2F,0xAF,0x9F,0xCB,0xBB,0xFF,0x0D,0x5D,0xE0, +0xCD,0xA8,0x09,0x62,0xCA,0x38,0x10,0x09,0x1B,0x81,0x2D,0xC2,0x3E,0x15,0x9E,0x36, +0x6B,0x10,0xF9,0xD9,0x55,0xBF,0x93,0x79,0xC0,0x0D,0x74,0x31,0x83,0xA4,0xB9,0x66, +0x30,0x6C,0xC9,0xA9,0xE6,0x93,0xF0,0x1D,0x61,0x18,0xBD,0x95,0xA5,0xB4,0x0F,0x69, +0xCD,0xD7,0xA3,0x4A,0x74,0x8B,0xBE,0x2D,0x90,0xA5,0x49,0x69,0x9B,0x59,0x29,0x3A, +0x4D,0x77,0xF0,0x4F,0x37,0x42,0x89,0x67,0xE2,0x62,0x91,0xC6,0x25,0xA6,0x2B,0x35, +0x2C,0x59,0x60,0xB4,0xAF,0x9F,0xBF,0x43,0x4E,0x32,0x11,0xCE,0x8F,0x7A,0x4C,0xA4, +0x26,0xBF,0x3A,0x35,0x70,0xD6,0x9F,0x0C,0x76,0xC8,0xCA,0x94,0xA0,0xD4,0x0B,0x2D +}; +const int sizeof_ca_cert_sig = sizeof(ca_cert_sig); +/* ./client-cert.der.sign, */ +const unsigned char client_cert_der_sign[] = +{ + 0x5D, 0x1F, 0x89, 0x41, 0xEC, 0x47, 0xC8, 0x90, 0x61, 0x79, + 0x8A, 0x16, 0x1F, 0x31, 0x96, 0x67, 0xD9, 0x3C, 0xEC, 0x6B, + 0x58, 0xC6, 0x5A, 0xED, 0x99, 0xB3, 0xEF, 0x27, 0x6F, 0x04, + 0x8C, 0xD9, 0x68, 0xB1, 0xD6, 0x23, 0x15, 0x84, 0x00, 0xE1, + 0x27, 0xD1, 0x1F, 0x68, 0xB7, 0x3F, 0x13, 0x53, 0x8A, 0x95, + 0x5A, 0x20, 0x7C, 0xB2, 0x76, 0x5B, 0xDC, 0xE0, 0xA6, 0x21, + 0x7C, 0x49, 0xCF, 0x93, 0xBA, 0xD5, 0x12, 0x9F, 0xEE, 0x90, + 0x5B, 0x3F, 0xA3, 0x9D, 0x13, 0x72, 0xAC, 0x72, 0x16, 0xFE, + 0x1D, 0xBE, 0xEB, 0x8E, 0xC7, 0xDC, 0xC4, 0xF8, 0x1A, 0xD8, + 0xA0, 0xA4, 0xF6, 0x04, 0x30, 0xF6, 0x7E, 0xB6, 0xC8, 0xE1, + 0xAB, 0x88, 0x37, 0x08, 0x63, 0x72, 0xAA, 0x46, 0xCC, 0xCA, + 0xF0, 0x9E, 0x02, 0x1E, 0x65, 0x67, 0xFF, 0x2C, 0x9D, 0x81, + 0x6C, 0x1E, 0xF1, 0x54, 0x05, 0x68, 0x68, 0x18, 0x72, 0x26, + 0x55, 0xB6, 0x2C, 0x95, 0xC0, 0xC9, 0xB2, 0xA7, 0x0B, 0x60, + 0xD7, 0xEB, 0x1D, 0x08, 0x1A, 0xA2, 0x54, 0x15, 0x89, 0xCB, + 0x83, 0x21, 0x5D, 0x15, 0x9B, 0x38, 0xAC, 0x89, 0x63, 0xD5, + 0x4B, 0xF4, 0x8B, 0x47, 0x93, 0x78, 0x43, 0xCB, 0x9B, 0x71, + 0xBF, 0x94, 0x76, 0xB5, 0xCE, 0x35, 0xA9, 0x1A, 0xD5, 0xA5, + 0xD8, 0x19, 0xA6, 0x04, 0x39, 0xB1, 0x09, 0x8C, 0x65, 0x02, + 0x58, 0x3A, 0x95, 0xEF, 0xA2, 0xC3, 0x85, 0x18, 0x61, 0x23, + 0x2D, 0xC5, 0xCD, 0x62, 0xC1, 0x19, 0x31, 0xE5, 0x36, 0x95, + 0x22, 0xDB, 0x3E, 0x1A, 0x3C, 0xE8, 0xC6, 0x2E, 0xDF, 0xD9, + 0x2F, 0x84, 0xC1, 0xF0, 0x38, 0x2B, 0xE5, 0x73, 0x35, 0x4F, + 0x05, 0xE2, 0xA5, 0x60, 0x79, 0xB0, 0x23, 0xDC, 0x56, 0x4C, + 0xE7, 0xD9, 0x1F, 0xCF, 0x6A, 0xFC, 0x55, 0xEB, 0xAA, 0x48, + 0x3E, 0x95, 0x2A, 0x10, 0x01, 0x05 +}; +const int sizeof_client_cert_der_sign = sizeof(client_cert_der_sign); + +uint32_t s_inst1[R_TSIP_SINST_WORD_SIZE] = { 0 }; +uint32_t s_inst2[R_TSIP_SINST2_WORD_SIZE]= { 0 }; +#endif diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.h b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.h new file mode 100644 index 0000000000..74e9ed2423 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.h @@ -0,0 +1,54 @@ +/* key_data.h + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifndef KEY_DATA_H_ +#define KEY_DATA_H_ + +#include + + +#if defined(WOLFSSL_RENESAS_TSIP) + +#include "r_tsip_rx_if.h" + +typedef struct st_key_block_data +{ + uint8_t encrypted_provisioning_key[R_TSIP_AES_CBC_IV_BYTE_SIZE * 2]; + uint8_t iv[R_TSIP_AES_CBC_IV_BYTE_SIZE]; + uint8_t encrypted_user_rsa2048_ne_key[R_TSIP_RSA2048_NE_KEY_BYTE_SIZE + 16]; + uint8_t encrypted_user_update_key[R_TSIP_AES256_KEY_BYTE_SIZE + 16]; +} st_key_block_data_t; + + +extern const uint32_t encrypted_user_key_type; +extern const st_key_block_data_t g_key_block_data; + +extern const unsigned char ca_cert_sig[]; +extern const unsigned char ca_cert_der[]; +extern const unsigned char client_cert_der_sign[]; +extern const int sizeof_ca_cert_der; + + +#endif /* (WOLFSSL_RENESAS_TSIP */ +#endif /* KEY_DATA_H_ */ + diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/test_main.c b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/test_main.c new file mode 100644 index 0000000000..7d336826a2 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/test_main.c @@ -0,0 +1,251 @@ +/* test_main.c + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#include "stdio.h" +#include "stdint.h" +#include +#include "wolfssl/wolfcrypt/types.h" +#include "wolfssl_demo.h" + +void main(void); +#ifdef __cplusplus +extern "C" { +void abort(void); +} +#endif + + +#if defined(TLS_CLIENT) || defined(TLS_SERVER) + #include "r_t4_itcpip.h" + #include "r_sys_time_rx_if.h" + #include "Pin.h" + + #define T4_WORK_SIZE (14800) + static UW tcpudp_work[(T4_WORK_SIZE / 4) + 1]; + + #if defined(WOLFSSL_RENESAS_TSIP) + #include "key_data.h" + #include + + extern const st_key_block_data_t g_key_block_data; + #endif + +#endif + +static long tick; +static void timeTick(void *pdata) +{ + tick++; +} + +typedef struct func_args { + int argc; + char** argv; + int return_code; +} func_args; + + +void wolfcrypt_test(func_args args); +int benchmark_test(void *args); + +double current_time(int reset) +{ + if(reset) tick = 0 ; + return ((double)tick/FREQ) ; +} + +#if defined(TLS_CLIENT) || defined(TLS_SERVER) + +int SetTsiptlsKey() +{ +#if defined(WOLFSSL_RENESAS_TSIP) && (WOLFSSL_RENESAS_TSIP_VER >=109) + + #if defined(TLS_CLIENT) + + tsip_inform_cert_sign((const byte *)ca_cert_sig); + tsip_inform_user_keys_ex( + (byte*)&g_key_block_data.encrypted_provisioning_key, + (byte*)&g_key_block_data.iv, + (byte*)&g_key_block_data.encrypted_user_rsa2048_ne_key, + encrypted_user_key_type); + + #elif defined(TLS_SERVER) + + tsip_inform_cert_sign((const byte *)client_cert_der_sign); + tsip_inform_user_keys_ex( + (byte*)&g_key_block_data.encrypted_provisioning_key, + (byte*)&g_key_block_data.iv, + (byte*)&g_key_block_data.encrypted_user_rsa2048_ne_key, + encrypted_user_key_type); + + #endif + +#elif defined(WOLFSSL_RENESAS_TSIP) && (WOLFSSL_RENESAS_TSIP_VER >=106) + + #if defined(TLS_CLIENT) + + tsip_inform_cert_sign((const byte *)ca_cert_sig); + tsip_inform_user_keys((byte*)&g_key_block_data.encrypted_session_key, + (byte*)&g_key_block_data.iv, + (byte*)&g_key_block_data.encrypted_user_rsa2048_ne_key); + + #elif defined(TLS_SERVER) + + tsip_inform_cert_sign((const byte *)client_cert_der_sign); + tsip_inform_user_keys((byte*)&g_key_block_data.encrypted_session_key, + (byte*)&g_key_block_data.iv, + (byte*)&g_key_block_data.encrypted_user_rsa2048_ne_key); + + #endif + +#endif + return 0; +} + +int Open_tcp( ) +{ + ER ercd; + W size; + sys_time_err_t sys_ercd; + char ver[128]; + + /* cast from uint8_t to char* */ + strcpy(ver, (char*)R_t4_version.library); + + sys_ercd = R_SYS_TIME_Open(); + if (sys_ercd != SYS_TIME_SUCCESS) { + printf("ERROR : R_SYS_TIME_Open() failed\n"); + return -1; + } + R_Pins_Create(); + /* start LAN controller */ + ercd = lan_open(); + /* initialize TCP/IP */ + size = tcpudp_get_ramsize(); + if (size > (sizeof(tcpudp_work))) { + printf("size > (sizeof(tcpudp_work))!\n"); + return -1; + } + ercd = tcpudp_open(tcpudp_work); + if (ercd != E_OK) { + printf("ERROR : tcpudp_open failed\n"); + return -1; + } + + return 0; +} + +void Close_tcp() +{ + /* end TCP/IP */ + tcpudp_close(); + lan_close(); + R_SYS_TIME_Close(); +} +#endif + +void main(void) +{ + (void)timeTick; + +#if defined(CRYPT_TEST) || defined(BENCHMARK) +#if defined(CRYPT_TEST) + int ret; + func_args args = { 0 }; + + if ((ret = wolfCrypt_Init()) != 0) { + printf("wolfCrypt_Init failed %d\n", ret); + } + + printf("Start wolfCrypt Test\n"); + wolfcrypt_test(args); + printf("End wolfCrypt Test\n"); + + if ((ret = wolfCrypt_Cleanup()) != 0) { + printf("wolfCrypt_Cleanup failed %d\n", ret); + } +#endif +#if defined(BENCHMARK) + #include "r_cmt_rx_if.h" + + uint32_t channel; + R_CMT_CreatePeriodic(FREQ, &timeTick, &channel); + + printf("Start wolfCrypt Benchmark\n"); + benchmark_test(NULL); + printf("End wolfCrypt Benchmark\n"); +#endif +#elif defined(TLS_CLIENT) + #include "r_cmt_rx_if.h" + +#if defined(WOLFSSL_RENESAS_TSIP) + const char* cipherlist[] = { + + "AES128-SHA", + "AES128-SHA256", + "AES256-SHA", + "AES256-SHA256" + }; + const int cipherlist_sz = 4; +#else + const char* cipherlist[] = { NULL }; + const int cipherlist_sz = 0; + +#endif + int i = 0; + + Open_tcp(); +#if defined(WOLFSSL_RENESAS_TSIP) + SetTsiptlsKey(); +#endif + + do { + if(cipherlist_sz > 0 ) printf("cipher : %s\n", cipherlist[i]); + + wolfSSL_TLS_client_init(cipherlist[i]); + + wolfSSL_TLS_client(); + + i++; + } while (i < cipherlist_sz); + + Close_tcp(); +#elif defined(TLS_SERVER) + + Open_tcp(); +#if defined(WOLFSSL_RENESAS_TSIP) + SetTsiptlsKey(); +#endif + + wolfSSL_TLS_server_init(); + wolfSSL_TLS_server(); + + Close_tcp(); +#endif +} + +#ifdef __cplusplus +void abort(void) +{ + +} +#endif diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_client.c b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_client.c new file mode 100644 index 0000000000..ff09b1a807 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_client.c @@ -0,0 +1,212 @@ +/* wolf_client.c + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include +#include "r_t4_itcpip.h" +#include "wolfssl/wolfcrypt/settings.h" +#include "wolfssl/ssl.h" +#include "wolfssl/certs_test.h" +#include "key_data.h" +#include "wolfssl_demo.h" + + +#define SIMPLE_TLSSEVER_IP "192.168.1.3" +#define SIMPLE_TLSSERVER_PORT "11111" + +ER t4_tcp_callback(ID cepid, FN fncd , VP p_parblk); +uint32_t g_encrypted_root_public_key[140]; + +static WOLFSSL_CTX *client_ctx; + + +static int my_IORecv(WOLFSSL* ssl, char* buff, int sz, void* ctx) +{ + int ret; + ID cepid; + + if(ctx != NULL) + cepid = *(ID *)ctx; + else + return WOLFSSL_CBIO_ERR_GENERAL; + + ret = tcp_rcv_dat(cepid, buff, sz, TMO_FEVR); + if(ret > 0) + return ret; + else + return WOLFSSL_CBIO_ERR_GENERAL; +} + +static int my_IOSend(WOLFSSL* ssl, char* buff, int sz, void* ctx) +{ + int ret; + ID cepid; + + if(ctx != NULL) + cepid = *(ID *)ctx; + else + return WOLFSSL_CBIO_ERR_GENERAL; + + ret = tcp_snd_dat(cepid, buff, sz, TMO_FEVR); + if(ret == sz) + return ret; + else + return WOLFSSL_CBIO_ERR_GENERAL; +} + +static int getIPaddr(char *arg) +{ + int a1, a2, a3, a4; + if(sscanf(arg, "%d.%d.%d.%d", &a1, &a2, &a3, &a4) == 4) + return (a1 << 24) | (a2 << 16) | (a3 << 8) | a4; + else return 0; +} + +static int getPort(char *arg) +{ + int port; + if(sscanf(arg, "%d", &port) == 1) + return port; + else return 0; +} + +void wolfSSL_TLS_client_init(const char* cipherlist) +{ + + #ifndef NO_FILESYSTEM + #ifdef USE_ECC_CERT + char *cert = "./certs/ca-ecc-cert.pem"; + #else + char *cert = "./certs/ca-cert.pem"; + #endif + #else + #ifdef USE_ECC_CERT + const unsigned char *cert = ca_ecc_der_256; + #define SIZEOF_CERT sizeof_ca_ecc_der_256 + #else + const unsigned char *cert = ca_cert_der_2048; + #define SIZEOF_CERT sizeof_ca_cert_der_2048 + #endif + #endif + + wolfSSL_Init(); + #ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); + #endif + + /* Create and initialize WOLFSSL_CTX */ + if ((client_ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method_ex((void *)NULL))) == NULL) { + printf("ERROR: failed to create WOLFSSL_CTX\n"); + return; + } + + #if !defined(NO_FILESYSTEM) + if (wolfSSL_CTX_load_verify_locations(client_ctx, cert, 0) != SSL_SUCCESS) { + printf("ERROR: can't load \"%s\"\n", cert); + return NULL; + } + #else + if (wolfSSL_CTX_load_verify_buffer(client_ctx, cert, SIZEOF_CERT, SSL_FILETYPE_ASN1) != SSL_SUCCESS){ + printf("ERROR: can't load certificate data\n"); + return; + } + #endif + + /* Register callbacks */ + wolfSSL_SetIORecv(client_ctx, my_IORecv); + wolfSSL_SetIOSend(client_ctx, my_IOSend); + + /* use specific cipher */ + if (cipherlist != NULL && wolfSSL_CTX_set_cipher_list(client_ctx, cipherlist) != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(client_ctx); client_ctx = NULL; + printf("client can't set cipher list 1"); + } +} + +void wolfSSL_TLS_client( ) +{ + ID cepid = 1; + ER ercd; + int ret; + WOLFSSL_CTX *ctx = (WOLFSSL_CTX *)client_ctx; + WOLFSSL *ssl; + + #define BUFF_SIZE 256 + static const char sendBuff[]= "Hello Server\n" ; + + char rcvBuff[BUFF_SIZE] = {0}; + + static T_IPV4EP my_addr = { 0, 0 }; + + T_IPV4EP dst_addr; + + if((dst_addr.ipaddr = getIPaddr(SIMPLE_TLSSEVER_IP)) == 0){ + printf("ERROR: IP address\n"); + return; + } + if((dst_addr.portno = getPort(SIMPLE_TLSSERVER_PORT)) == 0){ + printf("ERROR: IP address\n"); + return; + } + + if((ercd = tcp_con_cep(cepid, &my_addr, &dst_addr, TMO_FEVR)) != E_OK) { + printf("ERROR TCP Connect: %d\n", ercd); + return; + } + + if((ssl = wolfSSL_new(ctx)) == NULL) { + printf("ERROR wolfSSL_new: %d\n", wolfSSL_get_error(ssl, 0)); + return; + } + + /* set callback context */ + wolfSSL_SetIOReadCtx(ssl, (void *)&cepid); + wolfSSL_SetIOWriteCtx(ssl, (void *)&cepid); + + + if(wolfSSL_connect(ssl) != SSL_SUCCESS) { + printf("ERROR SSL connect: %d\n", wolfSSL_get_error(ssl, 0)); + return; + } + + if (wolfSSL_write(ssl, sendBuff, strlen(sendBuff)) != strlen(sendBuff)) { + printf("ERROR SSL write: %d\n", wolfSSL_get_error(ssl, 0)); + return; + } + + if ((ret=wolfSSL_read(ssl, rcvBuff, BUFF_SIZE)) < 0) { + printf("ERROR SSL read: %d\n", wolfSSL_get_error(ssl, 0)); + return; + } + + rcvBuff[ret] = '\0' ; + printf("Received: %s\n\n", rcvBuff); + + /* frees all data before client termination */ + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + wolfSSL_Cleanup(); + + tcp_sht_cep(cepid); + tcp_cls_cep(cepid, TMO_FEVR); + + return; +} diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_server.c b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_server.c new file mode 100644 index 0000000000..5d38b03588 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_server.c @@ -0,0 +1,203 @@ +/* wolf_server.c + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#include +#include +#include "r_t4_itcpip.h" + +#include "wolfssl/wolfcrypt/settings.h" +#include "wolfssl/ssl.h" +#include "wolfssl/certs_test.h" +#include "wolfssl_demo.h" + +static WOLFSSL_CTX *server_ctx; +static byte doCliCertCheck; + +static int my_IORecv(WOLFSSL* ssl, char* buff, int sz, void* ctx) +{ + int ret; + ID cepid; + + if(ctx != NULL) + cepid = *(ID *)ctx; + else + return WOLFSSL_CBIO_ERR_GENERAL; + + ret = tcp_rcv_dat(cepid, buff, sz, TMO_FEVR); + if(ret == sz) + return ret; + else + return WOLFSSL_CBIO_ERR_GENERAL; +} + +static int my_IOSend(WOLFSSL* ssl, char* buff, int sz, void* ctx) +{ + int ret; + ID cepid; + + if(ctx != NULL) + cepid = *(ID *)ctx; + else + return WOLFSSL_CBIO_ERR_GENERAL; + + ret = tcp_snd_dat(cepid, buff, sz, TMO_FEVR); + if(ret == sz) + return ret; + else + return WOLFSSL_CBIO_ERR_GENERAL; +} + + +void wolfSSL_TLS_server_init(byte doClientCheck) +{ + + int ret; + + + #ifndef NO_FILESYSTEM + #ifdef USE_ECC_CERT + char *cert = "./certs/server-ecc-cert.pem"; + char *key = "./certs/server-ecc-key.pem"; + #else + char *cert = "./certs/server-cert.pem"; + char *key = "./certs/server-key.pem"; + #endif + char *clientCert = "./certs/client-cert.pem"; + #else + #ifdef USE_ECC_CERT + char *cert = serv_ecc_der_256; + int sizeof_cert = sizeof_serv_ecc_der_256; + char *cert = serv_ecc_key_der_256; + int sizeof_key = sizeof_serv_ecc_key_der_256; + #else + const unsigned char *cert = server_cert_der_2048; + #define sizeof_cert sizeof_server_cert_der_2048 + const unsigned char *key = server_key_der_2048; + #define sizeof_key sizeof_server_key_der_2048 + const unsigned char *clientCert = client_cert_der_2048; + #define sizeof_clicert sizeof_client_cert_der_2048 + #endif + #endif + + + wolfSSL_Init(); + #ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); + #endif + + /* Create and initialize WOLFSSL_CTX */ + if ((server_ctx = wolfSSL_CTX_new(wolfSSLv23_server_method_ex((void *)NULL))) + == NULL) { + printf("ERROR: failed to create WOLFSSL_CTX\n"); + return; + } + + #if !defined(NO_FILESYSTEM) + ret = wolfSSL_CTX_use_certificate_file(server_ctx, cert, 0); + #else + ret = wolfSSL_CTX_use_certificate_buffer(server_ctx, cert, + sizeof_cert, SSL_FILETYPE_ASN1); + #endif + if (ret != SSL_SUCCESS) { + printf("Error %d loading server-cert!\n", ret); + return; + } + + /* Load server key into WOLFSSL_CTX */ + #if !defined(NO_FILESYSTEM) + ret = wolfSSL_CTX_use_PrivateKey_file(server_ctx, key, 0); + #else + ret = wolfSSL_CTX_use_PrivateKey_buffer(server_ctx, key, sizeof_key, + SSL_FILETYPE_ASN1); + #endif + if (ret != SSL_SUCCESS) { + printf("Error %d loading server-key!\n", ret); + return; + } +#if defined(WOLFSSL_RENESAS_TSIP) + doCliCertCheck = 1; +#endif + if (doCliCertCheck) { + wolfSSL_CTX_set_verify(server_ctx, WOLFSSL_VERIFY_PEER | + WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); +#if !defined(NO_FILESYSTEM) + if (wolfSSL_CTX_load_verify_locations(server_ctx, clientCert, 0) + != WOLFSSL_SUCCESS) +#else + if (wolfSSL_CTX_load_verify_buffer(server_ctx, clientCert, + sizeof_clicert, + SSL_FILETYPE_ASN1) != SSL_SUCCESS) +#endif + printf("can't load ca file, Please run from wolfSSL home dir\n"); + } + + /* Register callbacks */ + wolfSSL_SetIORecv(server_ctx, my_IORecv); + wolfSSL_SetIOSend(server_ctx, my_IOSend); + +} + +void wolfSSL_TLS_server( ) +{ + ID cepid = 1; + ID repid = 1; + ER ercd; + WOLFSSL_CTX *ctx = (WOLFSSL_CTX *)server_ctx; + + WOLFSSL *ssl; + int len; + #define BUFF_SIZE 256 + char buff[BUFF_SIZE]; + T_IPV4EP dst_addr = {0, 0}; + + if((ercd = tcp_acp_cep(cepid, repid, &dst_addr, TMO_FEVR)) != E_OK) { + printf("ERROR TCP Accept: %d\n", ercd); + return; + } + + if((ssl = wolfSSL_new(ctx)) == NULL) { + printf("ERROR: failed wolfSSL_new\n"); + return; + } + + wolfSSL_SetIOReadCtx(ssl, (void *)&cepid); + wolfSSL_SetIOWriteCtx(ssl, (void *)&cepid); + + if (wolfSSL_accept(ssl) < 0) { + printf("ERROR: SSL Accept(%d)\n", wolfSSL_get_error(ssl, 0)); + return; + } + + if ((len = wolfSSL_read(ssl, buff, sizeof(buff) - 1)) < 0) { + printf("ERROR: SSL Read(%d)\n", wolfSSL_get_error(ssl, 0)); + return; + } + + buff[len] = '\0'; + printf("Received: %s\n", buff); + + if (wolfSSL_write(ssl, buff, len) != len) { + printf("ERROR: SSL Write(%d)\n", wolfSSL_get_error(ssl, 0)); + return; + } + + wolfSSL_free(ssl); + tcp_sht_cep(cepid); +} diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolfssl_demo.h b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolfssl_demo.h new file mode 100644 index 0000000000..b2a2722452 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolfssl_demo.h @@ -0,0 +1,48 @@ +/* wolfssl_demo.h + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef WOLFSSL_DEMO_H_ +#define WOLFSSL_DEMO_H_ + +#define FREQ 10000 /* Hz */ + +/* Enable wolfcrypt test */ +/* can be enabled with benchmark test */ +/* #define CRYPT_TEST */ + +/* Enable benchmark */ +/* can be enabled with cyrpt test */ +/* #define BENCHMARK*/ + +/* Enable TLS client */ +/* cannot enable with other definition */ +/* #define TLS_CLIENT*/ + +/* Enable TLS server */ +/* cannot enable with other definition */ +/* #define TLS_SERVER */ + +void wolfSSL_TLS_client_init(); +void wolfSSL_TLS_client(); +void wolfSSL_TLS_server_init(); +void wolfSSL_TLS_server(); + +#endif /* WOLFSSL_DEMO_H_ */ diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/test_HardwareDebug.launch b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/test_HardwareDebug.launch new file mode 100644 index 0000000000..e4db5e81b6 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/test_HardwareDebug.launch @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/wolfssl/.cproject b/IDE/Renesas/e2studio/RX72NEnvisionKit/wolfssl/.cproject new file mode 100644 index 0000000000..d93a048063 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/wolfssl/.cproject @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/wolfssl/.project b/IDE/Renesas/e2studio/RX72NEnvisionKit/wolfssl/.project new file mode 100644 index 0000000000..46ee100915 --- /dev/null +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/wolfssl/.project @@ -0,0 +1,393 @@ + + + wolfssl + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + src/crl.c + 1 + PARENT-5-PROJECT_LOC/src/crl.c + + + src/internal.c + 1 + PARENT-5-PROJECT_LOC/src/internal.c + + + src/keys.c + 1 + PARENT-5-PROJECT_LOC/src/keys.c + + + src/ocsp.c + 1 + PARENT-5-PROJECT_LOC/src/ocsp.c + + + src/sniffer.c + 1 + PARENT-5-PROJECT_LOC/src/sniffer.c + + + src/ssl.c + 1 + PARENT-5-PROJECT_LOC/src/ssl.c + + + src/tls.c + 1 + PARENT-5-PROJECT_LOC/src/tls.c + + + src/tls13.c + 1 + PARENT-5-PROJECT_LOC/src/tls13.c + + + src/wolfio.c + 1 + PARENT-5-PROJECT_LOC/src/wolfio.c + + + wolfcrypt/port/renesas_tsip_aes.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/port/Renesas/renesas_tsip_aes.c + + + wolfcrypt/port/renesas_tsip_sha.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/port/Renesas/renesas_tsip_sha.c + + + wolfcrypt/port/renesas_tsip_util.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/port/Renesas/renesas_tsip_util.c + + + wolfcrypt/src/aes.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/aes.c + + + wolfcrypt/src/arc4.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/arc4.c + + + wolfcrypt/src/asm.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/asm.c + + + wolfcrypt/src/asn.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/asn.c + + + wolfcrypt/src/blake2b.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/blake2b.c + + + wolfcrypt/src/camellia.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/camellia.c + + + wolfcrypt/src/chacha.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/chacha.c + + + wolfcrypt/src/chacha20_poly1305.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/chacha20_poly1305.c + + + wolfcrypt/src/cmac.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/cmac.c + + + wolfcrypt/src/coding.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/coding.c + + + wolfcrypt/src/compress.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/compress.c + + + wolfcrypt/src/cpuid.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/cpuid.c + + + wolfcrypt/src/cryptocb.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/cryptocb.c + + + wolfcrypt/src/curve25519.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/curve25519.c + + + wolfcrypt/src/des3.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/des3.c + + + wolfcrypt/src/dh.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/dh.c + + + wolfcrypt/src/dsa.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/dsa.c + + + wolfcrypt/src/ecc.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/ecc.c + + + wolfcrypt/src/ecc_fp.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/ecc_fp.c + + + wolfcrypt/src/ed25519.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/ed25519.c + + + wolfcrypt/src/error.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/error.c + + + wolfcrypt/src/fe_low_mem.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/fe_low_mem.c + + + wolfcrypt/src/fe_operations.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/fe_operations.c + + + wolfcrypt/src/ge_low_mem.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/ge_low_mem.c + + + wolfcrypt/src/ge_operations.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/ge_operations.c + + + wolfcrypt/src/hash.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/hash.c + + + wolfcrypt/src/hc128.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/hc128.c + + + wolfcrypt/src/hmac.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/hmac.c + + + wolfcrypt/src/idea.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/idea.c + + + wolfcrypt/src/include.am + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/include.am + + + wolfcrypt/src/integer.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/integer.c + + + wolfcrypt/src/logging.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/logging.c + + + wolfcrypt/src/md2.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/md2.c + + + wolfcrypt/src/md4.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/md4.c + + + wolfcrypt/src/md5.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/md5.c + + + wolfcrypt/src/memory.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/memory.c + + + wolfcrypt/src/pkcs12.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/pkcs12.c + + + wolfcrypt/src/pkcs7.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/pkcs7.c + + + wolfcrypt/src/poly1305.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/poly1305.c + + + wolfcrypt/src/pwdbased.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/pwdbased.c + + + wolfcrypt/src/rabbit.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/rabbit.c + + + wolfcrypt/src/random.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/random.c + + + wolfcrypt/src/ripemd.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/ripemd.c + + + wolfcrypt/src/rsa.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/rsa.c + + + wolfcrypt/src/sha.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/sha.c + + + wolfcrypt/src/sha256.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/sha256.c + + + wolfcrypt/src/sha3.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/sha3.c + + + wolfcrypt/src/sha512.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/sha512.c + + + wolfcrypt/src/signature.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/signature.c + + + wolfcrypt/src/sp_arm32.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/sp_arm32.c + + + wolfcrypt/src/sp_arm64.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/sp_arm64.c + + + wolfcrypt/src/sp_c32.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/sp_c32.c + + + wolfcrypt/src/sp_c64.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/sp_c64.c + + + wolfcrypt/src/sp_int.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/sp_int.c + + + wolfcrypt/src/sp_x86_64.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/sp_x86_64.c + + + wolfcrypt/src/srp.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/srp.c + + + wolfcrypt/src/tfm.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/tfm.c + + + wolfcrypt/src/wc_encrypt.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/wc_encrypt.c + + + wolfcrypt/src/wc_port.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/wc_port.c + + + wolfcrypt/src/wolfevent.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/wolfevent.c + + + wolfcrypt/src/wolfmath.c + 1 + PARENT-5-PROJECT_LOC/wolfcrypt/src/wolfmath.c + + + diff --git a/IDE/WIN/user_settings.h b/IDE/WIN/user_settings.h old mode 100755 new mode 100644 diff --git a/IDE/XCODE/Benchmark/wolfBench.xcodeproj/project.pbxproj b/IDE/XCODE/Benchmark/wolfBench.xcodeproj/project.pbxproj index 9850627f92..46767b6a35 100644 --- a/IDE/XCODE/Benchmark/wolfBench.xcodeproj/project.pbxproj +++ b/IDE/XCODE/Benchmark/wolfBench.xcodeproj/project.pbxproj @@ -10,7 +10,6 @@ 52114C8721B5A7320022ADA1 /* sp_c64.c in Sources */ = {isa = PBXBuildFile; fileRef = 52114C8621B5A7320022ADA1 /* sp_c64.c */; }; A46FE16F2493E8F800A25BE7 /* armv8-chacha.c in Sources */ = {isa = PBXBuildFile; fileRef = A46FE14C2493E8F500A25BE7 /* armv8-chacha.c */; }; A46FE1702493E8F800A25BE7 /* sp_int.c in Sources */ = {isa = PBXBuildFile; fileRef = A46FE14D2493E8F600A25BE7 /* sp_int.c */; }; - A46FE1732493E8F800A25BE7 /* armv8-poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = A46FE1502493E8F600A25BE7 /* armv8-poly1305.c */; }; A46FE1742493E8F800A25BE7 /* sp_cortexm.c in Sources */ = {isa = PBXBuildFile; fileRef = A46FE1512493E8F600A25BE7 /* sp_cortexm.c */; }; A46FE1752493E8F800A25BE7 /* blake2s.c in Sources */ = {isa = PBXBuildFile; fileRef = A46FE1522493E8F600A25BE7 /* blake2s.c */; }; A46FE1772493E8F800A25BE7 /* wc_pkcs11.c in Sources */ = {isa = PBXBuildFile; fileRef = A46FE1542493E8F600A25BE7 /* wc_pkcs11.c */; }; @@ -95,17 +94,20 @@ A4ADF9281FCE0C5600A06E90 /* ecc.c in Sources */ = {isa = PBXBuildFile; fileRef = A4ADF8CC1FCE0C5500A06E90 /* ecc.c */; }; A4ADF92A1FCE0C5600A06E90 /* coding.c in Sources */ = {isa = PBXBuildFile; fileRef = A4ADF8CE1FCE0C5500A06E90 /* coding.c */; }; A4ADF92C1FCE0C5600A06E90 /* ge_low_mem.c in Sources */ = {isa = PBXBuildFile; fileRef = A4ADF8D01FCE0C5500A06E90 /* ge_low_mem.c */; }; + A4CA2EA324C8AF97003CCC50 /* armv8-sha512.c in Sources */ = {isa = PBXBuildFile; fileRef = A4CA2E9E24C8AF97003CCC50 /* armv8-sha512.c */; }; A4DFEC0D1FD4CAA300A7BB33 /* benchmark.c in Sources */ = {isa = PBXBuildFile; fileRef = A4DFEC0C1FD4CAA300A7BB33 /* benchmark.c */; }; A4DFEC101FD4CB8500A7BB33 /* armv8-sha256.c in Sources */ = {isa = PBXBuildFile; fileRef = A4DFEC0E1FD4CB8500A7BB33 /* armv8-sha256.c */; }; A4DFEC111FD4CB8500A7BB33 /* armv8-aes.c in Sources */ = {isa = PBXBuildFile; fileRef = A4DFEC0F1FD4CB8500A7BB33 /* armv8-aes.c */; }; A4DFEC3C1FD6B9CC00A7BB33 /* test.c in Sources */ = {isa = PBXBuildFile; fileRef = A4DFEC3B1FD6B9CC00A7BB33 /* test.c */; }; + CB81DE1D24C9284700B98DA6 /* armv8-poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = CB81DE1C24C9284700B98DA6 /* armv8-poly1305.c */; }; + CB81DE1F24C93EC000B98DA6 /* armv8-curve25519.S in Sources */ = {isa = PBXBuildFile; fileRef = CB81DE1E24C93EC000B98DA6 /* armv8-curve25519.S */; }; + CB81DE2324C93FB300B98DA6 /* armv8-sha512-asm.S in Sources */ = {isa = PBXBuildFile; fileRef = CB81DE2224C93FB300B98DA6 /* armv8-sha512-asm.S */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 52114C8621B5A7320022ADA1 /* sp_c64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sp_c64.c; path = ../../../wolfcrypt/src/sp_c64.c; sourceTree = ""; }; A46FE14C2493E8F500A25BE7 /* armv8-chacha.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "armv8-chacha.c"; path = "../../../wolfcrypt/src/port/arm/armv8-chacha.c"; sourceTree = ""; }; A46FE14D2493E8F600A25BE7 /* sp_int.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sp_int.c; path = ../../../wolfcrypt/src/sp_int.c; sourceTree = ""; }; - A46FE1502493E8F600A25BE7 /* armv8-poly1305.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "armv8-poly1305.c"; path = "../../../wolfcrypt/src/port/arm/armv8-poly1305.c"; sourceTree = ""; }; A46FE1512493E8F600A25BE7 /* sp_cortexm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sp_cortexm.c; path = ../../../wolfcrypt/src/sp_cortexm.c; sourceTree = ""; }; A46FE1522493E8F600A25BE7 /* blake2s.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = blake2s.c; path = ../../../wolfcrypt/src/blake2s.c; sourceTree = ""; }; A46FE1542493E8F600A25BE7 /* wc_pkcs11.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = wc_pkcs11.c; path = ../../../wolfcrypt/src/wc_pkcs11.c; sourceTree = ""; }; @@ -195,10 +197,14 @@ A4ADF8CC1FCE0C5500A06E90 /* ecc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ecc.c; path = ../../../wolfcrypt/src/ecc.c; sourceTree = ""; }; A4ADF8CE1FCE0C5500A06E90 /* coding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = coding.c; path = ../../../wolfcrypt/src/coding.c; sourceTree = ""; }; A4ADF8D01FCE0C5500A06E90 /* ge_low_mem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ge_low_mem.c; path = ../../../wolfcrypt/src/ge_low_mem.c; sourceTree = ""; }; + A4CA2E9E24C8AF97003CCC50 /* armv8-sha512.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "armv8-sha512.c"; path = "../../../wolfcrypt/src/port/arm/armv8-sha512.c"; sourceTree = ""; }; A4DFEC0C1FD4CAA300A7BB33 /* benchmark.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = benchmark.c; path = ../../../wolfcrypt/benchmark/benchmark.c; sourceTree = ""; }; A4DFEC0E1FD4CB8500A7BB33 /* armv8-sha256.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "armv8-sha256.c"; path = "../../../wolfcrypt/src/port/arm/armv8-sha256.c"; sourceTree = ""; }; A4DFEC0F1FD4CB8500A7BB33 /* armv8-aes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "armv8-aes.c"; path = "../../../wolfcrypt/src/port/arm/armv8-aes.c"; sourceTree = ""; }; A4DFEC3B1FD6B9CC00A7BB33 /* test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = test.c; path = ../../../wolfcrypt/test/test.c; sourceTree = ""; }; + CB81DE1C24C9284700B98DA6 /* armv8-poly1305.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "armv8-poly1305.c"; path = "../../../wolfcrypt/src/port/arm/armv8-poly1305.c"; sourceTree = ""; }; + CB81DE1E24C93EC000B98DA6 /* armv8-curve25519.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = "armv8-curve25519.S"; path = "../../../wolfcrypt/src/port/arm/armv8-curve25519.S"; sourceTree = ""; }; + CB81DE2224C93FB300B98DA6 /* armv8-sha512-asm.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = "armv8-sha512-asm.S"; path = "../../../wolfcrypt/src/port/arm/armv8-sha512-asm.S"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -273,8 +279,11 @@ A4ADF8921FCE0C4E00A06E90 /* arc4.c */, A4DFEC0F1FD4CB8500A7BB33 /* armv8-aes.c */, A46FE14C2493E8F500A25BE7 /* armv8-chacha.c */, - A46FE1502493E8F600A25BE7 /* armv8-poly1305.c */, + CB81DE1E24C93EC000B98DA6 /* armv8-curve25519.S */, + CB81DE1C24C9284700B98DA6 /* armv8-poly1305.c */, A4DFEC0E1FD4CB8500A7BB33 /* armv8-sha256.c */, + A4CA2E9E24C8AF97003CCC50 /* armv8-sha512.c */, + CB81DE2224C93FB300B98DA6 /* armv8-sha512-asm.S */, A4ADF8A01FCE0C4F00A06E90 /* asm.c */, A4ADF8C21FCE0C5300A06E90 /* asn.c */, A4ADF8B11FCE0C5100A06E90 /* blake2b.c */, @@ -434,6 +443,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + CB81DE2324C93FB300B98DA6 /* armv8-sha512-asm.S in Sources */, A4ADF9041FCE0C5600A06E90 /* des3.c in Sources */, A46FE18A2493E8F800A25BE7 /* ge_448.c in Sources */, A4ADF9121FCE0C5600A06E90 /* wc_port.c in Sources */, @@ -458,6 +468,8 @@ A4ADF90D1FCE0C5600A06E90 /* blake2b.c in Sources */, A4ADF9071FCE0C5600A06E90 /* dh.c in Sources */, A46FE1912493E8F800A25BE7 /* sp_c32.c in Sources */, + CB81DE1D24C9284700B98DA6 /* armv8-poly1305.c in Sources */, + CB81DE1F24C93EC000B98DA6 /* armv8-curve25519.S in Sources */, A4ADF8F31FCE0C5600A06E90 /* rsa.c in Sources */, A46FE1752493E8F800A25BE7 /* blake2s.c in Sources */, A4ADF8FA1FCE0C5600A06E90 /* pkcs12.c in Sources */, @@ -498,7 +510,6 @@ A4ADF9051FCE0C5600A06E90 /* cmac.c in Sources */, 52114C8721B5A7320022ADA1 /* sp_c64.c in Sources */, A4ADF8F41FCE0C5600A06E90 /* pkcs7.c in Sources */, - A46FE1732493E8F800A25BE7 /* armv8-poly1305.c in Sources */, A4ADF90B1FCE0C5600A06E90 /* logging.c in Sources */, A4ADF8E01FCE0C5600A06E90 /* ecc_fp.c in Sources */, A4ADF8EB1FCE0C5600A06E90 /* chacha20_poly1305.c in Sources */, @@ -522,6 +533,7 @@ A4ADF8D71FCE0C5600A06E90 /* wolfevent.c in Sources */, A46FE1802493E8F800A25BE7 /* ed448.c in Sources */, A4DFEC0D1FD4CAA300A7BB33 /* benchmark.c in Sources */, + A4CA2EA324C8AF97003CCC50 /* armv8-sha512.c in Sources */, A4ADF91D1FCE0C5600A06E90 /* cpuid.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -671,10 +683,10 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 2S2PAGNS5B; + DEVELOPMENT_TEAM = TJKX238PPD; INFOPLIST_FILE = wolfBench/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.wolfSSL.wolfBench; + PRODUCT_BUNDLE_IDENTIFIER = "com.wolfSSL.wolfBench-ios"; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -685,10 +697,10 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 2S2PAGNS5B; + DEVELOPMENT_TEAM = TJKX238PPD; INFOPLIST_FILE = wolfBench/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.wolfSSL.wolfBench; + PRODUCT_BUNDLE_IDENTIFIER = "com.wolfSSL.wolfBench-ios"; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; }; diff --git a/IDE/XCODE/user_settings.h b/IDE/XCODE/user_settings.h index 62da56ba32..53d8ebe113 100644 --- a/IDE/XCODE/user_settings.h +++ b/IDE/XCODE/user_settings.h @@ -56,7 +56,9 @@ #define HAVE_CHACHA #define HAVE_CURVE25519 - #define HAVE_ED25519 + #ifndef WOLFSSL_ARMASM + #define HAVE_ED25519 + #endif /* TLS extensions */ #define HAVE_ONE_TIME_AUTH diff --git a/IDE/include.am b/IDE/include.am index 1372979ff2..0fcc8642a9 100644 --- a/IDE/include.am +++ b/IDE/include.am @@ -26,6 +26,7 @@ include IDE/Renesas/cs+/Projects/include.am include IDE/Renesas/e2studio/Projects/include.am include IDE/Renesas/e2studio/RA6M3/include.am include IDE/Renesas/e2studio/GR-ROSE/include.am +include IDE/Renesas/e2studio/RX72NEnvisionKit/include.am include IDE/WICED-STUDIO/include.am include IDE/CRYPTOCELL/include.am include IDE/M68K/include.am diff --git a/Makefile.am b/Makefile.am index 37533fa230..94ce2f6801 100644 --- a/Makefile.am +++ b/Makefile.am @@ -118,7 +118,8 @@ CLEANFILES+= cert.der \ pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256.der \ pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der \ pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256.der \ - pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256_noattr.der + pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256_noattr.der \ + tests/test-log-dump-to-file.txt exampledir = $(docdir)/example dist_example_DATA= diff --git a/certs/include.am b/certs/include.am index 45193b5ae2..7a425515c6 100644 --- a/certs/include.am +++ b/certs/include.am @@ -108,6 +108,7 @@ include certs/ed25519/include.am include certs/ed448/include.am include certs/external/include.am include certs/ocsp/include.am +include certs/statickeys/include.am include certs/test/include.am include certs/test-pathlen/include.am include certs/intermediate/include.am diff --git a/certs/statickeys/dh-ffdhe2048-params.pem b/certs/statickeys/dh-ffdhe2048-params.pem new file mode 100644 index 0000000000..088f9673dc --- /dev/null +++ b/certs/statickeys/dh-ffdhe2048-params.pem @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz ++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a +87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 +YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi +7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD +ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== +-----END DH PARAMETERS----- \ No newline at end of file diff --git a/certs/statickeys/dh-ffdhe2048.der b/certs/statickeys/dh-ffdhe2048.der new file mode 100644 index 0000000000..f59cec3d22 Binary files /dev/null and b/certs/statickeys/dh-ffdhe2048.der differ diff --git a/certs/statickeys/dh-ffdhe2048.pem b/certs/statickeys/dh-ffdhe2048.pem new file mode 100644 index 0000000000..957a02544f --- /dev/null +++ b/certs/statickeys/dh-ffdhe2048.pem @@ -0,0 +1,9 @@ +-----BEGIN PRIVATE KEY----- +MIIBPwIBADCCARcGCSqGSIb3DQEDATCCAQgCggEBAP//////////rfhUWKK7Spqv +3FYgJz088di5xYPOLTaVqeE2QRRkM/vMk53OJJs++X0v42NjDHXY9oGyAq7EYXrT +3x7V1f1lYSQz9R9fBm7QhWNlVT3tGvO1VxNef1fJNZhPDHDg5ot34qaJ2vPv6HId +8VihNq3nNTCsyk9IOnl6vAqxgrMk+2HRCKlLssjj+7lq2rdg1/RoHU9Co945TfSu +Vu3nY3K7GQsHp8juCm1wngL84c334uzANATNKDQvYZFy/pzphYP/jk8SMu7ygYPD +/jsbTG+tczu1/LwuwiAFxY7xg30Wg7LG80omwbLv+ohrQjhhKFyX//////////8C +AQIEHwIdXPuG9/pRAnlxnsApmAPPPmVG9jS4sMFVOvfIQ7g= +-----END PRIVATE KEY----- diff --git a/certs/statickeys/ecc-secp256r1.der b/certs/statickeys/ecc-secp256r1.der new file mode 100644 index 0000000000..69614a58c7 Binary files /dev/null and b/certs/statickeys/ecc-secp256r1.der differ diff --git a/certs/statickeys/ecc-secp256r1.pem b/certs/statickeys/ecc-secp256r1.pem new file mode 100644 index 0000000000..0ee7cc57ac --- /dev/null +++ b/certs/statickeys/ecc-secp256r1.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINNrxmh23tiXlfbZji9Bc1P4A1ftkIAZ66pKkYqPMWNFoAoGCCqGSM49 +AwEHoUQDQgAEWKCAfFHs3UFfk6h6YEdH6c9aQOTdN+zKpxAcQ9roc4wo9cnsGjML +Ji6XgC7guAGRFrTMAhi1Hcy6PO0EyaiSNw== +-----END EC PRIVATE KEY----- diff --git a/certs/statickeys/gen-static.sh b/certs/statickeys/gen-static.sh new file mode 100644 index 0000000000..58289eecb7 --- /dev/null +++ b/certs/statickeys/gen-static.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# run from wolfssl root + +# SECP256R1 +openssl ecparam -name secp256r1 -genkey -noout -out certs/statickeys/ecc-secp256r1.pem -noout +openssl ec -inform pem -in certs/statickeys/ecc-secp256r1.pem -outform der -out certs/statickeys/ecc-secp256r1.der + +# DH 2048-bit (keySz = 29) +# Using one generated and capture with wolfSSL using wc_DhGenerateKeyPair (openssl generates DH keys with 2048-bits... based on the DH "p" prime size) +#openssl genpkey -paramfile certs/statickeys/dh-ffdhe2048-params.pem -out certs/statickeys/dh-ffdhe2048.der +openssl pkey -inform der -in certs/statickeys/dh-ffdhe2048.der -outform pem -out certs/statickeys/dh-ffdhe2048.pem diff --git a/certs/statickeys/include.am b/certs/statickeys/include.am new file mode 100644 index 0000000000..988b03dcc4 --- /dev/null +++ b/certs/statickeys/include.am @@ -0,0 +1,17 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + certs/statickeys/gen-static.sh + +# ECC +EXTRA_DIST += \ + certs/statickeys/ecc-secp256r1.der \ + certs/statickeys/ecc-secp256r1.pem + +# DH FFDHE Groups +EXTRA_DIST += \ + certs/statickeys/dh-ffdhe2048-params.pem \ + certs/statickeys/dh-ffdhe2048.der \ + certs/statickeys/dh-ffdhe2048.pem diff --git a/configure.ac b/configure.ac index 6e1dce91c4..11f8dd89c4 100644 --- a/configure.ac +++ b/configure.ac @@ -889,7 +889,7 @@ fi ENABLED_SNIFFTEST=no AS_IF([ test "x$ENABLED_SNIFFER" = "xyes" ], [ - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SNIFFER" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SNIFFER -DWOLFSSL_STATIC_EPHEMERAL" AC_CHECK_HEADERS([pcap/pcap.h], [ ENABLED_SNIFFTEST=yes ], [ AC_MSG_WARN([cannot enable sniffer test without having libpcap available.]) ] @@ -1545,13 +1545,18 @@ then ENABLED_ECC="yes" fi -if test "$ENABLED_ECC" = "yes" +if test "$ENABLED_ECC" != "no" then AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256" if test "$ENABLED_ECC_SHAMIR" = "yes" && test "$ENABLED_LOWRESOURCE" = "no" then AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR" fi + + if test "$ENABLED_ECC" = "nonblock" + then + AM_CFLAGS="$AM_CFLAGS -DWC_ECC_NONBLOCK" + fi fi @@ -3206,7 +3211,7 @@ then ENABLED_ENCRYPT_THEN_MAC=yes AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC -DHAVE_ALPN -DHAVE_TRUSTED_CA" # Check the ECC supported curves prereq - AS_IF([test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_CURVE25519" = "xyes" || test "x$ENABLED_TLS13" = "xyes"], + AS_IF([test "x$ENABLED_ECC" != "xno" || test "x$ENABLED_CURVE25519" = "xyes" || test "x$ENABLED_TLS13" = "xyes"], [ENABLED_SUPPORTED_CURVES=yes AM_CFLAGS="$AM_CFLAGS -DHAVE_SUPPORTED_CURVES"]) fi @@ -3762,7 +3767,7 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC" # Check the ECC supported curves prereq - AS_IF([test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_CURVE25519" = "xyes"], + AS_IF([test "x$ENABLED_ECC" != "xno" || test "x$ENABLED_CURVE25519" = "xyes"], [ENABLED_SUPPORTED_CURVES=yes AM_CFLAGS="$AM_CFLAGS -DHAVE_SUPPORTED_CURVES"]) fi @@ -3905,7 +3910,7 @@ then AC_MSG_ERROR([please enable psk if disabling asn.]) fi - if test "x$ENABLED_ECC" = "xyes" && test "x$ENABLED_ASN" = "xno" + if test "x$ENABLED_ECC" != "xno" && test "x$ENABLED_ASN" = "xno" then AC_MSG_ERROR([please disable ecc if disabling asn.]) fi @@ -4251,6 +4256,7 @@ ENABLED_SP_ECC=no ENABLED_SP_EC_256=no ENABLED_SP_EC_384=no ENABLED_SP_NO_MALLOC=no +ENABLED_SP_NONBLOCK=no for v in `echo $ENABLED_SP | tr "," " "` do case $v in @@ -4267,6 +4273,7 @@ do ENABLED_SP_EC_384=yes fi ;; + yes) ENABLED_SP_RSA=yes ENABLED_SP_DH=yes @@ -4279,6 +4286,7 @@ do ENABLED_SP_EC_384=yes fi ;; + no) ;; @@ -4312,7 +4320,6 @@ do ENABLED_SP_DH=yes ENABLED_SP_FF_2048=yes ;; - smallrsa2048) ENABLED_SP_SMALL=yes ENABLED_SP_RSA=yes @@ -4334,7 +4341,6 @@ do ENABLED_SP_DH=yes ENABLED_SP_FF_3072=yes ;; - smallrsa3072) ENABLED_SP_SMALL=yes ENABLED_SP_RSA=yes @@ -4351,19 +4357,16 @@ do ENABLED_SP_DH=yes ENABLED_SP_FF_4096=yes ;; - 4096 | +4096) ENABLED_SP_RSA=yes ENABLED_SP_DH=yes ENABLED_SP_FF_4096=yes ;; - smallrsa4096) ENABLED_SP_SMALL=yes ENABLED_SP_RSA=yes ENABLED_SP_FF_4096=yes ;; - rsa4096) ENABLED_SP_RSA=yes ENABLED_SP_FF_4096=yes @@ -4373,6 +4376,13 @@ do ENABLED_SP_NO_MALLOC=yes ;; + nonblock) + # Requires small and no malloc + ENABLED_SP_NONBLOCK=yes + ENABLED_SP_NO_MALLOC=yes + ENABLED_SP_SMALL=yes + ;; + *) AC_MSG_ERROR([Invalid choice of Single Precision length in bits [256, 2048, 3072]: $ENABLED_SP.]) break;; @@ -4404,7 +4414,7 @@ if test "$ENABLED_SP_RSA" = "yes" || test "$ENABLED_SP_DH" = "yes"; then AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_4096" fi fi -if test "$ENABLED_ECC" = "yes" && test "$ENABLED_SP_ECC" = "yes"; then +if test "$ENABLED_ECC" != "no" && test "$ENABLED_SP_ECC" = "yes"; then ENABLED_SP=yes AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_SP_ECC" AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_HAVE_SP_ECC" @@ -4425,6 +4435,10 @@ if test "$ENABLED_SP_NO_MALLOC" = "yes"; then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_MALLOC" AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_NO_MALLOC" fi +if test "$ENABLED_SP_NONBLOCK" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NONBLOCK" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_NONBLOCK" +fi AC_ARG_ENABLE([sp-asm], @@ -4436,6 +4450,9 @@ if test "$ENABLED_SP_ASM" = "yes"; then if test "$ENABLED_SP" = "no"; then AC_MSG_ERROR([Must have SP enabled: --enable-sp]) fi + if test "$ENABLED_SP_NONBLOCK" = "yes"; then + AC_MSG_ERROR([SP non-blocking not supported with sp-asm]) + fi if test "$ENABLED_ASM" = "no"; then AC_MSG_ERROR([Assembly code turned off]) fi @@ -4908,7 +4925,7 @@ AS_CASE(["$CFLAGS $CPPFLAGS"],[*'WOLFSSL_TRUST_PEER_CERT'*],[ENABLED_TRUSTED_PEE # dertermine if we have key validation mechanism -if test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_RSA" = "xyes" +if test "x$ENABLED_ECC" != "xno" || test "x$ENABLED_RSA" = "xyes" then if test "x$ENABLED_ASN" = "xyes" then @@ -4984,8 +5001,9 @@ AS_IF([test "x$ENABLED_LEANTLS" = "xyes" && \ [AC_MSG_ERROR([please enable ecc if enabling leantls.])]) AS_IF([test "x$ENABLED_SNIFFER" = "xyes" && \ - test "x$ENABLED_RSA" = "xno"], - [AC_MSG_ERROR([please enable rsa if enabling sniffer.])]) + test "x$ENABLED_RSA" = "xno" && \ + test "x$ENABLED_ECC" = "xno"], + [AC_MSG_ERROR([please enable ecc or rsa if enabling sniffer.])]) # Lean TLS forces off prereqs of SCEP. AS_IF([test "x$ENABLED_SCEP" = "xyes" && \ @@ -5046,7 +5064,7 @@ then ENABLED_AESKEYWRAP="yes" AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_KEYWRAP -DWOLFSSL_AES_DIRECT" fi - if test "x$ENABLED_X963KDF" = "xno" && test "$ENABLED_ECC" = "yes" + if test "x$ENABLED_X963KDF" = "xno" && test "$ENABLED_ECC" != "no" then ENABLED_X963KDF="yes" AM_CFLAGS="$AM_CFLAGS -DHAVE_X963_KDF" @@ -5218,7 +5236,7 @@ AM_CONDITIONAL([BUILD_BLAKE2],[test "x$ENABLED_BLAKE2" = "xyes" || test "x$ENABL AM_CONDITIONAL([BUILD_BLAKE2S],[test "x$ENABLED_BLAKE2S" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_SHA512],[test "x$ENABLED_SHA512" = "xyes" || test "x$ENABLED_SHA384" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_DSA],[test "x$ENABLED_DSA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) -AM_CONDITIONAL([BUILD_ECC],[test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_ECC],[test "x$ENABLED_ECC" != "xno" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_ED25519],[test "x$ENABLED_ED25519" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_ED25519_SMALL],[test "x$ENABLED_ED25519_SMALL" = "xyes"]) AM_CONDITIONAL([BUILD_FEMATH], [test "x$ENABLED_FEMATH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) diff --git a/doc/dox_comments/header_files/ecc.h b/doc/dox_comments/header_files/ecc.h index 1128af9e4f..f6568d26cf 100644 --- a/doc/dox_comments/header_files/ecc.h +++ b/doc/dox_comments/header_files/ecc.h @@ -149,6 +149,27 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id); WOLFSSL_API int wc_ecc_check_key(ecc_key* key); +/*! + \ingroup ECC + + \brief This function frees an ecc_key key after it has been used. + + + \param key pointer to the ecc_key structure to free + + _Example_ + \code + // initialize key and perform ECC operations + ... + wc_ecc_key_free(&key); + \endcode + + \sa wc_ecc_key_new + \sa wc_ecc_init_ex +*/ +WOLFSSL_API +void wc_ecc_key_free(ecc_key* key); + /*! \ingroup ECC @@ -541,6 +562,54 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, WOLFSSL_API int wc_ecc_init(ecc_key* key); +/*! + \ingroup ECC + + \brief This function initializes an ecc_key object for future + use with message verification or key negotiation. + + \return 0 Returned upon successfully initializing the ecc_key object + \return MEMORY_E Returned if there is an error allocating memory + + \param key pointer to the ecc_key object to initialize + \param devId ID to use with async hardware + \param heap pointer to a heap identifier + + _Example_ + \code + ecc_key key; + wc_ecc_init_ex(&key, heap, devId); + \endcode + + \sa wc_ecc_make_key + \sa wc_ecc_free + \sa wc_ecc_init +*/ +WOLFSSL_API +int wc_ecc_init_ex(ecc_key* key, void* heap, int devId); + +/*! + \ingroup ECC + + \brief This function uses a user defined heap and allocates space for the + key structure. + + \return 0 Returned upon successfully initializing the ecc_key object + \return MEMORY_E Returned if there is an error allocating memory + + + _Example_ + \code + wc_ecc_key_new(&heap); + \endcode + + \sa wc_ecc_make_key + \sa wc_ecc_key_free + \sa wc_ecc_init +*/ +WOLFSSL_API +ecc_key* wc_ecc_key_new(void* heap); + /*! \ingroup ECC @@ -1752,8 +1821,51 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, } \endcode - \sa Wc_ecc_encrypt + \sa wc_ecc_encrypt */ WOLFSSL_API int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx); + + +/*! + \ingroup ECC + + \brief Enable ECC support for non-blocking operations. Supported for + Single Precision (SP) math with the following build options: + WOLFSSL_SP_NONBLOCK + WOLFSSL_SP_SMALL + WOLFSSL_SP_NO_MALLOC + WC_ECC_NONBLOCK + + \return 0 Returned upon successfully setting the callback context the input message + + \param key pointer to the ecc_key object + \param ctx pointer to ecc_nb_ctx_t structure with stack data cache for SP + + _Example_ + \code + int ret; + ecc_key ecc; + ecc_nb_ctx_t nb_ctx; + + ret = wc_ecc_init(&ecc); + if (ret == 0) { + ret = wc_ecc_set_nonblock(&ecc, &nb_ctx); + if (ret == 0) { + do { + ret = wc_ecc_verify_hash_ex( + &r, &s, // r/s as mp_int + hash, hashSz, // computed hash digest + &verify_res, // verification result 1=success + &key + ); + + // TODO: Real-time work can be called here + } while (ret == FP_WOULDBLOCK); + } + wc_ecc_free(&key); + } + \endcode +*/ +WOLFSSL_API int wc_ecc_set_nonblock(ecc_key *key, ecc_nb_ctx_t* ctx); diff --git a/doc/dox_comments/header_files/random.h b/doc/dox_comments/header_files/random.h index 366dc8908d..8e5f0eb139 100644 --- a/doc/dox_comments/header_files/random.h +++ b/doc/dox_comments/header_files/random.h @@ -137,6 +137,38 @@ WOLFSSL_API int wc_InitRng(WC_RNG*); */ WOLFSSL_API int wc_RNG_GenerateBlock(WC_RNG*, byte*, word32 sz); +/*! + \ingroup Random + + \brief Creates a new WC_RNG structure. + + + \return WC_RNG structure on success + \return NULL on error + + + \param heap pointer to a heap identifier + \param nonce pointer to the buffer containing the nonce + \param nonceSz length of the nonce + + _Example_ + \code + RNG rng; + byte nonce[] = { initialize nonce }; + word32 nonceSz = sizeof(nonce); + + wc_rng_new(&nonce, nonceSz, &heap); + + + \endcode + + \sa wc_InitRng + \sa wc_rng_free + \sa wc_FreeRng + \sa wc_RNG_HealthTest +*/ +WOLFSSL_API WC_RNG* wc_rng_new(byte* nonce, word32 nonceSz, void* heap) + /*! \ingroup Random @@ -211,6 +243,36 @@ WOLFSSL_API int wc_RNG_GenerateByte(WC_RNG*, byte*); */ WOLFSSL_API int wc_FreeRng(WC_RNG*); +/*! + \ingroup Random + + \brief Should be called when RNG no longer needed in order to securely + free rng. + + + \param rng random number generator initialized with wc_InitRng + + _Example_ + \code + RNG rng; + byte nonce[] = { initialize nonce }; + word32 nonceSz = sizeof(nonce); + + rng = wc_rng_new(&nonce, nonceSz, &heap); + + // use rng + + wc_rng_free(&rng); + + \endcode + + \sa wc_InitRng + \sa wc_rng_new + \sa wc_FreeRng + \sa wc_RNG_HealthTest +*/ +WOLFSSL_API WC_RNG* wc_rng_free(WC_RNG* rng); + /*! \ingroup Random diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index 0944c3594c..061ce3b19f 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -2659,6 +2659,75 @@ WOLFSSL_API void wolfSSL_load_error_strings(void); */ WOLFSSL_API int wolfSSL_library_init(void); +/*! + \brief This function sets the Device Id at the WOLFSSL session level. + + \return WOLFSSL_SUCCESS upon success. + \return BAD_FUNC_ARG if ssl is NULL. + + \param ssl pointer to a SSL object, created with wolfSSL_new(). + \param devId ID to use with async hardware + + _Example_ + \code + WOLFSSL* ssl; + int DevId = -2; + + wolfSSL_SetDevId(ssl, devId); + + \endcode + + \sa wolfSSL_CTX_SetDevId + \sa wolfSSL_CTX_GetDevId +*/ +WOLFSSL_API int wolfSSL_SetDevId(WOLFSSL* ssl, int devId); + +/*! + \brief This function sets the Device Id at the WOLFSSL_CTX context level. + + \return WOLFSSL_SUCCESS upon success. + \return BAD_FUNC_ARG if ssl is NULL. + + \param ctx pointer to the SSL context, created with wolfSSL_CTX_new(). + \param devId ID to use with async hardware + + _Example_ + \code + WOLFSSL_CTX* ctx; + int DevId = -2; + + wolfSSL_CTX_SetDevId(ctx, devId); + + \endcode + + \sa wolfSSL_SetDevId + \sa wolfSSL_CTX_GetDevId +*/ +WOLFSSL_API int wolfSSL_CTX_SetDevId(WOLFSSL_CTX* ctx, int devId); + +/*! + \brief This function retrieves the Device Id. + + \return devId upon success. + \return INVALID_DEVID if both ssl and ctx are NULL. + + \param ctx pointer to the SSL context, created with wolfSSL_CTX_new(). + \param ssl pointer to a SSL object, created with wolfSSL_new(). + + _Example_ + \code + WOLFSSL_CTX* ctx; + + wolfSSL_CTX_GetDevId(ctx, ssl); + + \endcode + + \sa wolfSSL_SetDevId + \sa wolfSSL_CTX_SetDevId + +*/ +WOLFSSL_API int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl); + /*! \ingroup Setup @@ -4385,6 +4454,31 @@ WOLFSSL_API int wolfSSL_X509_NAME_get_text_by_NID( */ WOLFSSL_API int wolfSSL_X509_get_signature_type(WOLFSSL_X509*); +/*! + \brief This function frees a WOLFSSL_X509 structure. + + + \param x509 a pointer to the WOLFSSL_X509 struct. + + _Example_ + \code + WOLFSSL_X509* x509 = (WOLFSSL_X509*)XMALOC(sizeof(WOLFSSL_X509), NULL, + DYNAMIC_TYPE_X509) ; + + wolfSSL_X509_free(x509); + + \endcode + + \sa wolfSSL_X509_get_signature + \sa wolfSSL_X509_version + \sa wolfSSL_X509_get_der + \sa wolfSSL_X509_get_serial_number + \sa wolfSSL_X509_notBefore + \sa wolfSSL_X509_notAfter + +*/ +WOLFSSL_API void wolfSSL_X509_free(WOLFSSL_X509* x509); + /*! \ingroup CertsKeys @@ -4500,6 +4594,67 @@ WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain( WOLFSSL_API int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag); +/*! + \ingroup CertsKeys + + \brief This function the certificate "not before" validity encoded as + a byte array. + + + \return NULL returned if the WOLFSSL_X509 structure is NULL. + \return byte is returned that contains the notBeforeData. + + \param x509 pointer to a WOLFSSL_X509 structure. + + _Example_ + \code + WOLFSSL_X509* x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, + DYNAMIC_TYPE_X509); + ... + byte* notBeforeData = wolfSSL_X509_notBefore(x509); + + + \endcode + + \sa wolfSSL_X509_get_signature + \sa wolfSSL_X509_version + \sa wolfSSL_X509_get_der + \sa wolfSSL_X509_get_serial_number + \sa wolfSSL_X509_notAfter + \sa wolfSSL_X509_free +*/ +WOLFSSL_API const byte* wolfSSL_X509_notBefore(WOLFSSL_X509* x509); + +/*! + \ingroup CertsKeys + + \brief This function the certificate "not after" validity encoded as + a byte array. + + \return NULL returned if the WOLFSSL_X509 structure is NULL. + \return byte is returned that contains the notAfterData. + + \param x509 pointer to a WOLFSSL_X509 structure. + + _Example_ + \code + WOLFSSL_X509* x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, + DYNAMIC_TYPE_X509); + ... + byte* notAfterData = wolfSSL_X509_notAfter(x509); + + + \endcode + + \sa wolfSSL_X509_get_signature + \sa wolfSSL_X509_version + \sa wolfSSL_X509_get_der + \sa wolfSSL_X509_get_serial_number + \sa wolfSSL_X509_notBefore + \sa wolfSSL_X509_free +*/ +WOLFSSL_API const byte* wolfSSL_X509_notAfter(WOLFSSL_X509* x509); + /*! \ingroup Setup @@ -7567,6 +7722,27 @@ WOLFSSL_API int wolfSSL_DTLS_SetCookieSecret(WOLFSSL*, const unsigned char*, unsigned int); +/*! + \brief This function retrieves the random number. + + \return rng upon success. + \return NULL if ssl is NULL. + + \param ssl pointer to a SSL object, created with wolfSSL_new(). + + _Example_ + \code + WOLFSSL* ssl; + + wolfSSL_GetRNG(ssl); + + \endcode + + \sa wolfSSL_CTX_new_rng + +*/ +WOLFSSL_API WC_RNG* wolfSSL_GetRNG(WOLFSSL* ssl); + /*! \ingroup Setup @@ -13529,3 +13705,26 @@ WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_method_ex(void* heap); */ WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_method(void); +/*! + \ingroup SSL + \brief This function sets a fixed / static ephemeral key for testing only + \return 0 Key loaded successfully + \param ctx A WOLFSSL_CTX context pointer + \param keyAlgo enum wc_PkType like WC_PK_TYPE_DH and WC_PK_TYPE_ECDH + \param key key file path (if keySz == 0) or actual key buffer (PEM or ASN.1) + \param keySz key size (should be 0 for "key" arg is file path) + \param format WOLFSSL_FILETYPE_ASN1 or WOLFSSL_FILETYPE_PEM + */ +WOLFSSL_API int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, const char* key, unsigned int keySz, int format); + +/*! + \ingroup SSL + \brief This function sets a fixed / static ephemeral key for testing only + \return 0 Key loaded successfully + \param ssl A WOLFSSL object pointer + \param keyAlgo enum wc_PkType like WC_PK_TYPE_DH and WC_PK_TYPE_ECDH + \param key key file path (if keySz == 0) or actual key buffer (PEM or ASN.1) + \param keySz key size (should be 0 for "key" arg is file path) + \param format WOLFSSL_FILETYPE_ASN1 or WOLFSSL_FILETYPE_PEM + */ +WOLFSSL_API int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo, const char* key, unsigned int keySz, int format); diff --git a/doc/formats/html/footer.html b/doc/formats/html/footer.html index 996406d4b8..d4f5a624a2 100644 --- a/doc/formats/html/footer.html +++ b/doc/formats/html/footer.html @@ -32,7 +32,7 @@
-

Copyright © 2017 wolfSSL Inc.
All rights reserved.

+

Copyright © 2020 wolfSSL Inc.
All rights reserved.

Help and Support

    diff --git a/examples/benchmark/tls_bench.c b/examples/benchmark/tls_bench.c index be11be362d..f130f28d14 100644 --- a/examples/benchmark/tls_bench.c +++ b/examples/benchmark/tls_bench.c @@ -1285,7 +1285,7 @@ static int bench_tls_server(info_t* info) ret = SocketWaitClient(info); #ifdef BENCH_USE_NONBLOCK if (ret == -2) { - sleep(0); + XSLEEP_MS(0); continue; } #endif @@ -1831,7 +1831,7 @@ int bench_tls(void* args) info = &theadInfo[i]; if (!info->to_client.done || !info->to_server.done) { doShutdown = 0; - sleep(1); /* Allow other threads to run */ + XSLEEP_MS(1000); /* Allow other threads to run */ } } diff --git a/examples/client/client.c b/examples/client/client.c index f7630ae546..649d1cb3b4 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -86,6 +86,14 @@ static const char kHttpGetMsg[] = "GET /index.html HTTP/1.0\r\n\r\n"; /* Read needs to be at least sizeof server.c `webServerMsg` (226) */ #define CLI_REPLY_SZ 256 +#if defined(XSLEEP_US) && defined(NO_MAIN_DRIVER) + /* This is to force the server's thread to get a chance to + * execute before continuing the resume in non-blocking + * DTLS test cases. */ + #define TEST_DELAY() XSLEEP_US(10000) +#else + #define TEST_DELAY() XSLEEP_MS(1000) +#endif /* Note on using port 0: the client standalone example doesn't utilize the * port 0 port sharing; that is used by (1) the server in external control @@ -505,7 +513,7 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, /* Measures throughput in kbps. Throughput = number of bytes */ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, int dtlsUDP, int dtlsSCTP, int block, size_t throughput, int useX25519, - int useX448) + int useX448, int exitWithRet) { double start, conn_time = 0, tx_time = 0, rx_time = 0; SOCKET_T sockfd; @@ -610,7 +618,9 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, } while (err == WC_PENDING_E); if (ret != len) { printf("SSL_write bench error %d!\n", err); - err_sys("SSL_write failed"); + if (!exitWithRet) + err_sys("SSL_write failed"); + goto doExit; } tx_time += current_time(0) - start; @@ -664,6 +674,7 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, else { err_sys("Client buffer malloc failed"); } +doExit: if(tx_buffer) XFREE(tx_buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); if(rx_buffer) XFREE(rx_buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); } @@ -675,6 +686,9 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, wolfSSL_free(ssl); ssl = NULL; CloseSocket(sockfd); + if (exitWithRet) + return err; + #if !defined(__MINGW32__) printf("wolfSSL Client Benchmark %zu bytes\n" #else @@ -1602,6 +1616,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) StackTrap(); + /* Reinitialize the global myVerifyAction. */ + myVerifyAction = VERIFY_OVERRIDE_ERROR; + #ifndef WOLFSSL_VXWORKS /* Not used: All used */ while ((ch = mygetopt(argc, argv, "?:" @@ -2385,10 +2402,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif -#if defined(WOLFSSL_SNIFFER) +#ifdef WOLFSSL_SNIFFER if (cipherList == NULL && version < 4) { - /* don't use EDH, can't sniff tmp keys */ - if (wolfSSL_CTX_set_cipher_list(ctx, "AES128-SHA") != WOLFSSL_SUCCESS) { + /* static RSA or ECC cipher suites */ + const char* staticCipherList = "AES128-SHA:ECDH-ECDSA-AES128-SHA"; + if (wolfSSL_CTX_set_cipher_list(ctx, staticCipherList) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("client can't set cipher list 3"); } @@ -2620,9 +2638,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (throughput) { ((func_args*)args)->return_code = ClientBenchmarkThroughput(ctx, host, port, dtlsUDP, dtlsSCTP, - block, throughput, useX25519, useX448); + block, throughput, useX25519, useX448, + exitWithRet); wolfSSL_CTX_free(ctx); ctx = NULL; - XEXIT_T(EXIT_SUCCESS); + if (!exitWithRet) + XEXIT_T(EXIT_SUCCESS); + else + goto exit; } #if defined(WOLFSSL_MDK_ARM) @@ -3146,13 +3168,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) /* allow some time for exporting the session */ #ifdef WOLFSSL_SESSION_EXPORT_DEBUG -#ifdef USE_WINDOWS_API - Sleep(500); -#elif defined(WOLFSSL_TIRTOS) - Task_sleep(1); -#else - sleep(1); -#endif + TEST_DELAY(); #endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ #ifdef WOLFSSL_TLS13 @@ -3163,12 +3179,16 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) err = ClientWrite(ssl, msg, msgSz, "", exitWithRet); if (exitWithRet && (err != 0)) { ((func_args*)args)->return_code = err; + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; goto exit; } err = ClientRead(ssl, reply, sizeof(reply)-1, 1, "", exitWithRet); if (exitWithRet && (err != 0)) { ((func_args*)args)->return_code = err; + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; goto exit; } @@ -3248,13 +3268,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif if (dtlsUDP) { -#ifdef USE_WINDOWS_API - Sleep(500); -#elif defined(WOLFSSL_TIRTOS) - Task_sleep(1); -#else - sleep(1); -#endif + TEST_DELAY(); } tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, sslResume); if (wolfSSL_set_fd(sslResume, sockfd) != WOLFSSL_SUCCESS) { @@ -3376,13 +3390,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) /* allow some time for exporting the session */ #ifdef WOLFSSL_SESSION_EXPORT_DEBUG - #ifdef USE_WINDOWS_API - Sleep(500); - #elif defined(WOLFSSL_TIRTOS) - Task_sleep(1); - #else - sleep(1); - #endif + TEST_DELAY(); #endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ #ifdef HAVE_SECURE_RENEGOTIATION diff --git a/examples/server/server.c b/examples/server/server.c index 86d10b33cb..dba33fecae 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -391,6 +391,10 @@ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int block, err_sys_ex(runWithErrors, "SSL_read failed"); break; } + if (err == WOLFSSL_ERROR_ZERO_RETURN) { + free(buffer); + return WOLFSSL_ERROR_ZERO_RETURN; + } } else { rx_pos += ret; @@ -449,7 +453,7 @@ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int block, ); } - return EXIT_SUCCESS; + return 0; } static void ServerRead(WOLFSSL* ssl, char* input, int inputLen) @@ -1103,6 +1107,10 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef WOLFSSL_VXWORKS useAnyAddr = 1; #else + + /* Reinitialize the global myVerifyAction. */ + myVerifyAction = VERIFY_OVERRIDE_ERROR; + /* Not Used: h, z, F, T, V, W, X */ while ((ch = mygetopt(argc, argv, "?:" "abc:defgijk:l:mnop:q:rstuv:wxy" @@ -1652,6 +1660,25 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb); #endif +#if defined(WOLFSSL_SNIFFER) && defined(WOLFSSL_STATIC_EPHEMERAL) + /* used for testing only to set a static/fixed ephemeral key + for use with the sniffer */ +#if defined(HAVE_ECC) && !defined(NO_ECC_SECP) && \ + (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) + ret = wolfSSL_CTX_set_ephemeral_key(ctx, WC_PK_TYPE_ECDH, + "./certs/statickeys/ecc-secp256r1.pem", 0, WOLFSSL_FILETYPE_PEM); + if (ret != 0) { + err_sys_ex(runWithErrors, "error loading static ECDH key"); + } +#elif !defined(NO_DH) + ret = wolfSSL_CTX_set_ephemeral_key(ctx, WC_PK_TYPE_DH, + "./certs/statickeys/dh-ffdhe2048.pem", 0, WOLFSSL_FILETYPE_PEM); + if (ret != 0) { + err_sys_ex(runWithErrors, "error loading static DH key"); + } +#endif +#endif /* WOLFSSL_SNIFFER && WOLFSSL_STATIC_EPHEMERAL */ + if (cipherList && !useDefCipherList) { if (SSL_CTX_set_cipher_list(ctx, cipherList) != WOLFSSL_SUCCESS) err_sys_ex(runWithErrors, "server can't set custom cipher list"); @@ -1813,7 +1840,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) SSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER | (usePskPlus ? WOLFSSL_VERIFY_FAIL_EXCEPT_PSK : WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT), - myVerifyAction == VERIFY_OVERRIDE_DATE_ERR ? myVerify : NULL); + (myVerifyAction == VERIFY_OVERRIDE_DATE_ERR || + myVerifyAction == VERIFY_FORCE_FAIL) ? myVerify : NULL); #ifdef TEST_BEFORE_DATE verify_flags |= WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY; @@ -1836,11 +1864,13 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) } #endif -#if defined(WOLFSSL_SNIFFER) - /* don't use EDH, can't sniff tmp keys */ +#ifdef WOLFSSL_SNIFFER if (cipherList == NULL && version < 4) { - if (SSL_CTX_set_cipher_list(ctx, "AES128-SHA") != WOLFSSL_SUCCESS) + /* static RSA or static ECC cipher suites */ + const char* staticCipherList = "AES128-SHA:ECDH-ECDSA-AES128-SHA"; + if (SSL_CTX_set_cipher_list(ctx, staticCipherList) != WOLFSSL_SUCCESS) { err_sys_ex(runWithErrors, "server can't set cipher list 3"); + } } #endif @@ -2456,7 +2486,15 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #endif } else if (err == 0 || err == WOLFSSL_ERROR_ZERO_RETURN) { - ServerEchoData(ssl, clientfd, echoData, block, throughput); + err = ServerEchoData(ssl, clientfd, echoData, block, throughput); + if (err != 0) { + SSL_free(ssl); ssl = NULL; + SSL_CTX_free(ctx); ctx = NULL; + CloseSocket(clientfd); + CloseSocket(sockfd); + ((func_args*)args)->return_code = err; + goto exit; + } } #if defined(WOLFSSL_MDK_SHELL) && defined(HAVE_MDK_RTX) diff --git a/scripts/cleanup_testfiles.sh b/scripts/cleanup_testfiles.sh index c7f3885fc8..5d96211ed2 100755 --- a/scripts/cleanup_testfiles.sh +++ b/scripts/cleanup_testfiles.sh @@ -12,3 +12,4 @@ rm -f ./certeccrsa.der rm -f ./ecc-key.der rm -f ./ecc-key.pem rm -f ./ecc-public-key.der +rm -f ./tests/test-log-dump-to-file.txt diff --git a/scripts/include.am b/scripts/include.am index 195dae78a1..50eeed9a3a 100644 --- a/scripts/include.am +++ b/scripts/include.am @@ -85,6 +85,9 @@ endif EXTRA_DIST += scripts/testsuite.pcap \ scripts/sniffer-ipv6.pcap \ + scripts/sniffer-tls13-dh.pcap \ + scripts/sniffer-tls13-ecc.pcap \ + scripts/sniffer-tls13-gen.sh \ scripts/ping.test # leave openssl.test as extra until non bash works diff --git a/scripts/sniffer-testsuite.test b/scripts/sniffer-testsuite.test index 491c1197e4..9bfb39b46e 100755 --- a/scripts/sniffer-testsuite.test +++ b/scripts/sniffer-testsuite.test @@ -2,13 +2,34 @@ #sniffer-testsuite.test +# ./configure --enable-sniffer [--enable-session-ticket] +# Resumption tests require "--enable-session-ticket" + echo -e "\nStaring snifftest on testsuite.pcap...\n" ./sslSniffer/sslSnifferTest/snifftest ./scripts/testsuite.pcap ./certs/server-key.pem 127.0.0.1 11111 RESULT=$? [ $RESULT -ne 0 ] && echo -e "\nsnifftest failed\n" && exit 1 +# TLS v1.3 sniffer test ECC (and resumption) +if test $# -ne 0 +then + ./sslSniffer/sslSnifferTest/snifftest ./scripts/sniffer-tls13-ecc.pcap ./certs/statickeys/ecc-secp256r1.pem 127.0.0.1 11111 + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "\nsnifftest TLS v1.3 ECC\n" && exit 1 +fi + +# TLS v1.3 sniffer test DH (and resumption) +if test $# -ne 0 +then + ./sslSniffer/sslSnifferTest/snifftest ./scripts/sniffer-tls13-dh.pcap ./certs/statickeys/dh-ffdhe2048.pem 127.0.0.1 11111 + + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "\nsnifftest TLS v1.3 DH\n" && exit 1 +fi + +# IPv6 if test $# -ne 0 && test "x$1" = "x-6"; then echo -e "\nStaring snifftest on sniffer-ipv6.pcap...\n" diff --git a/scripts/sniffer-tls13-dh.pcap b/scripts/sniffer-tls13-dh.pcap new file mode 100644 index 0000000000..f1d5d30619 Binary files /dev/null and b/scripts/sniffer-tls13-dh.pcap differ diff --git a/scripts/sniffer-tls13-ecc.pcap b/scripts/sniffer-tls13-ecc.pcap new file mode 100644 index 0000000000..f692d37504 Binary files /dev/null and b/scripts/sniffer-tls13-ecc.pcap differ diff --git a/scripts/sniffer-tls13-gen.sh b/scripts/sniffer-tls13-gen.sh new file mode 100755 index 0000000000..7f7f537c93 --- /dev/null +++ b/scripts/sniffer-tls13-gen.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Run these configures and the example server/client below +# Script to generate wireshark trace for sniffer-tls13-ecc.pcap +#./configure --enable-sniffer --enable-session-ticket && make + +# Script to generate wireshark trace for sniffer-tls13-dh.pcap +#./configure --enable-sniffer --enable-session-ticket --disable-ecc && make + +# TLS v1.3 +./examples/server/server -v 4 -l TLS13-AES128-GCM-SHA256 & +./examples/client/client -v 4 -l TLS13-AES128-GCM-SHA256 +./examples/server/server -v 4 -l TLS13-AES256-GCM-SHA384 & +./examples/client/client -v 4 -l TLS13-AES256-GCM-SHA384 +./examples/server/server -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 & +./examples/client/client -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 + +# TLS v1.3 Resumption +./examples/server/server -v 4 -l TLS13-AES128-GCM-SHA256 -r & +./examples/client/client -v 4 -l TLS13-AES128-GCM-SHA256 -r +./examples/server/server -v 4 -l TLS13-AES256-GCM-SHA384 -r & +./examples/client/client -v 4 -l TLS13-AES256-GCM-SHA384 -r +./examples/server/server -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 -r & +./examples/client/client -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 -r diff --git a/src/internal.c b/src/internal.c index 36eed125f1..5c8ab15c87 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1897,6 +1897,11 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) ctx->alpn_cli_protos = NULL; } #endif +#ifdef WOLFSSL_STATIC_EPHEMERAL + if (ctx->staticKE.key) { + FreeDer(&ctx->staticKE.key); + } +#endif #ifdef WOLFSSL_STATIC_MEMORY if (ctx->heap != NULL) { #ifdef WOLFSSL_HEAP_TEST @@ -5680,6 +5685,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->options.useClientOrder = ctx->useClientOrder; ssl->options.mutualAuth = ctx->mutualAuth; +#ifdef WOLFSSL_STATIC_EPHEMERAL + ssl->staticKE = ctx->staticKE; +#endif + #ifdef WOLFSSL_TLS13 #ifdef HAVE_SESSION_TICKET ssl->options.noTicketTls13 = ctx->noTicketTls13; @@ -6409,6 +6418,11 @@ void SSL_ResourceFree(WOLFSSL* ssl) XFREE(curr, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); } #endif +#ifdef WOLFSSL_STATIC_EPHEMERAL + if (ssl->staticKE.key != NULL && ssl->staticKE.key != ssl->ctx->staticKE.key) { + FreeDer(&ssl->staticKE.key); + } +#endif #ifdef WOLFSSL_STATIC_MEMORY /* check if using fixed io buffers and free them */ @@ -7674,49 +7688,46 @@ static int EdDSA_Update(WOLFSSL* ssl, const byte* data, int sz) } #endif /* (HAVE_ED25519 || HAVE_ED448) && !WOLFSSL_NO_CLIENT_AUTH */ -int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) +int HashRaw(WOLFSSL* ssl, const byte* data, int sz) { int ret = 0; - (void)output; + (void)data; (void)sz; - if (ssl->hsHashes == NULL) + if (ssl->hsHashes == NULL) { return BAD_FUNC_ARG; + } -#ifdef HAVE_FUZZER - if (ssl->fuzzerCb) - ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx); -#endif #ifndef NO_OLD_TLS #ifndef NO_SHA - wc_ShaUpdate(&ssl->hsHashes->hashSha, output, sz); + wc_ShaUpdate(&ssl->hsHashes->hashSha, data, sz); #endif #ifndef NO_MD5 - wc_Md5Update(&ssl->hsHashes->hashMd5, output, sz); + wc_Md5Update(&ssl->hsHashes->hashMd5, data, sz); #endif #endif /* NO_OLD_TLS */ if (IsAtLeastTLSv1_2(ssl)) { #ifndef NO_SHA256 - ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, output, sz); + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, data, sz); if (ret != 0) return ret; #endif #ifdef WOLFSSL_SHA384 - ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, output, sz); + ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, data, sz); if (ret != 0) return ret; #endif #ifdef WOLFSSL_SHA512 - ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, output, sz); + ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, data, sz); if (ret != 0) return ret; #endif #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) - ret = EdDSA_Update(ssl, output, sz); + ret = EdDSA_Update(ssl, data, sz); if (ret != 0) return ret; #endif @@ -7728,7 +7739,6 @@ int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) /* add output to md5 and sha handshake hashes, exclude record header */ int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) { - int ret = 0; const byte* adj; if (ssl->hsHashes == NULL) @@ -7747,55 +7757,23 @@ int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) sz -= DTLS_RECORD_EXTRA; } #endif -#ifndef NO_OLD_TLS - #ifndef NO_SHA - wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz); - #endif - #ifndef NO_MD5 - wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz); - #endif -#endif - if (IsAtLeastTLSv1_2(ssl)) { - #ifndef NO_SHA256 - ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz); - if (ret != 0) - return ret; - #endif - #ifdef WOLFSSL_SHA384 - ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz); - if (ret != 0) - return ret; - #endif - #ifdef WOLFSSL_SHA512 - ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz); - if (ret != 0) - return ret; - #endif - #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ - ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ - (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) - ret = EdDSA_Update(ssl, adj, sz); - if (ret != 0) - return ret; - #endif - } - - return ret; + return HashRaw(ssl, adj, sz); } /* add input to md5 and sha handshake hashes, include handshake header */ int HashInput(WOLFSSL* ssl, const byte* input, int sz) { - int ret = 0; const byte* adj; + if (ssl->hsHashes == NULL) { + return BAD_FUNC_ARG; + } + adj = input - HANDSHAKE_HEADER_SZ; sz += HANDSHAKE_HEADER_SZ; - (void)adj; - #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { adj -= DTLS_HANDSHAKE_EXTRA; @@ -7803,45 +7781,7 @@ int HashInput(WOLFSSL* ssl, const byte* input, int sz) } #endif - if (ssl->hsHashes == NULL) { - return BAD_FUNC_ARG; - } - -#ifndef NO_OLD_TLS - #ifndef NO_SHA - wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz); - #endif - #ifndef NO_MD5 - wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz); - #endif -#endif - - if (IsAtLeastTLSv1_2(ssl)) { - #ifndef NO_SHA256 - ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz); - if (ret != 0) - return ret; - #endif - #ifdef WOLFSSL_SHA384 - ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz); - if (ret != 0) - return ret; - #endif - #ifdef WOLFSSL_SHA512 - ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz); - if (ret != 0) - return ret; - #endif - #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ - ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ - (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) - ret = EdDSA_Update(ssl, adj, sz); - if (ret != 0) - return ret; - #endif - } - - return ret; + return HashRaw(ssl, adj, sz); } @@ -10007,6 +9947,8 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, /* Determine if verify was okay */ if (ret == 0) { verify_ok = 1; + use_cb = 1; /* use verify callback on success, in case callback + * could force fail a cert */ } /* Determine if verify callback should be used */ @@ -11062,8 +11004,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, } else if (ret == ASN_PARSE_E || ret == BUFFER_E) { WOLFSSL_MSG("Got Peer cert ASN PARSE or BUFFER ERROR"); + #if defined(WOLFSSL_EXTRA_ALERTS) || defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) + DoCertFatalAlert(ssl, ret); + #endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - SendAlert(ssl, alert_fatal, bad_certificate); ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; #endif args->fatal = 1; @@ -11078,12 +11023,20 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, "\tCallback override available, will continue"); /* check if fatal error */ args->fatal = (args->verifyErr) ? 1 : 0; + #if defined(WOLFSSL_EXTRA_ALERTS) || \ + defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) + if (args->fatal) + DoCertFatalAlert(ssl, ret); + #endif } else { WOLFSSL_MSG("\tNo callback override available, fatal"); args->fatal = 1; - #ifdef OPENSSL_EXTRA - SendAlert(ssl, alert_fatal, bad_certificate); + #if defined(WOLFSSL_EXTRA_ALERTS) || \ + defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) + DoCertFatalAlert(ssl, ret); #endif } } @@ -15327,6 +15280,13 @@ int ProcessReply(WOLFSSL* ssl) if (ssl->options.tls1_3) { word16 i = (word16)(ssl->buffers.inputBuffer.length - ssl->keys.padSz); + + /* sanity check on underflow */ + if (ssl->keys.padSz >= ssl->buffers.inputBuffer.length) { + WOLFSSL_ERROR(DECRYPT_ERROR); + return DECRYPT_ERROR; + } + /* Remove padding from end of plain text. */ for (--i; i > ssl->buffers.inputBuffer.idx; i--) { if (ssl->buffers.inputBuffer.buffer[i] != 0) @@ -16920,15 +16880,15 @@ int SendCertificate(WOLFSSL* ssl) if (!ssl->options.dtls) { AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl); if (!IsEncryptionOn(ssl, 1)) - HashOutputRaw(ssl, output + RECORD_HEADER_SZ, + HashRaw(ssl, output + RECORD_HEADER_SZ, HANDSHAKE_HEADER_SZ); } else { #ifdef WOLFSSL_DTLS AddHeaders(output, payloadSz, certificate, ssl); - HashOutputRaw(ssl, - output + RECORD_HEADER_SZ + DTLS_RECORD_EXTRA, - HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA); + HashRaw(ssl, + output + RECORD_HEADER_SZ + DTLS_RECORD_EXTRA, + HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA); /* Adding the headers increments these, decrement them for * actual message header. */ ssl->keys.dtls_handshake_number--; @@ -16940,22 +16900,22 @@ int SendCertificate(WOLFSSL* ssl) /* list total */ c32to24(listSz, output + i); if (ssl->options.dtls || !IsEncryptionOn(ssl, 1)) - HashOutputRaw(ssl, output + i, CERT_HEADER_SZ); + HashRaw(ssl, output + i, CERT_HEADER_SZ); i += CERT_HEADER_SZ; length -= CERT_HEADER_SZ; fragSz -= CERT_HEADER_SZ; if (certSz) { c32to24(certSz, output + i); if (ssl->options.dtls || !IsEncryptionOn(ssl, 1)) - HashOutputRaw(ssl, output + i, CERT_HEADER_SZ); + HashRaw(ssl, output + i, CERT_HEADER_SZ); i += CERT_HEADER_SZ; length -= CERT_HEADER_SZ; fragSz -= CERT_HEADER_SZ; if (ssl->options.dtls || !IsEncryptionOn(ssl, 1)) { - HashOutputRaw(ssl, ssl->buffers.certificate->buffer, certSz); + HashRaw(ssl, ssl->buffers.certificate->buffer, certSz); if (certChainSz) - HashOutputRaw(ssl, ssl->buffers.certChain->buffer, + HashRaw(ssl, ssl->buffers.certChain->buffer, certChainSz); } } @@ -17709,9 +17669,11 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) len = wolfSSL_GetMaxRecordSize(ssl, sz - sent); -#ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - len = min(len, MAX_UDP_SIZE); +#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_DTLS_SIZE_CHECK) + if (ssl->options.dtls && (len < sz - sent)) { + ssl->error = DTLS_SIZE_ERROR; + WOLFSSL_ERROR(ssl->error); + return ssl->error; } #endif buffSz = len; @@ -18439,6 +18401,12 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case TLS13_SECRET_CB_E: return "TLS1.3 Secret Callback Error"; + case DTLS_SIZE_ERROR: + return "DTLS trying to send too much in single datagram error"; + + case NO_CERT_ERROR: + return "TLS1.3 No Certificate Set Error"; + default : return "unknown error number"; } @@ -21004,7 +20972,7 @@ exit_dpk: return ret; } -#endif /* HAVE_ECC */ +#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ /* Persistable DoServerKeyExchange arguments */ typedef struct DskeArgs { @@ -28077,6 +28045,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif } InternalTicket; + /* RFC 5077 defines this for session tickets */ /* fit within SESSION_TICKET_LEN */ typedef struct ExternalTicket { byte key_name[WOLFSSL_TICKET_NAME_SZ]; /* key context name */ @@ -29977,7 +29946,7 @@ int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment) } #endif /* HAVE_MAX_FRAGMENT */ #ifdef WOLFSSL_DTLS - if ((ssl->options.dtls) && (maxFragment > MAX_UDP_SIZE)) { + if (IsDtlsNotSctpMode(ssl) && (maxFragment > MAX_UDP_SIZE)) { maxFragment = MAX_UDP_SIZE; } #endif diff --git a/src/sniffer.c b/src/sniffer.c index 72b4c1077a..e83aa982b3 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -44,7 +44,6 @@ #define SNPRINTF snprintf #endif -#include #include #include #include @@ -90,13 +89,36 @@ enum { TRACE_MSG_SZ = 80, /* Trace Message buffer size */ HASH_SIZE = 499, /* Session Hash Table Rows */ PSEUDO_HDR_SZ = 12, /* TCP Pseudo Header size in bytes */ - FATAL_ERROR_STATE = 1, /* SnifferSession fatal error state */ + FATAL_ERROR_STATE = 1, /* SnifferSession fatal error state */ TICKET_HINT_LEN = 4, /* Session Ticket Hint length */ - EXT_TYPE_SZ = 2, /* Extension length */ + TICKET_HINT_AGE_LEN= 4, /* Session Ticket Age add length */ + EXT_TYPE_SZ = 2, /* Extension type length */ MAX_INPUT_SZ = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA + MTU_EXTRA, /* Max input sz of reassembly */ - EXT_MASTER_SECRET = 0x17, /* Extended Master Secret Extension ID */ - TICKET_EXT_ID = 0x23 /* Session Ticket Extension ID */ + + /* TLS Extensions */ + EXT_SERVER_NAME = 0x0000, /* a.k.a. SNI */ + EXT_MAX_FRAGMENT_LENGTH = 0x0001, + EXT_TRUSTED_CA_KEYS = 0x0003, + EXT_TRUNCATED_HMAC = 0x0004, + EXT_STATUS_REQUEST = 0x0005, /* a.k.a. OCSP stapling */ + EXT_SUPPORTED_GROUPS = 0x000a, /* a.k.a. Supported Curves */ + EXT_EC_POINT_FORMATS = 0x000b, + EXT_SIGNATURE_ALGORITHMS = 0x000d, + EXT_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */ + EXT_STATUS_REQUEST_V2 = 0x0011, /* a.k.a. OCSP stapling v2 */ + EXT_ENCRYPT_THEN_MAC = 0x0016, /* RFC 7366 */ + EXT_MASTER_SECRET = 0x0017, /* Extended Master Secret Extension ID */ + EXT_TICKET_ID = 0x0023, /* Session Ticket Extension ID */ + EXT_PRE_SHARED_KEY = 0x0029, + EXT_EARLY_DATA = 0x002a, + EXT_SUPPORTED_VERSIONS = 0x002b, + EXT_COOKIE = 0x002c, + EXT_PSK_KEY_EXCHANGE_MODES = 0x002d, + EXT_POST_HANDSHAKE_AUTH = 0x0031, + EXT_SIGNATURE_ALGORITHMS_CERT = 0x0032, + EXT_KEY_SHARE = 0x0033, + EXT_RENEGOTIATION_INFO = 0xff01 }; @@ -275,7 +297,8 @@ static const char* const msgTable[] = /* 91 */ "No data destination Error", "Store data callback failed", - "Loading chain input" + "Loading chain input", + "Got encrypted extension", }; @@ -318,6 +341,7 @@ typedef struct NamedKey { word32 nameSz; /* size of server DNS name */ byte* key; /* DER private key */ word32 keySz; /* size of DER private key */ + int isEphemeralKey; struct NamedKey* next; /* for list */ } NamedKey; @@ -335,7 +359,7 @@ typedef struct IpAddrInfo { /* Sniffer Server holds info for each server/port monitored */ typedef struct SnifferServer { - SSL_CTX* ctx; /* SSL context */ + WOLFSSL_CTX* ctx; /* SSL context */ char address[MAX_SERVER_ADDRESS]; /* passed in server address */ IpAddrInfo server; /* network order address */ int port; /* server port */ @@ -364,16 +388,17 @@ typedef struct Flags { #ifdef HAVE_EXTENDED_MASTER byte expectEms; /* expect extended master secret */ #endif + byte gotFinished; /* processed finished */ } Flags; /* Out of Order FIN capture */ -typedef struct FinCaputre { +typedef struct FinCapture { word32 cliFinSeq; /* client relative sequence FIN 0 is no */ word32 srvFinSeq; /* server relative sequence FIN, 0 is no */ byte cliCounted; /* did we count yet, detects duplicates */ byte srvCounted; /* did we count yet, detects duplicates */ -} FinCaputre; +} FinCapture; typedef struct HsHashes { @@ -384,7 +409,7 @@ typedef struct HsHashes { #ifndef NO_MD5 wc_Md5 hashMd5; #endif -#endif +#endif /* !NO_OLD_TLS */ #ifndef NO_SHA256 wc_Sha256 hashSha256; #endif @@ -393,12 +418,22 @@ typedef struct HsHashes { #endif } HsHashes; +typedef struct KeyShareInfo { + word16 named_group; + int key_len; + const byte* key; + + /* additional info */ + int dh_key_bits; + int curve_id; +} KeyShareInfo; + /* Sniffer Session holds info for each client/server SSL/TLS session */ typedef struct SnifferSession { SnifferServer* context; /* server context */ - SSL* sslServer; /* SSL server side decode */ - SSL* sslClient; /* SSL client side decode */ + WOLFSSL* sslServer; /* SSL server side decode */ + WOLFSSL* sslClient; /* SSL client side decode */ IpAddrInfo server; /* server address in network byte order */ IpAddrInfo client; /* client address in network byte order */ word16 srvPort; /* server port */ @@ -407,21 +442,27 @@ typedef struct SnifferSession { word32 srvSeqStart; /* server start sequence */ word32 cliExpected; /* client expected sequence (relative) */ word32 srvExpected; /* server expected sequence (relative) */ - FinCaputre finCaputre; /* retain out of order FIN s */ + FinCapture finCapture; /* retain out of order FIN s */ Flags flags; /* session flags */ - time_t lastUsed; /* last used ticks */ + time_t lastUsed; /* last used ticks */ word32 keySz; /* size of the private key */ PacketBuffer* cliReassemblyList; /* client out of order packets */ PacketBuffer* srvReassemblyList; /* server out of order packets */ word32 cliReassemblyMemory; /* client packet memory used */ word32 srvReassemblyMemory; /* server packet memory used */ - struct SnifferSession* next; /* for hash table list */ - byte* ticketID; /* mac ID of session ticket */ + struct SnifferSession* next; /* for hash table list */ + byte* ticketID; /* mac ID of session ticket */ #ifdef HAVE_SNI const char* sni; /* server name indication */ #endif #ifdef HAVE_EXTENDED_MASTER - HsHashes* hash; + HsHashes* hash; +#endif +#ifdef WOLFSSL_TLS13 + byte* cliKeyShare; + word32 cliKeyShareSz; + KeyShareInfo srvKs; + KeyShareInfo cliKs; #endif } SnifferSession; @@ -558,7 +599,7 @@ static void FreeSnifferServer(SnifferServer* srv) wc_UnLockMutex(&srv->namedKeysMutex); wc_FreeMutex(&srv->namedKeysMutex); #endif - SSL_CTX_free(srv->ctx); + wolfSSL_CTX_free(srv->ctx); } XFREE(srv, NULL, DYNAMIC_TYPE_SNIFFER_SERVER); } @@ -594,8 +635,8 @@ static void FreePacketList(PacketBuffer* in) static void FreeSnifferSession(SnifferSession* session) { if (session) { - SSL_free(session->sslClient); - SSL_free(session->sslServer); + wolfSSL_free(session->sslClient); + wolfSSL_free(session->sslServer); FreePacketList(session->cliReassemblyList); FreePacketList(session->srvReassemblyList); @@ -603,6 +644,10 @@ static void FreeSnifferSession(SnifferSession* session) XFREE(session->ticketID, NULL, DYNAMIC_TYPE_SNIFFER_TICKET_ID); #ifdef HAVE_EXTENDED_MASTER XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES); +#endif +#ifdef WOLFSSL_TLS13 + if (session->cliKeyShare) + XFREE(session->cliKeyShare, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif } XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); @@ -677,11 +722,10 @@ static int HashInit(HsHashes* hash) ret = wc_InitSha(&hash->hashSha); #endif #ifndef NO_MD5 - if (ret == 0) { + if (ret == 0) ret = wc_InitMd5(&hash->hashMd5); - } -#endif #endif +#endif /* !NO_OLD_TLS */ #ifndef NO_SHA256 if (ret == 0) ret = wc_InitSha256(&hash->hashSha256); @@ -694,7 +738,6 @@ static int HashInit(HsHashes* hash) return ret; } - static int HashUpdate(HsHashes* hash, const byte* input, int sz) { int ret = 0; @@ -708,11 +751,10 @@ static int HashUpdate(HsHashes* hash, const byte* input, int sz) ret = wc_ShaUpdate(&hash->hashSha, input, sz); #endif #ifndef NO_MD5 - if (ret == 0) { + if (ret == 0) ret = wc_Md5Update(&hash->hashMd5, input, sz); - } -#endif #endif +#endif /* !NO_OLD_TLS */ #ifndef NO_SHA256 if (ret == 0) ret = wc_Sha256Update(&hash->hashSha256, input, sz); @@ -725,23 +767,21 @@ static int HashUpdate(HsHashes* hash, const byte* input, int sz) return ret; } - static int HashCopy(HS_Hashes* d, HsHashes* s) { #ifndef NO_OLD_TLS #ifndef NO_SHA - XMEMCPY(&d->hashSha, &s->hashSha, sizeof(wc_Sha)); + XMEMCPY(&d->hashSha, &s->hashSha, sizeof(wc_Sha)); #endif #ifndef NO_MD5 - XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(wc_Md5)); + XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(wc_Md5)); #endif -#endif - +#endif /* !NO_OLD_TLS */ #ifndef NO_SHA256 - XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(wc_Sha256)); + XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(wc_Sha256)); #endif #ifdef WOLFSSL_SHA384 - XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(wc_Sha384)); + XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(wc_Sha384)); #endif return 0; @@ -765,9 +805,9 @@ static void InitFlags(Flags* flags) /* Initialize FIN Capture */ -static void InitFinCapture(FinCaputre* cap) +static void InitFinCapture(FinCapture* cap) { - XMEMSET(cap, 0, sizeof(FinCaputre)); + XMEMSET(cap, 0, sizeof(FinCapture)); } @@ -776,7 +816,7 @@ static void InitSession(SnifferSession* session) { XMEMSET(session, 0, sizeof(SnifferSession)); InitFlags(&session->flags); - InitFinCapture(&session->finCaputre); + InitFinCapture(&session->finCapture); } @@ -1461,7 +1501,7 @@ static int CreateWatchSnifferServer(char* error) return -1; } InitSnifferServer(sniffer); - sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method()); + sniffer->ctx = wolfSSL_CTX_new(SSLv23_client_method()); if (!sniffer->ctx) { SetError(MEMORY_STR, error, NULL, 0); FreeSnifferServer(sniffer); @@ -1480,7 +1520,8 @@ static int CreateWatchSnifferServer(char* error) static int SetNamedPrivateKey(const char* name, const char* address, int port, - const char* keyFile, int keySz, int typeKey, const char* password, char* error) + const char* keyFile, int keySz, int typeKey, const char* password, + char* error, int isEphemeralKey) { SnifferServer* sniffer; int ret; @@ -1509,7 +1550,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, namedKey->nameSz = sizeof(namedKey->name)-1; XSTRNCPY(namedKey->name, name, namedKey->nameSz); namedKey->name[MAX_SERVER_NAME-1] = '\0'; - + namedKey->isEphemeralKey = isEphemeralKey; ret = LoadKeyFile(&namedKey->key, &namedKey->keySz, keyFile, keySz, type, password); if (ret < 0) { @@ -1551,7 +1592,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, sniffer->server = serverIp; sniffer->port = port; - sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method()); + sniffer->ctx = wolfSSL_CTX_new(SSLv23_client_method()); if (!sniffer->ctx) { SetError(MEMORY_STR, error, NULL, 0); #ifdef HAVE_SNI @@ -1565,17 +1606,31 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, if (name == NULL) { if (password) { #ifdef WOLFSSL_ENCRYPTED_KEYS - SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword); - SSL_CTX_set_default_passwd_cb_userdata( + wolfSSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword); + wolfSSL_CTX_set_default_passwd_cb_userdata( sniffer->ctx, (void*)password); #endif } - if (keySz == 0) { - ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type); + + #ifdef WOLFSSL_STATIC_EPHEMERAL + if (isEphemeralKey) { + /* auto detect key type with WC_PK_TYPE_NONE */ + /* keySz == 0 mean load file */ + ret = wolfSSL_CTX_set_ephemeral_key(sniffer->ctx, WC_PK_TYPE_NONE, + keyFile, 0, type); + if (ret == 0) + ret = WOLFSSL_SUCCESS; } - else { - ret = wolfSSL_CTX_use_PrivateKey_buffer(sniffer->ctx, - (const byte*)keyFile, keySz, type); + else + #endif + { + if (keySz == 0) { + ret = wolfSSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type); + } + else { + ret = wolfSSL_CTX_use_PrivateKey_buffer(sniffer->ctx, + (const byte*)keyFile, keySz, type); + } } if (ret != WOLFSSL_SUCCESS) { SetError(KEY_FILE_STR, error, NULL, 0); @@ -1606,7 +1661,6 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, #ifdef HAVE_SNI - /* Sets the private key for a specific name, server and port */ /* returns 0 on success, -1 on error */ int ssl_SetNamedPrivateKey(const char* name, @@ -1621,7 +1675,7 @@ int ssl_SetNamedPrivateKey(const char* name, wc_LockMutex(&ServerListMutex); ret = SetNamedPrivateKey(name, address, port, keyFile, 0, - typeKey, password, error); + typeKey, password, error, 0); wc_UnLockMutex(&ServerListMutex); if (ret == 0) @@ -1630,12 +1684,10 @@ int ssl_SetNamedPrivateKey(const char* name, return ret; } - int ssl_SetNamedPrivateKeyBuffer(const char* name, - const char* address, int port, - const char* keyBuf, int keySz, - int typeKey, const char* password, - char* error) + const char* address, int port, + const char* keyBuf, int keySz, int typeKey, + const char* password, char* error) { int ret; @@ -1644,7 +1696,7 @@ int ssl_SetNamedPrivateKeyBuffer(const char* name, wc_LockMutex(&ServerListMutex); ret = SetNamedPrivateKey(name, address, port, keyBuf, keySz, - typeKey, password, error); + typeKey, password, error, 0); wc_UnLockMutex(&ServerListMutex); if (ret == 0) @@ -1652,14 +1704,13 @@ int ssl_SetNamedPrivateKeyBuffer(const char* name, return ret; } - -#endif - +#endif /* HAVE_SNI */ /* Sets the private key for a specific server and port */ /* returns 0 on success, -1 on error */ -int ssl_SetPrivateKey(const char* address, int port, const char* keyFile, - int typeKey, const char* password, char* error) +int ssl_SetPrivateKey(const char* address, int port, + const char* keyFile, int typeKey, + const char* password, char* error) { int ret; @@ -1668,7 +1719,7 @@ int ssl_SetPrivateKey(const char* address, int port, const char* keyFile, wc_LockMutex(&ServerListMutex); ret = SetNamedPrivateKey(NULL, address, port, keyFile, 0, - typeKey, password, error); + typeKey, password, error, 0); wc_UnLockMutex(&ServerListMutex); if (ret == 0) @@ -1678,9 +1729,8 @@ int ssl_SetPrivateKey(const char* address, int port, const char* keyFile, } int ssl_SetPrivateKeyBuffer(const char* address, int port, - const char* keyBuf, int keySz, - int typeKey, const char* password, - char* error) + const char* keyBuf, int keySz, int typeKey, + const char* password, char* error) { int ret; @@ -1689,7 +1739,7 @@ int ssl_SetPrivateKeyBuffer(const char* address, int port, wc_LockMutex(&ServerListMutex); ret = SetNamedPrivateKey(NULL, address, port, keyBuf, keySz, - typeKey, password, error); + typeKey, password, error, 0); wc_UnLockMutex(&ServerListMutex); if (ret == 0) @@ -1698,6 +1748,95 @@ int ssl_SetPrivateKeyBuffer(const char* address, int port, return ret; } +#ifdef WOLFSSL_STATIC_EPHEMERAL +#ifdef HAVE_SNI +/* Sets the ephemeral key for a specific name, server and port */ +/* returns 0 on success, -1 on error */ +int ssl_SetNamedEphemeralKey(const char* name, + const char* address, int port, + const char* keyFile, int typeKey, + const char* password, char* error) +{ + int ret; + + TraceHeader(); + TraceSetNamedServer(name, address, port, keyFile); + + wc_LockMutex(&ServerListMutex); + ret = SetNamedPrivateKey(name, address, port, keyFile, 0, + typeKey, password, error, 1); + wc_UnLockMutex(&ServerListMutex); + + if (ret == 0) + Trace(NEW_SERVER_STR); + + return ret; +} + +int ssl_SetNamedEphemeralKeyBuffer(const char* name, + const char* address, int port, + const char* keyBuf, int keySz, int typeKey, + const char* password, char* error) +{ + int ret; + + TraceHeader(); + TraceSetNamedServer(name, address, port, NULL); + + wc_LockMutex(&ServerListMutex); + ret = SetNamedPrivateKey(name, address, port, keyBuf, keySz, + typeKey, password, error, 1); + wc_UnLockMutex(&ServerListMutex); + + if (ret == 0) + Trace(NEW_SERVER_STR); + + return ret; +} +#endif /* HAVE_SNI */ + +/* Sets the ephemeral key for a specific server and port */ +/* returns 0 on success, -1 on error */ +int ssl_SetEphemeralKey(const char* address, int port, + const char* keyFile, int typeKey, + const char* password, char* error) +{ + int ret; + + TraceHeader(); + TraceSetServer(address, port, keyFile); + + wc_LockMutex(&ServerListMutex); + ret = SetNamedPrivateKey(NULL, address, port, keyFile, 0, + typeKey, password, error, 1); + wc_UnLockMutex(&ServerListMutex); + + if (ret == 0) + Trace(NEW_SERVER_STR); + + return ret; +} + +int ssl_SetEphemeralKeyBuffer(const char* address, int port, + const char* keyBuf, int keySz, int typeKey, + const char* password, char* error) +{ + int ret; + + TraceHeader(); + TraceSetServer(address, port, NULL); + + wc_LockMutex(&ServerListMutex); + ret = SetNamedPrivateKey(NULL, address, port, keyBuf, keySz, + typeKey, password, error, 1); + wc_UnLockMutex(&ServerListMutex); + + if (ret == 0) + Trace(NEW_SERVER_STR); + + return ret; +} +#endif /* WOLFSSL_STATIC_EPHEMERAL */ /* Check IP Header for IPV6, TCP, and a registered server address */ /* returns 0 on success, -1 on error */ @@ -1739,7 +1878,7 @@ static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error) info->length = exthdrsz; info->total = ntohs(iphdr->length) + info->length; - /* IPv6 doesn't include its own header size in the length like v4. */ + /* IPv6 doesn't include its own header size in the length like v4. */ info->src.version = IPV6; XMEMCPY(info->src.ip6, iphdr->src, sizeof(info->src.ip6)); info->dst.version = IPV6; @@ -1863,14 +2002,14 @@ static void CopySessionInfo(SnifferSession* session, SSLInfo* sslInfo) [sizeof(sslInfo->serverCipherSuiteName) - 1] = '\0'; } sslInfo->keySize = session->keySz; - #ifdef HAVE_SNI + #ifdef HAVE_SNI if (NULL != session->sni) { XSTRNCPY((char*)sslInfo->serverNameIndication, session->sni, sizeof(sslInfo->serverNameIndication)); sslInfo->serverNameIndication [sizeof(sslInfo->serverNameIndication) - 1] = '\0'; } - #endif + #endif TraceSessionInfo(sslInfo); } } @@ -1887,41 +2026,51 @@ static void CallConnectionCb(SnifferSession* session) } } +#ifdef SHOW_SECRETS +static void PrintSecret(const char* desc, const byte* buf, int sz) +{ + int i; + printf("%s: ", desc); + for (i = 0; i < sz; i++) { + printf("%02x", buf[i]); + } + printf("\n"); +} -/* Process Client Key Exchange, RSA or static ECDH */ -static int ProcessClientKeyExchange(const byte* input, int* sslBytes, - SnifferSession* session, char* error) +static void ShowTlsSecrets(SnifferSession* session) +{ + PrintSecret("server master secret", session->sslServer->arrays->masterSecret, SECRET_LEN); + PrintSecret("client master secret", session->sslClient->arrays->masterSecret, SECRET_LEN); + printf("server suite = %d\n", session->sslServer->options.cipherSuite); + printf("client suite = %d\n", session->sslClient->options.cipherSuite); +} +#endif /* SHOW_SECRETS */ + + +/* Process Keys */ +static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session, + char* error, KeyShareInfo* ksInfo, DerBuffer* keyBuf) { word32 idx = 0; - int tryEcc = 0; int ret; - if (session->sslServer->buffers.key == NULL || - session->sslServer->buffers.key->buffer == NULL || - session->sslServer->buffers.key->length == 0) { - - SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE); - return -1; - } - - { +#ifndef NO_RSA + /* Static RSA */ + if (ksInfo == NULL) { RsaKey key; int length; ret = wc_InitRsaKey(&key, 0); if (ret == 0) { - ret = wc_RsaPrivateKeyDecode( - session->sslServer->buffers.key->buffer, - &idx, &key, session->sslServer->buffers.key->length); + ret = wc_RsaPrivateKeyDecode(keyBuf->buffer, &idx, &key, keyBuf->length); if (ret != 0) { - tryEcc = 1; - #ifndef HAVE_ECC - SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE); - #else - /* If we can do ECC, this isn't fatal. Not loading an ECC - * key will be fatal, though. */ - SetError(RSA_DECODE_STR, error, session, 0); - #endif + #ifndef HAVE_ECC + SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE); + #else + /* If we can do ECC, this isn't fatal. Not loading an ECC + * key will be fatal, though. */ + SetError(RSA_DECODE_STR, error, session, 0); + #endif } } @@ -1970,9 +2119,99 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, wc_FreeRsaKey(&key); } +#endif /* !NO_RSA */ + +#if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA) + /* Static Ephemeral DH Key */ + if (ksInfo && ksInfo->dh_key_bits != 0) { + DhKey dhKey; + const DhParams* params; + word32 privKeySz; + byte privKey[52]; /* max for TLS */ + + /* get DH params */ + switch (ksInfo->named_group) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + params = wc_Dh_ffdhe2048_Get(); + privKeySz = 29; + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + params = wc_Dh_ffdhe3072_Get(); + privKeySz = 34; + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + params = wc_Dh_ffdhe4096_Get(); + privKeySz = 39; + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + params = wc_Dh_ffdhe6144_Get(); + privKeySz = 46; + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + params = wc_Dh_ffdhe8192_Get(); + privKeySz = 52; + break; + #endif + default: + return BAD_FUNC_ARG; + } + + ret = wc_InitDhKey(&dhKey); + if (ret == 0) { + ret = wc_DhSetKey(&dhKey, + (byte*)params->p, params->p_len, + (byte*)params->g, params->g_len); + if (ret == 0) { + ret = wc_DhKeyDecode(keyBuf->buffer, &idx, &dhKey, + keyBuf->length); + } + if (ret == 0) { + ret = wc_DhExportKeyPair(&dhKey, privKey, &privKeySz, NULL, + NULL); + } + + /* Derive secret from private key and peer's public key */ + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &dhPriv.asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_DhAgree(&dhKey, + session->sslServer->arrays->preMasterSecret, + &session->sslServer->arrays->preMasterSz, + privKey, privKeySz, + input, *sslBytes); + } + } while (ret == WC_PENDING_E); + + wc_FreeDhKey(&dhKey); + + /* left-padded with zeros up to the size of the prime */ + if (params->p_len > session->sslServer->arrays->preMasterSz) { + word32 diff = params->p_len - session->sslServer->arrays->preMasterSz; + XMEMMOVE(session->sslServer->arrays->preMasterSecret + diff, + session->sslServer->arrays->preMasterSecret, + session->sslServer->arrays->preMasterSz); + XMEMSET(session->sslServer->arrays->preMasterSecret, 0, diff); + session->sslServer->arrays->preMasterSz = params->p_len; + } + } + } +#endif /* !NO_DH && WOLFSSL_DH_EXTRA */ - if (tryEcc) { #ifdef HAVE_ECC + /* Static Ephemeral ECC Key */ + if (ksInfo && ksInfo->curve_id != 0) { ecc_key key; ecc_key pubKey; int length, keyInit = 0, pubKeyInit = 0; @@ -1985,9 +2224,7 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, } if (ret == 0) { pubKeyInit = 1; - ret = wc_EccPrivateKeyDecode( - session->sslServer->buffers.key->buffer, - &idx, &key, session->sslServer->buffers.key->length); + ret = wc_EccPrivateKeyDecode(keyBuf->buffer, &idx, &key, keyBuf->length); if (ret != 0) { SetError(ECC_DECODE_STR, error, session, FATAL_ERROR_STATE); } @@ -1997,19 +2234,18 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, length = wc_ecc_size(&key) * 2 + 1; /* The length should be 2 times the key size (x and y), plus 1 * for the type byte. */ - if (IsTLS(session->sslServer)) { + if (IsTLS(session->sslServer) && !IsAtLeastTLSv1_3(session->sslServer->version)) { input += 1; /* Don't include the TLS length for the key. */ } - if (length + 1 > *sslBytes) { - SetError(PARTIAL_INPUT_STR, - error, session, FATAL_ERROR_STATE); + if (length > *sslBytes) { + SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE); ret = -1; } } if (ret == 0) { - ret = wc_ecc_import_x963_ex(input, length, &pubKey, ECC_CURVE_DEF); + ret = wc_ecc_import_x963_ex(input, length, &pubKey, ksInfo->curve_id); if (ret != 0) { SetError(ECC_PUB_DECODE_STR, error, session, FATAL_ERROR_STATE); } @@ -2044,8 +2280,8 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, wc_ecc_free(&key); if (pubKeyInit) wc_ecc_free(&pubKey); -#endif } +#endif /* HAVE_ECC */ /* store for client side as well */ XMEMCPY(session->sslClient->arrays->preMasterSecret, @@ -2054,15 +2290,11 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, session->sslClient->arrays->preMasterSz = session->sslServer->arrays->preMasterSz; - #ifdef SHOW_SECRETS - { - word32 i; - printf("pre master secret: "); - for (i = 0; i < session->sslServer->arrays->preMasterSz; i++) - printf("%02x", session->sslServer->arrays->preMasterSecret[i]); - printf("\n"); - } - #endif +#ifdef SHOW_SECRETS + PrintSecret("pre master secret", + session->sslServer->arrays->preMasterSecret, + session->sslServer->arrays->preMasterSz); +#endif if (SetCipherSpecs(session->sslServer) != 0) { SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE); @@ -2074,32 +2306,41 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, return -1; } - ret = MakeMasterSecret(session->sslServer); - ret += MakeMasterSecret(session->sslClient); - ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE); - ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE); - +#ifdef WOLFSSL_TLS13 + /* TLS v1.3 derive handshake key */ + if (IsAtLeastTLSv1_3(session->sslServer->version)) { + ret = DeriveEarlySecret(session->sslServer); + ret += DeriveEarlySecret(session->sslClient); + ret += DeriveHandshakeSecret(session->sslServer); + ret += DeriveHandshakeSecret(session->sslClient); + ret += DeriveTls13Keys(session->sslServer, handshake_key, ENCRYPT_AND_DECRYPT_SIDE, 1); + ret += DeriveTls13Keys(session->sslClient, handshake_key, ENCRYPT_AND_DECRYPT_SIDE, 1); + #ifdef WOLFSSL_EARLY_DATA + ret += SetKeysSide(session->sslServer, DECRYPT_SIDE_ONLY); + ret += SetKeysSide(session->sslClient, DECRYPT_SIDE_ONLY); + #else + ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE); + ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE); + #endif + } + else +#endif + { + ret = MakeMasterSecret(session->sslServer); + ret += MakeMasterSecret(session->sslClient); + ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE); + ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE); + } if (ret != 0) { SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE); return -1; } #ifdef SHOW_SECRETS - { - int i; - printf("server master secret: "); - for (i = 0; i < SECRET_LEN; i++) - printf("%02x", session->sslServer->arrays->masterSecret[i]); - printf("\n"); - - printf("client master secret: "); - for (i = 0; i < SECRET_LEN; i++) - printf("%02x", session->sslClient->arrays->masterSecret[i]); - printf("\n"); - - printf("server suite = %d\n", session->sslServer->options.cipherSuite); - printf("client suite = %d\n", session->sslClient->options.cipherSuite); - } + #ifdef WOLFSSL_TLS13 + if (!IsAtLeastTLSv1_3(session->sslServer->version)) + #endif + ShowTlsSecrets(session); #endif CallConnectionCb(session); @@ -2107,35 +2348,241 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, return ret; } +/* Process Client Key Exchange, static RSA */ +static int ProcessClientKeyExchange(const byte* input, int* sslBytes, + SnifferSession* session, char* error) +{ + if (session->sslServer->buffers.key == NULL || + session->sslServer->buffers.key->buffer == NULL || + session->sslServer->buffers.key->length == 0) { + + SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + return SetupKeys(input, sslBytes, session, error, NULL, + session->sslServer->buffers.key); +} + +#ifdef WOLFSSL_TLS13 +static int ProcessKeyShare(KeyShareInfo* info, const byte* input, int len, + word16 filter_group) +{ + int index = 0; + while (index < len) { + /* Named group and public key */ + info->named_group = (word16)((input[index] << 8) | input[index+1]); + index += OPAQUE16_LEN; + info->key_len = (word16)((input[index] << 8) | input[index+1]); + index += OPAQUE16_LEN; + if (info->key_len == 0 || info->key_len > len - index) { + return -1; + } + info->key = &input[index]; + index += info->key_len; + + switch (info->named_group) { + #ifndef NO_DH + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + info->dh_key_bits = 2048; + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + info->dh_key_bits = 3072; + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + info->dh_key_bits = 4096; + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + info->dh_key_bits = 6144; + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + info->dh_key_bits = 8192; + break; + #endif + #endif /* !NO_DH */ + #ifdef HAVE_ECC + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + info->curve_id = ECC_SECP256R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + info->curve_id = ECC_SECP384R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: + info->curve_id = ECC_SECP521R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #endif /* HAVE_ECC */ + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: + info->curve_id = ECC_X25519; + break; + #endif + #ifdef HAVE_X448 + case WOLFSSL_ECC_X448: + info->curve_id = ECC_X448; + break; + #endif + default: + /* unsupported curve */ + return ECC_PEERKEY_ERROR; + } + + if (filter_group == 0 || filter_group == info->named_group) { + return 0; + } + } + return -1; +} + +static int ProcessServerKeyShare(SnifferSession* session, const byte* input, int len, + char* error) +{ + int ret; + + if (session->cliKeyShare == NULL || session->cliKeyShareSz == 0) { + SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + /* Get server_hello key share */ + ret = ProcessKeyShare(&session->srvKs, input, len, 0); + if (ret == 0) { + /* Get client_hello key share */ + ret = ProcessKeyShare(&session->cliKs, session->cliKeyShare, + session->cliKeyShareSz, session->srvKs.named_group); + } + if (ret != 0) { + SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + return ret; +} +#endif /* WOLFSSL_TLS13 */ /* Process Session Ticket */ static int ProcessSessionTicket(const byte* input, int* sslBytes, SnifferSession* session, char* error) { word16 len; + WOLFSSL* ssl; - /* make sure can read through hint and len */ - if (TICKET_HINT_LEN + LENGTH_SZ > *sslBytes) { + if (session->flags.side == WOLFSSL_SERVER_END) + ssl = session->sslServer; + else + ssl = session->sslClient; + + /* make sure can read through hint len */ + if (TICKET_HINT_LEN > *sslBytes) { SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE); return -1; } - - input += TICKET_HINT_LEN; /* skip over hint */ + input += TICKET_HINT_LEN; /* skip over hint len */ *sslBytes -= TICKET_HINT_LEN; - len = (word16)((input[0] << 8) | input[1]); - input += LENGTH_SZ; - *sslBytes -= LENGTH_SZ; +#ifdef WOLFSSL_TLS13 + /* TLS v1.3 has hint age and nonce */ + if (IsAtLeastTLSv1_3(ssl->version)) { + /* make sure can read through hint age and nonce len */ + if (TICKET_HINT_AGE_LEN + 1 > *sslBytes) { + SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + input += TICKET_HINT_AGE_LEN; /* skip over hint age */ + *sslBytes -= TICKET_HINT_AGE_LEN; - /* make sure can read through ticket */ - if (len > *sslBytes || len < ID_LEN) { + /* ticket nonce */ + len = input[0]; + if (len > MAX_TICKET_NONCE_SZ) { + SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + input += OPAQUE8_LEN; + *sslBytes -= OPAQUE8_LEN; + #ifdef HAVE_SESSION_TICKET + /* store nonce in server for DeriveResumptionPSK */ + session->sslServer->session.ticketNonce.len = len; + if (len > 0) + XMEMCPY(&session->sslServer->session.ticketNonce.data, input, len); + #endif + input += len; + *sslBytes -= len; + } +#endif + + /* make sure can read through len */ + if (OPAQUE16_LEN > *sslBytes) { SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE); return -1; } - /* store session with macID as sessionID */ - session->sslServer->options.haveSessionId = 1; - XMEMCPY(session->sslServer->arrays->sessionID, input + len - ID_LEN,ID_LEN); + len = (word16)((input[0] << 8) | input[1]); + input += OPAQUE16_LEN; + *sslBytes -= OPAQUE16_LEN; + + /* make sure can read through ticket */ + if (len > *sslBytes) { + SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + +#ifdef WOLFSSL_TLS13 + /* TLS v1.3 has hint age and nonce */ + if (IsAtLeastTLSv1_3(ssl->version)) { + #ifdef HAVE_SESSION_TICKET + if (SetTicket(ssl, input, len) != 0) { + SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + /* set haveSessionId to use the wolfSession cache */ + ssl->options.haveSessionId = 1; + + /* Use the wolf Session cache to retain resumption secret */ + if (session->flags.cached == 0) { + WOLFSSL_SESSION* sess = GetSession(ssl, NULL, 0); + if (sess == NULL) { + AddSession(ssl); /* don't re add */ + #ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslResumptionInserts); + #endif + } + session->flags.cached = 1; + } + #endif /* HAVE_SESSION_TICKET */ + } + else +#endif /* WOLFSSL_TLS13 */ + { + /* make sure ticket id isn't too long */ + if (len > ID_LEN) { + SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + /* store session with macID as sessionID */ + session->sslServer->options.haveSessionId = 1; + XMEMCPY(session->sslServer->arrays->sessionID, + input + len - ID_LEN, ID_LEN); + } return 0; } @@ -2145,10 +2592,11 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes, static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, SnifferSession* session, char* error) { + int ret = 0; ProtocolVersion pv; byte b, b0; int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN; - int doResume = 0; + int doResume = 0; int initialBytes = *sslBytes; (void)msgSz; @@ -2175,7 +2623,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN); XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN); - input += RAN_LEN; + input += RAN_LEN; *sslBytes -= RAN_LEN; b = *input++; @@ -2187,6 +2635,9 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, return -1; } if (b) { + #ifdef WOLFSSL_TLS13 + XMEMCPY(session->sslServer->session.sessionID, input, ID_LEN); + #endif XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN); session->sslServer->options.haveSessionId = 1; } @@ -2230,7 +2681,6 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, return -1; } -#ifdef HAVE_EXTENDED_MASTER /* extensions */ if ((initialBytes - *sslBytes) < msgSz) { word16 len; @@ -2251,15 +2701,14 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, } while (len >= EXT_TYPE_SZ + LENGTH_SZ) { - byte extType[EXT_TYPE_SZ]; + word16 extType; word16 extLen; - extType[0] = input[0]; - extType[1] = input[1]; + extType = (word16)((input[0] << 8) | input[1]); input += EXT_TYPE_SZ; *sslBytes -= EXT_TYPE_SZ; - extLen = (word16)((input[0] << 8) | input[1]); + extLen = (word16)((input[0] << 8) | input[1]); input += LENGTH_SZ; *sslBytes -= LENGTH_SZ; @@ -2270,8 +2719,40 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, return -1; } - if (extType[0] == 0x00 && extType[1] == EXT_MASTER_SECRET) { + switch (extType) { + #ifdef WOLFSSL_TLS13 + case EXT_KEY_SHARE: + ret = ProcessServerKeyShare(session, input, extLen, error); + if (ret != 0) { + SetError(SERVER_HELLO_INPUT_STR, error, session, + FATAL_ERROR_STATE); + return -1; + } + break; + #endif + #ifdef HAVE_SESSION_TICKET + case EXT_PRE_SHARED_KEY: + /* indicates we want to use resumption */ + session->sslServer->options.resuming = 1; + session->sslClient->options.resuming = 1; + /* default nonce to len = 1, data = 0 */ + session->sslServer->session.ticketNonce.len = 1; + session->sslServer->session.ticketNonce.data[0] = 0; + session->sslClient->session.ticketNonce.len = 1; + session->sslClient->session.ticketNonce.data[0] = 0; + break; + #endif + case EXT_SUPPORTED_VERSIONS: + session->sslServer->version.major = input[0]; + session->sslServer->version.minor = input[1]; + session->sslClient->version.major = input[0]; + session->sslClient->version.minor = input[1]; + break; + case EXT_MASTER_SECRET: + #ifdef HAVE_EXTENDED_MASTER session->flags.expectEms = 1; + #endif + break; } input += extLen; @@ -2280,6 +2761,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, } } +#ifdef HAVE_EXTENDED_MASTER if (!session->flags.expectEms) { XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES); session->hash = NULL; @@ -2288,13 +2770,15 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, if (session->sslServer->options.haveSessionId) { if (XMEMCMP(session->sslServer->arrays->sessionID, - session->sslClient->arrays->sessionID, ID_LEN) == 0) + session->sslClient->arrays->sessionID, ID_LEN) == 0) { doResume = 1; - } + } + } else if (session->sslClient->options.haveSessionId == 0 && session->sslServer->options.haveSessionId == 0 && - session->ticketID) + session->ticketID) { doResume = 1; + } if (session->ticketID && doResume) { /* use ticketID to retrieve from session, prefer over sessionID */ @@ -2303,10 +2787,16 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, actual sessionID */ } - if (doResume ) { - int ret = 0; - SSL_SESSION* resume = GetSession(session->sslServer, - session->sslServer->arrays->masterSecret, 0); + if (doResume) { + WOLFSSL_SESSION* resume; + if (IsAtLeastTLSv1_3(session->sslServer->version)) { + resume = GetSession(session->sslServer, + session->sslServer->session.masterSecret, 0); + } + else { + resume = GetSession(session->sslServer, + session->sslServer->arrays->masterSecret, 0); + } if (resume == NULL) { #ifdef WOLFSSL_SNIFFER_STATS INC_STAT(SnifferStats.sslResumeMisses); @@ -2314,9 +2804,16 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE); return -1; } + /* make sure client has master secret too */ - XMEMCPY(session->sslClient->arrays->masterSecret, - session->sslServer->arrays->masterSecret, SECRET_LEN); + if (IsAtLeastTLSv1_3(session->sslServer->version)) { + XMEMCPY(session->sslClient->session.masterSecret, + session->sslServer->session.masterSecret, SECRET_LEN); + } + else { + XMEMCPY(session->sslClient->arrays->masterSecret, + session->sslServer->arrays->masterSecret, SECRET_LEN); + } session->flags.resuming = 1; Trace(SERVER_DID_RESUMPTION_STR); @@ -2334,16 +2831,35 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, return -1; } - if (session->sslServer->options.tls) { - ret = DeriveTlsKeys(session->sslServer); - ret += DeriveTlsKeys(session->sslClient); + #ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(session->sslServer->version)) { + #ifdef HAVE_SESSION_TICKET + /* Resumption PSK is resumption master secret. */ + session->sslServer->arrays->psk_keySz = session->sslServer->specs.hash_size; + session->sslClient->arrays->psk_keySz = session->sslClient->specs.hash_size; + ret = DeriveResumptionPSK(session->sslServer, session->sslServer->session.ticketNonce.data, + session->sslServer->session.ticketNonce.len, session->sslServer->arrays->psk_key); + /* Copy resumption PSK to client */ + XMEMCPY(session->sslClient->arrays->psk_key, + session->sslServer->arrays->psk_key, + session->sslServer->arrays->psk_keySz); + #endif + /* handshake key setup below and traffic keys done in SetupKeys */ } - else { - ret = DeriveKeys(session->sslServer); - ret += DeriveKeys(session->sslClient); + else + #endif + { + if (IsTLS(session->sslServer)) { + ret = DeriveTlsKeys(session->sslServer); + ret += DeriveTlsKeys(session->sslClient); + } + else { + ret = DeriveKeys(session->sslServer); + ret += DeriveKeys(session->sslClient); + } + ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE); + ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE); } - ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE); - ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE); if (ret != 0) { SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE); @@ -2355,17 +2871,34 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, INC_STAT(SnifferStats.sslStandardConns); #endif } + #ifdef SHOW_SECRETS - { - int i; - printf("cipher suite = 0x%02x\n", - session->sslServer->options.cipherSuite); - printf("server random: "); - for (i = 0; i < RAN_LEN; i++) - printf("%02x", session->sslServer->arrays->serverRandom[i]); - printf("\n"); + printf("cipher suite = 0x%02x\n", session->sslServer->options.cipherSuite); + PrintSecret("server random", session->sslServer->arrays->serverRandom, RAN_LEN); +#endif + +#ifdef WOLFSSL_TLS13 + /* Setup handshake keys */ + if (IsAtLeastTLSv1_3(session->sslServer->version)) { + DerBuffer* key = session->sslServer->buffers.key; + #ifdef WOLFSSL_STATIC_EPHEMERAL + if (session->sslServer->staticKE.key) + key = session->sslServer->staticKE.key; + #endif + ret = SetupKeys(session->cliKs.key, &session->cliKs.key_len, + session, error, &session->cliKs, key); + if (ret != 0) { + SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return ret; + } + + if (session->flags.side == WOLFSSL_SERVER_END) + session->flags.serverCipherOn = 1; + else + session->flags.clientCipherOn = 1; } #endif + return 0; } @@ -2374,15 +2907,19 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, static int ProcessClientHello(const byte* input, int* sslBytes, SnifferSession* session, char* error) { + int ret = 0; byte bLen; word16 len; int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN; + const byte* inputHello = input; + int inputHelloSz = *sslBytes; + WOLFSSL* ssl = session->sslServer; + int didHash = 0; #ifdef HAVE_SNI { byte name[MAX_SERVER_NAME]; word32 nameSz = sizeof(name); - int ret; ret = wolfSSL_SNI_GetFromBuffer( input - HANDSHAKE_HEADER_SZ - RECORD_HEADER_SZ, @@ -2400,9 +2937,23 @@ static int ProcessClientHello(const byte* input, int* sslBytes, while (namedKey != NULL) { if (nameSz == namedKey->nameSz && XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) { - if (wolfSSL_use_PrivateKey_buffer(session->sslServer, - namedKey->key, namedKey->keySz, - WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + #ifdef WOLFSSL_STATIC_EPHEMERAL + if (namedKey->isEphemeralKey) { + /* auto detect key type with WC_PK_TYPE_NONE */ + ret = wolfSSL_set_ephemeral_key(ssl, + WC_PK_TYPE_NONE, (const char*)namedKey->key, + namedKey->keySz, WOLFSSL_FILETYPE_ASN1); + if (ret == 0) + ret = WOLFSSL_SUCCESS; + } + else + #endif + { + ret = wolfSSL_use_PrivateKey_buffer(ssl, + namedKey->key, namedKey->keySz, + WOLFSSL_FILETYPE_ASN1); + } + if (ret != WOLFSSL_SUCCESS) { wc_UnLockMutex(&session->context->namedKeysMutex); SetError(CLIENT_HELLO_LATE_KEY_STR, error, session, FATAL_ERROR_STATE); @@ -2446,17 +2997,15 @@ static int ProcessClientHello(const byte* input, int* sslBytes, return -1; } Trace(CLIENT_RESUME_TRY_STR); +#ifdef WOLFSSL_TLS13 + XMEMCPY(session->sslClient->session.sessionID, input, ID_LEN); +#endif XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN); session->sslClient->options.haveSessionId = 1; } + #ifdef SHOW_SECRETS - { - int i; - printf("client random: "); - for (i = 0; i < RAN_LEN; i++) - printf("%02x", session->sslServer->arrays->clientRandom[i]); - printf("\n"); - } + PrintSecret("client random", ssl->arrays->clientRandom, RAN_LEN); #endif input += bLen; @@ -2511,15 +3060,14 @@ static int ProcessClientHello(const byte* input, int* sslBytes, } while (len >= EXT_TYPE_SZ + LENGTH_SZ) { - byte extType[EXT_TYPE_SZ]; + word16 extType; word16 extLen; - extType[0] = input[0]; - extType[1] = input[1]; + extType = (word16)((input[0] << 8) | input[1]); input += EXT_TYPE_SZ; *sslBytes -= EXT_TYPE_SZ; - extLen = (word16)((input[0] << 8) | input[1]); + extLen = (word16)((input[0] << 8) | input[1]); input += LENGTH_SZ; *sslBytes -= LENGTH_SZ; @@ -2529,17 +3077,101 @@ static int ProcessClientHello(const byte* input, int* sslBytes, return -1; } - if (extType[0] == 0x00 && extType[1] == TICKET_EXT_ID) { + switch (extType) { + #ifdef WOLFSSL_TLS13 + case EXT_KEY_SHARE: + { + word16 ksLen = (word16)((input[0] << 8) | input[1]); + if (ksLen + OPAQUE16_LEN > extLen) { + SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + /* cache key share data till server_hello */ + session->cliKeyShareSz = ksLen; + session->cliKeyShare = (byte*)XMALLOC(ksLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (session->cliKeyShare == NULL) { + SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); + break; + } + XMEMCPY(session->cliKeyShare, &input[2], ksLen); + /* The server side handshake encryption is on for future packets */ + session->flags.serverCipherOn = 1; + break; + } + #ifdef HAVE_SESSION_TICKET + case EXT_PRE_SHARED_KEY: + { + word16 idsLen, idLen, bindersLen, idx = 0; + word32 ticketAge; + const byte *identity, *binders; + + idsLen = (word16)((input[idx] << 8) | input[idx+1]); + if (idsLen + OPAQUE16_LEN + idx > extLen) { + SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + idx += OPAQUE16_LEN; + + /* PSK identity */ + idLen = (word16)((input[idx] << 8) | input[idx+1]); + if (idLen + OPAQUE16_LEN + idx > extLen) { + SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + idx += OPAQUE16_LEN; + identity = &input[idx]; + idx += idLen; + + /* Obfuscated Ticket Age 32-bits */ + ticketAge = (word32)((input[idx] << 24) | (input[idx+1] << 16) | + (input[idx+2] << 8) | input[idx+3]); + (void)ticketAge; /* not used */ + idx += OPAQUE32_LEN; + + /* binders - all binders */ + bindersLen = (word16)((input[idx] << 8) | input[idx+1]); + if (bindersLen + OPAQUE16_LEN + idx > extLen) { + SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + idx += OPAQUE16_LEN; + binders = &input[idx]; + bindersLen += OPAQUE16_LEN; /* includes 2 bytes for total len */ + (void)binders; /* not used */ + + /* Hash data up to binders for deriving binders in PSK extension. */ + HashRaw(session->sslServer, inputHello - HANDSHAKE_HEADER_SZ, + inputHelloSz - bindersLen + HANDSHAKE_HEADER_SZ); + HashRaw(session->sslClient, inputHello - HANDSHAKE_HEADER_SZ, + inputHelloSz - bindersLen + HANDSHAKE_HEADER_SZ); + + /* call to decrypt session ticket */ + if (DoClientTicket(ssl, identity, idLen) != 0) { + /* we aren't decrypting the resumption, since we know the master secret */ + /* ignore errors */ + } + ssl->options.resuming = 1; + + /* Hash the rest of the ClientHello. */ + HashRaw(session->sslServer, inputHello + inputHelloSz - bindersLen, bindersLen); + HashRaw(session->sslClient, inputHello + inputHelloSz - bindersLen, bindersLen); + didHash = 1; + break; + } + #endif /* HAVE_SESSION_TICKET */ + #endif /* WOLFSSL_TLS13 */ + case EXT_SUPPORTED_VERSIONS: + break; + case EXT_TICKET_ID: /* make sure can read through ticket if there is a non blank one */ if (extLen && extLen < ID_LEN) { SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); return -1; } - if (extLen) { - if (session->ticketID == 0) { + if (session->ticketID == NULL) { session->ticketID = (byte*)XMALLOC(ID_LEN, NULL, DYNAMIC_TYPE_SNIFFER_TICKET_ID); if (session->ticketID == 0) { @@ -2550,6 +3182,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes, } XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN); } + break; } input += extLen; @@ -2557,33 +3190,74 @@ static int ProcessClientHello(const byte* input, int* sslBytes, len -= extLen + EXT_TYPE_SZ + LENGTH_SZ; } - return 0; + if (!didHash) { + HashRaw(session->sslServer, inputHello - HANDSHAKE_HEADER_SZ, + inputHelloSz + HANDSHAKE_HEADER_SZ); + HashRaw(session->sslClient, inputHello - HANDSHAKE_HEADER_SZ, + inputHelloSz + HANDSHAKE_HEADER_SZ); + } + + (void)ssl; + + return ret; } #ifdef WOLFSSL_SNIFFER_WATCH -/* Process Certificate */ -static int ProcessCertificate(const byte* input, int* sslBytes, - SnifferSession* session, char* error) +static int KeyWatchCall(SnifferSession* session, const byte* data, int dataSz, + char* error) { - Sha256 sha; - const byte* certChain; - word32 certChainSz; - word32 certSz; int ret; + Sha256 sha; byte digest[SHA256_DIGEST_SIZE]; - /* If the receiver is the server, this is the client certificate message, - * and it should be ignored at this point. */ - if (session->flags.side == WOLFSSL_SERVER_END) - return 0; - if (WatchCb == NULL) { SetError(WATCH_CB_MISSING_STR, error, session, FATAL_ERROR_STATE); return -1; } + ret = wc_InitSha256(&sha); + if (ret == 0) + ret = wc_Sha256Update(&sha, data, dataSz); + if (ret == 0) + ret = wc_Sha256Final(&sha, digest); + if (ret != 0) { + SetError(WATCH_HASH_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + ret = WatchCb((void*)session, digest, sizeof(digest), + data, dataSz, WatchCbCtx, error); + if (ret != 0) { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslKeysUnmatched); +#endif + SetError(WATCH_FAIL_STR, error, session, FATAL_ERROR_STATE); + ret = -1; + } + else { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslKeyMatches); +#endif + } + return ret; +} + +/* Process Certificate */ +static int ProcessCertificate(const byte* input, int* sslBytes, + SnifferSession* session, char* error) +{ + int ret; + const byte* certChain; + word32 certChainSz; + word32 certSz; + + /* If the receiver is the server, this is the client certificate message, + * and it should be ignored at this point. */ + if (session->flags.side == WOLFSSL_SERVER_END) + return 0; + if (*sslBytes < CERT_HEADER_SZ) { SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE); return -1; @@ -2607,32 +3281,7 @@ static int ProcessCertificate(const byte* input, int* sslBytes, *sslBytes -= certChainSz; - ret = wc_InitSha256(&sha); - if (ret == 0) - ret = wc_Sha256Update(&sha, input, certSz); - if (ret == 0) - ret = wc_Sha256Final(&sha, digest); - if (ret != 0) { - SetError(WATCH_HASH_STR, error, session, FATAL_ERROR_STATE); - return -1; - } - - ret = WatchCb((void*)session, digest, sizeof(digest), - certChain, certChainSz, WatchCbCtx, error); - if (ret != 0) { -#ifdef WOLFSSL_SNIFFER_STATS - INC_STAT(SnifferStats.sslKeysUnmatched); -#endif - SetError(WATCH_FAIL_STR, error, session, FATAL_ERROR_STATE); - return -1; - } - else { -#ifdef WOLFSSL_SNIFFER_STATS - INC_STAT(SnifferStats.sslKeyMatches); -#endif - } - - return 0; + return KeyWatchCall(session, input, certSz, error); } #endif @@ -2642,7 +3291,7 @@ static int ProcessCertificate(const byte* input, int* sslBytes, static int ProcessFinished(const byte* input, int size, int* sslBytes, SnifferSession* session, char* error) { - SSL* ssl; + WOLFSSL* ssl; word32 inOutIdx = 0; int ret; @@ -2651,8 +3300,20 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes, else ssl = session->sslClient; - ret = DoFinished(ssl, input, &inOutIdx, (word32) size, (word32) *sslBytes, - SNIFF); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { + ret = DoTls13Finished(ssl, input, &inOutIdx, (word32)size, + (word32)*sslBytes, SNIFF); + + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + else +#endif + { + ret = DoFinished(ssl, input, &inOutIdx, (word32)size, + (word32)*sslBytes, SNIFF); + } *sslBytes -= (int)inOutIdx; if (ret < 0) { @@ -2673,6 +3334,62 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes, } } +#ifdef WOLFSSL_TLS13 + /* Derive TLS v1.3 traffic keys */ + if (IsAtLeastTLSv1_3(ssl->version)) { + if (!session->flags.gotFinished) { + /* When either side gets "finished" derive master secret and keys */ + ret = DeriveMasterSecret(session->sslServer); + ret += DeriveMasterSecret(session->sslClient); + #ifdef WOLFSSL_EARLY_DATA + ret += DeriveTls13Keys(session->sslServer, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data); + ret += DeriveTls13Keys(session->sslClient, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data); + #else + ret += DeriveTls13Keys(session->sslServer, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1); + ret += DeriveTls13Keys(session->sslClient, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1); + #endif + + if (ret != 0) { + SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE); + return -1; + } + + session->flags.gotFinished = 1; + #ifdef SHOW_SECRETS + ShowTlsSecrets(session); + #endif + } + + if (session->flags.side == WOLFSSL_SERVER_END) { + /* finished from client to server */ + ret = SetKeysSide(session->sslServer, DECRYPT_SIDE_ONLY); + ret += SetKeysSide(session->sslClient, ENCRYPT_SIDE_ONLY); + + #ifdef HAVE_SESSION_TICKET + /* derive resumption secret for next session - on finished (from client) */ + ret += DeriveResumptionSecret(session->sslClient, session->sslClient->session.masterSecret); + + /* copy resumption secret to server */ + XMEMCPY(session->sslServer->session.masterSecret, + session->sslClient->session.masterSecret, SECRET_LEN); + #ifdef SHOW_SECRETS + PrintSecret("resumption secret", session->sslClient->session.masterSecret, SECRET_LEN); + #endif + #endif + } + else { + /* finished from server to client */ + ret = SetKeysSide(session->sslServer, ENCRYPT_SIDE_ONLY); + ret += SetKeysSide(session->sslClient, DECRYPT_SIDE_ONLY); + } + + if (ret != 0) { + SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE); + return -1; + } + } +#endif + /* If receiving a finished message from one side, free the resources * from the other side's tracker. */ if (session->flags.side == WOLFSSL_SERVER_END) @@ -2692,6 +3409,7 @@ static int DoHandShake(const byte* input, int* sslBytes, int size; int ret = 0; int startBytes; + WOLFSSL* ssl; if (*sslBytes < HANDSHAKE_HEADER_SZ) { SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE); @@ -2710,14 +3428,34 @@ static int DoHandShake(const byte* input, int* sslBytes, return ret; } - /* A session's arrays are released when the handshake is completed. */ - if (session->sslServer->arrays == NULL && - session->sslClient->arrays == NULL) { + if (session->flags.side == WOLFSSL_SERVER_END) + ssl = session->sslServer; + else + ssl = session->sslClient; - SetError(NO_SECURE_RENEGOTIATION, error, session, FATAL_ERROR_STATE); - return -1; +#ifdef HAVE_SECURE_RENEGOTIATION + if (!IsAtLeastTLSv1_3(ssl->version)) { + /* A session's arrays are released when the handshake is completed. */ + if (session->sslServer->arrays == NULL && + session->sslClient->arrays == NULL) { + + SetError(NO_SECURE_RENEGOTIATION, error, session, FATAL_ERROR_STATE); + return -1; + } } +#endif +#ifdef WOLFSSL_TLS13 + if (type != client_hello) { + /* For resumption the hash is before / after client_hello PSK binder */ + /* hash the packet including header */ + /* TLS v1.3 requires the hash for the handshake and transfer key derivation */ + /* we hash even for non TLS v1.3, since we don't know if its actually + TLS v1.3 till later at EXT_SUPPORTED_VERSIONS in server_hello */ + HashRaw(session->sslServer, input - HANDSHAKE_HEADER_SZ, size + HANDSHAKE_HEADER_SZ); + HashRaw(session->sslClient, input - HANDSHAKE_HEADER_SZ, size + HANDSHAKE_HEADER_SZ); + } +#endif #ifdef HAVE_EXTENDED_MASTER if (session->hash) { if (HashUpdate(session->hash, input, size) != 0) { @@ -2755,6 +3493,10 @@ static int DoHandShake(const byte* input, int* sslBytes, SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE); ret = -1; break; + case encrypted_extensions: + Trace(GOT_ENC_EXT_STR); + ssl->msgsReceived.got_encrypted_extensions = 1; + break; case certificate: Trace(GOT_CERT_STR); if (session->flags.side == WOLFSSL_SERVER_END) { @@ -2824,7 +3566,7 @@ static int DoHandShake(const byte* input, int* sslBytes, /* Decrypt input into plain output, 0 on success */ -static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) +static int Decrypt(WOLFSSL* ssl, byte* output, const byte* input, word32 sz) { int ret = 0; @@ -2881,7 +3623,6 @@ static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) { /* scratch buffer, sniffer ignores auth tag*/ byte authTag[WOLFSSL_MIN_AUTH_TAG_SZ]; - byte nonce[AESGCM_NONCE_SZ]; XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ); XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); @@ -2903,7 +3644,7 @@ static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) ret = -1; } break; - #endif + #endif #ifdef HAVE_NULL_CIPHER case wolfssl_cipher_null: @@ -2922,19 +3663,28 @@ static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) /* Decrypt input message into output, adjust output steam if needed */ -static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz, - byte* output, int* error, int* advance) +static const byte* DecryptMessage(WOLFSSL* ssl, const byte* input, word32 sz, + byte* output, int* error, int* advance, RecordLayerHeader* rh) { int ivExtra = 0; - - int ret = Decrypt(ssl, output, input, sz); + int ret; + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { + ret = DecryptTls13(ssl, output, input, sz, (byte*)rh, RECORD_HEADER_SZ); + } + else +#endif + { + ret = Decrypt(ssl, output, input, sz); + } if (ret != 0) { *error = ret; return NULL; } ssl->keys.encryptSz = sz; if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) { - output += ssl->specs.block_size; /* go past TLSv1.1 IV */ + output += ssl->specs.block_size; /* go past TLSv1.1 IV */ ivExtra = ssl->specs.block_size; *advance = ssl->specs.block_size; } @@ -2949,6 +3699,21 @@ static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz, if (ssl->specs.cipher_type == block) ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1; +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { + word16 i = (word16)(sz - ssl->keys.padSz); + /* Remove padding from end of plain text. */ + for (--i; i > 0; i--) { + if (output[i] != 0) + break; + } + /* Get the real content type from the end of the data. */ + rh->type = output[i]; + ssl->keys.padSz = sz - i; + } +#endif + (void)rh; + return output; } @@ -3066,15 +3831,15 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, return 0; } - session->sslServer = SSL_new(session->context->ctx); + session->sslServer = wolfSSL_new(session->context->ctx); if (session->sslServer == NULL) { SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE); XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); return 0; } - session->sslClient = SSL_new(session->context->ctx); + session->sslClient = wolfSSL_new(session->context->ctx); if (session->sslClient == NULL) { - SSL_free(session->sslServer); + wolfSSL_free(session->sslServer); session->sslServer = 0; SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE); @@ -3433,12 +4198,12 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, static int AddFinCapture(SnifferSession* session, word32 sequence) { if (session->flags.side == WOLFSSL_SERVER_END) { - if (session->finCaputre.cliCounted == 0) - session->finCaputre.cliFinSeq = sequence; + if (session->finCapture.cliCounted == 0) + session->finCapture.cliFinSeq = sequence; } else { - if (session->finCaputre.srvCounted == 0) - session->finCaputre.srvFinSeq = sequence; + if (session->finCapture.srvCounted == 0) + session->finCapture.srvFinSeq = sequence; } return 1; } @@ -3574,7 +4339,7 @@ static int FindNextRecordInAssembly(SnifferSession* session, word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ? &session->cliReassemblyMemory : &session->srvReassemblyMemory; - SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ? + WOLFSSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ? session->sslServer : session->sslClient; ProtocolVersion pv = ssl->version; @@ -3755,7 +4520,7 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, void* vChain, word32 chainSz, char* error) { word32 length; - SSL* ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ? + WOLFSSL* ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ? (*session)->sslServer : (*session)->sslClient; byte skipPartial = ((*session)->flags.side == WOLFSSL_SERVER_END) ? (*session)->flags.srvSkipPartial : @@ -3894,16 +4659,16 @@ static int HaveMoreInput(SnifferSession* session, const byte** sslFrame, word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ? &session->cliExpected : &session->srvExpected; /* buffer is on receiving end */ - word32* length = (session->flags.side == WOLFSSL_SERVER_END) ? + word32* length = (session->flags.side == WOLFSSL_SERVER_END) ? &session->sslServer->buffers.inputBuffer.length : &session->sslClient->buffers.inputBuffer.length; byte** myBuffer = (session->flags.side == WOLFSSL_SERVER_END) ? &session->sslServer->buffers.inputBuffer.buffer : &session->sslClient->buffers.inputBuffer.buffer; - word32* bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ? + word32* bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ? &session->sslServer->buffers.inputBuffer.bufferSize : &session->sslClient->buffers.inputBuffer.bufferSize; - SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ? + WOLFSSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ? session->sslServer : session->sslClient; word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ? &session->cliReassemblyMemory : &session->srvReassemblyMemory; @@ -3965,8 +4730,8 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session, int decoded = 0; /* bytes stored for user in data */ int notEnough; /* notEnough bytes yet flag */ int decrypted = 0; /* was current msg decrypted */ - SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ? - session->sslServer : session->sslClient; + WOLFSSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ? + session->sslServer : session->sslClient; doMessage: notEnough = 0; if (sslBytes < 0) { @@ -4022,7 +4787,7 @@ doMessage: } sslFrame = DecryptMessage(ssl, sslFrame, rhSize, ssl->buffers.outputBuffer.buffer, &errCode, - &ivAdvance); + &ivAdvance, &rh); recordEnd = sslFrame - ivAdvance + rhSize; /* sslFrame moved so should recordEnd */ decrypted = 1; @@ -4207,21 +4972,21 @@ static int CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, SnifferSession* session) { int ret = 0; - if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <= + if (session->finCapture.cliFinSeq && session->finCapture.cliFinSeq <= session->cliExpected) { - if (session->finCaputre.cliCounted == 0) { + if (session->finCapture.cliCounted == 0) { session->flags.finCount += 1; - session->finCaputre.cliCounted = 1; - TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected); + session->finCapture.cliCounted = 1; + TraceClientFin(session->finCapture.cliFinSeq, session->cliExpected); } } - if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <= + if (session->finCapture.srvFinSeq && session->finCapture.srvFinSeq <= session->srvExpected) { - if (session->finCaputre.srvCounted == 0) { + if (session->finCapture.srvCounted == 0) { session->flags.finCount += 1; - session->finCaputre.srvCounted = 1; - TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected); + session->finCapture.srvCounted = 1; + TraceServerFin(session->finCapture.srvFinSeq, session->srvExpected); } } diff --git a/src/ssl.c b/src/ssl.c index 2a2ab77865..9d1f69c1d4 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2025,7 +2025,7 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) #ifdef WOLFSSL_SCTP if (ssl->options.dtlsSctp) #endif -#if defined(WOLLSSL_SCTP) || defined(WOLFSSL_DTLS_MTU) +#if defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU) ssl->dtls_expected_rx = max(ssl->dtls_expected_rx, ssl->dtlsMtuSz); #endif } @@ -17388,9 +17388,39 @@ WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len) return newX509; } + +int wolfSSL_X509_get_isCA(WOLFSSL_X509* x509) +{ + int isCA = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_isCA"); + + if (x509 != NULL) + isCA = x509->isCa; + + WOLFSSL_LEAVE("wolfSSL_X509_get_isCA", isCA); + + return isCA; +} #endif /* KEEP_PEER_CERT || SESSION_CERTS || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* returns the number of entries in the WOLFSSL_X509_NAME */ +int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME* name) +{ + int count = 0; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_entry_count"); + + if (name != NULL) + count = name->entrySz; + + WOLFSSL_LEAVE("wolfSSL_X509_NAME_entry_count", count); + return count; +} +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + #if defined(OPENSSL_ALL) || defined(KEEP_OUR_CERT) || defined(KEEP_PEER_CERT) || \ @@ -17416,20 +17446,6 @@ WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len) return ret; } - int wolfSSL_X509_get_isCA(WOLFSSL_X509* x509) - { - int isCA = 0; - - WOLFSSL_ENTER("wolfSSL_X509_get_isCA"); - - if (x509 != NULL) - isCA = x509->isCa; - - WOLFSSL_LEAVE("wolfSSL_X509_get_isCA", isCA); - - return isCA; - } - int wolfSSL_X509_get_signature(WOLFSSL_X509* x509, unsigned char* buf, int* bufSz) { @@ -20264,21 +20280,6 @@ int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b) return id; } - - - /* returns the number of entries in the WOLFSSL_X509_NAME */ - int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME* name) - { - int count = 0; - - WOLFSSL_ENTER("wolfSSL_X509_NAME_entry_count"); - - if (name != NULL) - count = name->entrySz; - - WOLFSSL_LEAVE("wolfSSL_X509_NAME_entry_count", count); - return count; - } #endif /* !NO_CERTS && OPENSSL_EXTRA */ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ @@ -24958,9 +24959,9 @@ long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg) #endif /* HAVE_PK_CALLBACKS */ #if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) -const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *sess, unsigned int *sid_ctx_length) +const unsigned char *SSL_SESSION_get0_id_context(const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length) { - const byte *c = wolfSSL_SESSION_get_id((SSL_SESSION *)sess, sid_ctx_length); + const byte *c = wolfSSL_SESSION_get_id((WOLFSSL_SESSION *)sess, sid_ctx_length); return c; } #endif @@ -28686,21 +28687,21 @@ int SetDhInternal(WOLFSSL_DH* dh) int ret = WOLFSSL_FATAL_ERROR; int pSz = 1024; int gSz = 1024; -#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +#ifdef WOLFSSL_DH_EXTRA int privSz = 256; /* Up to 2048-bit */ int pubSz = 256; #endif #ifdef WOLFSSL_SMALL_STACK unsigned char* p = NULL; unsigned char* g = NULL; - #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + #ifdef WOLFSSL_DH_EXTRA unsigned char* priv_key = NULL; unsigned char* pub_key = NULL; #endif #else unsigned char p[1024]; unsigned char g[1024]; - #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + #ifdef WOLFSSL_DH_EXTRA unsigned char priv_key[256]; unsigned char pub_key[256]; #endif @@ -28714,21 +28715,22 @@ int SetDhInternal(WOLFSSL_DH* dh) WOLFSSL_MSG("Bad p internal size"); else if (wolfSSL_BN_bn2bin(dh->g, NULL) > gSz) WOLFSSL_MSG("Bad g internal size"); - #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +#ifdef WOLFSSL_DH_EXTRA else if (wolfSSL_BN_bn2bin(dh->priv_key, NULL) > privSz) WOLFSSL_MSG("Bad private key internal size"); else if (wolfSSL_BN_bn2bin(dh->pub_key, NULL) > privSz) WOLFSSL_MSG("Bad public key internal size"); - #endif +#endif else { #ifdef WOLFSSL_SMALL_STACK p = (unsigned char*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); g = (unsigned char*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - - #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) - priv_key = (unsigned char*)XMALLOC(privSz,NULL,DYNAMIC_TYPE_PRIVATE_KEY); - pub_key = (unsigned char*)XMALLOC(pubSz,NULL,DYNAMIC_TYPE_PUBLIC_KEY); - #endif + #ifdef WOLFSSL_DH_EXTRA + priv_key = (unsigned char*)XMALLOC(privSz, NULL, + DYNAMIC_TYPE_PRIVATE_KEY); + pub_key = (unsigned char*)XMALLOC(pubSz, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + #endif if (p == NULL || g == NULL) { XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); @@ -28737,7 +28739,7 @@ int SetDhInternal(WOLFSSL_DH* dh) } #endif /* WOLFSSL_SMALL_STACK */ - #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + #ifdef WOLFSSL_DH_EXTRA privSz = wolfSSL_BN_bn2bin(dh->priv_key, priv_key); pubSz = wolfSSL_BN_bn2bin(dh->pub_key, pub_key); if (privSz <= 0) { @@ -28747,13 +28749,17 @@ int SetDhInternal(WOLFSSL_DH* dh) WOLFSSL_MSG("No public key size."); } if (privSz > 0 || pubSz > 0) { - ret = wc_DhSetFullKeys((DhKey*)dh->internal,priv_key,privSz, - pub_key,pubSz); - if (ret == WOLFSSL_FAILURE) { + ret = wc_DhImportKeyPair((DhKey*)dh->internal, priv_key, privSz, + pub_key, pubSz); + if (ret == 0) { + ret = WOLFSSL_SUCCESS; + } + else { WOLFSSL_MSG("Failed setting private or public key."); + ret = WOLFSSL_FAILURE; } } - #endif /* WOLFSSL_QT || OPENSSL_ALL */ + #endif /* WOLFSSL_DH_EXTRA */ pSz = wolfSSL_BN_bn2bin(dh->p, p); gSz = wolfSSL_BN_bn2bin(dh->g, g); @@ -28770,14 +28776,13 @@ int SetDhInternal(WOLFSSL_DH* dh) #ifdef WOLFSSL_SMALL_STACK XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + #ifdef WOLFSSL_DH_EXTRA XFREE(priv_key, NULL, DYNAMIC_TYPE_PRIVATE_KEY); XFREE(pub_key, NULL, DYNAMIC_TYPE_PUBLIC_KEY); #endif #endif } - return ret; } @@ -29441,9 +29446,10 @@ int wolfSSL_DH_set0_pqg(WOLFSSL_DH *dh, WOLFSSL_BIGNUM *p, #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ #endif /* NO_DH */ +#endif /* OPENSSL_EXTRA */ - -#ifndef NO_DSA +#if !defined(NO_DSA) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) static void InitwolfSSL_DSA(WOLFSSL_DSA* dsa) { if (dsa) { @@ -29516,12 +29522,6 @@ void wolfSSL_DSA_free(WOLFSSL_DSA* dsa) } } -#endif /* NO_DSA */ -#endif /* OPENSSL_EXTRA */ - -#ifdef OPENSSL_EXTRA - -#ifndef NO_DSA /* wolfSSL -> OpenSSL */ int SetDsaExternal(WOLFSSL_DSA* dsa) { @@ -29564,7 +29564,10 @@ int SetDsaExternal(WOLFSSL_DSA* dsa) return WOLFSSL_SUCCESS; } +#endif /* !NO_DSA && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */ + +#if !defined(NO_DSA) && defined(OPENSSL_EXTRA) /* Openssl -> WolfSSL */ int SetDsaInternal(WOLFSSL_DSA* dsa) { @@ -29620,8 +29623,7 @@ int SetDsaInternal(WOLFSSL_DSA* dsa) return WOLFSSL_SUCCESS; } -#endif /* NO_DSA */ -#endif /* OPENSSL_EXTRA */ +#endif /* !NO_DSA && OPENSSL_EXTRA */ #ifdef OPENSSL_EXTRA @@ -35559,8 +35561,8 @@ int wolfSSL_RSA_set0_key(WOLFSSL_RSA *r, WOLFSSL_BIGNUM *n, WOLFSSL_BIGNUM *e, #endif /* OPENSSL_EXTRA */ #endif /* NO_RSA */ -#ifdef OPENSSL_EXTRA -#ifndef NO_DSA +#if !defined(NO_DSA) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) /* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */ int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* derBuf, int derSz) { @@ -35630,8 +35632,9 @@ int wolfSSL_DSA_LoadDer_ex(WOLFSSL_DSA* dsa, const unsigned char* derBuf, return WOLFSSL_SUCCESS; } -#endif /* !NO_DSA */ +#endif /* !NO_DSA && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */ +#ifdef OPENSSL_EXTRA #ifdef HAVE_ECC /* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */ int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, @@ -36748,9 +36751,16 @@ static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName) int hashType; int sigType = WOLFSSL_FAILURE; + #if !defined(NO_PWDBASED) /* Convert key type and hash algorithm to a signature algorithm */ - if (wolfSSL_EVP_get_hashinfo(md, &hashType, NULL) == WOLFSSL_FAILURE) + if (wolfSSL_EVP_get_hashinfo(md, &hashType, NULL) == WOLFSSL_FAILURE) { return WOLFSSL_FAILURE; + } + #else + (void)md; + WOLFSSL_MSG("Cannot get hashinfo when NO_PWDBASED is defined"); + return WOLFSSL_FAILURE; + #endif /* !defined(NO_PWDBASED) */ if (pkey->type == EVP_PKEY_RSA) { @@ -47743,4 +47753,106 @@ int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey) } #endif /* OPENSSL_EXTRA && !NO_CERTS && WOLFSSL_CERT_GEN && WOLFSSL_CERT_REQ */ +#ifdef WOLFSSL_STATIC_EPHEMERAL +static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo, + const char* key, unsigned int keySz, int format, void* heap) +{ + int ret = 0; + byte* keyBuf = NULL; +#ifndef NO_FILESYSTEM + const char* keyFile = NULL; +#endif + /* allow empty key to free buffer */ + if (staticKE == NULL || (key == NULL && keySz > 0)) { + return BAD_FUNC_ARG; + } + + /* check if just free'ing key */ + if (key == NULL && keySz == 0) { + return 0; + } + +#ifndef NO_FILESYSTEM + /* load file from filesystem */ + if (key && keySz == 0) { + size_t keyBufSz = 0; + keyFile = (const char*)key; + ret = wc_FileLoad(keyFile, &keyBuf, &keyBufSz, heap); + if (ret != 0) { + return ret; + } + keySz = (unsigned int)keyBufSz; + } + else +#endif + { + /* use as key buffer directly */ + keyBuf = (byte*)key; + } + + if (format == WOLFSSL_FILETYPE_PEM) { + #ifdef WOLFSSL_PEM_TO_DER + int keyFormat = 0; + ret = PemToDer(keyBuf, keySz, PRIVATEKEY_TYPE, &staticKE->key, + heap, NULL, &keyFormat); + /* auto detect key type */ + if (ret == 0 && keyAlgo == 0) { + if (keyFormat == ECDSAk) + keyAlgo = WC_PK_TYPE_ECDH; + else + keyAlgo = WC_PK_TYPE_DH; + } + #else + ret = NOT_COMPILED_IN; + #endif + } + else { + ret = AllocDer(&staticKE->key, keySz, PRIVATEKEY_TYPE, heap); + if (ret == 0) { + XMEMCPY(staticKE->key->buffer, keyBuf, keySz); + } + } + staticKE->keyAlgo = keyAlgo; + +#ifndef NO_FILESYSTEM + if (keyFile && keyBuf) { + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return ret; +} + +int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, + const char* key, unsigned int keySz, int format) +{ + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + /* if key is already set free it */ + if (ctx->staticKE.key != NULL) { + FreeDer(&ctx->staticKE.key); + } + + return SetStaticEphemeralKey(&ctx->staticKE, keyAlgo, key, keySz, format, + ctx->heap); +} + +int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo, + const char* key, unsigned int keySz, int format) +{ + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + /* if key is already set and not created by ctx... set free it */ + if (ssl->staticKE.key != NULL && ssl->staticKE.key != ssl->ctx->staticKE.key) { + FreeDer(&ssl->staticKE.key); + } + + return SetStaticEphemeralKey(&ssl->staticKE, keyAlgo, key, keySz, format, + ssl->heap); +} + +#endif /* WOLFSSL_STATIC_EPHEMERAL */ diff --git a/src/tls.c b/src/tls.c index ff410ebf9a..292dfb8718 100644 --- a/src/tls.c +++ b/src/tls.c @@ -3528,14 +3528,19 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, return 0; #endif - /* accept the first good status_type and return */ - ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, + /* TLS 1.3 servers MUST NOT act upon presence or information in + * this extension (RFC 8448 Section 4.4.2.1). + */ + if (!IsAtLeastTLSv1_3(ssl->version)) { + /* accept the first good status_type and return */ + ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, status_type, 0, ssl->heap, ssl->devId); - if (ret != WOLFSSL_SUCCESS) - return ret; /* throw error */ + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ - TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST_V2); - ssl->status_request_v2 = status_type; + TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST_V2); + ssl->status_request_v2 = status_type; + } return 0; } @@ -6621,14 +6626,14 @@ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse) return ret; } - /* Allocate space for the public key. */ + /* Allocate space for the public key */ dataSz = params->p_len; keyData = (byte*)XMALLOC(dataSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (keyData == NULL) { ret = MEMORY_E; goto end; } - /* Allocate space for the private key. */ + /* Allocate space for the private key */ key = (byte*)XMALLOC(keySz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); if (key == NULL) { ret = MEMORY_E; @@ -6642,20 +6647,34 @@ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse) if (ret != 0) goto end; - /* Generate a new key pair. */ - ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, (byte*)key, &keySz, keyData, - &dataSz); -#ifdef WOLFSSL_ASYNC_CRYPT - /* TODO: Make this function non-blocking */ - if (ret == WC_PENDING_E) { - ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); +#if defined(WOLFSSL_STATIC_EPHEMERAL) && defined(WOLFSSL_DH_EXTRA) + if (ssl->staticKE.key && ssl->staticKE.keyAlgo == WC_PK_TYPE_DH) { + DerBuffer* keyDer = ssl->staticKE.key; + word32 idx = 0; + WOLFSSL_MSG("Using static DH key"); + ret = wc_DhKeyDecode(keyDer->buffer, &idx, dhKey, keyDer->length); + if (ret == 0) { + ret = wc_DhExportKeyPair(dhKey, (byte*)key, &keySz, keyData, &dataSz); + } } + else #endif + { + /* Generate a new key pair */ + ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, (byte*)key, &keySz, keyData, + &dataSz); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make this function non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + } if (ret != 0) goto end; if (params->p_len != dataSz) { - /* Pad the front of the key data with zeros. */ + /* Zero pad the front of the public key to match prime "p" size */ XMEMMOVE(keyData + params->p_len - dataSz, keyData, dataSz); XMEMSET(keyData, 0, params->p_len - dataSz); } @@ -6913,13 +6932,26 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) ret = wc_ecc_init_ex(eccKey, ssl->heap, ssl->devId); if (ret != 0) goto end; - ret = wc_ecc_make_key_ex(ssl->rng, keySize, eccKey, curveId); -#ifdef WOLFSSL_ASYNC_CRYPT - /* TODO: Make this function non-blocking */ - if (ret == WC_PENDING_E) { - ret = wc_AsyncWait(ret, &eccKey->asyncDev, WC_ASYNC_FLAG_NONE); + +#ifdef WOLFSSL_STATIC_EPHEMERAL + if (ssl->staticKE.key && ssl->staticKE.keyAlgo == WC_PK_TYPE_ECDH) { + DerBuffer* keyDer = ssl->staticKE.key; + word32 idx = 0; + WOLFSSL_MSG("Using static ECDH key"); + ret = wc_EccPrivateKeyDecode(keyDer->buffer, &idx, eccKey, keyDer->length); } + else #endif + { + /* Generate ephemeral ECC key */ + ret = wc_ecc_make_key_ex(ssl->rng, keySize, eccKey, curveId); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make this function non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &eccKey->asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + } if (ret != 0) goto end; @@ -9120,6 +9152,7 @@ void TLSX_FreeAll(TLSX* list, void* heap) MFL_FREE_ALL(extension->data, heap); break; + case TLSX_EXTENDED_MASTER_SECRET: case TLSX_TRUNCATED_HMAC: /* Nothing to do. */ break; @@ -9235,7 +9268,6 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType, /* extension type + extension data length. */ length += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN; - switch (extension->type) { case TLSX_SERVER_NAME: @@ -9254,6 +9286,7 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType, length += MFL_GET_SIZE(extension->data); break; + case TLSX_EXTENDED_MASTER_SECRET: case TLSX_TRUNCATED_HMAC: /* always empty. */ break; @@ -9404,6 +9437,11 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore, offset += MFL_WRITE((byte*)extension->data, output + offset); break; + case TLSX_EXTENDED_MASTER_SECRET: + WOLFSSL_MSG("Extended Master Secret"); + /* always empty. */ + break; + case TLSX_TRUNCATED_HMAC: WOLFSSL_MSG("Truncated HMAC extension to write"); /* always empty. */ @@ -10294,6 +10332,7 @@ int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word16* pLength) #ifdef WOLFSSL_TLS13 #ifndef NO_CERTS else if (msgType == certificate_request) { + /* Don't send out any extension except those that are turned off. */ XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); #if !defined(WOLFSSL_NO_SIGALG) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); @@ -10388,6 +10427,7 @@ int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset) #ifdef WOLFSSL_TLS13 #ifndef NO_CERTS else if (msgType == certificate_request) { + /* Don't send out any extension except those that are turned off. */ XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); #if !defined(WOLFSSL_NO_SIGALG) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); @@ -10491,6 +10531,7 @@ int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength) #ifdef WOLFSSL_TLS13 case encrypted_extensions: + /* Send out all extension except those that are turned on. */ TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET)); @@ -10501,6 +10542,9 @@ int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength) #ifdef HAVE_CERTIFICATE_STATUS_REQUEST TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); #endif + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2)); + #endif #if defined(HAVE_SECURE_RENEGOTIATION) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO)); #endif @@ -10520,6 +10564,7 @@ int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength) #ifdef WOLFSSL_TLS13 #ifndef NO_CERTS case certificate: + /* Don't send out any extension except those that are turned off. */ XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, @@ -10607,6 +10652,7 @@ int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset #ifdef WOLFSSL_TLS13 case encrypted_extensions: + /* Send out all extension except those that are turned on. */ TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET)); @@ -10617,6 +10663,9 @@ int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset #ifdef HAVE_CERTIFICATE_STATUS_REQUEST TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); #endif + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2)); + #endif #if defined(HAVE_SECURE_RENEGOTIATION) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO)); #endif @@ -10636,6 +10685,8 @@ int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset #ifdef WOLFSSL_TLS13 #ifndef NO_CERTS case certificate: + /* Don't send out any extension except those that are turned + * off. */ XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, diff --git a/src/tls13.c b/src/tls13.c index eef2aa06d6..755a916d1d 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -444,6 +444,9 @@ static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] = static int DeriveBinderKey(WOLFSSL* ssl, byte* key) { WOLFSSL_MSG("Derive Binder Key"); + if (ssl == NULL || ssl->arrays == NULL) { + return BAD_FUNC_ARG; + } return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret, binderKeyLabel, BINDER_KEY_LABEL_SZ, NULL, 0, ssl->specs.mac_algorithm); @@ -467,6 +470,9 @@ static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] = static int DeriveBinderKeyResume(WOLFSSL* ssl, byte* key) { WOLFSSL_MSG("Derive Binder Key - Resumption"); + if (ssl == NULL || ssl->arrays == NULL) { + return BAD_FUNC_ARG; + } return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret, binderKeyResumeLabel, BINDER_KEY_RESUME_LABEL_SZ, NULL, 0, ssl->specs.mac_algorithm); @@ -491,6 +497,9 @@ static int DeriveEarlyTrafficSecret(WOLFSSL* ssl, byte* key) { int ret; WOLFSSL_MSG("Derive Early Traffic Secret"); + if (ssl == NULL || ssl->arrays == NULL) { + return BAD_FUNC_ARG; + } ret = DeriveKey(ssl, key, -1, ssl->arrays->secret, earlyTrafficLabel, EARLY_TRAFFIC_LABEL_SZ, ssl->specs.mac_algorithm, 1); @@ -523,6 +532,9 @@ static int DeriveEarlyExporterSecret(WOLFSSL* ssl, byte* key) { int ret; WOLFSSL_MSG("Derive Early Exporter Secret"); + if (ssl == NULL || ssl->arrays == NULL) { + return BAD_FUNC_ARG; + } ret = DeriveKey(ssl, key, -1, ssl->arrays->secret, earlyExporterLabel, EARLY_EXPORTER_LABEL_SZ, ssl->specs.mac_algorithm, 1); @@ -556,6 +568,9 @@ static int DeriveClientHandshakeSecret(WOLFSSL* ssl, byte* key) { int ret; WOLFSSL_MSG("Derive Client Handshake Secret"); + if (ssl == NULL || ssl->arrays == NULL) { + return BAD_FUNC_ARG; + } ret = DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret, clientHandshakeLabel, CLIENT_HANDSHAKE_LABEL_SZ, ssl->specs.mac_algorithm, 1); @@ -587,6 +602,9 @@ static int DeriveServerHandshakeSecret(WOLFSSL* ssl, byte* key) { int ret; WOLFSSL_MSG("Derive Server Handshake Secret"); + if (ssl == NULL || ssl->arrays == NULL) { + return BAD_FUNC_ARG; + } ret = DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret, serverHandshakeLabel, SERVER_HANDSHAKE_LABEL_SZ, ssl->specs.mac_algorithm, 1); @@ -618,6 +636,9 @@ static int DeriveClientTrafficSecret(WOLFSSL* ssl, byte* key) { int ret; WOLFSSL_MSG("Derive Client Traffic Secret"); + if (ssl == NULL || ssl->arrays == NULL) { + return BAD_FUNC_ARG; + } ret = DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, clientAppLabel, CLIENT_APP_LABEL_SZ, ssl->specs.mac_algorithm, 1); @@ -649,6 +670,9 @@ static int DeriveServerTrafficSecret(WOLFSSL* ssl, byte* key) { int ret; WOLFSSL_MSG("Derive Server Traffic Secret"); + if (ssl == NULL || ssl->arrays == NULL) { + return BAD_FUNC_ARG; + } ret = DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, serverAppLabel, SERVER_APP_LABEL_SZ, ssl->specs.mac_algorithm, 1); @@ -681,6 +705,9 @@ static int DeriveExporterSecret(WOLFSSL* ssl, byte* key) { int ret; WOLFSSL_MSG("Derive Exporter Secret"); + if (ssl == NULL || ssl->arrays == NULL) { + return BAD_FUNC_ARG; + } ret = DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, exporterMasterLabel, EXPORTER_MASTER_LABEL_SZ, ssl->specs.mac_algorithm, 1); @@ -710,9 +737,12 @@ static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] = * key The derived key. * returns 0 on success, otherwise failure. */ -static int DeriveResumptionSecret(WOLFSSL* ssl, byte* key) +int DeriveResumptionSecret(WOLFSSL* ssl, byte* key) { WOLFSSL_MSG("Derive Resumption Secret"); + if (ssl == NULL || ssl->arrays == NULL) { + return BAD_FUNC_ARG; + } return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, resumeMasterLabel, RESUME_MASTER_LABEL_SZ, ssl->specs.mac_algorithm, 1); @@ -761,9 +791,12 @@ static int DeriveTrafficSecret(WOLFSSL* ssl, byte* secret) * * ssl The SSL/TLS object. */ -static int DeriveEarlySecret(WOLFSSL* ssl) +int DeriveEarlySecret(WOLFSSL* ssl) { WOLFSSL_MSG("Derive Early Secret"); + if (ssl == NULL || ssl->arrays == NULL) { + return BAD_FUNC_ARG; + } #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0, ssl->arrays->psk_key, ssl->arrays->psk_keySz, @@ -784,13 +817,14 @@ static const byte derivedLabel[DERIVED_LABEL_SZ + 1] = * * ssl The SSL/TLS object. */ -static int DeriveHandshakeSecret(WOLFSSL* ssl) +int DeriveHandshakeSecret(WOLFSSL* ssl) { byte key[WC_MAX_DIGEST_SIZE]; int ret; - WOLFSSL_MSG("Derive Handshake Secret"); - + if (ssl == NULL || ssl->arrays == NULL) { + return BAD_FUNC_ARG; + } ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret, derivedLabel, DERIVED_LABEL_SZ, NULL, 0, ssl->specs.mac_algorithm); @@ -807,13 +841,14 @@ static int DeriveHandshakeSecret(WOLFSSL* ssl) * * ssl The SSL/TLS object. */ -static int DeriveMasterSecret(WOLFSSL* ssl) +int DeriveMasterSecret(WOLFSSL* ssl) { byte key[WC_MAX_DIGEST_SIZE]; int ret; - WOLFSSL_MSG("Derive Master Secret"); - + if (ssl == NULL || ssl->arrays == NULL) { + return BAD_FUNC_ARG; + } ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->preMasterSecret, derivedLabel, DERIVED_LABEL_SZ, NULL, 0, ssl->specs.mac_algorithm); @@ -838,8 +873,7 @@ static const byte resumptionLabel[RESUMPTION_LABEL_SZ+1] = "resumption"; * secret The derived secret. * returns 0 on success, otherwise failure. */ -static int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, - byte* secret) +int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret) { int digestAlg; /* Only one protocol version defined at this time. */ @@ -894,6 +928,10 @@ static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash, int hashSz = WC_SHA256_DIGEST_SIZE; int ret = BAD_FUNC_ARG; + if (ssl == NULL || key == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + /* Get the hash of the previous handshake messages. */ switch (ssl->specs.mac_algorithm) { #ifndef NO_SHA256 @@ -965,7 +1003,7 @@ static const byte writeIVLabel[WRITE_IV_LABEL_SZ+1] = "iv"; * store ready for provisioning. * returns 0 on success, otherwise failure. */ -static int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store) +int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store) { int ret = BAD_FUNC_ARG; /* Assume failure */ int i = 0; @@ -1321,39 +1359,6 @@ end: #endif /* HAVE_SESSION_TICKET || !NO_PSK */ -#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_SESSION_TICKET) || \ - !defined(NO_PSK)) -/* Add input to all handshake hashes. - * - * ssl The SSL/TLS object. - * input The data to hash. - * sz The size of the data to hash. - * returns 0 on success, otherwise failure. - */ -static int HashInputRaw(WOLFSSL* ssl, const byte* input, int sz) -{ - int ret = BAD_FUNC_ARG; - -#ifndef NO_SHA256 - ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, input, sz); - if (ret != 0) - return ret; -#endif -#ifdef WOLFSSL_SHA384 - ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, input, sz); - if (ret != 0) - return ret; -#endif -#ifdef WOLFSSL_TLS13_SHA512 - ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, input, sz); - if (ret != 0) - return ret; -#endif - - return ret; -} -#endif - /* Extract the handshake header information. * * ssl The SSL/TLS object. @@ -2402,10 +2407,10 @@ static int RestartHandshakeHash(WOLFSSL* ssl) ret = InitHandshakeHashes(ssl); if (ret != 0) return ret; - ret = HashOutputRaw(ssl, header, sizeof(header)); + ret = HashRaw(ssl, header, sizeof(header)); if (ret != 0) return ret; - return HashOutputRaw(ssl, hash, hashSz); + return HashRaw(ssl, hash, hashSz); } /* The value in the random field of a ServerHello to indicate @@ -2578,7 +2583,7 @@ static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) return ret; /* Hash binders to complete the hash of the ClientHello. */ - ret = HashOutputRaw(ssl, output + idx, len); + ret = HashRaw(ssl, output + idx, len); if (ret < 0) return ret; @@ -3197,7 +3202,13 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, ssl->options.sendVerify = SEND_CERT; } else { +#ifndef WOLFSSL_NO_CLIENT_CERT_ERROR ssl->options.sendVerify = SEND_BLANK_CERT; +#else + WOLFSSL_MSG("Certificate required but none set on client"); + SendAlert(ssl, alert_fatal, illegal_parameter); + return NO_CERT_ERROR; +#endif } /* This message is always encrypted so add encryption padding. */ @@ -3456,7 +3467,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, } /* Hash the rest of the ClientHello. */ - ret = HashInputRaw(ssl, input + helloSz - bindersLen, bindersLen); + ret = HashRaw(ssl, input + helloSz - bindersLen, bindersLen); if (ret != 0) return ret; @@ -3624,9 +3635,9 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl); if ((ret = InitHandshakeHashes(ssl)) != 0) return ret; - if ((ret = HashOutputRaw(ssl, header, sizeof(header))) != 0) + if ((ret = HashRaw(ssl, header, sizeof(header))) != 0) return ret; - if ((ret = HashOutputRaw(ssl, cookieData + idx, hashSz)) != 0) + if ((ret = HashRaw(ssl, cookieData + idx, hashSz)) != 0) return ret; /* Reconstruct the HelloRetryMessage for handshake hash. */ @@ -3705,9 +3716,9 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) WOLFSSL_BUFFER(cookieData, cookie->len); #endif - if ((ret = HashOutputRaw(ssl, hrr, hrrIdx)) != 0) + if ((ret = HashRaw(ssl, hrr, hrrIdx)) != 0) return ret; - return HashOutputRaw(ssl, cookieData, cookie->len); + return HashRaw(ssl, cookieData, cookie->len); } #endif @@ -5849,7 +5860,7 @@ exit_dcv: * sniff Indicates whether we are sniffing packets. * returns 0 on success and otherwise failure. */ -static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, +int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, word32 totalSz, int sniff) { int ret; @@ -5888,19 +5899,22 @@ static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, secret = ssl->keys.server_write_MAC_secret; } - else + else { secret = ssl->keys.client_write_MAC_secret; + } - ret = BuildTls13HandshakeHmac(ssl, secret, mac, &finishedSz); - if (ret != 0) - return ret; - if (size != finishedSz) - return BUFFER_ERROR; + if (sniff == NO_SNIFF) { + ret = BuildTls13HandshakeHmac(ssl, secret, mac, &finishedSz); + if (ret != 0) + return ret; + if (size != finishedSz) + return BUFFER_ERROR; + } - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName(ssl, "Finished"); - if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo); - #endif +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "Finished"); + if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo); +#endif if (sniff == NO_SNIFF) { /* Actually check verify data. */ @@ -6349,8 +6363,8 @@ static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input, word32 ageAdd; word16 length; word32 now; - const byte* nonce; - byte nonceLength; + const byte* nonce; + byte nonceLength; WOLFSSL_START(WC_FUNC_NEW_SESSION_TICKET_DO); WOLFSSL_ENTER("DoTls13NewSessionTicket"); @@ -6506,14 +6520,14 @@ static int ExpectedResumptionSecret(WOLFSSL* ssl) #ifdef WOLFSSL_EARLY_DATA if (ssl->earlyData != no_early_data) { static byte endOfEarlyData[] = { 0x05, 0x00, 0x00, 0x00 }; - ret = HashInputRaw(ssl, endOfEarlyData, sizeof(endOfEarlyData)); + ret = HashRaw(ssl, endOfEarlyData, sizeof(endOfEarlyData)); if (ret != 0) return ret; } #endif - if ((ret = HashInputRaw(ssl, header, sizeof(header))) != 0) + if ((ret = HashRaw(ssl, header, sizeof(header))) != 0) return ret; - if ((ret = HashInputRaw(ssl, mac, finishedSz)) != 0) + if ((ret = HashRaw(ssl, mac, finishedSz)) != 0) return ret; if ((ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret)) != 0) diff --git a/sslSniffer/README.md b/sslSniffer/README.md new file mode 100644 index 0000000000..a9c48eecc6 --- /dev/null +++ b/sslSniffer/README.md @@ -0,0 +1,640 @@ +# wolfSSL Sniffer + +The wolfSSL sniffer can be used to passively sniff SSL traffic including https traffic. Of course the server’s private key is required in order to decode the SSL handshake and allow future decryption of SSL messages. Input to the sniffer should be raw packets beginning with the IP header. + +## Installation + +The wolfSSL sniffer requires the wolfSSL library version 1.8.0 or later. Future releases can be obtained from http://www.wolfssl.com + +To build and install wolfSSL including the wolfSSL sniffer: + +```sh +./configure --enable-sniffer +make +sudo make install +``` + + +## Build Options + +The wolfSSL sniffer has several build options to include some extra behavior: SSL Statistics, Session Watching, Store Data Callback, Chain Input, and allowing STARTTLS protocols. + +The SSL Statistics option provides the logging of some additional statistics regarding the sessions being decoded. The statistics tracking uses a mutex to protect access to the tracking storage. To enable this option, use the following configure command line and build as before: + +`./configure --enable-sniffer CPPFLAGS=-DWOLFSSL_SNIFFER_STATS` + +The Session Watching option allows the sniffer to watch any packet provided it without initial setup. It will start to decode all TLS sessions and when the server’s certificate is detected, the certificate is given to a callback function provided by the user which should provide the appropriate private key. To enable this option, use the following configure command line and build as before: + +`./configure --enable-sniffer CPPFLAGS=-DWOLFSSL_SNIFFER_WATCH` + +The Store Data Callback option allows the sniffer to take a callback that is called when storing the application data into a custom buffer rather than into the reallocated data pointer the callback is called in a loop until all data is consumed. To enable this option, use the following configure command line and build as before: + +`./configure --enable-sniffer CPPFLAGS=-DWOLFSSL_SNIFFER_STORE_DATA_CB` + +The Chain Input option allows the sniffer to receive its input as a struct iovec list rather than a pointer to a raw packet. To enable this option, use the following configure command line and build as before: + +`./configure --enable-sniffer CPPFLAGS=-DWOLFSSL_SNIFFER_CHAIN_INPUT` + +The STARTTLS option allows the sniffer to receive and ignore plaintext before receiving the first TLS handshake message. This is useful for protocols like SMTP and POP3 which start out in plaintext and switch to TLS during the connection. To enable this option, use the following configure command line and build as before: + +`./configure --enable-sniffer CPPFLAGS=-DSTARTTLS_ALLOWED` + +All options may be enabled with the following configure command line: + +```sh +./configure --enable-sniffer \ + CPPFLAGS=”-DWOLFSSL_SNIFFER_STATS -DWOLFSSL_SNIFFER_WATCH \ + -DWOLFSSL_SNIFFER_STORE_DATA_CB -DWOLFSSL_SNIFFER_CHAIN_INPUT \ + -DSTARTTLS_ALLOWED” +``` + +To add some other cipher support to the sniffer, you can add options like: + +```sh +--enable-arc4 +--enable-nullcipher +--enable-des3 +``` + +By default, wolfSSL restricts RSA key sizes to 1024-bits minimum. To allow the decoding of smaller, less secure RSA keys like 512-bit keys, you will need to add the compiler flag `-DWOLFSSL_MIN_RSA_BITS=512` to CFLAGS or CPPFLAGS, or define it in your user-settings header. + + +## Synchronous Cryptography Offload Options + +The sniffer can take advantage of some crypto offload hardware if available. If you have an Intel QuickAssist board or a Cavium OCTEON II or III. Currently, only the algorithms AES-CBC, AES-GCM, and DES3-CBC are offloaded to the hardware. These directions assume you already have the QAT or OCTEON-SDK libraries built. + +To build for QAT, use the following configure options: + +```sh +./configure --enable-sniffer --enable-cryptocb \ + --with-intelqa-sync=/path/to/qat +``` + +To build with OCTEON II support for a standalone host: + +```sh +./configure --enable-sniffer --enable-cryptocb \ + --with-octeon-sync=/path/to/octeon-sdk +``` + +To build with OCTEON III support for a Linux host: + +```sh +./configure --enable-sniffer --enable-cryptocb \ + --with-octeon-sync=/path/to/octeon-sdk \ + OCTEON_OBJ=obj-octeon3 OCTEON_HOST=linux +``` + + +## Command Line Options + +The wolfSSL sniffer includes a test application `snifftest` in the `sslSniffer/sslSnifferTest/ directory`. The command line application has several options that can be passed in at runtime to change the default behavior of the application. To execute a “live” sniff just run the application without any parameters and then pick an interface to sniff on followed by the port. + +An example startup may look like this: + +```sh +$ cd sslSniffer/sslSnifferTest +$ ./snifftest + +1. en0 (No description available) +2. fw0 (No description available) +3. en1 (No description available) +4. fw1 (No description available) +5. p2p0 (No description available) +6. en3 (No description available) +7. lo0 (No description available) + +Enter the interface number (1-7): 7 +server = 127.0.0.1 +server = ::1 +server = fe80::1 + +Enter the port to scan: 11111 +``` + +The above example sniffs on the localhost interface (lo0) with the default wolfSSL port of 11111 and uses the default wolfSSL server key `../../certs/server-key.pem` for RSA and `../../certs/ecc-key.pem` for ECC. + +Trace output will be written to a file named `tracefile.txt`. + +To decode a previously saved pcap file you will need to enter a few parameters. + +The following table lists the accepted inputs in saved file mode. + +Synopsis: + +`snifftest dumpFile pemKey [server] [port] [password]` + +`snifftest` Options Summary: + +``` +Option Description Default Value +dumpFile A previously saved pcap file NA +pemKey The server’s private key in PEM format NA +server The server’s IP address (v4 or v6) 127.0.0.1 +port The server port to sniff 443 +password Private Key Password if required NA +``` + +To decode a pcap file named test.pcap with a server key file called myKey.pem that was generated on the localhost with a server at port 443 just use: + +`./snifftest test.pcap myKey.pem` + +If the server was on 10.0.1.2 and on port 12345 you could instead use: + +`./snifftest test.pcap myKey.pem 10.0.1.2 12345` + +If the server was on localhost using IPv6 and on port 12345 you could instead use: + +`./snifftest test.pcap myKey.pem ::1 12345` + + +## API Usage + +The wolfSSL sniffer can be integrated into any application using the existing sniffer API. + +Use the include `#include `. + +### ssl_InitSniffer + +```c +void ssl_InitSniffer(void); +``` + +Initializes the wolfSSL sniffer for use and should be called once per application. + +### ssl_FreeSniffer + +```c +void ssl_FreeSniffer(void); +``` + +Frees all resources consumed by the wolfSSL sniffer and should be called when use of the wolfSSL sniffer is no longer required. + +### ssl_Trace + +```c +int ssl_Trace(const char* traceFile, char* error); +``` + +Enables Tracing when a file is passed in. Disables Tracing if previously on and a NULL value is passed in for the file. + +Returns Values: + +* 0 on success +* -1 if a problem occurred, the string error will hold a message describing the problem + +### ssl_SetPrivateKey + +```c +int ssl_SetPrivateKey(const char* serverAddress, int port, + const char* keyFile, int keyFormat, + const char* password, char* error); +``` + +Creates a sniffer session based on the `serverAddress` and `port` inputs using the ECC or RSA `keyFile` as the server’s key. + +The `keyFormat` can be either `FILETYPE_PEM` or `FILETYPE_DER`. If the keyFile has password protection then the password parameter can hold the proper value. + +Return Values: + +* 0 on success +* -1 if a problem occurred, the string error will hold a message describing the problem + +### ssl_SetPrivateKeyBuffer + +```c +int ssl_SetPrivateKeyBuffer(const char* address, int port, + const char* keyBuf, int keySz, int typeKey, + const char* password, char* error) +``` + +Creates a sniffer session based on the `serverAddress` and `port` inputs using the ECC or RSA `keyBuf` and `keySz` as the server’s key. + +The `keyFormat` can be either `FILETYPE_PEM` or `FILETYPE_DER`. If the keyFile has password protection then the password parameter can hold the proper value. + +Return Values: + +* 0 on success +* -1 if a problem occurred, the string error will hold a message describing the problem + + +### ssl_SetNamedPrivateKey + +```c +int ssl_SetNamedPrivateKey(const char* name, + const char* serverAddress, int port, + const char* keyFile, int keyFormat, + const char* password, char* error); +``` + +Creates a sniffer session for a server named `name` based on the `serverAddress` and `port` inputs using the ECC or RSA `keyFile` as the server’s key. + +The `keyFormat` can be either `FILETYPE_PEM` or `FILETYPE_DER`. If the keyFile has password protection then the password parameter can hold the proper value. + +This function requires that the SNI extension is enabled in the build (`HAVE_SNI`). + +Return Values: + +* 0 on success +* -1 if a problem occurred, the string error will hold a message describing the problem + +### ssl_SetNamedPrivateKeyBuffer + +```c +int ssl_SetNamedPrivateKeyBuffer(const char* name, + const char* address, int port, + const char* keyBuf, int keySz, int typeKey, + const char* password, char* error) +``` + +Creates a sniffer session for a server named `name` based on the `serverAddress` and `port` inputs using the ECC or RSA `keyBuf` and `keySz` as the server’s key. + +The `keyFormat` can be either `FILETYPE_PEM` or `FILETYPE_DER`. If the keyFile has password protection then the password parameter can hold the proper value. + +This function requires that the SNI extension is enabled in the build (`HAVE_SNI`). + +Return Values: + +* 0 on success +* -1 if a problem occurred, the string error will hold a message describing the problem + +### ssl_SetNamedEphemeralKey + +```c +int ssl_SetNamedEphemeralKey(const char* name, + const char* address, int port, + const char* keyFile, int typeKey, + const char* password, char* error) +``` + +Creates a sniffer session for a server named `name` based on the `serverAddress` and `port` inputs using ECC or DH static ephemeral key. + +The `keyFormat` can be either `FILETYPE_PEM` or `FILETYPE_DER`. If the keyFile has password protection then the password parameter can hold the proper value. + +This function requires that static ephemeral key support (`WOLFSSL_STATIC_EPHEMERAL`) and the SNI extension (`HAVE_SNI`) are enabled in the build. + +Return Values: + +* 0 on success +* -1 if a problem occurred, the string error will hold a message describing the problem + +### ssl_SetEphemeralKey + +```c +int ssl_SetEphemeralKey(const char* address, int port, + const char* keyFile, int typeKey, + const char* password, char* error) +``` +Creates a sniffer session based on the `serverAddress` and `port` inputs using ECC or DH static ephemeral key. + +The `keyFormat` can be either `FILETYPE_PEM` or `FILETYPE_DER`. If the keyFile has password protection then the password parameter can hold the proper value. + +This function requires that static ephemeral key support (`WOLFSSL_STATIC_EPHEMERAL`) and the SNI extension (`HAVE_SNI`) are enabled in the build. + +Return Values: + +* 0 on success +* -1 if a problem occurred, the string error will hold a message describing the problem + +### ssl_DecodePacket + +```c +int ssl_DecodePacket(const unsigned char** packet, int length, + unsigned char* data, char* error); +``` + +### ssl_DecodePacketWithSessionInfo + +```c +int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length, + unsigned char** data, SSLInfo* sslInfo, char* error); +``` + +Decodes a raw packet that begins with the IP header and is length bytes long. Any SSL application data will be stored in data which should be at least 16,384 bytes, the maximum SSL record size. Information about the SSL session will be copied into `sslInfo` if it is non-null. + +The `SSLInfo` structure can be found in `sniffer.h`. It has information about the protocol version, cipher suite, server name indication, and key size in bits. + +```c +typedef struct SSLInfo +{ + unsigned char isValid; /* indicates if the info in this struct is valid: 0 = no, 1 = yes */ + unsigned char protocolVersionMajor; /* SSL Version: major */ + unsigned char protocolVersionMinor; /* SSL Version: minor */ + unsigned char serverCipherSuite0; /* first byte, normally 0 */ + unsigned char serverCipherSuite; /* second byte, actual suite */ + unsigned char serverCipherSuiteName[256]; /* cipher name, e.g., "TLS_RSA_..." */ + unsigned char serverNameIndication[128]; + unsigned int keySize; +} SSLInfo; +``` + +Return Values: + +* >0 on success and indicates the number of bytes written to data +* 0 indicates no SSL data is ready yet +* -1 if a problem occurred, the string error will hold a message describing the problem + + +### ssl_SetConnectionCb + +```c +int ssl_SetConnectionCb(SSLConnCb cb); +``` + +Sets a callback function that will be called when the full session information is known and will provide a pointer to the session’s information. The callback function has the signature: + +```c +typedef void (*SSLConnCb)(const void* session, SSLInfo* info, void* ctx); +``` + +Where session is the current session. info will be a pointer to the session’s info. The ctx is application specific context data passed to the callback. + +Return Values: + +* >0 on success and indicates the number of bytes written to data +* 0 indicates no SSL data is ready yet +* -1 if a problem occurred, the string error will hold a message describing the problem + +### ssl_SetConnectionCtx + +```c +int ssl_SetConnectionCtx(void* ctx); +``` + +Stores ctx, a pointer to application specific context data that will be passed to the connection callback function. The wolfSSL sniffer will not know anything about the context data. + +Return Values: + +* 0 on success +* -1 if a problem occurred + + +## API Usage: SSL Statistics options + +For an example on the use of the sniffer stats option, search the source `snifftest.c` for `WOLFSSL_SNIFFER_STATS`. + +See the header file `sniffer.h` for the structure `SSLStats` for the list of statistics that can be read. + +```c +typedef struct SSLStats +{ + unsigned long int sslStandardConns; + unsigned long int sslClientAuthConns; + unsigned long int sslResumedConns; + unsigned long int sslEphemeralMisses; + unsigned long int sslResumeMisses; + unsigned long int sslCiphersUnsupported; + unsigned long int sslKeysUnmatched; + unsigned long int sslKeyFails; + unsigned long int sslDecodeFails; + unsigned long int sslAlerts; + unsigned long int sslDecryptedBytes; + unsigned long int sslEncryptedBytes; + unsigned long int sslEncryptedPackets; + unsigned long int sslDecryptedPackets; + unsigned long int sslKeyMatches; + unsigned long int sslEncryptedConns; + + unsigned long int sslResumptionValid; + unsigned long int sslResumptionInserts; +} SSLStats; +``` + +### ssl_ResetStatistics + +```c +int ssl_ResetStatistics(void); +``` + +Zeroes out the SSL sniffer statistics tracking storage. + +Return Values: + +* 0 on success +* -1 if a problem occurred + +### ssl_ReadStatistics + +```c +int ssl_ReadStatistics(SSLStats* stats); +``` + +Copies the SSL sniffer statistics into the provided `SSLStats` record, stats. + +Return Values: + +* 0 on success +* -1 if a problem occurred + +### ssl_ReadResetStatistics + +```c +int ssl_ReadResetStatistics(SSLStats* stats); +``` + +Copies the SSL sniffer statistics into the provided `SSLStats` records, stats, and then zeroes out the SSL sniffer statistics tracking storage in one action. + +Return Values: + +* 0 on success +* -1 if a problem occurred + + +## API Usage: Session Watching option + +For an example on the use of the session watching option, search the source `snifftest.c` for `WOLFSSL_SNIFFER_WATCH`. + +### ssl_SetWatchKeyCallback + +```c +int ssl_SetWatchKeyCallback(SSLWatchCb cb, char* error); +int ssl_SetWatchKeyCallback_ex(SSLWatchCb cb, int devId, char* error); +``` + +Assigns a callback function to the wolfSSL sniffer used to locate and load a private key for a session at the time the sniffer knows the true identity of the server, when receiving its certificate message. The callback function is given to the parameter cb and any error string will be written into error. The function ssl_SetWatchKeyCallback_ex() takes an additional parameter called devId, the device ID of the hardware device handling the cryptography. The callback function has the signature: + +```c +typedef int (*SSLWatchCb)(void* vSniffer, + const unsigned char* certHash, unsigned int certHashSz, + const unsigned char* certChain, unsigned int certChainSz, + void* ctx, char* error); +``` + +The parameter `vSniffer` is a typeless pointer to the current sniffer session and is meant to be passed directly to the function `ssl_SetWatchKey`. `certHash` is a SHA-256 hash of the certificate sent by the server, and its size is `certHashSz`. A pointer to certificate message’s payload is provided in the parameter `certChain`, and the certificate chain’s size in `certChainSz`. This will be a list of pairs of 24-bit certificate sizes and raw DER certificates in network order from the wire. The application space callback context data is provided in parameter ctx and is set by the function `ssl_SetWatchKeyCtx`. Any error string is copied into parameter error. Your callback function can use these values to locate the appropriate private key and load it into the sniffer session with the function `ssl_SetWatchKey`. + +Return Values: + +* 0 on success +* -1 if a problem occurred, the string error will hold a message describing the problem + +### ssl_SetWatchKeyCtx + +```c +int ssl_SetWatchKeyCtx(void* ctx, char* error); +``` + +Stores ctx, a pointer to application specific context data that will be passed to the watch key callback function. The wolfSSL sniffer will not know anything about the context data. + +Return Values: + +* 0 on success +* -1 if a problem occurred, the string error will hold a message describing the problem + +### ssl_SetWatchKey_file + +```c +int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType, + const char* password, char* error); +``` + +This function must be called from the watch key callback. Gives the sniffer session, vSniffer, the private key to be used to decrypt the pre-master secret. The key’s file name is given in the parameter keyFile, and that file will be loaded. The keyType is either `FILETYPE_PEM` or `FILETYPE_DER`. If the private key is encrypted, provide the text string password. Any error string is returned in error. + +Return Values: + +* 0 on success +* -1 if a problem occurred, the string error will hold a message describing the problem + +### ssl_SetWatchKey_buffer + +```c +int ssl_SetWatchKey_buffer(void* vSniffer, const unsigned char* key, + unsigned int keySz, int keyType, char* error); +``` + +This function must be called from the watch key callback. Gives the sniffer session, vSniffer, the private key to be used to decrypt the pre-master secret. The key is passed in by the pointer key, and is of size keySz. The keyType is either `FILETYPE_PEM` or `FILETYPE_DER`. Any error string is returned in error. + +Return Values: + +* 0 on success +* -1 if a problem occurred, the string error will hold a message describing the problem + + +## API Usage: Store Data Callback option + +For an example on the use of the store data callback option, search the source `snifftest.c` for `WOLFSSL_SNIFFER_STORE_DATA_CB`. + +### ssl_SetStoreDataCallback + +```c +int ssl_SetStoreDataCallback(SSLStoreDataCb cb); +``` + +Assigns a callback function to the wolfSSL sniffer used to store data when processing an application data record. The callback function is given to the parameter cb. + +The callback function has the signature: + +```c +typedef int (*SSLStoreDataCb)(const unsigned char* decryptBuf, + unsigned int decryptBufSz, unsigned int decryptBufOffset, + void* ctx); +``` + +The parameter `decryptBuf` is a pointer to the beginning of the decrypted application data buffer. The value `decryptBufSz` is the number of bytes stored in the `decryptBuf`. `decryptBufOffset` is the offset into the `decryptBuf` where a copy should start. The `ctx` is an application specific parameter passed in the call to `ssl_DecodePacketWithSessionInfoStoreData()`. The callback should return the number of bytes copied out of `decryptBuf`. `decryptBufOffset` is a running sum of the bytes returned by the callback, and the loop stops when all bytes are consumed. + +Return Values: + +* 0 on success +* -1 if a problem occurred + +### ssl_DecodePacketWithSessionInfoStoreData + +```c +int ssl_DecodePacketWithSessionInfoStoreData(const unsigned char* packet, + in1t length, void* ctx, SSLInfo* sslInfo, char* error); +``` + +Decodes a raw packet that begins with the IP header and is length bytes long. Any SSL application data will be handed to the store data callback function, along with the parameter `ctx`. Information about the SSL session will be copied into `sslInfo` if it is non-null. + +The SSLInfo structure can be found in sniffer.h. It has information about the protocol version, cipher suite, server name indication, and key size in bits. + +Return Values: + +* >0 on success and indicates the number of bytes written by the store data callback +* 0 indicates no SSL data is ready yet +* -1 if a problem occurred, the string error will hold a message describing the problem + + +## API Usage: Chain Input option + +For an example on the use of the chain input option, search the source `snifftest.c` for `WOLFSSL_SNIFFER_CHAIN_INPUT`. + +### ssl_DecodePacketWithChain + +```c +int ssl_DecodePacketWithChain(void* vChain, unsigned int chainSz, + unsigned char** data, char* error); +``` + +Decodes a raw chain of packet buffers stored in an iovec passed in as the value vChain. The first buffer in the chain begins with the IP header. The chain is chainSz packets long. Any SSL application data will be stored in data, which may be allocated by the sniffer. Information about the SSL session will be copied into sslInfo if it is non-null. + +The SSLInfo structure can be found in sniffer.h. It has information about the protocol version, cipher suite, server name indication, and key size in bits. + +Return Values: + +* >0 on success and indicates the number of bytes written by the store data callback +* 0 indicates no SSL data is ready yet +* -1 if a problem occurred, the string error will hold a message describing the problem + +### ssl_DecodePacketWithChainSessionInfoStoreData + +```c +int ssl_DecodePacketWithChainSessionInfoStoreData(void* vChain, + unsigned int chainSz, void* ctx, SSLInfo* sslInfo, char* error); +``` + +This combines the options of decoding a chain input and storing data using a callback. Decodes a raw chain of packet buffers stored in an iovec passed in as the value vChain. The first buffer in the chain begins with the IP header. The chain is chainSz packets long. Any SSL application data will be handed to the store data callback function, along with the parameter ctx. Information about the SSL session will be copied into sslInfo if it is non-null. + +The SSLInfo structure can be found in sniffer.h. It has information about the protocol version, cipher suite, server name indication, and key size in bits. + +Return Values: + +* >0 on success and indicates the number of bytes written by the store data callback +* 0 indicates no SSL data is ready yet +* -1 if a problem occurred, the string error will hold a message describing the problem + + +## Notes + +### Performance + +Once your SSL sniffing is working as expected you should be able to get some performance gains by compiling wolfSSL with fastmath enabled. You can do this by adding `--enable-fastmath` to your ./configure options. + +### Start up + +Remember to always start the sniffing application before the server. This is important because if the SSL handshake is missed then future packets from that session will not be decoded. In addition, any future sessions that use the “missed” session to do session resumption, renegotiation, or use session tickets based on that “missed” session will have the same problems. + +### Cipher Suite Limitations + +As a passive sniffer the wolfSSL sniffer will not be able to decode any SSL session that uses DHE (Ephemeral Diffie-Hellman) because it will not have access to the temporary key that the server generates. You may need to disable DHE cipher suites on the server and/or client to prevent these cipher suites from being used. + +### Thread Safety + +Access to the sniffer session table is thread safe. What is not thread safe, is using the same sniffer session from multiple threads. For example, say sniffer session A is created by thread X. If 3 new packets come in for session A and threads X, Y, and Z all try to handle those packets concurrently that's a problem. Ideally, the main thread would associate an ssl sniffer session (client ip/client port <-> server ip/server port) with a particular thread and use that same thread for the lifetime of the session. Short of that, the sniffer session would need a lock which isn't ideal in a multithreaded scenario because once thread X locks the first packet from session A threads Y and Z would be blocked until thread X is done. That defeats the whole purpose doing multithreaded sniffing. + +### Server Name Indication + +Some webservers use virtual domain name mapping where multiple servers using separate SSL keys and certificates are sharing the same IP address and port. The Server Name Indication client hello extension allows the SSL client to specify the name of the server it is connecting to. When running the configure command in section 2.1, add the option --enable-sni. + +### STARTTLS + +Many protocols use ssl as a layer between them and the network layer, and have a dedicated port for the secure connection. Other protocols start out on their classic well known port number in the clear and then offer the “STARTTLS” command which tells the server the client wants to use ssl. The server responds with an affirmation, and the client sends its TLS client hello message and starts negotiation. The sniffer can ignore non-TLS messages on a session until the client starts to negotiate TLS and then proceed as normal. + + +## Missing Features + +### PSK + +While wolfSSL supports Pre Shared Keys, the current version of the sniffer does not. + +### Client Certificate URLs + +Neither wolfSSL nor the sniffer current supports the TLS extension Client Certificate URLs. + +### Secure Renegotiation + +While wolfSSL supports secure renegotiation, the current version of the sniffer does not. The sniffer does support session resumption. + + +## Support + +For issues or questions please email support@wolfssl.com. diff --git a/sslSniffer/sslSnifferTest/include.am b/sslSniffer/sslSnifferTest/include.am index 23de07f914..56ce4f81f4 100644 --- a/sslSniffer/sslSnifferTest/include.am +++ b/sslSniffer/sslSnifferTest/include.am @@ -8,6 +8,7 @@ sslSniffer_sslSnifferTest_snifftest_SOURCES = sslSniffer/sslSnifferTest/snifftes sslSniffer_sslSnifferTest_snifftest_LDADD = src/libwolfssl.la -lpcap $(LIB_STATIC_ADD) sslSniffer_sslSnifferTest_snifftest_DEPENDENCIES = src/libwolfssl.la endif +EXTRA_DIST += sslSniffer/README.md EXTRA_DIST += sslSniffer/sslSniffer.vcproj EXTRA_DIST += sslSniffer/sslSniffer.vcxproj EXTRA_DIST += sslSniffer/sslSnifferTest/sslSniffTest.vcproj diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index f8873962b9..2330f693a4 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/sslSniffer/sslSnifferTest/snifftest.c @@ -25,6 +25,8 @@ #endif #include +#include +#include #ifdef WOLFSSL_SNIFFER_STORE_DATA_CB #include @@ -49,8 +51,8 @@ int main(void) /* do a full build */ #ifdef _MSC_VER - /* builds on *nix too, for scanf device and port */ - #define _CRT_SECURE_NO_WARNINGS + /* builds on *nix too, for scanf device and port */ + #define _CRT_SECURE_NO_WARNINGS #endif #include /* pcap stuff */ @@ -96,6 +98,44 @@ enum { #endif +#define DEFAULT_SERVER_EPH_KEY_ECC "../../certs/statickeys/ecc-secp256r1.pem" +#define DEFAULT_SERVER_EPH_KEY_DH "../../certs/statickeys/dh-ffdhe2048.pem" +#ifndef DEFAULT_SERVER_EPH_KEY + #if defined(HAVE_ECC) && !defined(NO_ECC_SECP) && \ + (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) + #define DEFAULT_SERVER_EPH_KEY DEFAULT_SERVER_EPH_KEY_ECC + #elif !defined(NO_DH) + #define DEFAULT_SERVER_EPH_KEY DEFAULT_SERVER_EPH_KEY_DH + #endif +#endif + +#define DEFAULT_SERVER_KEY_RSA "../../certs/server-key.pem" +#define DEFAULT_SERVER_KEY_ECC "../../certs/ecc-key.pem" +#ifndef DEFAULT_SERVER_KEY + #ifndef NO_RSA + #define DEFAULT_SERVER_KEY DEFAULT_SERVER_KEY_RSA + #elif defined(HAVE_ECC) + #define DEFAULT_SERVER_KEY DEFAULT_SERVER_KEY_ECC + #endif +#endif + + +#ifdef WOLFSSL_SNIFFER_WATCH +static const byte rsaHash[] = { + 0x4e, 0xa8, 0x55, 0x02, 0xe1, 0x84, 0x7e, 0xe1, + 0xb5, 0x97, 0xd2, 0xf0, 0x92, 0x3a, 0xfd, 0x0d, + 0x98, 0x26, 0x06, 0x85, 0x8d, 0xa4, 0xc7, 0x35, + 0xd4, 0x74, 0x8f, 0xd0, 0xe7, 0xa8, 0x27, 0xaa +}; +static const byte eccHash[] = { + 0x80, 0x3d, 0xff, 0xca, 0x2e, 0x20, 0xd9, 0xdf, + 0xfe, 0x64, 0x4e, 0x25, 0x6a, 0xee, 0xee, 0x60, + 0xc1, 0x48, 0x7b, 0xff, 0xa0, 0xfb, 0xeb, 0xac, + 0xe2, 0xa4, 0xdd, 0xb5, 0x18, 0x38, 0x78, 0x38 +}; +#endif + + pcap_t* pcap = NULL; pcap_if_t* alldevs = NULL; @@ -113,7 +153,6 @@ static void FreeAll(void) #ifdef WOLFSSL_SNIFFER_STATS - static void DumpStats(void) { SSLStats sslStats; @@ -152,8 +191,7 @@ static void DumpStats(void) printf("SSL Stats (sslEncryptedConns):%lu\n", sslStats.sslEncryptedConns); } - -#endif +#endif /* WOLFSSL_SNIFFER_STATS */ static void sig_handler(const int sig) @@ -170,64 +208,45 @@ static void sig_handler(const int sig) static void err_sys(const char* msg) { - fprintf(stderr, "%s\n", msg); + fprintf(stderr, "%s\n", msg); if (msg) - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } #ifdef _WIN32 - #define SNPRINTF _snprintf + #define SNPRINTF _snprintf #else - #define SNPRINTF snprintf + #define SNPRINTF snprintf #endif static char* iptos(const struct in_addr* addr) { - static char output[32]; - byte *p = (byte*)&addr->s_addr; + static char output[32]; + byte *p = (byte*)&addr->s_addr; - snprintf(output, sizeof(output), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + snprintf(output, sizeof(output), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - return output; + return output; } - static const char* ip6tos(const struct in6_addr* addr) { - static char output[42]; - return inet_ntop(AF_INET6, addr, output, 42); + static char output[42]; + return inet_ntop(AF_INET6, addr, output, 42); } #if defined(WOLFSSL_SNIFFER_STORE_DATA_CB) || defined(WOLFSSL_SNIFFER_CHAIN_INPUT) - static inline unsigned int min(unsigned int a, unsigned int b) { return a > b ? b : a; } - #endif #ifdef WOLFSSL_SNIFFER_WATCH - -const byte rsaHash[] = { - 0xD1, 0xB6, 0x12, 0xAD, 0xB6, 0x50, 0x7B, 0x59, - 0x97, 0x83, 0x6B, 0xCB, 0x35, 0xF5, 0xB8, 0x67, - 0xEB, 0x83, 0x75, 0x40, 0x1B, 0x42, 0x61, 0xF1, - 0x03, 0x72, 0xDC, 0x09, 0x0D, 0x60, 0x83, 0x15 -}; - -const byte eccHash[] = { - 0xDA, 0x08, 0x6D, 0xB5, 0x0B, 0xC4, 0x9F, 0x8A, - 0x9E, 0x61, 0x9E, 0x87, 0x57, 0x5F, 0x00, 0xAA, - 0x76, 0xE5, 0x1C, 0x9C, 0x74, 0x2A, 0x19, 0xBE, - 0x22, 0xAE, 0x25, 0x3F, 0xA8, 0xAF, 0x8E, 0x7F -}; - - static int myWatchCb(void* vSniffer, const unsigned char* certHash, unsigned int certHashSz, const unsigned char* certChain, unsigned int certChainSz, @@ -240,23 +259,23 @@ static int myWatchCb(void* vSniffer, (void)ctx; if (certHashSz == sizeof(rsaHash) && - memcmp(certHash, rsaHash, certHashSz) == 0) - certName = "../../certs/server-key.pem"; + XMEMCMP(certHash, rsaHash, certHashSz) == 0) { + certName = DEFAULT_SERVER_KEY_RSA; + } if (certHashSz == sizeof(eccHash) && - memcmp(certHash, eccHash, certHashSz) == 0) - certName = "../../certs/ecc-key.pem"; + XMEMCMP(certHash, eccHash, certHashSz) == 0) { + certName = DEFAULT_SERVER_KEY_ECC; + } if (certName == NULL) return -1; return ssl_SetWatchKey_file(vSniffer, certName, FILETYPE_PEM, NULL, error); } - -#endif +#endif /* WOLFSSL_SNIFFER_WATCH */ #ifdef WOLFSSL_SNIFFER_STORE_DATA_CB - static int myStoreDataCb(const unsigned char* decryptBuf, unsigned int decryptBufSz, unsigned int decryptBufOffset, void* ctx) { @@ -283,29 +302,28 @@ static int myStoreDataCb(const unsigned char* decryptBuf, *data = tmpData; } - memcpy(*data + decryptBufOffset, decryptBuf + decryptBufOffset, qty); + XMEMCPY(*data + decryptBufOffset, decryptBuf + decryptBufOffset, qty); return qty; } - -#endif +#endif /* WOLFSSL_SNIFFER_STORE_DATA_CB */ int main(int argc, char** argv) { int ret = 0; int hadBadPacket = 0; - int inum; - int port; + int inum = 0; + int port = 0; int saveFile = 0; - int i = 0; + int i = 0, defDev = 0; int frame = ETHER_IF_FRAME_LEN; char err[PCAP_ERRBUF_SIZE]; - char filter[32]; - const char *server = NULL; - struct bpf_program fp; - pcap_if_t *d; - pcap_addr_t *a; + char filter[32]; + const char *server = NULL; + struct bpf_program fp; + pcap_if_t *d; + pcap_addr_t *a; #ifdef WOLFSSL_SNIFFER_CHAIN_INPUT struct iovec chain[CHAIN_INPUT_COUNT]; int chainSz; @@ -315,6 +333,9 @@ int main(int argc, char** argv) #ifndef _WIN32 ssl_InitSniffer(); /* dll load on Windows */ +#endif +#ifdef DEBUG_WOLFSSL + //wolfSSL_Debugging_ON(); #endif ssl_Trace("./tracefile.txt", err); ssl_EnableRecovery(1, -1, err); @@ -326,54 +347,58 @@ int main(int argc, char** argv) #endif if (argc == 1) { + char cmdLineArg[128]; /* normal case, user chooses device and port */ - if (pcap_findalldevs(&alldevs, err) == -1) - err_sys("Error in pcap_findalldevs"); + if (pcap_findalldevs(&alldevs, err) == -1) + err_sys("Error in pcap_findalldevs"); - for (d = alldevs; d; d=d->next) { - printf("%d. %s", ++i, d->name); - if (d->description) - printf(" (%s)\n", d->description); - else - printf(" (No description available)\n"); - } - - if (i == 0) - err_sys("No interfaces found! Make sure pcap or WinPcap is" - " installed correctly and you have sufficient permissions"); - - printf("Enter the interface number (1-%d): ", i); - ret = scanf("%d", &inum); - if (ret != 1) { - printf("scanf port failed\n"); + for (d = alldevs; d; d=d->next) { + printf("%d. %s", ++i, d->name); + if (strcmp(d->name, "lo0") == 0) { + defDev = i; + } + if (d->description) + printf(" (%s)\n", d->description); + else + printf(" (No description available)\n"); } - if (inum < 1 || inum > i) - err_sys("Interface number out of range"); + if (i == 0) + err_sys("No interfaces found! Make sure pcap or WinPcap is" + " installed correctly and you have sufficient permissions"); - /* Jump to the selected adapter */ - for (d = alldevs, i = 0; i < inum - 1; d = d->next, i++); + printf("Enter the interface number (1-%d) [default: %d]: ", i, defDev); + XMEMSET(cmdLineArg, 0, sizeof(cmdLineArg)); + if (XFGETS(cmdLineArg, sizeof(cmdLineArg), stdin)) + inum = XATOI(cmdLineArg); + if (inum == 0) + inum = defDev; + else if (inum < 1 || inum > i) + err_sys("Interface number out of range"); - pcap = pcap_create(d->name, err); + /* Jump to the selected adapter */ + for (d = alldevs, i = 0; i < inum - 1; d = d->next, i++); + + pcap = pcap_create(d->name, err); if (pcap == NULL) printf("pcap_create failed %s\n", err); /* print out addresses for selected interface */ - for (a = d->addresses; a; a = a->next) { + for (a = d->addresses; a; a = a->next) { if (a->addr->sa_family == AF_INET) { - server = + server = iptos(&((struct sockaddr_in *)a->addr)->sin_addr); - printf("server = %s\n", server); + printf("server = %s\n", server); } else if (a->addr->sa_family == AF_INET6) { server = ip6tos(&((struct sockaddr_in6 *)a->addr)->sin6_addr); - printf("server = %s\n", server); + printf("server = %s\n", server); } - } - if (server == NULL) - err_sys("Unable to get device IPv4 or IPv6 address"); + } + if (server == NULL) + err_sys("Unable to get device IPv4 or IPv6 address"); ret = pcap_set_snaplen(pcap, 65536); if (ret != 0) printf("pcap_set_snaplen failed %s\n", pcap_geterr(pcap)); @@ -383,7 +408,7 @@ int main(int argc, char** argv) ret = pcap_set_buffer_size(pcap, 1000000); if (ret != 0) - printf("pcap_set_buffer_size failed %s\n", pcap_geterr(pcap)); + printf("pcap_set_buffer_size failed %s\n", pcap_geterr(pcap)); ret = pcap_set_promisc(pcap, 1); if (ret != 0) printf("pcap_set_promisc failed %s\n", pcap_geterr(pcap)); @@ -392,24 +417,27 @@ int main(int argc, char** argv) ret = pcap_activate(pcap); if (ret != 0) printf("pcap_activate failed %s\n", pcap_geterr(pcap)); - printf("Enter the port to scan: "); - ret = scanf("%d", &port); - if (ret != 1) - printf("scanf port failed\n"); + printf("Enter the port to scan [default: 11111]: "); + XMEMSET(cmdLineArg, 0, sizeof(cmdLineArg)); + if (XFGETS(cmdLineArg, sizeof(cmdLineArg), stdin)) { + port = XATOI(cmdLineArg); + } + if (port <= 0) + port = 11111; - SNPRINTF(filter, sizeof(filter), "tcp and port %d", port); + SNPRINTF(filter, sizeof(filter), "tcp and port %d", port); - ret = pcap_compile(pcap, &fp, filter, 0, 0); + ret = pcap_compile(pcap, &fp, filter, 0, 0); if (ret != 0) printf("pcap_compile failed %s\n", pcap_geterr(pcap)); ret = pcap_setfilter(pcap, &fp); if (ret != 0) printf("pcap_setfilter failed %s\n", pcap_geterr(pcap)); - /* get IPv4 or IPv6 addresses for selected interface */ - for (a = d->addresses; a; a = a->next) { + /* get IPv4 or IPv6 addresses for selected interface */ + for (a = d->addresses; a; a = a->next) { server = NULL; if (a->addr->sa_family == AF_INET) { - server = + server = iptos(&((struct sockaddr_in *)a->addr)->sin_addr); } else if (a->addr->sa_family == AF_INET6) { @@ -418,35 +446,41 @@ int main(int argc, char** argv) } if (server) { - #ifndef WOLFSSL_SNIFFER_WATCH - ret = ssl_SetPrivateKey(server, port, - "../../certs/server-key.pem", - FILETYPE_PEM, NULL, err); + #ifdef DEFAULT_SERVER_KEY + ret = ssl_SetPrivateKey(server, port, DEFAULT_SERVER_KEY, + FILETYPE_PEM, NULL, err); if (ret != 0) { printf("Please run directly from sslSniffer/sslSnifferTest" "dir\n"); } + #endif + #if defined(WOLFSSL_STATIC_EPHEMERAL) && defined(DEFAULT_SERVER_EPH_KEY) + ret = ssl_SetEphemeralKey(server, port, DEFAULT_SERVER_EPH_KEY, + FILETYPE_PEM, NULL, err); + if (ret != 0) { + printf("Please run directly from sslSniffer/sslSnifferTest" + "dir\n"); + } + #endif /* WOLFSSL_STATIC_EPHEMERAL */ + #ifndef WOLFSSL_SNIFFER_WATCH #ifdef HAVE_SNI - { - char altName[128]; - - printf("Enter alternate SNI: "); - ret = scanf("%s", altName); - - if (strnlen(altName, 128) > 0) { - ret = ssl_SetNamedPrivateKey(altName, - server, port, "../../certs/server-key.pem", + printf("Enter alternate SNI: "); + XMEMSET(cmdLineArg, 0, sizeof(cmdLineArg)); + if (XFGETS(cmdLineArg, sizeof(cmdLineArg), stdin)) { + if (XSTRLEN(cmdLineArg) > 0) { + ret = ssl_SetNamedPrivateKey(cmdLineArg, + server, port, DEFAULT_SERVER_KEY, FILETYPE_PEM, NULL, err); if (ret != 0) { printf("Please run directly from " - "sslSniffer/sslSnifferTest dir\n"); + "sslSniffer/sslSnifferTest dir\n"); } } } - #endif - #endif + #endif /* HAVE_SNI */ + #endif /* WOLFSSL_SNIFFER_WATCH */ } - } + } } else if (argc >= 3) { saveFile = 1; @@ -457,6 +491,8 @@ int main(int argc, char** argv) } else { const char* passwd = NULL; + int loadCount = 0; + /* defaults for server and port */ port = 443; server = "127.0.0.1"; @@ -465,13 +501,30 @@ int main(int argc, char** argv) server = argv[3]; if (argc >= 5) - port = atoi(argv[4]); + port = XATOI(argv[4]); if (argc >= 6) passwd = argv[5]; + /* try and load as both static ephemeral and private key */ + /* only fail if no key is loaded */ + #ifdef WOLFSSL_STATIC_EPHEMERAL + ret = ssl_SetEphemeralKey(server, port, argv[2], + FILETYPE_PEM, passwd, err); + if (ret == 0) + loadCount++; + #endif ret = ssl_SetPrivateKey(server, port, argv[2], - FILETYPE_PEM, passwd, err); + FILETYPE_PEM, passwd, err); + if (ret == 0) + loadCount++; + if (loadCount > 0) { + ret = 0; + } + else { + printf("Failed loading private key %d\n", ret); + exit(EXIT_FAILURE); + } } } else { @@ -498,8 +551,8 @@ int main(int argc, char** argv) byte* data = NULL; if (header.caplen > 40) { /* min ip(20) + min tcp(20) */ - packet += frame; - header.caplen -= frame; + packet += frame; + header.caplen -= frame; } else continue; diff --git a/tests/api.c b/tests/api.c index 454bd91e33..8bd8b52672 100644 --- a/tests/api.c +++ b/tests/api.c @@ -131,7 +131,7 @@ #endif #endif #if !defined(DER_SZ) - #define DER_SZ (keySz * 2 + 1) + #define DER_SZ(ks) (ks * 2 + 1) #endif #endif #ifndef NO_ASN @@ -7710,7 +7710,7 @@ static int test_wc_Sha224Final (void) static int test_wc_Sha224SetFlags (void) { int flag = 0; -#if !defined(NO_SHA224) && \ +#if defined(WOLFSSL_SHA224) && \ (defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)) wc_Sha224 sha224; word32 flags = 0; @@ -7742,7 +7742,7 @@ static int test_wc_Sha224SetFlags (void) static int test_wc_Sha224GetFlags (void) { int flag = 0; -#if !defined(NO_SHA224) && \ +#if defined(WOLFSSL_SHA224) && \ (defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)) wc_Sha224 sha224; word32 flags = 0; @@ -7775,7 +7775,7 @@ static int test_wc_Sha224GetFlags (void) static int test_wc_Sha224Free (void) { int flag = 0; -#if !defined(NO_SHA224) && \ +#if defined(WOLFSSL_SHA224) && \ (defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)) printf(testingFmt, "wc_Sha224Free()"); @@ -7794,7 +7794,7 @@ static int test_wc_Sha224Free (void) static int test_wc_Sha224GetHash (void) { int flag = 0; -#if !defined(NO_SHA224) && \ +#if defined(WOLFSSL_SHA224) && \ (defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)) wc_Sha224 sha224; byte hash1[WC_SHA224_DIGEST_SIZE]; @@ -7841,7 +7841,7 @@ static int test_wc_Sha224GetHash (void) static int test_wc_Sha224Copy (void) { int flag = 0; -#if !defined(NO_SHA224) && \ +#if defined(WOLFSSL_SHA224) && \ (defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)) wc_Sha224 sha224; wc_Sha224 temp; @@ -13662,6 +13662,63 @@ static int test_wc_SetKeyUsage (void) return ret; } /* END test_wc_SetKeyUsage */ +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +static void sample_mutex_cb (int flag, int type, const char* file, int line) +{ + (void)flag; + (void)type; + (void)file; + (void)line; +} +#endif +/* + * Testing wc_LockMutex_ex + */ +static int test_wc_LockMutex_ex (void) +{ + int ret = 0; +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + int flag = CRYPTO_LOCK; + int type = 0; + const char* file = "./test-LockMutex_ex.txt"; + int line = 0; + + printf(testingFmt, "wc_LockMutex_ex()"); + + /*without SetMutexCb*/ + ret = wc_LockMutex_ex(flag, type, file, line); + if (ret == BAD_STATE_E) { + ret = 0; + } + /*with SetMutexCb*/ + if (ret == 0) { + ret = wc_SetMutexCb(sample_mutex_cb); + if (ret == 0) { + ret = wc_LockMutex_ex(flag, type, file, line); + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +}/*End test_wc_LockMutex_ex*/ +/* + * Testing wc_SetMutexCb + */ +static int test_wc_SetMutexCb (void) +{ + int ret = 0; +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + + printf(testingFmt, "wc_SetMutexCb()"); + + ret = wc_SetMutexCb(sample_mutex_cb); + + printf(resultFmt, ret == 0 ? passed : failed); +#endif + return ret; +}/*End test_wc_SetMutexCb*/ /* * Testing wc_RsaKeyToDer() @@ -20018,9 +20075,9 @@ static int test_wc_ecc_pointFns (void) ecc_point* cpypt = NULL; int idx = 0; int keySz = KEY32; - byte der[DER_SZ]; + byte der[DER_SZ(KEY32)]; word32 derlenChk = 0; - word32 derSz = (int)sizeof(der); + word32 derSz = DER_SZ(KEY32); /* Init stack variables. */ XMEMSET(der, 0, derSz); @@ -27361,7 +27418,113 @@ static void test_wolfSSL_ERR_print_errors_cb(void) printf(resultFmt, passed); #endif } +/* + * Testing WOLFSSL_ERROR_MSG + */ +static int test_WOLFSSL_ERROR_MSG (void) +{ + int ret = 0; +#if defined(DEBUG_WOLFSSL) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) ||\ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) + const char* msg = "Everyone gets Friday off."; + printf(testingFmt, "WOLFSSL_ERROR_MSG()"); + + WOLFSSL_ERROR_MSG(msg); + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +}/*End test_WOLFSSL_ERROR_MSG*/ +/* + * Testing wc_ERR_remove_state + */ +static int test_wc_ERR_remove_state (void) +{ + int ret = 0; +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + + printf(testingFmt, "wc_ERR_remove_state()"); + + wc_ERR_remove_state(); + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +}/*End test_wc_ERR_remove_state*/ +/* + * Testing wc_ERR_print_errors_fp + */ +static int test_wc_ERR_print_errors_fp (void) +{ + int ret = 0; +#if (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)) && \ + (!defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)) + long sz; + + printf(testingFmt, "wc_ERR_print_errors_fp()"); + + WOLFSSL_ERROR(BAD_FUNC_ARG); + XFILE fp = XFOPEN("./tests/test-log-dump-to-file.txt", "ar"); + wc_ERR_print_errors_fp(fp); +#if defined(DEBUG_WOLFSSL) + AssertTrue(XFSEEK(fp, 0, XSEEK_END) == 0); + sz = XFTELL(fp); + if (sz == 0) { + ret = BAD_FUNC_ARG; + } +#endif + printf(resultFmt, ret == 0 ? passed : failed); + XFCLOSE(fp); + (void)sz; +#endif + return ret; +}/*End test_wc_ERR_print_errors_fp*/ +#ifdef DEBUG_WOLFSSL +static void Logging_cb(const int logLevel, const char *const logMessage) +{ + (void)logLevel; + (void)logMessage; +} +#endif +/* + * Testing wolfSSL_GetLoggingCb + */ +static int test_wolfSSL_GetLoggingCb (void) +{ + int ret = 0; +#ifdef DEBUG_WOLFSSL + printf(testingFmt, "wolfSSL_GetLoggingCb()"); + + /*Testing without wolfSSL_SetLoggingCb()*/ + if (ret == 0) { + if(wolfSSL_GetLoggingCb() == NULL){ /*Should be true*/ + ret = 0; + } + if(wolfSSL_GetLoggingCb() != NULL){ /*Should not be true*/ + ret = -1; + } + } + /*Testing with wolfSSL_SetLoggingCb()*/ + if (ret == 0) { + ret = wolfSSL_SetLoggingCb(Logging_cb); + if (ret == 0){ + if(wolfSSL_GetLoggingCb() == NULL){ /*Should not be true*/ + ret = -1; + } + if (ret == 0) { + if(wolfSSL_GetLoggingCb() == Logging_cb){ /*Should be true*/ + ret = 0; + } + } + } + } + printf(resultFmt, ret == 0 ? passed : failed); +#endif + return ret; +}/*End test_wolfSSL_GetLoggingCb*/ static void test_wolfSSL_HMAC(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_SHA256) @@ -33603,7 +33766,7 @@ static int test_wc_InitRngNonce(void) { int ret=0; #if !defined(WC_NO_RNG) && !defined(HAVE_SELFTEST) && \ - (!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION >= 2)) + (!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION >= 2)) WC_RNG rng; byte nonce[] = "\x0D\x74\xDB\x42\xA9\x10\x77\xDE" "\x45\xAC\x13\x7A\xE1\x48\xAF\x16"; @@ -33629,14 +33792,14 @@ static int test_wc_InitRngNonce_ex(void) { int ret=0; #if !defined(WC_NO_RNG) && !defined(HAVE_SELFTEST) && \ - (!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION >= 2)) + (!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION >= 2)) WC_RNG rng; byte nonce[] = "\x0D\x74\xDB\x42\xA9\x10\x77\xDE" "\x45\xAC\x13\x7A\xE1\x48\xAF\x16"; word32 nonceSz = sizeof(nonce); printf(testingFmt, "wc_InitRngNonce_ex()"); - + if (ret == 0){ ret = wc_InitRngNonce_ex(&rng, nonce, nonceSz, HEAP_HINT, devId); } @@ -34432,7 +34595,7 @@ static void test_wolfSSL_ASN1_STRING_print(void){ asnStr = ASN1_STRING_type_new(V_ASN1_OCTET_STRING); ASN1_STRING_set(asnStr,(const void*)unprintableData, - sizeof(unprintableData)); + (int)sizeof(unprintableData)); /* test */ p_len = wolfSSL_ASN1_STRING_print(bio, asnStr); AssertIntEQ(p_len, 46); @@ -35141,6 +35304,10 @@ void ApiTest(void) test_wolfSSL_ERR_peek_last_error_line(); #endif test_wolfSSL_ERR_print_errors_cb(); + AssertFalse(test_wolfSSL_GetLoggingCb()); + AssertFalse(test_WOLFSSL_ERROR_MSG()); + AssertFalse(test_wc_ERR_remove_state()); + AssertFalse(test_wc_ERR_print_errors_fp()); test_wolfSSL_set_options(); test_wolfSSL_sk_SSL_CIPHER(); test_wolfSSL_X509_STORE_CTX(); @@ -35472,6 +35639,8 @@ void ApiTest(void) AssertIntEQ(test_wc_MakeRsaKey(), 0); AssertIntEQ(test_wc_SetKeyUsage (), 0); + AssertIntEQ(test_wc_SetMutexCb(), 0); + AssertIntEQ(test_wc_LockMutex_ex(), 0); AssertIntEQ(test_wc_RsaKeyToDer(), 0); AssertIntEQ(test_wc_RsaKeyToPublicDer(), 0); diff --git a/tests/include.am b/tests/include.am index 07230abf34..1ef0a7cdf5 100644 --- a/tests/include.am +++ b/tests/include.am @@ -31,6 +31,7 @@ EXTRA_DIST += tests/test.conf \ tests/test-psk-no-id.conf \ tests/test-psk-no-id-sha2.conf \ tests/test-dtls.conf \ + tests/test-dtls-fails.conf \ tests/test-dtls-group.conf \ tests/test-dtls-reneg-client.conf \ tests/test-dtls-reneg-server.conf \ diff --git a/tests/suites.c b/tests/suites.c index d4e4107af6..72ae8fddf3 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -455,6 +455,7 @@ static int execute_test_case(int svr_argc, char** svr_argv, return NOT_BUILT_IN; } printf("trying client command line[%d]: %s\n", tests, commandLine); + tests++; /* determine based on args if this test is expected to fail */ if (XSTRSTR(commandLine, exitWithRetFlag) != NULL) { @@ -881,6 +882,20 @@ int SuiteTest(int argc, char** argv) goto exit; } #endif +#ifndef WOLFSSL_NO_DTLS_SIZE_CHECK + /* failure tests */ + args.argc = 3; + strcpy(argv0[1], "tests/test-dtls-fails.conf"); + strcpy(argv0[2], "expFail"); /* tests are expected to fail */ + printf("starting dtls tests that expect failure\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } + strcpy(argv0[2], ""); +#endif #endif #ifdef WOLFSSL_SCTP /* add dtls-sctp extra suites */ @@ -1038,7 +1053,7 @@ int SuiteTest(int argc, char** argv) args.argc = 3; strcpy(argv0[1], "tests/test-dhprime.conf"); strcpy(argv0[2], "doDH"); /* add DH prime flag */ - printf("starting tests that expect failure\n"); + printf("starting dh prime tests\n"); test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); diff --git a/tests/test-dtls-fails.conf b/tests/test-dtls-fails.conf new file mode 100644 index 0000000000..07492f2f7b --- /dev/null +++ b/tests/test-dtls-fails.conf @@ -0,0 +1,16 @@ +# DTLS test +# server DTLSv1.2 too big test +-v 3 +-l ECDHE-ECDSA-AES128-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem +-u +-B 9000 + +# client DTLSv1.2 too big test +-v 3 +-l ECDHE-ECDSA-AES128-SHA256 +-A ./certs/ca-ecc-cert.pem +-u +-B 9000 + diff --git a/tests/test-sctp-sha2.conf b/tests/test-sctp-sha2.conf index 4c72d4b408..a40c0ea08f 100644 --- a/tests/test-sctp-sha2.conf +++ b/tests/test-sctp-sha2.conf @@ -18,49 +18,49 @@ -v 2 -l AES256-SHA256 -# server TLSv1 ECDHE-PSK-AES128-SHA256 +# server DTLSv1 ECDHE-PSK-AES128-SHA256 -s -G -v 1 -l ECDHE-PSK-AES128-SHA256 -# client TLSv1 ECDHE-PSK-AES128-SHA256 +# client DTLSv1 ECDHE-PSK-AES128-SHA256 -s -G -v 1 -l ECDHE-PSK-AES128-SHA256 -# server TLSv1.1 ECDHE-PSK-AES128-SHA256 +# server DTLSv1.1 ECDHE-PSK-AES128-SHA256 -s -G -v 2 -l ECDHE-PSK-AES128-SHA256 -# client TLSv1.1 ECDHE-PSK-AES128-SHA256 +# client DTLSv1.1 ECDHE-PSK-AES128-SHA256 -s -G -v 2 -l ECDHE-PSK-AES128-SHA256 -# server TLSv1 ECDHE-PSK-NULL-SHA256 +# server DTLSv1 ECDHE-PSK-NULL-SHA256 -s -G -v 1 -l ECDHE-PSK-NULL-SHA256 -# client TLSv1 ECDHE-PSK-NULL-SHA256 +# client DTLSv1 ECDHE-PSK-NULL-SHA256 -s -G -v 1 -l ECDHE-PSK-NULL-SHA256 -# server TLSv1.1 ECDHE-PSK-NULL-SHA256 +# server DTLSv1.1 ECDHE-PSK-NULL-SHA256 -s -G -v 2 -l ECDHE-PSK-NULL-SHA256 -# client TLSv1.1 ECDHE-PSK-NULL-SHA256 +# client DTLSv1.1 ECDHE-PSK-NULL-SHA256 -s -G -v 2 diff --git a/tests/test-sctp.conf b/tests/test-sctp.conf index a2c2bc052a..5dfae30c99 100644 --- a/tests/test-sctp.conf +++ b/tests/test-sctp.conf @@ -1,36 +1,3 @@ -# server DTLSv1 DHE-RSA-CHACHA20-POLY1305 --G --v 2 --l DHE-RSA-CHACHA20-POLY1305 - -# client DTLSv1 DHE-RSA-CHACHA20-POLY1305 --G --v 2 --l DHE-RSA-CHACHA20-POLY1305 - -# server DTLSv1 ECDHE-RSA-CHACHA20-POLY1305 --G --v 2 --l ECDHE-RSA-CHACHA20-POLY1305 - -# client DTLSv1 ECDHE-RSA-CHACHA20-POLY1305 --G --v 2 --l ECDHE-RSA-CHACHA20-POLY1305 - -# server DTLSv1 ECDHE-EDCSA-CHACHA20-POLY1305 --G --v 2 --l ECDHE-ECDSA-CHACHA20-POLY1305 --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1 ECDHE-ECDSA-CHACHA20-POLY1305 --G --v 2 --l ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/ca-ecc-cert.pem - # server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 -G -v 3 @@ -64,37 +31,37 @@ -l ECDHE-ECDSA-CHACHA20-POLY1305 -A ./certs/ca-ecc-cert.pem -# server TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +# server DTLSv1.2 DHE-PSK-CHACHA20-POLY1305 -G -v 3 -s -l DHE-PSK-CHACHA20-POLY1305 -# client TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +# client DTLSv1.2 DHE-PSK-CHACHA20-POLY1305 -G -v 3 -s -l DHE-PSK-CHACHA20-POLY1305 -# server TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +# server DTLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 -G -v 3 -s -l ECDHE-PSK-CHACHA20-POLY1305 -# client TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +# client DTLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 -G -v 3 -s -l ECDHE-PSK-CHACHA20-POLY1305 -# server TLSv1.2 PSK-CHACHA20-POLY1305 +# server DTLSv1.2 PSK-CHACHA20-POLY1305 -G -v 3 -s -l PSK-CHACHA20-POLY1305 -# client TLSv1.2 PSK-CHACHA20-POLY1305 +# client DTLSv1.2 PSK-CHACHA20-POLY1305 -G -v 3 -s @@ -333,40 +300,40 @@ -v 3 -l ECDHE-RSA-AES256-SHA -# server TLSv1 ECDHE-ECDSA-NULL-SHA +# server DTLSv1 ECDHE-ECDSA-NULL-SHA -G -v 1 -l ECDHE-ECDSA-NULL-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1 ECDHE-ECDSA-NULL-SHA +# client DTLSv1 ECDHE-ECDSA-NULL-SHA -G -v 1 -l ECDHE-ECDSA-NULL-SHA -A ./certs/ca-ecc-cert.pem -# server TLSv1.1 ECDHE-ECDSA-NULL-SHA +# server DTLSv1.1 ECDHE-ECDSA-NULL-SHA -G -v 2 -l ECDHE-ECDSA-NULL-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1 ECDHE-ECDSA-NULL-SHA +# client DTLSv1 ECDHE-ECDSA-NULL-SHA -G -v 2 -l ECDHE-ECDSA-NULL-SHA -A ./certs/ca-ecc-cert.pem -# server TLSv1.2 ECDHE-ECDSA-NULL-SHA +# server DTLSv1.2 ECDHE-ECDSA-NULL-SHA -G -v 3 -l ECDHE-ECDSA-NULL-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDHE-ECDSA-NULL-SHA +# client DTLSv1.2 ECDHE-ECDSA-NULL-SHA -G -v 3 -l ECDHE-ECDSA-NULL-SHA @@ -762,25 +729,25 @@ -l ECDH-ECDSA-AES256-SHA384 -A ./certs/ca-ecc-cert.pem -# server TLSv1.2 ECDHE-PSK-AES128-SHA256 +# server DTLSv1.2 ECDHE-PSK-AES128-SHA256 -s -G -v 3 -l ECDHE-PSK-AES128-SHA256 -# client TLSv1.2 ECDHE-PSK-AES128-SHA256 +# client DTLSv1.2 ECDHE-PSK-AES128-SHA256 -s -G -v 3 -l ECDHE-PSK-AES128-SHA256 -# server TLSv1.2 ECDHE-PSK-NULL-SHA256 +# server DTLSv1.2 ECDHE-PSK-NULL-SHA256 -s -G -v 3 -l ECDHE-PSK-NULL-SHA256 -# client TLSv1.2 ECDHE-PSK-NULL-SHA256 +# client DTLSv1.2 ECDHE-PSK-NULL-SHA256 -s -G -v 3 diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index b0001f1982..a44ee72b33 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -926,7 +926,7 @@ #ifdef NEED_AES_TABLES -static const word32 rcon[] = { +static const FLASH_QUALIFIER word32 rcon[] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, @@ -934,7 +934,7 @@ static const word32 rcon[] = { }; #ifndef WOLFSSL_AES_SMALL_TABLES -static const word32 Te[4][256] = { +static const FLASH_QUALIFIER word32 Te[4][256] = { { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, @@ -1202,7 +1202,7 @@ static const word32 Te[4][256] = { }; #ifdef HAVE_AES_DECRYPT -static const word32 Td[4][256] = { +static const FLASH_QUALIFIER word32 Td[4][256] = { { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, @@ -1475,7 +1475,7 @@ static const word32 Td[4][256] = { #ifdef HAVE_AES_DECRYPT #if (defined(HAVE_AES_CBC) && !defined(WOLFSSL_DEVCRYPTO_CBC)) \ || defined(WOLFSSL_AES_DIRECT) -static const byte Td4[256] = +static const FLASH_QUALIFIER byte Td4[256] = { 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 54f91d7b8b..9201ae5767 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1521,9 +1521,9 @@ static word32 SetBitString16Bit(word16 val, byte* output) #ifdef HAVE_ED448 static const byte keyEd448Oid[] = {43, 101, 113}; #endif /* HAVE_ED448 */ -#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) +#ifndef NO_DH static const byte keyDhOid[] = {42, 134, 72, 134, 247, 13, 1, 3, 1}; -#endif /* ! NO_DH ... */ +#endif /* !NO_DH */ /* curveType */ #ifdef HAVE_ECC @@ -1869,12 +1869,12 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(keyEd448Oid); break; #endif /* HAVE_ED448 */ - #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) + #ifndef NO_DH case DHk: oid = keyDhOid; *oidSz = sizeof(keyDhOid); break; - #endif /* ! NO_DH && (WOLFSSL_QT || OPENSSL_ALL */ + #endif /* !NO_DH */ default: break; } @@ -4416,17 +4416,20 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, #endif /* !NO_RSA */ #ifndef NO_DH - +/* Supports either: + * - DH params G/P (PKCS#3 DH) file or + * - DH key file (if WOLFSSL_DH_EXTRA enabled) */ +/* The wc_DhParamsLoad function also loads DH params, but directly into buffers, not DhKey */ int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) { int ret = 0; int length; - #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) - #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ - (HAVE_FIPS_VERSION>2)) +#ifdef WOLFSSL_DH_EXTRA + #if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)) word32 oid = 0, temp = 0; #endif - #endif +#endif WOLFSSL_ENTER("wc_DhKeyDecode"); @@ -4435,26 +4438,33 @@ int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; - #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) - #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ - (HAVE_FIPS_VERSION>2)) - temp = *inOutIdx; - #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ - #endif +#ifdef WOLFSSL_DH_EXTRA + #if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)) + temp = *inOutIdx; + #endif +#endif /* Assume input started after 1.2.840.113549.1.3.1 dhKeyAgreement */ if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || GetInt(&key->g, input, inOutIdx, inSz) < 0) { ret = ASN_DH_KEY_E; } - #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) - #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ - (HAVE_FIPS_VERSION>2)) +#ifdef WOLFSSL_DH_EXTRA + #if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)) /* If ASN_DH_KEY_E: Check if input started at beginning of key */ if (ret == ASN_DH_KEY_E) { - /* rewind back to after the first sequence */ *inOutIdx = temp; + + /* the version (0) */ + if (GetASNInt(input, inOutIdx, &length, inSz) < 0) { + return ASN_PARSE_E; + } + *inOutIdx += length; + + /* Size of dhKeyAgreement section */ if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -4466,8 +4476,8 @@ int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; - if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || - GetInt(&key->g, input, inOutIdx, inSz) < 0) { + if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || + GetInt(&key->g, input, inOutIdx, inSz) < 0) { return ASN_DH_KEY_E; } } @@ -4487,7 +4497,9 @@ int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) /* Found Octet String */ if (GetInt(&key->priv, input, inOutIdx, inSz) == 0) { WOLFSSL_MSG("Found Private Key"); - ret = 0; + + /* Compute public */ + ret = mp_exptmod(&key->g, &key->priv, &key->p, &key->pub); } } else { /* Don't use length from failed CheckBitString/GetOctetString */ @@ -4496,14 +4508,13 @@ int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) } } #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ - #endif /* WOLFSSL_QT || OPENSSL_ALL */ +#endif /* WOLFSSL_DH_EXTRA */ - WOLFSSL_MSG("wc_DhKeyDecode Success"); + WOLFSSL_LEAVE("wc_DhKeyDecode", ret); return ret; } - int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz, byte* g, word32* gInOutSz) { @@ -4541,7 +4552,7 @@ int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz, return 0; } -#endif /* NO_DH */ +#endif /* !NO_DH */ #ifndef NO_DSA @@ -6078,6 +6089,32 @@ int ExtractDate(const unsigned char* date, unsigned char format, certTime->tm_year *= 100; } +#ifdef AVR + /* Extract the time from the struct tm and adjust tm_year, tm_mon */ + /* AVR libc stores these as uint8_t instead of int */ + /* AVR time_t also offsets from midnight 1 Jan 2000 */ + int tm_year = certTime->tm_year - 2000; + int tm_mon = certTime->tm_mon - 1; + int tm_mday = certTime->tm_mday; + int tm_hour = certTime->tm_hour; + int tm_min = certTime->tm_min; + int tm_sec = certTime->tm_sec; + + if (GetTime(&tm_year, date, idx) != 0) return 0; + if (GetTime(&tm_mon , date, idx) != 0) return 0; + if (GetTime(&tm_mday, date, idx) != 0) return 0; + if (GetTime(&tm_hour, date, idx) != 0) return 0; + if (GetTime(&tm_min , date, idx) != 0) return 0; + if (GetTime(&tm_sec , date, idx) != 0) return 0; + + /* Re-populate certTime with computed values */ + certTime->tm_year = tm_year; + certTime->tm_mon = tm_mon; + certTime->tm_mday = tm_mday; + certTime->tm_hour = tm_hour; + certTime->tm_min = tm_min; + certTime->tm_sec = tm_sec; +#else /* adjust tm_year, tm_mon */ if (GetTime(&certTime->tm_year, date, idx) != 0) return 0; certTime->tm_year -= 1900; @@ -6087,6 +6124,7 @@ int ExtractDate(const unsigned char* date, unsigned char format, if (GetTime(&certTime->tm_hour, date, idx) != 0) return 0; if (GetTime(&certTime->tm_min , date, idx) != 0) return 0; if (GetTime(&certTime->tm_sec , date, idx) != 0) return 0; +#endif return 1; } @@ -9895,7 +9933,7 @@ int wc_PemGetHeaderFooter(int type, const char** header, const char** footer) if (footer) *footer = END_PUB_KEY; ret = 0; break; - #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) + #ifndef NO_DH case DH_PRIVATEKEY_TYPE: #endif case PKCS8_PRIVATEKEY_TYPE: @@ -10555,9 +10593,22 @@ int PemToDer(const unsigned char* buff, long longSz, int type, #ifndef NO_WOLFSSL_SKIP_TRAILING_PAD #ifndef NO_DES3 if (info->cipherType == WC_CIPHER_DES3) { - padVal = der->buffer[der->length-1]; - if (padVal <= DES_BLOCK_SIZE) { - der->length -= padVal; + /* Assuming there is padding: + * (der->length > 0 && + * (der->length % DES_BLOCK_SIZE) != 0) + * and assuming the last value signifies the number of + * padded bytes IE if last value is 0x08 then there are + * 8 bytes of padding: + * padVal = der->buffer[der->length-1]; + * then strip this padding before proceeding: + * der->length -= padVal; + */ + if (der->length > 0 && + (der->length % DES_BLOCK_SIZE) != 0) { + padVal = der->buffer[der->length-1]; + if (padVal <= DES_BLOCK_SIZE) { + der->length -= padVal; + } } } #endif /* !NO_DES3 */ @@ -15068,7 +15119,7 @@ int StoreDHparams(byte* out, word32* outLen, mp_int* p, mp_int* g) return 0; } -#endif /* !NO_DH && WOLFSSL_QT || OPENSSL_ALL */ +#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ #ifdef HAVE_ECC diff --git a/wolfcrypt/src/des3.c b/wolfcrypt/src/des3.c index 9daa195eb5..a6548dc5d6 100644 --- a/wolfcrypt/src/des3.c +++ b/wolfcrypt/src/des3.c @@ -1170,7 +1170,7 @@ #ifdef NEED_SOFT_DES /* permuted choice table (key) */ - static const byte pc1[] = { + static const FLASH_QUALIFIER byte pc1[] = { 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, @@ -1183,12 +1183,12 @@ }; /* number left rotations of pc1 */ - static const byte totrot[] = { + static const FLASH_QUALIFIER byte totrot[] = { 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; /* permuted choice key (table) */ - static const byte pc2[] = { + static const FLASH_QUALIFIER byte pc2[] = { 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, @@ -1202,11 +1202,11 @@ /* End of DES-defined tables */ /* bit 0 is left-most in byte */ - static const int bytebit[] = { + static const FLASH_QUALIFIER int bytebit[] = { 0200,0100,040,020,010,04,02,01 }; - static const word32 Spbox[8][64] = { + static const FLASH_QUALIFIER word32 Spbox[8][64] = { { 0x01010400,0x00000000,0x00010000,0x01010404, 0x01010004,0x00010404,0x00000004,0x00010000, 0x00000400,0x01010400,0x01010404,0x00000400, diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index 78decc3f8b..7661ff2b9b 100644 --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -930,10 +930,10 @@ int wc_InitDhKey_ex(DhKey* key, void* heap, int devId) key->heap = heap; /* for XMALLOC/XFREE in future */ -#if !defined(WOLFSSL_QT) && !defined(OPENSSL_ALL) - if (mp_init_multi(&key->p, &key->g, &key->q, NULL, NULL, NULL) != MP_OKAY) +#ifdef WOLFSSL_DH_EXTRA + if (mp_init_multi(&key->p, &key->g, &key->q, &key->pub, &key->priv, NULL) != MP_OKAY) #else - if (mp_init_multi(&key->p,&key->g,&key->q,&key->pub,&key->priv,NULL) != MP_OKAY) + if (mp_init_multi(&key->p, &key->g, &key->q, NULL, NULL, NULL) != MP_OKAY) #endif return MEMORY_E; @@ -960,6 +960,10 @@ int wc_FreeDhKey(DhKey* key) mp_clear(&key->p); mp_clear(&key->g); mp_clear(&key->q); + #ifdef WOLFSSL_DH_EXTRA + mp_clear(&key->pub); + mp_forcezero(&key->priv); + #endif #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_DH); @@ -1148,7 +1152,6 @@ static int GeneratePrivateDh186(DhKey* key, WC_RNG* rng, byte* priv, } mp_forcezero(tmpX); - mp_clear(tmpX); mp_clear(tmpQ); #ifdef WOLFSSL_SMALL_STACK XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH); @@ -1798,7 +1801,6 @@ int wc_DhCheckKeyPair(DhKey* key, const byte* pub, word32 pubSz, } mp_forcezero(privateKey); - mp_clear(privateKey); mp_clear(publicKey); mp_clear(checkKey); #ifdef WOLFSSL_SMALL_STACK @@ -1834,7 +1836,6 @@ int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, return ret; } - static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz) { @@ -2065,76 +2066,113 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, return ret; } -#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +#ifdef WOLFSSL_DH_EXTRA /* Sets private and public key in DhKey if both are available, otherwise sets - either private or public key, depending on which is available. - Returns WOLFSSL_SUCCESS if at least one of the keys was set. */ -WOLFSSL_LOCAL int wc_DhSetFullKeys(DhKey* key,const byte* priv_key,word32 privSz, - const byte* pub_key, word32 pubSz) + either private or public key, depending on which is available. */ +int wc_DhImportKeyPair(DhKey* key, const byte* priv, word32 privSz, + const byte* pub, word32 pubSz) { - byte havePriv = 0; - byte havePub = 0; - mp_int* keyPriv = NULL; - mp_int* keyPub = NULL; + byte havePriv, havePub; + mp_int *keyPriv = NULL, *keyPub = NULL; if (key == NULL) { return BAD_FUNC_ARG; } - havePriv = ( (priv_key != NULL) && (privSz > 0) ); - havePub = ( (pub_key != NULL) && (pubSz > 0) ); + havePriv = ( (priv != NULL) && (privSz > 0) ); + havePub = ( (pub != NULL) && (pubSz > 0) ); if (!havePub && !havePriv) { WOLFSSL_MSG("No Public or Private Key to Set"); return BAD_FUNC_ARG; } + /* Set Private Key */ - if (havePriv == TRUE) { + if (havePriv) { /* may have leading 0 */ - if (priv_key[0] == 0) { - privSz--; priv_key++; + if (priv[0] == 0) { + privSz--; priv++; } if (mp_init(&key->priv) != MP_OKAY) - havePriv = FALSE; + havePriv = 0; } - - if (havePriv == TRUE) { - if (mp_read_unsigned_bin(&key->priv, priv_key, privSz) != MP_OKAY) { - havePriv = FALSE; + if (havePriv) { + if (mp_read_unsigned_bin(&key->priv, priv, privSz) != MP_OKAY) { + mp_clear(&key->priv); + havePriv = 0; } else { keyPriv = &key->priv; - WOLFSSL_MSG("DH Private Key Set."); + WOLFSSL_MSG("DH Private Key Set"); } } /* Set Public Key */ - if (havePub == TRUE) { + if (havePub) { /* may have leading 0 */ - if (pub_key[0] == 0) { - pubSz--; pub_key++; + if (pub[0] == 0) { + pubSz--; pub++; } if (mp_init(&key->pub) != MP_OKAY) - havePub = FALSE; + havePub = 0; } - - if (havePub == TRUE) { - if (mp_read_unsigned_bin(&key->pub, pub_key, pubSz) != MP_OKAY) { - havePub = FALSE; + if (havePub) { + if (mp_read_unsigned_bin(&key->pub, pub, pubSz) != MP_OKAY) { + mp_clear(&key->pub); + havePub = 0; } else { keyPub = &key->pub; - WOLFSSL_MSG("DH Public Key Set."); + WOLFSSL_MSG("DH Public Key Set"); } } - /* Free Memory if error occured */ - if (havePriv == FALSE && keyPriv != NULL) + /* Free Memory if error occurred */ + if (havePriv == 0 && keyPriv != NULL) mp_clear(keyPriv); - if (havePub == FALSE && keyPub != NULL) + if (havePub == 0 && keyPub != NULL) mp_clear(keyPub); - /* WOLFSSL_SUCCESS if private or public was set else WOLFSSL_FAILURE */ - return havePriv || havePub; + if (havePriv == 0 && havePub == 0) { + return MEMORY_E; + } + + return 0; } -#endif + +/* Can be used with WOLFSSL_DH_EXTRA when key is loaded with + wc_DhKeyDecode or wc_DhImportKeyPair */ +int wc_DhExportKeyPair(DhKey* key, byte* priv, word32* pPrivSz, + byte* pub, word32* pPubSz) +{ + int ret = 0; + word32 pubSz, privSz; + + if (key == NULL || (priv && pPrivSz == NULL) || (pub && pPubSz == NULL)) { + return BAD_FUNC_ARG; + } + + if (priv) { + privSz = mp_unsigned_bin_size(&key->priv); + if (privSz > *pPrivSz) { + return BUFFER_E; + } + *pPrivSz = privSz; + ret |= mp_to_unsigned_bin(&key->priv, priv); + } + + if (pub) { + pubSz = mp_unsigned_bin_size(&key->pub); + if (pubSz > *pPubSz) { + return BUFFER_E; + } + *pPubSz = pubSz; + ret |= mp_to_unsigned_bin(&key->pub, pub); + } + + if (ret != 0) + ret = ASN_DH_KEY_E; + return ret; +} + +#endif /* WOLFSSL_DH_EXTRA */ static int _DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz, const byte* q, word32 qSz, int trusted, diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index f3f21c258a..fec7903bf9 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -48,7 +48,7 @@ Possible ECC enable options: * WOLFSSL_CUSTOM_CURVES: Allow non-standard curves. default: off * Includes the curve "a" variable in calculation * ECC_DUMP_OID: Enables dump of OID encoding and sum default: off - * ECC_CACHE_CURVE: Enables cache of curve info to improve perofrmance + * ECC_CACHE_CURVE: Enables cache of curve info to improve performance default: off * FP_ECC: ECC Fixed Point Cache default: off * USE_ECC_B_PARAM: Enable ECC curve B param default: off @@ -56,6 +56,10 @@ Possible ECC enable options: * WOLFSSL_ECC_CURVE_STATIC: default off (on for windows) For the ECC curve paramaters `ecc_set_type` use fixed array for hex string + * WC_ECC_NONBLOCK: Enable non-blocking support for sign/verify. + Requires SP with WOLFSSL_SP_NONBLOCK + * WC_ECC_NONBLOCK_ONLY Enable the non-blocking function only, no fall-back to + normal blocking API's */ /* @@ -4891,60 +4895,73 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, } #ifdef WOLFSSL_SP_MATH -#ifndef WOLFSSL_SP_NO_256 - if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { - #ifndef WOLFSSL_ECDSA_SET_K - return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, NULL, key->heap); - #else - return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->sign_k, - key->heap); - #endif + if (key->idx == ECC_CUSTOM_IDX || + (ecc_sets[key->idx].id != ECC_SECP256R1 && + ecc_sets[key->idx].id != ECC_SECP384R1)) { + return WC_KEY_SIZE_E; } #endif -#ifdef WOLFSSL_SP_384 - if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { - #ifndef WOLFSSL_ECDSA_SET_K - return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, NULL, key->heap); - #else - return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, key->sign_k, - key->heap); - #endif - } -#endif - return WC_KEY_SIZE_E; -#else -#ifdef WOLFSSL_HAVE_SP_ECC - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) - if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC) - #endif - { -#ifndef WOLFSSL_SP_NO_256 - if (key->idx != ECC_CUSTOM_IDX && - ecc_sets[key->idx].id == ECC_SECP256R1) { - #ifndef WOLFSSL_ECDSA_SET_K - return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, NULL, - key->heap); - #else - return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->sign_k, - key->heap); - #endif - } -#endif -#ifdef WOLFSSL_SP_384 - if (key->idx != ECC_CUSTOM_IDX && - ecc_sets[key->idx].id == ECC_SECP384R1) { - #ifndef WOLFSSL_ECDSA_SET_K - return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, NULL, - key->heap); - #else - return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, key->sign_k, - key->heap); - #endif - } -#endif - } -#endif /* WOLFSSL_HAVE_SP_ECC */ +#if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_HAVE_SP_ECC) + if (key->idx != ECC_CUSTOM_IDX + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + && key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC + #endif + ) { + #ifdef WOLFSSL_ECDSA_SET_K + mp_int* sign_k = key->sign_k; + #else + mp_int* sign_k = NULL; + #endif + #if defined(WC_ECC_NONBLOCK) && defined(WC_ECC_NONBLOCK_ONLY) + /* perform blocking call to non-blocking function */ + ecc_nb_ctx_t nb_ctx; + XMEMSET(&nb_ctx, 0, sizeof(nb_ctx)); + #endif + #ifndef WOLFSSL_SP_NO_256 + if (ecc_sets[key->idx].id == ECC_SECP256R1) { + #ifdef WC_ECC_NONBLOCK + if (key->nb_ctx) { + return sp_ecc_sign_256_nb(&key->nb_ctx->sp_ctx, in, inlen, rng, + &key->k, r, s, sign_k, key->heap); + } + #ifdef WC_ECC_NONBLOCK_ONLY + do { /* perform blocking call to non-blocking function */ + err = sp_ecc_sign_256_nb(&nb_ctx.sp_ctx, in, inlen, rng, + &key->k, r, s, sign_k, key->heap); + } while (err == FP_WOULDBLOCK); + return err; + #endif + #endif /* WC_ECC_NONBLOCK */ + #if !defined(WC_ECC_NONBLOCK) || (defined(WC_ECC_NONBLOCK) && !defined(WC_ECC_NONBLOCK_ONLY)) + return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, sign_k, + key->heap); + #endif + } + #endif + #ifdef WOLFSSL_SP_384 + if (ecc_sets[key->idx].id == ECC_SECP384R1) { + #ifdef WC_ECC_NONBLOCK + if (key->nb_ctx) { + return sp_ecc_sign_384_nb(&key->nb_ctx->sp_ctx, in, inlen, rng, + &key->k, r, s, sign_k, key->heap); + } + #ifdef WC_ECC_NONBLOCK_ONLY + do { /* perform blocking call to non-blocking function */ + err = sp_ecc_sign_384_nb(&nb_ctx.sp_ctx, in, inlen, rng, + &key->k, r, s, sign_k, key->heap); + } while (err == FP_WOULDBLOCK); + return err; + #endif + #endif /* WC_ECC_NONBLOCK */ + #if !defined(WC_ECC_NONBLOCK) || (defined(WC_ECC_NONBLOCK) && !defined(WC_ECC_NONBLOCK_ONLY)) + return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, sign_k, + key->heap); + #endif + } + #endif + } +#endif #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ defined(WOLFSSL_ASYNC_CRYPT_TEST) @@ -4962,6 +4979,9 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, } #endif + +#ifndef WOLFSSL_SP_MATH + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V) err = wc_ecc_alloc_mpint(key, &key->e); if (err != 0) { @@ -5288,7 +5308,7 @@ int wc_ecc_sign_set_k(const byte* k, word32 klen, ecc_key* key) #endif /* WOLFSSL_ECDSA_SET_K */ #endif /* WOLFSSL_ATECC508A && WOLFSSL_CRYPTOCELL*/ -#endif /* HAVE_ECC_SIGN */ +#endif /* !HAVE_ECC_SIGN */ #ifdef WOLFSSL_CUSTOM_CURVES void wc_ecc_free_curve(const ecc_set_type* curve, void* heap) @@ -5984,52 +6004,85 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, #if defined(WOLFSSL_DSP) && !defined(FREESCALE_LTC_ECC) if (key->handle != -1) { - return sp_dsp_ecc_verify_256(key->handle, hash, hashlen, key->pubkey.x, key->pubkey.y, - key->pubkey.z, r, s, res, key->heap); + return sp_dsp_ecc_verify_256(key->handle, hash, hashlen, key->pubkey.x, + key->pubkey.y, key->pubkey.z, r, s, res, key->heap); } if (wolfSSL_GetHandleCbSet() == 1) { - return sp_dsp_ecc_verify_256(0, hash, hashlen, key->pubkey.x, key->pubkey.y, - key->pubkey.z, r, s, res, key->heap); + return sp_dsp_ecc_verify_256(0, hash, hashlen, key->pubkey.x, + key->pubkey.y, key->pubkey.z, r, s, res, key->heap); } #endif + #if defined(WOLFSSL_SP_MATH) && !defined(FREESCALE_LTC_ECC) -#ifndef WOLFSSL_SP_NO_256 - if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { - return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, key->pubkey.y, - key->pubkey.z, r, s, res, key->heap); - } -#endif -#ifdef WOLFSSL_SP_384 - if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { - return sp_ecc_verify_384(hash, hashlen, key->pubkey.x, key->pubkey.y, - key->pubkey.z, r, s, res, key->heap); - } -#endif - return WC_KEY_SIZE_E; -#else -#if defined WOLFSSL_HAVE_SP_ECC && !defined(FREESCALE_LTC_ECC) - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) - if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC) - #endif - { -#ifndef WOLFSSL_SP_NO_256 - if (key->idx != ECC_CUSTOM_IDX && - ecc_sets[key->idx].id == ECC_SECP256R1) { - return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, - key->pubkey.y, key->pubkey.z,r, s, res, - key->heap); - } -#endif /* WOLFSSL_SP_NO_256 */ -#ifdef WOLFSSL_SP_384 - if (key->idx != ECC_CUSTOM_IDX && - ecc_sets[key->idx].id == ECC_SECP384R1) { - return sp_ecc_verify_384(hash, hashlen, key->pubkey.x, - key->pubkey.y, key->pubkey.z,r, s, res, - key->heap); - } -#endif /* WOLFSSL_SP_384 */ + if (key->idx == ECC_CUSTOM_IDX || + (ecc_sets[key->idx].id != ECC_SECP256R1 && + ecc_sets[key->idx].id != ECC_SECP384R1)) { + return WC_KEY_SIZE_E; } -#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif + +#if (defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_HAVE_SP_ECC)) && \ + !defined(FREESCALE_LTC_ECC) + if (key->idx != ECC_CUSTOM_IDX + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + && key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC + #endif + ) { + #if defined(WC_ECC_NONBLOCK) && defined(WC_ECC_NONBLOCK_ONLY) + /* perform blocking call to non-blocking function */ + ecc_nb_ctx_t nb_ctx; + XMEMSET(&nb_ctx, 0, sizeof(nb_ctx)); + #endif + #ifndef WOLFSSL_SP_NO_256 + if (ecc_sets[key->idx].id == ECC_SECP256R1) { + #ifdef WC_ECC_NONBLOCK + if (key->nb_ctx) { + return sp_ecc_verify_256_nb(&key->nb_ctx->sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, + key->heap); + } + #ifdef WC_ECC_NONBLOCK_ONLY + do { /* perform blocking call to non-blocking function */ + err = sp_ecc_verify_256_nb(&nb_ctx->sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, + key->heap); + } while (err == FP_WOULDBLOCK); + return err; + #endif + #endif /* WC_ECC_NONBLOCK */ + #if !defined(WC_ECC_NONBLOCK) || (defined(WC_ECC_NONBLOCK) && !defined(WC_ECC_NONBLOCK_ONLY)) + return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, + key->pubkey.y, key->pubkey.z, r, s, res, key->heap); + #endif + } + #endif + #ifdef WOLFSSL_SP_384 + if (ecc_sets[key->idx].id == ECC_SECP384R1) { + #ifdef WC_ECC_NONBLOCK + if (key->nb_ctx) { + return sp_ecc_verify_384_nb(&key->nb_ctx->sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, + key->heap); + } + #ifdef WC_ECC_NONBLOCK_ONLY + do { /* perform blocking call to non-blocking function */ + err = sp_ecc_verify_384_nb(&nb_ctx.sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, + key->heap); + } while (err == FP_WOULDBLOCK); + return err; + #endif + #endif /* WC_ECC_NONBLOCK */ + #if !defined(WC_ECC_NONBLOCK) || (defined(WC_ECC_NONBLOCK) && !defined(WC_ECC_NONBLOCK_ONLY)) + return sp_ecc_verify_384(hash, hashlen, key->pubkey.x, + key->pubkey.y, key->pubkey.z, r, s, res, key->heap); + #endif + } + #endif + } +#endif + +#if !defined(WOLFSSL_SP_MATH) || defined(FREESCALE_LTC_ECC) ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); @@ -6287,7 +6340,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, wc_ecc_curve_free(curve); FREE_CURVE_SPECS(); -#endif /* WOLFSSL_SP_MATH */ +#endif /* !WOLFSSL_SP_MATH || FREESCALE_LTC_ECC */ #endif /* WOLFSSL_ATECC508A */ (void)keySz; @@ -10816,4 +10869,18 @@ int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz, } #endif /* HAVE_X963_KDF */ +#ifdef WC_ECC_NONBLOCK +/* Enable ECC support for non-blocking operations */ +int wc_ecc_set_nonblock(ecc_key *key, ecc_nb_ctx_t* ctx) +{ + if (key) { + if (ctx) { + XMEMSET(ctx, 0, sizeof(ecc_nb_ctx_t)); + } + key->nb_ctx = ctx; + } + return 0; +} +#endif /* WC_ECC_NONBLOCK */ + #endif /* HAVE_ECC */ diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index e9f777b429..decb1b37ef 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -1988,7 +1988,7 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, calls/ifs) */ #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C if (((P->used * 2 + 1) < (int)MP_WARRAY) && - P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + P->used < (1L << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { redux = fast_mp_montgomery_reduce; } else #endif @@ -2234,7 +2234,7 @@ int mp_exptmod_base_2(mp_int * X, mp_int * P, mp_int * Y) calls/ifs) */ #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C if (((P->used * 2 + 1) < (int)MP_WARRAY) && - P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + P->used < (1L << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { redux = fast_mp_montgomery_reduce; } else #endif @@ -2594,7 +2594,7 @@ int mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) digs = n->used * 2 + 1; if ((digs < (int)MP_WARRAY) && n->used < - (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + (1L << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { return fast_mp_montgomery_reduce (x, n, rho); } @@ -3041,7 +3041,7 @@ int mp_mul (mp_int * a, mp_int * b, mp_int * c) if ((digs < (int)MP_WARRAY) && MIN(a->used, b->used) <= - (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + (1L << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { res = fast_s_mp_mul_digs (a, b, c, digs); } else #endif @@ -3504,7 +3504,7 @@ int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* can we use the fast multiplier? */ if ((digs < (int)MP_WARRAY) && MIN (a->used, b->used) < - (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + (1L << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { return fast_s_mp_mul_digs (a, b, c, digs); } @@ -4012,7 +4012,7 @@ int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) #ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C if (((a->used + b->used + 1) < (int)MP_WARRAY) && MIN (a->used, b->used) < - (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + (1L << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { return fast_s_mp_mul_high_digs (a, b, c, digs); } #endif @@ -4322,6 +4322,8 @@ int mp_sub_d (mp_int * a, mp_digit b, mp_int * c) mp_digit *tmpa, *tmpc, mu; int res, ix, oldused; + if (b > MP_MASK) return MP_VAL; + /* grow c as required */ if (c->alloc < a->used + 1) { if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { @@ -4541,7 +4543,7 @@ int mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) #if defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) -const mp_digit ltm_prime_tab[PRIME_SIZE] = { +const FLASH_QUALIFIER mp_digit ltm_prime_tab[PRIME_SIZE] = { 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, diff --git a/wolfcrypt/src/port/arm/armv8-chacha.c b/wolfcrypt/src/port/arm/armv8-chacha.c index df76bece0b..93387cd819 100644 --- a/wolfcrypt/src/port/arm/armv8-chacha.c +++ b/wolfcrypt/src/port/arm/armv8-chacha.c @@ -2186,17 +2186,15 @@ static WC_INLINE void wc_Chacha_encrypt_64(const word32* input, const byte* m, "BEQ L_chacha20_arm64_64_done_%= \n\t" "\n" "L_chacha20_arm64_64_lt_8_%=: \n\t" - "MOV x4, v0.D[0] \n\t" - "LSL x5, %[bytes], #3 \n\t" + "MOV x4, v0.D[0] \n\t" "\n" "L_chacha20_arm64_64_loop_lt_8_%=: \n\t" - "LDRB w6, [%[m], %[bytes]] \n\t" - "ROR x7, x4, x5 \n\t" - "EOR w6, w6, w7 \n\t" - "STRB w6, [%[c], %[bytes]] \n\t" - "SUBS %[bytes], %[bytes], #1 \n\t" - "SUB x5, x5, #8 \n\t" - "BGE L_chacha20_arm64_64_loop_lt_8_%= \n\t" + "LDRB w6, [%[m]], #1 \n\t" + "EOR w6, w6, w4 \n\t" + "STRB w6, [%[c]], #1 \n\t" + "SUBS %[bytes], %[bytes], #1 \n\t" + "LSR x4, x4, #8 \n\t" + "BGT L_chacha20_arm64_64_loop_lt_8_%= \n\t" "\n" "L_chacha20_arm64_64_done_%=: \n\t" : [input] "+r" (input), [m] "+r" (m), [c] "+r" (c), [bytes] "+r" (bytes64) diff --git a/wolfcrypt/src/port/arm/armv8-curve25519.S b/wolfcrypt/src/port/arm/armv8-curve25519.S index 36be60de56..e8da5267ff 100644 --- a/wolfcrypt/src/port/arm/armv8-curve25519.S +++ b/wolfcrypt/src/port/arm/armv8-curve25519.S @@ -19,36 +19,66 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#ifdef HAVE_CONFIG_H + #include +#endif /* HAVE_CONFIG_H */ +#include + /* Generated using (from wolfssl): * cd ../scripts * ruby ./x25519/x25519.rb arm64 ../wolfssl/wolfcrypt/src/port/arm/armv8-curve25519.S */ #ifdef WOLFSSL_ARMASM #ifdef __aarch64__ - .text - .align 2 - .globl fe_init - .type fe_init, %function +#ifndef __APPLE__ +.text +.globl fe_init +.type fe_init,@function +.align 2 fe_init: +#else +.section __TEXT,__text +.globl _fe_init +.p2align 2 +_fe_init: +#endif /* __APPLE__ */ ret +#ifndef __APPLE__ .size fe_init,.-fe_init - .text - .align 2 - .globl fe_frombytes - .type fe_frombytes, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_frombytes +.type fe_frombytes,@function +.align 2 fe_frombytes: +#else +.section __TEXT,__text +.globl _fe_frombytes +.p2align 2 +_fe_frombytes: +#endif /* __APPLE__ */ ldp x2, x3, [x1] ldp x4, x5, [x1, #16] and x5, x5, #0x7fffffffffffffff stp x2, x3, [x0] stp x4, x5, [x0, #16] ret +#ifndef __APPLE__ .size fe_frombytes,.-fe_frombytes - .text - .align 2 - .globl fe_tobytes - .type fe_tobytes, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_tobytes +.type fe_tobytes,@function +.align 2 fe_tobytes: +#else +.section __TEXT,__text +.globl _fe_tobytes +.p2align 2 +_fe_tobytes: +#endif /* __APPLE__ */ mov x7, #19 ldp x2, x3, [x1] ldp x4, x5, [x1, #16] @@ -65,45 +95,81 @@ fe_tobytes: stp x2, x3, [x0] stp x4, x5, [x0, #16] ret +#ifndef __APPLE__ .size fe_tobytes,.-fe_tobytes - .text - .align 2 - .globl fe_1 - .type fe_1, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_1 +.type fe_1,@function +.align 2 fe_1: +#else +.section __TEXT,__text +.globl _fe_1 +.p2align 2 +_fe_1: +#endif /* __APPLE__ */ # Set one mov x1, #1 stp x1, xzr, [x0] stp xzr, xzr, [x0, #16] ret +#ifndef __APPLE__ .size fe_1,.-fe_1 - .text - .align 2 - .globl fe_0 - .type fe_0, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_0 +.type fe_0,@function +.align 2 fe_0: +#else +.section __TEXT,__text +.globl _fe_0 +.p2align 2 +_fe_0: +#endif /* __APPLE__ */ # Set zero stp xzr, xzr, [x0] stp xzr, xzr, [x0, #16] ret +#ifndef __APPLE__ .size fe_0,.-fe_0 - .text - .align 2 - .globl fe_copy - .type fe_copy, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_copy +.type fe_copy,@function +.align 2 fe_copy: +#else +.section __TEXT,__text +.globl _fe_copy +.p2align 2 +_fe_copy: +#endif /* __APPLE__ */ # Copy ldp x2, x3, [x1] ldp x4, x5, [x1, #16] stp x2, x3, [x0] stp x4, x5, [x0, #16] ret +#ifndef __APPLE__ .size fe_copy,.-fe_copy - .text - .align 2 - .globl fe_sub - .type fe_sub, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sub +.type fe_sub,@function +.align 2 fe_sub: +#else +.section __TEXT,__text +.globl _fe_sub +.p2align 2 +_fe_sub: +#endif /* __APPLE__ */ # Sub ldp x3, x4, [x1] ldp x5, x6, [x1, #16] @@ -126,12 +192,21 @@ fe_sub: stp x3, x4, [x0] stp x5, x6, [x0, #16] ret +#ifndef __APPLE__ .size fe_sub,.-fe_sub - .text - .align 2 - .globl fe_add - .type fe_add, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_add +.type fe_add,@function +.align 2 fe_add: +#else +.section __TEXT,__text +.globl _fe_add +.p2align 2 +_fe_add: +#endif /* __APPLE__ */ # Add ldp x3, x4, [x1] ldp x5, x6, [x1, #16] @@ -154,12 +229,21 @@ fe_add: stp x3, x4, [x0] stp x5, x6, [x0, #16] ret +#ifndef __APPLE__ .size fe_add,.-fe_add - .text - .align 2 - .globl fe_neg - .type fe_neg, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_neg +.type fe_neg,@function +.align 2 fe_neg: +#else +.section __TEXT,__text +.globl _fe_neg +.p2align 2 +_fe_neg: +#endif /* __APPLE__ */ ldp x2, x3, [x1] ldp x4, x5, [x1, #16] mov x6, #-19 @@ -173,12 +257,21 @@ fe_neg: stp x6, x7, [x0] stp x8, x9, [x0, #16] ret +#ifndef __APPLE__ .size fe_neg,.-fe_neg - .text - .align 2 - .globl fe_isnonzero - .type fe_isnonzero, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_isnonzero +.type fe_isnonzero,@function +.align 2 fe_isnonzero: +#else +.section __TEXT,__text +.globl _fe_isnonzero +.p2align 2 +_fe_isnonzero: +#endif /* __APPLE__ */ mov x6, #19 ldp x1, x2, [x0] ldp x3, x4, [x0, #16] @@ -196,12 +289,21 @@ fe_isnonzero: orr x3, x3, x4 orr x0, x0, x3 ret +#ifndef __APPLE__ .size fe_isnonzero,.-fe_isnonzero - .text - .align 2 - .globl fe_isnegative - .type fe_isnegative, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_isnegative +.type fe_isnegative,@function +.align 2 fe_isnegative: +#else +.section __TEXT,__text +.globl _fe_isnegative +.p2align 2 +_fe_isnegative: +#endif /* __APPLE__ */ mov x6, #19 ldp x1, x2, [x0] ldp x3, x4, [x0, #16] @@ -212,12 +314,21 @@ fe_isnegative: and x0, x1, #1 eor x0, x0, x5, lsr 63 ret +#ifndef __APPLE__ .size fe_isnegative,.-fe_isnegative - .text - .align 2 - .globl fe_cmov_table - .type fe_cmov_table, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_cmov_table +.type fe_cmov_table,@function +.align 2 fe_cmov_table: +#else +.section __TEXT,__text +.globl _fe_cmov_table +.p2align 2 +_fe_cmov_table: +#endif /* __APPLE__ */ stp x29, x30, [sp, #-128]! add x29, sp, #0 str x17, [x29, #40] @@ -438,12 +549,21 @@ fe_cmov_table: ldr x28, [x29, #120] ldp x29, x30, [sp], #0x80 ret +#ifndef __APPLE__ .size fe_cmov_table,.-fe_cmov_table - .text - .align 2 - .globl fe_mul - .type fe_mul, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_mul +.type fe_mul,@function +.align 2 fe_mul: +#else +.section __TEXT,__text +.globl _fe_mul +.p2align 2 +_fe_mul: +#endif /* __APPLE__ */ stp x29, x30, [sp, #-64]! add x29, sp, #0 str x17, [x29, #24] @@ -596,12 +716,21 @@ fe_mul: ldr x22, [x29, #56] ldp x29, x30, [sp], #0x40 ret +#ifndef __APPLE__ .size fe_mul,.-fe_mul - .text - .align 2 - .globl fe_sq - .type fe_sq, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq +.type fe_sq,@function +.align 2 fe_sq: +#else +.section __TEXT,__text +.globl _fe_sq +.p2align 2 +_fe_sq: +#endif /* __APPLE__ */ # Square ldp x13, x14, [x1] ldp x15, x16, [x1, #16] @@ -709,12 +838,21 @@ fe_sq: stp x5, x6, [x0] stp x7, x8, [x0, #16] ret +#ifndef __APPLE__ .size fe_sq,.-fe_sq - .text - .align 2 - .globl fe_invert - .type fe_invert, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_invert +.type fe_invert,@function +.align 2 fe_invert: +#else +.section __TEXT,__text +.globl _fe_invert +.p2align 2 +_fe_invert: +#endif /* __APPLE__ */ stp x29, x30, [sp, #-176]! add x29, sp, #0 str x20, [x29, #168] @@ -722,124 +860,245 @@ fe_invert: str x0, [x29, #144] str x1, [x29, #152] add x0, x29, #16 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ add x0, x29, #48 add x1, x29, #16 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ add x1, x29, #48 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ ldr x1, [x29, #152] add x2, x29, #48 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #16 add x1, x29, #16 add x2, x29, #48 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #0x50 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ add x0, x29, #48 add x1, x29, #48 add x2, x29, #0x50 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #0x50 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x20, #4 add x1, x29, #0x50 L_fe_invert1: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x20, x20, #1 cmp x20, #0 bne L_fe_invert1 add x0, x29, #48 add x2, x29, #48 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #0x50 add x1, x29, #48 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x20, #9 add x1, x29, #0x50 L_fe_invert2: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x20, x20, #1 cmp x20, #0 bne L_fe_invert2 add x2, x29, #48 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #0x70 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x20, #19 add x1, x29, #0x70 L_fe_invert3: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x20, x20, #1 cmp x20, #0 bne L_fe_invert3 add x0, x29, #0x50 add x2, x29, #0x50 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ mov x20, #10 add x1, x29, #0x50 L_fe_invert4: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x20, x20, #1 cmp x20, #0 bne L_fe_invert4 add x0, x29, #48 add x2, x29, #48 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #0x50 add x1, x29, #48 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x20, #49 add x1, x29, #0x50 L_fe_invert5: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x20, x20, #1 cmp x20, #0 bne L_fe_invert5 add x2, x29, #48 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #0x70 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x20, #0x63 add x1, x29, #0x70 L_fe_invert6: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x20, x20, #1 cmp x20, #0 bne L_fe_invert6 add x0, x29, #0x50 add x2, x29, #0x50 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ mov x20, #50 add x1, x29, #0x50 L_fe_invert7: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x20, x20, #1 cmp x20, #0 bne L_fe_invert7 add x0, x29, #48 add x2, x29, #48 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ mov x20, #5 add x1, x29, #48 L_fe_invert8: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x20, x20, #1 cmp x20, #0 bne L_fe_invert8 ldr x0, [x29, #144] add x2, x29, #16 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ ldr x20, [x29, #168] ldp x29, x30, [sp], #0xb0 ret +#ifndef __APPLE__ .size fe_invert,.-fe_invert - .text - .align 2 - .globl curve25519 - .type curve25519, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl curve25519 +.type curve25519,@function +.align 2 curve25519: +#else +.section __TEXT,__text +.globl _curve25519 +.p2align 2 +_curve25519: +#endif /* __APPLE__ */ stp x29, x30, [sp, #-288]! add x29, sp, #0 str x17, [x29, #200] @@ -2157,115 +2416,227 @@ L_curve25519_bits: # Invert add x0, x29, #48 add x1, x29, #16 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ add x0, x29, #0x50 add x1, x29, #48 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ add x1, x29, #0x50 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ add x1, x29, #16 add x2, x29, #0x50 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #48 add x1, x29, #48 add x2, x29, #0x50 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #0x70 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ add x0, x29, #0x50 add x1, x29, #0x50 add x2, x29, #0x70 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #0x70 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x24, #4 add x1, x29, #0x70 L_curve25519_inv_1: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x24, x24, #1 cmp x24, #0 bne L_curve25519_inv_1 add x0, x29, #0x50 add x2, x29, #0x50 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #0x70 add x1, x29, #0x50 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x24, #9 add x1, x29, #0x70 L_curve25519_inv_2: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x24, x24, #1 cmp x24, #0 bne L_curve25519_inv_2 add x2, x29, #0x50 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #0x90 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x24, #19 add x1, x29, #0x90 L_curve25519_inv_3: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x24, x24, #1 cmp x24, #0 bne L_curve25519_inv_3 add x0, x29, #0x70 add x2, x29, #0x70 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ mov x24, #10 add x1, x29, #0x70 L_curve25519_inv_4: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x24, x24, #1 cmp x24, #0 bne L_curve25519_inv_4 add x0, x29, #0x50 add x2, x29, #0x50 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #0x70 add x1, x29, #0x50 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x24, #49 add x1, x29, #0x70 L_curve25519_inv_5: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x24, x24, #1 cmp x24, #0 bne L_curve25519_inv_5 add x2, x29, #0x50 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #0x90 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x24, #0x63 add x1, x29, #0x90 L_curve25519_inv_6: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x24, x24, #1 cmp x24, #0 bne L_curve25519_inv_6 add x0, x29, #0x70 add x2, x29, #0x70 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ mov x24, #50 add x1, x29, #0x70 L_curve25519_inv_7: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x24, x24, #1 cmp x24, #0 bne L_curve25519_inv_7 add x0, x29, #0x50 add x2, x29, #0x50 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ mov x24, #5 add x1, x29, #0x50 L_curve25519_inv_8: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x24, x24, #1 cmp x24, #0 bne L_curve25519_inv_8 add x0, x29, #16 add x2, x29, #48 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ ldr x0, [x29, #176] # Multiply ldp x6, x7, [x0] @@ -2417,12 +2788,21 @@ L_curve25519_inv_8: ldr x28, [x29, #280] ldp x29, x30, [sp], #0x120 ret +#ifndef __APPLE__ .size curve25519,.-curve25519 - .text - .align 2 - .globl fe_pow22523 - .type fe_pow22523, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_pow22523 +.type fe_pow22523,@function +.align 2 fe_pow22523: +#else +.section __TEXT,__text +.globl _fe_pow22523 +.p2align 2 +_fe_pow22523: +#endif /* __APPLE__ */ stp x29, x30, [sp, #-144]! add x29, sp, #0 str x21, [x29, #136] @@ -2430,123 +2810,244 @@ fe_pow22523: str x0, [x29, #112] str x1, [x29, #120] add x0, x29, #16 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ add x0, x29, #48 add x1, x29, #16 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ add x1, x29, #48 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ ldr x1, [x29, #120] add x2, x29, #48 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #16 add x1, x29, #16 add x2, x29, #48 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ add x1, x29, #48 add x2, x29, #16 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #48 add x1, x29, #16 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x21, #4 add x1, x29, #48 L_fe_pow22523_1: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x21, x21, #1 cmp x21, #0 bne L_fe_pow22523_1 add x0, x29, #16 add x2, x29, #16 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #48 add x1, x29, #16 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x21, #9 add x1, x29, #48 L_fe_pow22523_2: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x21, x21, #1 cmp x21, #0 bne L_fe_pow22523_2 add x2, x29, #16 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #0x50 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x21, #19 add x1, x29, #0x50 L_fe_pow22523_3: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x21, x21, #1 cmp x21, #0 bne L_fe_pow22523_3 add x0, x29, #48 add x2, x29, #48 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ mov x21, #10 add x1, x29, #48 L_fe_pow22523_4: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x21, x21, #1 cmp x21, #0 bne L_fe_pow22523_4 add x0, x29, #16 add x2, x29, #16 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #48 add x1, x29, #16 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x21, #49 add x1, x29, #48 L_fe_pow22523_5: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x21, x21, #1 cmp x21, #0 bne L_fe_pow22523_5 add x2, x29, #16 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ add x0, x29, #0x50 +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ mov x21, #0x63 add x1, x29, #0x50 L_fe_pow22523_6: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x21, x21, #1 cmp x21, #0 bne L_fe_pow22523_6 add x0, x29, #48 add x2, x29, #48 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ mov x21, #50 add x1, x29, #48 L_fe_pow22523_7: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x21, x21, #1 cmp x21, #0 bne L_fe_pow22523_7 add x0, x29, #16 add x2, x29, #16 +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ mov x21, #2 add x1, x29, #16 L_fe_pow22523_8: +#ifndef __APPLE__ bl fe_sq +#else + bl _fe_sq +#endif /* __APPLE__ */ sub x21, x21, #1 cmp x21, #0 bne L_fe_pow22523_8 ldr x0, [x29, #112] ldr x2, [x29, #120] +#ifndef __APPLE__ bl fe_mul +#else + bl _fe_mul +#endif /* __APPLE__ */ ldr x21, [x29, #136] ldp x29, x30, [sp], #0x90 ret +#ifndef __APPLE__ .size fe_pow22523,.-fe_pow22523 - .text - .align 2 - .globl fe_ge_to_p2 - .type fe_ge_to_p2, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_to_p2 +.type fe_ge_to_p2,@function +.align 2 fe_ge_to_p2: +#else +.section __TEXT,__text +.globl _fe_ge_to_p2 +.p2align 2 +_fe_ge_to_p2: +#endif /* __APPLE__ */ stp x29, x30, [sp, #-112]! add x29, sp, #0 str x17, [x29, #72] @@ -2990,12 +3491,21 @@ fe_ge_to_p2: ldr x22, [x29, #104] ldp x29, x30, [sp], #0x70 ret +#ifndef __APPLE__ .size fe_ge_to_p2,.-fe_ge_to_p2 - .text - .align 2 - .globl fe_ge_to_p3 - .type fe_ge_to_p3, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_to_p3 +.type fe_ge_to_p3,@function +.align 2 fe_ge_to_p3: +#else +.section __TEXT,__text +.globl _fe_ge_to_p3 +.p2align 2 +_fe_ge_to_p3: +#endif /* __APPLE__ */ stp x29, x30, [sp, #-160]! add x29, sp, #0 str x17, [x29, #88] @@ -3578,12 +4088,21 @@ fe_ge_to_p3: ldr x26, [x29, #152] ldp x29, x30, [sp], #0xa0 ret +#ifndef __APPLE__ .size fe_ge_to_p3,.-fe_ge_to_p3 - .text - .align 2 - .globl fe_ge_dbl - .type fe_ge_dbl, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_dbl +.type fe_ge_dbl,@function +.align 2 fe_ge_dbl: +#else +.section __TEXT,__text +.globl _fe_ge_dbl +.p2align 2 +_fe_ge_dbl: +#endif /* __APPLE__ */ stp x29, x30, [sp, #-176]! add x29, sp, #0 str x17, [x29, #88] @@ -4134,12 +4653,21 @@ fe_ge_dbl: ldr x28, [x29, #168] ldp x29, x30, [sp], #0xb0 ret +#ifndef __APPLE__ .size fe_ge_dbl,.-fe_ge_dbl - .text - .align 2 - .globl fe_ge_madd - .type fe_ge_madd, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_madd +.type fe_ge_madd,@function +.align 2 fe_ge_madd: +#else +.section __TEXT,__text +.globl _fe_ge_madd +.p2align 2 +_fe_ge_madd: +#endif /* __APPLE__ */ stp x29, x30, [sp, #-176]! add x29, sp, #0 str x17, [x29, #88] @@ -4709,12 +5237,21 @@ fe_ge_madd: ldr x28, [x29, #168] ldp x29, x30, [sp], #0xb0 ret +#ifndef __APPLE__ .size fe_ge_madd,.-fe_ge_madd - .text - .align 2 - .globl fe_ge_msub - .type fe_ge_msub, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_msub +.type fe_ge_msub,@function +.align 2 fe_ge_msub: +#else +.section __TEXT,__text +.globl _fe_ge_msub +.p2align 2 +_fe_ge_msub: +#endif /* __APPLE__ */ stp x29, x30, [sp, #-176]! add x29, sp, #0 str x17, [x29, #88] @@ -5284,12 +5821,21 @@ fe_ge_msub: ldr x28, [x29, #168] ldp x29, x30, [sp], #0xb0 ret +#ifndef __APPLE__ .size fe_ge_msub,.-fe_ge_msub - .text - .align 2 - .globl fe_ge_add - .type fe_ge_add, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_add +.type fe_ge_add,@function +.align 2 fe_ge_add: +#else +.section __TEXT,__text +.globl _fe_ge_add +.p2align 2 +_fe_ge_add: +#endif /* __APPLE__ */ stp x29, x30, [sp, #-176]! add x29, sp, #0 str x17, [x29, #88] @@ -5998,12 +6544,21 @@ fe_ge_add: ldr x28, [x29, #168] ldp x29, x30, [sp], #0xb0 ret +#ifndef __APPLE__ .size fe_ge_add,.-fe_ge_add - .text - .align 2 - .globl fe_ge_sub - .type fe_ge_sub, %function +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_sub +.type fe_ge_sub,@function +.align 2 fe_ge_sub: +#else +.section __TEXT,__text +.globl _fe_ge_sub +.p2align 2 +_fe_ge_sub: +#endif /* __APPLE__ */ stp x29, x30, [sp, #-176]! add x29, sp, #0 str x17, [x29, #88] @@ -6712,7 +7267,9 @@ fe_ge_sub: ldr x28, [x29, #168] ldp x29, x30, [sp], #0xb0 ret +#ifndef __APPLE__ .size fe_ge_sub,.-fe_ge_sub +#endif /* __APPLE__ */ #endif /* __aarch64__ */ #endif /* WOLFSSL_ARMASM */ diff --git a/wolfcrypt/src/port/arm/armv8-curve25519.c b/wolfcrypt/src/port/arm/armv8-curve25519.c index b84a9d1902..97d30025f5 100644 --- a/wolfcrypt/src/port/arm/armv8-curve25519.c +++ b/wolfcrypt/src/port/arm/armv8-curve25519.c @@ -19,17 +19,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#ifdef HAVE_CONFIG_H + #include +#endif /* HAVE_CONFIG_H */ +#include + /* Generated using (from wolfssl): * cd ../scripts * ruby ./x25519/x25519.rb arm64 ../wolfssl/wolfcrypt/src/port/arm/armv8-curve25519.c */ #ifdef WOLFSSL_ARMASM #ifdef __aarch64__ -#include -#ifdef HAVE_CONFIG_H - #include -#endif /* HAVE_CONFIG_H */ -#include #include void fe_init() @@ -771,123 +771,235 @@ void fe_invert(fe r, const fe a) "str %x[r], [x29, #144]\n\t" "str %x[a], [x29, #152]\n\t" "add x0, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "add x0, x29, #48\n\t" "add x1, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "add x1, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "ldr x1, [x29, #152]\n\t" "add x2, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #16\n\t" "add x1, x29, #16\n\t" "add x2, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "add x0, x29, #48\n\t" "add x1, x29, #48\n\t" "add x2, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x20, #4\n\t" "add x1, x29, #0x50\n\t" "\n" "L_fe_invert1_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x20, x20, #1\n\t" "cmp x20, #0\n\t" "bne L_fe_invert1_%=\n\t" "add x0, x29, #48\n\t" "add x2, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x50\n\t" "add x1, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x20, #9\n\t" "add x1, x29, #0x50\n\t" "\n" "L_fe_invert2_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x20, x20, #1\n\t" "cmp x20, #0\n\t" "bne L_fe_invert2_%=\n\t" "add x2, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x70\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x20, #19\n\t" "add x1, x29, #0x70\n\t" "\n" "L_fe_invert3_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x20, x20, #1\n\t" "cmp x20, #0\n\t" "bne L_fe_invert3_%=\n\t" "add x0, x29, #0x50\n\t" "add x2, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "mov x20, #10\n\t" "add x1, x29, #0x50\n\t" "\n" "L_fe_invert4_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x20, x20, #1\n\t" "cmp x20, #0\n\t" "bne L_fe_invert4_%=\n\t" "add x0, x29, #48\n\t" "add x2, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x50\n\t" "add x1, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x20, #49\n\t" "add x1, x29, #0x50\n\t" "\n" "L_fe_invert5_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x20, x20, #1\n\t" "cmp x20, #0\n\t" "bne L_fe_invert5_%=\n\t" "add x2, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x70\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x20, #0x63\n\t" "add x1, x29, #0x70\n\t" "\n" "L_fe_invert6_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x20, x20, #1\n\t" "cmp x20, #0\n\t" "bne L_fe_invert6_%=\n\t" "add x0, x29, #0x50\n\t" "add x2, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "mov x20, #50\n\t" "add x1, x29, #0x50\n\t" "\n" "L_fe_invert7_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x20, x20, #1\n\t" "cmp x20, #0\n\t" "bne L_fe_invert7_%=\n\t" "add x0, x29, #48\n\t" "add x2, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "mov x20, #5\n\t" "add x1, x29, #48\n\t" "\n" "L_fe_invert8_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x20, x20, #1\n\t" "cmp x20, #0\n\t" "bne L_fe_invert8_%=\n\t" "ldr x0, [x29, #144]\n\t" "add x2, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "ldp x29, x30, [sp], #0xa0\n\t" : [r] "+r" (r), [a] "+r" (a) : @@ -2210,123 +2322,235 @@ int curve25519(byte* r, byte* n, byte* a) /* Invert */ "add x0, x29, #48\n\t" "add x1, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x50\n\t" "add x1, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "add x1, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "add x1, x29, #16\n\t" "add x2, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #48\n\t" "add x1, x29, #48\n\t" "add x2, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x70\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x50\n\t" "add x1, x29, #0x50\n\t" "add x2, x29, #0x70\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x70\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x24, #4\n\t" "add x1, x29, #0x70\n\t" "\n" "L_curve25519_inv_1_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x24, x24, #1\n\t" "cmp x24, #0\n\t" "bne L_curve25519_inv_1_%=\n\t" "add x0, x29, #0x50\n\t" "add x2, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x70\n\t" "add x1, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x24, #9\n\t" "add x1, x29, #0x70\n\t" "\n" "L_curve25519_inv_2_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x24, x24, #1\n\t" "cmp x24, #0\n\t" "bne L_curve25519_inv_2_%=\n\t" "add x2, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x90\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x24, #19\n\t" "add x1, x29, #0x90\n\t" "\n" "L_curve25519_inv_3_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x24, x24, #1\n\t" "cmp x24, #0\n\t" "bne L_curve25519_inv_3_%=\n\t" "add x0, x29, #0x70\n\t" "add x2, x29, #0x70\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "mov x24, #10\n\t" "add x1, x29, #0x70\n\t" "\n" "L_curve25519_inv_4_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x24, x24, #1\n\t" "cmp x24, #0\n\t" "bne L_curve25519_inv_4_%=\n\t" "add x0, x29, #0x50\n\t" "add x2, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x70\n\t" "add x1, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x24, #49\n\t" "add x1, x29, #0x70\n\t" "\n" "L_curve25519_inv_5_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x24, x24, #1\n\t" "cmp x24, #0\n\t" "bne L_curve25519_inv_5_%=\n\t" "add x2, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x90\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x24, #0x63\n\t" "add x1, x29, #0x90\n\t" "\n" "L_curve25519_inv_6_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x24, x24, #1\n\t" "cmp x24, #0\n\t" "bne L_curve25519_inv_6_%=\n\t" "add x0, x29, #0x70\n\t" "add x2, x29, #0x70\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "mov x24, #50\n\t" "add x1, x29, #0x70\n\t" "\n" "L_curve25519_inv_7_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x24, x24, #1\n\t" "cmp x24, #0\n\t" "bne L_curve25519_inv_7_%=\n\t" "add x0, x29, #0x50\n\t" "add x2, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "mov x24, #5\n\t" "add x1, x29, #0x50\n\t" "\n" "L_curve25519_inv_8_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x24, x24, #1\n\t" "cmp x24, #0\n\t" "bne L_curve25519_inv_8_%=\n\t" "add x0, x29, #16\n\t" "add x2, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "ldr %x[r], [x29, #176]\n\t" /* Multiply */ "ldp x6, x7, [%x[r]]\n\t" @@ -2486,122 +2710,234 @@ void fe_pow22523(fe r, const fe a) "str %x[r], [x29, #112]\n\t" "str %x[a], [x29, #120]\n\t" "add x0, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "add x0, x29, #48\n\t" "add x1, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "add x1, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "ldr x1, [x29, #120]\n\t" "add x2, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #16\n\t" "add x1, x29, #16\n\t" "add x2, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "add x1, x29, #48\n\t" "add x2, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #48\n\t" "add x1, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x21, #4\n\t" "add x1, x29, #48\n\t" "\n" "L_fe_pow22523_1_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x21, x21, #1\n\t" "cmp x21, #0\n\t" "bne L_fe_pow22523_1_%=\n\t" "add x0, x29, #16\n\t" "add x2, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #48\n\t" "add x1, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x21, #9\n\t" "add x1, x29, #48\n\t" "\n" "L_fe_pow22523_2_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x21, x21, #1\n\t" "cmp x21, #0\n\t" "bne L_fe_pow22523_2_%=\n\t" "add x2, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x21, #19\n\t" "add x1, x29, #0x50\n\t" "\n" "L_fe_pow22523_3_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x21, x21, #1\n\t" "cmp x21, #0\n\t" "bne L_fe_pow22523_3_%=\n\t" "add x0, x29, #48\n\t" "add x2, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "mov x21, #10\n\t" "add x1, x29, #48\n\t" "\n" "L_fe_pow22523_4_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x21, x21, #1\n\t" "cmp x21, #0\n\t" "bne L_fe_pow22523_4_%=\n\t" "add x0, x29, #16\n\t" "add x2, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #48\n\t" "add x1, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x21, #49\n\t" "add x1, x29, #48\n\t" "\n" "L_fe_pow22523_5_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x21, x21, #1\n\t" "cmp x21, #0\n\t" "bne L_fe_pow22523_5_%=\n\t" "add x2, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "add x0, x29, #0x50\n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "mov x21, #0x63\n\t" "add x1, x29, #0x50\n\t" "\n" "L_fe_pow22523_6_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x21, x21, #1\n\t" "cmp x21, #0\n\t" "bne L_fe_pow22523_6_%=\n\t" "add x0, x29, #48\n\t" "add x2, x29, #48\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "mov x21, #50\n\t" "add x1, x29, #48\n\t" "\n" "L_fe_pow22523_7_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x21, x21, #1\n\t" "cmp x21, #0\n\t" "bne L_fe_pow22523_7_%=\n\t" "add x0, x29, #16\n\t" "add x2, x29, #16\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "mov x21, #2\n\t" "add x1, x29, #16\n\t" "\n" "L_fe_pow22523_8_%=: \n\t" +#ifndef __APPLE__ "bl fe_sq\n\t" +#else + "bl _fe_sq\n\t" +#endif /* __APPLE__ */ "sub x21, x21, #1\n\t" "cmp x21, #0\n\t" "bne L_fe_pow22523_8_%=\n\t" "ldr x0, [x29, #112]\n\t" "ldr x2, [x29, #120]\n\t" +#ifndef __APPLE__ "bl fe_mul\n\t" +#else + "bl _fe_mul\n\t" +#endif /* __APPLE__ */ "ldp x29, x30, [sp], #0x80\n\t" : [r] "+r" (r), [a] "+r" (a) : diff --git a/wolfcrypt/src/port/arm/armv8-poly1305.c b/wolfcrypt/src/port/arm/armv8-poly1305.c index 3df07f701a..11f3c7c63a 100644 --- a/wolfcrypt/src/port/arm/armv8-poly1305.c +++ b/wolfcrypt/src/port/arm/armv8-poly1305.c @@ -24,9 +24,6 @@ * and Daniel J. Bernstein */ - -#ifdef __aarch64__ - #ifdef HAVE_CONFIG_H #include #endif @@ -34,6 +31,8 @@ #include #ifdef WOLFSSL_ARMASM +#ifdef __aarch64__ + #ifdef HAVE_POLY1305 #include #include @@ -208,11 +207,11 @@ void poly1305_blocks(Poly1305* ctx, const unsigned char *m, "MOV v28.D[0], x9 \n\t" "AND x22, x22, #0x3ffffff \n\t" /* Zero accumulator registers */ - "MOVI v15.2D, #0x0 \n\t" - "MOVI v16.2D, #0x0 \n\t" - "MOVI v17.2D, #0x0 \n\t" - "MOVI v18.2D, #0x0 \n\t" - "MOVI v19.2D, #0x0 \n\t" + "MOVI v15.16B, #0x0 \n\t" + "MOVI v16.16B, #0x0 \n\t" + "MOVI v17.16B, #0x0 \n\t" + "MOVI v18.16B, #0x0 \n\t" + "MOVI v19.16B, #0x0 \n\t" /* Set hibit */ "CMP %[finished], #0 \n\t" "CSET x9, EQ \n\t" @@ -1162,5 +1161,5 @@ int wc_Poly1305Final(Poly1305* ctx, byte* mac) } #endif /* HAVE_POLY1305 */ -#endif /* WOLFSSL_ARMASM */ #endif /* __aarch64__ */ +#endif /* WOLFSSL_ARMASM */ diff --git a/wolfcrypt/src/port/arm/armv8-sha512-asm.S b/wolfcrypt/src/port/arm/armv8-sha512-asm.S index 6ae7a30c4d..8cff141da0 100644 --- a/wolfcrypt/src/port/arm/armv8-sha512-asm.S +++ b/wolfcrypt/src/port/arm/armv8-sha512-asm.S @@ -19,17 +19,30 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#ifdef HAVE_CONFIG_H + #include +#endif /* HAVE_CONFIG_H */ +#include + /* Generated using (from wolfssl): * cd ../scripts * ruby ./sha2/sha512.rb arm64 ../wolfssl/wolfcrypt/src/port/arm/armv8-sha512-asm.S */ #ifdef WOLFSSL_ARMASM #ifdef __aarch64__ +#ifndef __APPLE__ .text - .section .rodata .type L_SHA512_transform_neon_len_k, %object + .section .rodata .size L_SHA512_transform_neon_len_k, 640 +#else + .section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ .align 3 +#else + .p2align 3 +#endif /* __APPLE__ */ L_SHA512_transform_neon_len_k: .xword 0x428a2f98d728ae22 .xword 0x7137449123ef65cd @@ -111,18 +124,33 @@ L_SHA512_transform_neon_len_k: .xword 0x597f299cfc657e2a .xword 0x5fcb6fab3ad6faec .xword 0x6c44198c4a475817 +#ifndef __APPLE__ .text - .section .rodata .type L_SHA512_transform_neon_len_ror8, %object + .section .rodata .size L_SHA512_transform_neon_len_ror8, 16 +#else + .section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ .align 4 +#else + .p2align 4 +#endif /* __APPLE__ */ L_SHA512_transform_neon_len_ror8: .xword 0x7060504030201, 0x80f0e0d0c0b0a09 - .text - .align 2 - .globl Transform_Sha512_Len - .type Transform_Sha512_Len, %function +#ifndef __APPLE__ +.text +.globl Transform_Sha512_Len +.type Transform_Sha512_Len,@function +.align 2 Transform_Sha512_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha512_Len +.p2align 2 +_Transform_Sha512_Len: +#endif /* __APPLE__ */ stp x29, x30, [sp, #-128]! add x29, sp, #0 str x17, [x29, #16] @@ -133,8 +161,18 @@ Transform_Sha512_Len: stp x26, x27, [x29, #80] stp d8, d9, [x29, #96] stp d10, d11, [x29, #112] +#ifndef __APPLE__ adr x3, L_SHA512_transform_neon_len_k +#else + adrp x3, L_SHA512_transform_neon_len_k@PAGE + add x3, x3, :lo12:L_SHA512_transform_neon_len_k@PAGEOFF +#endif /* __APPLE__ */ +#ifndef __APPLE__ adr x27, L_SHA512_transform_neon_len_ror8 +#else + adrp x27, L_SHA512_transform_neon_len_ror8@PAGE + add x27, x27, :lo12:L_SHA512_transform_neon_len_ror8@PAGEOFF +#endif /* __APPLE__ */ ld1 {v11.16b}, [x27] # Load digest into working vars ldp x4, x5, [x0] @@ -1026,7 +1064,12 @@ L_sha512_len_neon_start: add x6, x6, x21 add x5, x5, x20 add x4, x4, x19 +#ifndef __APPLE__ adr x3, L_SHA512_transform_neon_len_k +#else + adrp x3, L_SHA512_transform_neon_len_k@PAGE + add x3, x3, :lo12:L_SHA512_transform_neon_len_k@PAGEOFF +#endif /* __APPLE__ */ subs w2, w2, #0x80 bne L_sha512_len_neon_begin stp x4, x5, [x0] @@ -1043,7 +1086,9 @@ L_sha512_len_neon_start: ldp d10, d11, [x29, #112] ldp x29, x30, [sp], #0x80 ret +#ifndef __APPLE__ .size Transform_Sha512_Len,.-Transform_Sha512_Len +#endif /* __APPLE__ */ #endif /* __aarch64__ */ #endif /* WOLFSSL_ARMASM */ diff --git a/wolfcrypt/src/port/arm/armv8-sha512-asm.c b/wolfcrypt/src/port/arm/armv8-sha512-asm.c index 1ecfa3ebbb..49dffd7789 100644 --- a/wolfcrypt/src/port/arm/armv8-sha512-asm.c +++ b/wolfcrypt/src/port/arm/armv8-sha512-asm.c @@ -19,17 +19,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#ifdef HAVE_CONFIG_H + #include +#endif /* HAVE_CONFIG_H */ +#include + /* Generated using (from wolfssl): * cd ../scripts * ruby ./sha2/sha512.rb arm64 ../wolfssl/wolfcrypt/src/port/arm/armv8-sha512-asm.c */ #ifdef WOLFSSL_ARMASM #ifdef __aarch64__ -#include -#ifdef HAVE_CONFIG_H - #include -#endif /* HAVE_CONFIG_H */ -#include #include static const uint64_t L_SHA512_transform_neon_len_k[] = { @@ -125,8 +125,18 @@ void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data, word32 len) __asm__ __volatile__ ( "stp x29, x30, [sp, #-16]!\n\t" "add x29, sp, #0\n\t" +#ifndef __APPLE__ "adr x3, %[L_SHA512_transform_neon_len_k]\n\t" +#else + "adrp x3, %[L_SHA512_transform_neon_len_k]@PAGE\n\t" + "add x3, x3, %[L_SHA512_transform_neon_len_k]@PAGEOFF\n\t" +#endif /* __APPLE__ */ +#ifndef __APPLE__ "adr x27, %[L_SHA512_transform_neon_len_ror8]\n\t" +#else + "adrp x27, %[L_SHA512_transform_neon_len_ror8]@PAGE\n\t" + "add x27, x27, %[L_SHA512_transform_neon_len_ror8]@PAGEOFF\n\t" +#endif /* __APPLE__ */ "ld1 {v11.16b}, [x27]\n\t" /* Load digest into working vars */ "ldp x4, x5, [%x[sha512]]\n\t" @@ -1020,7 +1030,12 @@ void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data, word32 len) "add x6, x6, x21\n\t" "add x5, x5, x20\n\t" "add x4, x4, x19\n\t" +#ifndef __APPLE__ "adr x3, %[L_SHA512_transform_neon_len_k]\n\t" +#else + "adrp x3, %[L_SHA512_transform_neon_len_k]@PAGE\n\t" + "add x3, x3, %[L_SHA512_transform_neon_len_k]@PAGEOFF\n\t" +#endif /* __APPLE__ */ "subs %w[len], %w[len], #0x80\n\t" "bne L_sha512_len_neon_begin_%=\n\t" "stp x4, x5, [%x[sha512]]\n\t" diff --git a/wolfcrypt/src/port/atmel/atmel.c b/wolfcrypt/src/port/atmel/atmel.c index 27da811a11..cb287b124a 100644 --- a/wolfcrypt/src/port/atmel/atmel.c +++ b/wolfcrypt/src/port/atmel/atmel.c @@ -336,6 +336,7 @@ int atmel_get_enc_key_default(byte* enckey, word16 keysize) /** * \brief Write enc key before. */ +#if defined(WOLFSSL_ATECC_ECDH_ENC) || defined(WOLFSSL_ATECC_ECDH_IOENC) static int atmel_init_enc_key(void) { int ret; @@ -370,6 +371,7 @@ static int atmel_init_enc_key(void) return ret; } +#endif int atmel_get_rev_info(word32* revision) { @@ -516,6 +518,7 @@ int atmel_init(void) device_init_default(); #endif +#if defined(WOLFSSL_ATECC_ECDH_ENC) || defined(WOLFSSL_ATECC_ECDH_IOENC) /* Init the I2C pipe encryption key. */ /* Value is generated/stored during pair for the ATECC508A and stored on micro flash */ @@ -524,6 +527,7 @@ int atmel_init(void) WOLFSSL_MSG("Failed to initialize transport key"); return WC_HW_E; } +#endif mAtcaInitDone = 1; } diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index afed0a4bbe..dfec753164 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -1107,20 +1107,20 @@ exit_rng_ht: } -const byte seedA[] = { +const FLASH_QUALIFIER byte seedA_data[] = { 0x63, 0x36, 0x33, 0x77, 0xe4, 0x1e, 0x86, 0x46, 0x8d, 0xeb, 0x0a, 0xb4, 0xa8, 0xed, 0x68, 0x3f, 0x6a, 0x13, 0x4e, 0x47, 0xe0, 0x14, 0xc7, 0x00, 0x45, 0x4e, 0x81, 0xe9, 0x53, 0x58, 0xa5, 0x69, 0x80, 0x8a, 0xa3, 0x8f, 0x2a, 0x72, 0xa6, 0x23, 0x59, 0x91, 0x5a, 0x9f, 0x8a, 0x04, 0xca, 0x68 }; -const byte reseedSeedA[] = { +const FLASH_QUALIFIER byte reseedSeedA_data[] = { 0xe6, 0x2b, 0x8a, 0x8e, 0xe8, 0xf1, 0x41, 0xb6, 0x98, 0x05, 0x66, 0xe3, 0xbf, 0xe3, 0xc0, 0x49, 0x03, 0xda, 0xd4, 0xac, 0x2c, 0xdf, 0x9f, 0x22, 0x80, 0x01, 0x0a, 0x67, 0x39, 0xbc, 0x83, 0xd3 }; -const byte outputA[] = { +const FLASH_QUALIFIER byte outputA_data[] = { 0x04, 0xee, 0xc6, 0x3b, 0xb2, 0x31, 0xdf, 0x2c, 0x63, 0x0a, 0x1a, 0xfb, 0xe7, 0x24, 0x94, 0x9d, 0x00, 0x5a, 0x58, 0x78, 0x51, 0xe1, 0xaa, 0x79, 0x5e, 0x47, 0x73, 0x47, 0xc8, 0xb0, 0x56, 0x62, 0x1c, 0x18, 0xbd, 0xdc, @@ -1134,7 +1134,7 @@ const byte outputA[] = { 0xa1, 0x80, 0x18, 0x3a, 0x07, 0xdf, 0xae, 0x17 }; -const byte seedB[] = { +const FLASH_QUALIFIER byte seedB_data[] = { 0xa6, 0x5a, 0xd0, 0xf3, 0x45, 0xdb, 0x4e, 0x0e, 0xff, 0xe8, 0x75, 0xc3, 0xa2, 0xe7, 0x1f, 0x42, 0xc7, 0x12, 0x9d, 0x62, 0x0f, 0xf5, 0xc1, 0x19, 0xa9, 0xef, 0x55, 0xf0, 0x51, 0x85, 0xe0, 0xfb, /* nonce next */ @@ -1142,7 +1142,7 @@ const byte seedB[] = { 0xdb, 0xcb, 0xcc, 0x2e }; -const byte outputB[] = { +const FLASH_QUALIFIER byte outputB_data[] = { 0xd3, 0xe1, 0x60, 0xc3, 0x5b, 0x99, 0xf3, 0x40, 0xb2, 0x62, 0x82, 0x64, 0xd1, 0x75, 0x10, 0x60, 0xe0, 0x04, 0x5d, 0xa3, 0x83, 0xff, 0x57, 0xa5, 0x7d, 0x73, 0xa6, 0x73, 0xd2, 0xb8, 0xd8, 0x0d, 0xaa, 0xf6, 0xa6, 0xc3, @@ -1175,17 +1175,65 @@ static int wc_RNG_HealthTestLocal(int reseed) #endif if (reseed) { - ret = wc_RNG_HealthTest(1, seedA, sizeof(seedA), - reseedSeedA, sizeof(reseedSeedA), +#ifdef WOLFSSL_USE_FLASHMEM + byte* seedA = (byte*)XMALLOC(sizeof(seedA_data), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + byte* reseedSeedA = (byte*)XMALLOC(sizeof(reseedSeedA_data), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + byte* outputA = (byte*)XMALLOC(sizeof(outputA_data), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (!seedA || !reseedSeedA || !outputA) { + XFREE(seedA, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(reseedSeedA, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(outputA, NULL, DYNAMIC_TYPE_TMP_BUFFER); + ret = MEMORY_E; + } + else { + XMEMCPY_P(seedA, seedA_data, sizeof(seedA_data)); + XMEMCPY_P(reseedSeedA, reseedSeedA_data, sizeof(reseedSeedA_data)); + XMEMCPY_P(outputA, outputA_data, sizeof(outputA_data)); +#else + const byte* seedA = seedA_data; + const byte* reseedSeedA = reseedSeedA_data; + const byte* outputA = outputA_data; +#endif + ret = wc_RNG_HealthTest(1, seedA, sizeof(seedA_data), + reseedSeedA, sizeof(reseedSeedA_data), check, RNG_HEALTH_TEST_CHECK_SIZE); if (ret == 0) { if (ConstantCompare(check, outputA, RNG_HEALTH_TEST_CHECK_SIZE) != 0) ret = -1; } + +#ifdef WOLFSSL_USE_FLASHMEM + XFREE(seedA, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(reseedSeedA, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(outputA, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif } else { - ret = wc_RNG_HealthTest(0, seedB, sizeof(seedB), +#ifdef WOLFSSL_USE_FLASHMEM + byte* seedB = (byte*)XMALLOC(sizeof(seedB_data), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + byte* outputB = (byte*)XMALLOC(sizeof(outputB_data), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (!seedB || !outputB) { + XFREE(seedB, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(outputB, NULL, DYNAMIC_TYPE_TMP_BUFFER); + ret = MEMORY_E; + } + else { + XMEMCPY_P(seedB, seedB_data, sizeof(seedB_data)); + XMEMCPY_P(outputB, outputB_data, sizeof(outputB_data)); +#else + const byte* seedB = seedB_data; + const byte* outputB = outputB_data; +#endif + ret = wc_RNG_HealthTest(0, seedB, sizeof(seedB_data), NULL, 0, check, RNG_HEALTH_TEST_CHECK_SIZE); if (ret == 0) { @@ -1200,16 +1248,22 @@ static int wc_RNG_HealthTestLocal(int reseed) * byte 32, feed them into the health test separately. */ if (ret == 0) { ret = wc_RNG_HealthTest_ex(0, - seedB + 32, sizeof(seedB) - 32, + seedB + 32, sizeof(seedB_data) - 32, seedB, 32, NULL, 0, check, RNG_HEALTH_TEST_CHECK_SIZE, NULL, INVALID_DEVID); if (ret == 0) { - if (ConstantCompare(check, outputB, sizeof(outputB)) != 0) + if (ConstantCompare(check, outputB, sizeof(outputB_data)) != 0) ret = -1; } } + +#ifdef WOLFSSL_USE_FLASHMEM + XFREE(seedB, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(outputB, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif } #ifdef WOLFSSL_SMALL_STACK diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 48b0ffe8a9..2b2521bbde 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -709,7 +709,7 @@ static int InitSha256(wc_Sha256* sha256) #ifdef NEED_SOFT_SHA256 - static const ALIGN32 word32 K[64] = { + static const FLASH_QUALIFIER ALIGN32 word32 K[64] = { 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL, 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L, 0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, diff --git a/wolfcrypt/src/sp_arm32.c b/wolfcrypt/src/sp_arm32.c index c0743d619a..085d8c0690 100644 --- a/wolfcrypt/src/sp_arm32.c +++ b/wolfcrypt/src/sp_arm32.c @@ -7394,11 +7394,11 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, sp_digit a[128], m[64], r[128]; #else sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; #endif - sp_digit *ah; + sp_digit *ah = NULL; sp_digit e[1]; int err = MP_OKAY; @@ -7734,10 +7734,10 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -7796,16 +7796,16 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, sp_digit tmpa[64], tmpb[64]; #else sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* tmpa; - sp_digit* tmpb; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; #endif - sp_digit* r; - sp_digit* qi; - sp_digit* dq; + sp_digit* r = NULL; + sp_digit* qi = NULL; + sp_digit* dq = NULL; sp_digit c; int err = MP_OKAY; @@ -18953,11 +18953,11 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, sp_digit a[192], m[96], r[192]; #else sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; #endif - sp_digit *ah; + sp_digit *ah = NULL; sp_digit e[1]; int err = MP_OKAY; @@ -19373,10 +19373,10 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -19435,16 +19435,16 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, sp_digit tmpa[96], tmpb[96]; #else sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* tmpa; - sp_digit* tmpb; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; #endif - sp_digit* r; - sp_digit* qi; - sp_digit* dq; + sp_digit* r = NULL; + sp_digit* qi = NULL; + sp_digit* dq = NULL; sp_digit c; int err = MP_OKAY; @@ -26940,11 +26940,11 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, sp_digit a[256], m[128], r[256]; #else sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; #endif - sp_digit *ah; + sp_digit *ah = NULL; sp_digit e[1]; int err = MP_OKAY; @@ -27440,10 +27440,10 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -27502,16 +27502,16 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, sp_digit tmpa[128], tmpb[128]; #else sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* tmpa; - sp_digit* tmpb; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; #endif - sp_digit* r; - sp_digit* qi; - sp_digit* dq; + sp_digit* r = NULL; + sp_digit* qi = NULL; + sp_digit* dq = NULL; sp_digit c; int err = MP_OKAY; @@ -31332,6 +31332,141 @@ static void sp_256_div2_8(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_8_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_8_ctx; + +static int sp_256_proj_point_dbl_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_8_ctx* ctx = (sp_256_proj_point_dbl_8_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*8; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_8(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_8(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_8(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_8(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_8(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_8(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_8(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_8(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_8(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_8(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_8(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_8(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_8(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_8(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -31504,6 +31639,209 @@ static int sp_256_cmp_equal_8(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_8_ctx { + int state; + sp_256_proj_point_dbl_8_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_8_ctx; + +static int sp_256_proj_point_add_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_8_ctx* ctx = (sp_256_proj_point_add_8_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*8; + ctx->t3 = t + 4*8; + ctx->t4 = t + 6*8; + ctx->t5 = t + 8*8; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_8(ctx->t1, p256_mod, q->y); + sp_256_norm_8(ctx->t1); + if ((sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<8; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<8; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<8; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_8(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_8(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_8(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_8(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_8(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_8(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_8(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_8(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_8(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_8(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_8(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_8(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_8(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_8(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_8(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_8(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_8(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -35706,6 +36044,46 @@ static void sp_256_mont_sqr_n_order_8(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_8_ctx { + int state; + int i; +} sp_256_mont_inv_order_8_ctx; +static int sp_256_mont_inv_order_8_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_8_ctx* ctx = (sp_256_mont_inv_order_8_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 8); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_8(t, t); + if ((p256_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_256_mont_mul_order_8(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 8U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -35821,6 +36199,165 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_256_mont_inv_order_8_ctx mont_inv_order_ctx; + }; + sp_digit e[2*8]; + sp_digit x[2*8]; + sp_digit k[2*8]; + sp_digit r[2*8]; + sp_digit tmp[3 * 2*8]; + sp_point_256 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_256_ctx; + +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + (void)heap; + + switch (ctx->state) { + case 0: /* INIT */ + ctx->s = ctx->e; + ctx->kInv = ctx->k; + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->e, 8, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_256_from_mp(ctx->x, 8, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_8(rng, ctx->k); + } + else { + sp_256_from_mp(ctx->k, 8, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p256_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 8U); + sp_256_norm_8(ctx->r); + c = sp_256_cmp_8(ctx->r, p256_order); + sp_256_cond_sub_8(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(ctx->k, ctx->k, p256_norm_order); + err = sp_256_mod_8(ctx->k, ctx->k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_8(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_256_mont_inv_order_8_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_256_norm_8(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_256_mul_8(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_256_mod_8(ctx->x, ctx->x, p256_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_256_norm_8(ctx->x); + carry = sp_256_add_8(ctx->s, ctx->e, ctx->x); + sp_256_cond_sub_8(ctx->s, ctx->s, p256_order, 0 - carry); + sp_256_norm_8(ctx->s); + c = sp_256_cmp_8(ctx->s, p256_order); + sp_256_cond_sub_8(ctx->s, ctx->s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(ctx->s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(ctx->s, ctx->s, ctx->kInv); + sp_256_norm_8(ctx->s); + + /* Check that signature is usable. */ + if (sp_256_iszero_8(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_256_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_256_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -35992,6 +36529,169 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_256_mont_inv_order_8_ctx mont_inv_order_ctx; + sp_256_proj_point_dbl_8_ctx dbl_ctx; + sp_256_proj_point_add_8_ctx add_ctx; + }; + sp_digit u1[2*8]; + sp_digit u2[2*8]; + sp_digit s[2*8]; + sp_digit tmp[2*8 * 5]; + sp_point_256 p1; + sp_point_256 p2; +} sp_ecc_verify_256_ctx; + +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->u1, 8, hash, (int)hashLen); + sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->s, 8, sm); + sp_256_from_mp(ctx->p2.x, 8, pX); + sp_256_from_mp(ctx->p2.y, 8, pY); + sp_256_from_mp(ctx->p2.z, 8, pZ); + sp_256_mul_8(ctx->s, ctx->s, p256_norm_order); + err = sp_256_mod_8(ctx->s, ctx->s, p256_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_256_norm_8(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_256_mont_inv_order_8_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_256_mont_mul_order_8(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_256_mont_mul_order_8(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_256_proj_point_add_8_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_256_iszero_8(ctx->p1.z)) { + if (sp_256_iszero_8(ctx->p1.x) && sp_256_iszero_8(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<8; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(ctx->u2, 8, r); + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_256_from_mp(ctx->u2, 8, r); + carry = sp_256_add_8(ctx->u2, ctx->u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_8(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(ctx->u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { @@ -40102,6 +40802,141 @@ static void sp_384_div2_12(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_12_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_12_ctx; + +static int sp_384_proj_point_dbl_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_12_ctx* ctx = (sp_384_proj_point_dbl_12_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*12; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_12(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_12(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_12(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_12(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_12(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_12(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_12(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_12(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_12(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_12(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_12(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_12(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_12(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_12(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -40177,6 +41012,209 @@ static int sp_384_cmp_equal_12(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_12_ctx { + int state; + sp_384_proj_point_dbl_12_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_12_ctx; + +static int sp_384_proj_point_add_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_12_ctx* ctx = (sp_384_proj_point_add_12_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*12; + ctx->t3 = t + 4*12; + ctx->t4 = t + 6*12; + ctx->t5 = t + 8*12; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_12(ctx->t1, p384_mod, q->y); + sp_384_norm_12(ctx->t1); + if ((sp_384_cmp_equal_12(p->x, q->x) & sp_384_cmp_equal_12(p->z, q->z) & + (sp_384_cmp_equal_12(p->y, q->y) | sp_384_cmp_equal_12(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<12; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<12; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<12; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_12(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_12(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_12(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_12(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_12(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_12(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_12(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_12(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_12(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_12(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_12(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_12(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_12(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_12(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_12(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_12(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_12(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_12(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_12(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -43458,6 +44496,46 @@ static void sp_384_mont_sqr_n_order_12(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_12_ctx { + int state; + int i; +} sp_384_mont_inv_order_12_ctx; +static int sp_384_mont_inv_order_12_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_12_ctx* ctx = (sp_384_mont_inv_order_12_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 12); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_12(t, t); + if ((p384_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_384_mont_mul_order_12(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 12U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -43544,6 +44622,165 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_384_mont_inv_order_12_ctx mont_inv_order_ctx; + }; + sp_digit e[2*12]; + sp_digit x[2*12]; + sp_digit k[2*12]; + sp_digit r[2*12]; + sp_digit tmp[3 * 2*12]; + sp_point_384 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_384_ctx; + +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + (void)heap; + + switch (ctx->state) { + case 0: /* INIT */ + ctx->s = ctx->e; + ctx->kInv = ctx->k; + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->e, 12, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_384_from_mp(ctx->x, 12, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_12(rng, ctx->k); + } + else { + sp_384_from_mp(ctx->k, 12, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p384_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 12U); + sp_384_norm_12(ctx->r); + c = sp_384_cmp_12(ctx->r, p384_order); + sp_384_cond_sub_12(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_12(ctx->k, ctx->k, p384_norm_order); + err = sp_384_mod_12(ctx->k, ctx->k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_12(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_384_mont_inv_order_12_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_384_norm_12(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_384_mul_12(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_384_mod_12(ctx->x, ctx->x, p384_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_384_norm_12(ctx->x); + carry = sp_384_add_12(ctx->s, ctx->e, ctx->x); + sp_384_cond_sub_12(ctx->s, ctx->s, p384_order, 0 - carry); + sp_384_norm_12(ctx->s); + c = sp_384_cmp_12(ctx->s, p384_order); + sp_384_cond_sub_12(ctx->s, ctx->s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(ctx->s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_12(ctx->s, ctx->s, ctx->kInv); + sp_384_norm_12(ctx->s); + + /* Check that signature is usable. */ + if (sp_384_iszero_12(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_384_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_384_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -43715,6 +44952,169 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_384_mont_inv_order_12_ctx mont_inv_order_ctx; + sp_384_proj_point_dbl_12_ctx dbl_ctx; + sp_384_proj_point_add_12_ctx add_ctx; + }; + sp_digit u1[2*12]; + sp_digit u2[2*12]; + sp_digit s[2*12]; + sp_digit tmp[2*12 * 5]; + sp_point_384 p1; + sp_point_384 p2; +} sp_ecc_verify_384_ctx; + +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->u1, 12, hash, (int)hashLen); + sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->s, 12, sm); + sp_384_from_mp(ctx->p2.x, 12, pX); + sp_384_from_mp(ctx->p2.y, 12, pY); + sp_384_from_mp(ctx->p2.z, 12, pZ); + sp_384_mul_12(ctx->s, ctx->s, p384_norm_order); + err = sp_384_mod_12(ctx->s, ctx->s, p384_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_384_norm_12(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_384_mont_inv_order_12_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_384_mont_mul_order_12(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_384_mont_mul_order_12(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_384_proj_point_add_12_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_384_iszero_12(ctx->p1.z)) { + if (sp_384_iszero_12(ctx->p1.x) && sp_384_iszero_12(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<12; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(ctx->u2, 12, r); + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_12(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_384_from_mp(ctx->u2, 12, r); + carry = sp_384_add_12(ctx->u2, ctx->u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_12(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_12(ctx->u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { diff --git a/wolfcrypt/src/sp_arm64.c b/wolfcrypt/src/sp_arm64.c index 3ea3c4ec10..067b4a1266 100644 --- a/wolfcrypt/src/sp_arm64.c +++ b/wolfcrypt/src/sp_arm64.c @@ -4888,11 +4888,11 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, sp_digit a[64], m[32], r[64]; #else sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; #endif - sp_digit *ah; + sp_digit *ah = NULL; sp_digit e[1]; int err = MP_OKAY; @@ -5124,10 +5124,10 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -5186,16 +5186,16 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, sp_digit tmpa[32], tmpb[32]; #else sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* tmpa; - sp_digit* tmpb; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; #endif - sp_digit* r; - sp_digit* qi; - sp_digit* dq; + sp_digit* r = NULL; + sp_digit* qi = NULL; + sp_digit* dq = NULL; sp_digit c; int err = MP_OKAY; @@ -12597,11 +12597,11 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, sp_digit a[96], m[48], r[96]; #else sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; #endif - sp_digit *ah; + sp_digit *ah = NULL; sp_digit e[1]; int err = MP_OKAY; @@ -12861,10 +12861,10 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -12923,16 +12923,16 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, sp_digit tmpa[48], tmpb[48]; #else sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* tmpa; - sp_digit* tmpb; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; #endif - sp_digit* r; - sp_digit* qi; - sp_digit* dq; + sp_digit* r = NULL; + sp_digit* qi = NULL; + sp_digit* dq = NULL; sp_digit c; int err = MP_OKAY; @@ -17528,11 +17528,11 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, sp_digit a[128], m[64], r[128]; #else sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; #endif - sp_digit *ah; + sp_digit *ah = NULL; sp_digit e[1]; int err = MP_OKAY; @@ -17820,10 +17820,10 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -17882,16 +17882,16 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, sp_digit tmpa[64], tmpb[64]; #else sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* tmpa; - sp_digit* tmpb; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; #endif - sp_digit* r; - sp_digit* qi; - sp_digit* dq; + sp_digit* r = NULL; + sp_digit* qi = NULL; + sp_digit* dq = NULL; sp_digit c; int err = MP_OKAY; @@ -20053,6 +20053,141 @@ static void sp_256_div2_4(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_4_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_4_ctx; + +static int sp_256_proj_point_dbl_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_4_ctx* ctx = (sp_256_proj_point_dbl_4_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*4; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_4(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_4(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_4(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_4(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_4(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_4(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_4(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_4(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_4(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_4(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_4(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_4(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_4(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_4(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_4(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -20303,6 +20438,209 @@ static int sp_256_cmp_equal_4(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_4_ctx { + int state; + sp_256_proj_point_dbl_4_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_4_ctx; + +static int sp_256_proj_point_add_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_4_ctx* ctx = (sp_256_proj_point_add_4_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*4; + ctx->t3 = t + 4*4; + ctx->t4 = t + 6*4; + ctx->t5 = t + 8*4; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_4(ctx->t1, p256_mod, q->y); + sp_256_norm_4(ctx->t1); + if ((sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & + (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_4_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<4; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<4; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<4; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_4(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_4(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_4(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_4(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_4(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_4(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_4(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_4(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_4(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_4(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_4(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_4(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_4(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_4(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_4(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_4(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_4(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_4(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_4(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_4(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -35477,6 +35815,46 @@ static void sp_256_mont_sqr_n_order_4(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_4_ctx { + int state; + int i; +} sp_256_mont_inv_order_4_ctx; +static int sp_256_mont_inv_order_4_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_4_ctx* ctx = (sp_256_mont_inv_order_4_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 4); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_4(t, t); + if ((p256_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_256_mont_mul_order_4(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 4U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_4(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -35592,6 +35970,165 @@ static void sp_256_mont_inv_order_4(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_256_ctx { + int state; + union { + sp_256_ecc_mulmod_4_ctx mulmod_ctx; + sp_256_mont_inv_order_4_ctx mont_inv_order_ctx; + }; + sp_digit e[2*4]; + sp_digit x[2*4]; + sp_digit k[2*4]; + sp_digit r[2*4]; + sp_digit tmp[3 * 2*4]; + sp_point_256 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_256_ctx; + +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + (void)heap; + + switch (ctx->state) { + case 0: /* INIT */ + ctx->s = ctx->e; + ctx->kInv = ctx->k; + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->e, 4, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_256_from_mp(ctx->x, 4, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_4(rng, ctx->k); + } + else { + sp_256_from_mp(ctx->k, 4, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p256_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int64_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 4U); + sp_256_norm_4(ctx->r); + c = sp_256_cmp_4(ctx->r, p256_order); + sp_256_cond_sub_4(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_4(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_4(ctx->k, ctx->k, p256_norm_order); + err = sp_256_mod_4(ctx->k, ctx->k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_4(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_256_mont_inv_order_4_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_256_norm_4(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_256_mul_4(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_256_mod_4(ctx->x, ctx->x, p256_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int64_t c; + sp_256_norm_4(ctx->x); + carry = sp_256_add_4(ctx->s, ctx->e, ctx->x); + sp_256_cond_sub_4(ctx->s, ctx->s, p256_order, 0 - carry); + sp_256_norm_4(ctx->s); + c = sp_256_cmp_4(ctx->s, p256_order); + sp_256_cond_sub_4(ctx->s, ctx->s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_4(ctx->s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_4(ctx->s, ctx->s, ctx->kInv); + sp_256_norm_4(ctx->s); + + /* Check that signature is usable. */ + if (sp_256_iszero_4(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_256_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_256_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 4U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -35763,6 +36300,169 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_256_ctx { + int state; + union { + sp_256_ecc_mulmod_4_ctx mulmod_ctx; + sp_256_mont_inv_order_4_ctx mont_inv_order_ctx; + sp_256_proj_point_dbl_4_ctx dbl_ctx; + sp_256_proj_point_add_4_ctx add_ctx; + }; + sp_digit u1[2*4]; + sp_digit u2[2*4]; + sp_digit s[2*4]; + sp_digit tmp[2*4 * 5]; + sp_point_256 p1; + sp_point_256 p2; +} sp_ecc_verify_256_ctx; + +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->u1, 4, hash, (int)hashLen); + sp_256_from_mp(ctx->u2, 4, r); + sp_256_from_mp(ctx->s, 4, sm); + sp_256_from_mp(ctx->p2.x, 4, pX); + sp_256_from_mp(ctx->p2.y, 4, pY); + sp_256_from_mp(ctx->p2.z, 4, pZ); + sp_256_mul_4(ctx->s, ctx->s, p256_norm_order); + err = sp_256_mod_4(ctx->s, ctx->s, p256_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_256_norm_4(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_256_mont_inv_order_4_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_256_mont_mul_order_4(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_256_mont_mul_order_4(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_256_proj_point_add_4_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_256_iszero_4(ctx->p1.z)) { + if (sp_256_iszero_4(ctx->p1.x) && sp_256_iszero_4(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<4; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_256_proj_point_dbl_4_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(ctx->u2, 4, r); + err = sp_256_mod_mul_norm_4(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_4(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_256_mont_mul_4(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_256_cmp_4(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int64_t c; + + /* Reload r and add order. */ + sp_256_from_mp(ctx->u2, 4, r); + carry = sp_256_add_4(ctx->u2, ctx->u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_4(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_4(ctx->u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_4(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_4(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_4(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { @@ -38098,6 +38798,141 @@ static void sp_384_div2_6(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_6_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_6_ctx; + +static int sp_384_proj_point_dbl_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_6_ctx* ctx = (sp_384_proj_point_dbl_6_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*6; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_6(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_6(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_6(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_6(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_6(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_6(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_6(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_6(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_6(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_6(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_6(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_6(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_6(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_6(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -38260,6 +39095,209 @@ static int sp_384_cmp_equal_6(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_6_ctx { + int state; + sp_384_proj_point_dbl_6_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_6_ctx; + +static int sp_384_proj_point_add_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_6_ctx* ctx = (sp_384_proj_point_add_6_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*6; + ctx->t3 = t + 4*6; + ctx->t4 = t + 6*6; + ctx->t5 = t + 8*6; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_6(ctx->t1, p384_mod, q->y); + sp_384_norm_6(ctx->t1); + if ((sp_384_cmp_equal_6(p->x, q->x) & sp_384_cmp_equal_6(p->z, q->z) & + (sp_384_cmp_equal_6(p->y, q->y) | sp_384_cmp_equal_6(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_6_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<6; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<6; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<6; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_6(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_6(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_6(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_6(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_6(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_6(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_6(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_6(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_6(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_6(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_6(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_6(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_6(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_6(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_6(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_6(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_6(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_6(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_6(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_6(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -41099,6 +42137,46 @@ static void sp_384_mont_sqr_n_order_6(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_6_ctx { + int state; + int i; +} sp_384_mont_inv_order_6_ctx; +static int sp_384_mont_inv_order_6_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_6_ctx* ctx = (sp_384_mont_inv_order_6_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 6); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_6(t, t); + if ((p384_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_384_mont_mul_order_6(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 6U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_6(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -41185,6 +42263,165 @@ static void sp_384_mont_inv_order_6(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_384_ctx { + int state; + union { + sp_384_ecc_mulmod_6_ctx mulmod_ctx; + sp_384_mont_inv_order_6_ctx mont_inv_order_ctx; + }; + sp_digit e[2*6]; + sp_digit x[2*6]; + sp_digit k[2*6]; + sp_digit r[2*6]; + sp_digit tmp[3 * 2*6]; + sp_point_384 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_384_ctx; + +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + (void)heap; + + switch (ctx->state) { + case 0: /* INIT */ + ctx->s = ctx->e; + ctx->kInv = ctx->k; + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->e, 6, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_384_from_mp(ctx->x, 6, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_6(rng, ctx->k); + } + else { + sp_384_from_mp(ctx->k, 6, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p384_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int64_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 6U); + sp_384_norm_6(ctx->r); + c = sp_384_cmp_6(ctx->r, p384_order); + sp_384_cond_sub_6(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_6(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_6(ctx->k, ctx->k, p384_norm_order); + err = sp_384_mod_6(ctx->k, ctx->k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_6(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_384_mont_inv_order_6_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_384_norm_6(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_384_mul_6(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_384_mod_6(ctx->x, ctx->x, p384_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int64_t c; + sp_384_norm_6(ctx->x); + carry = sp_384_add_6(ctx->s, ctx->e, ctx->x); + sp_384_cond_sub_6(ctx->s, ctx->s, p384_order, 0 - carry); + sp_384_norm_6(ctx->s); + c = sp_384_cmp_6(ctx->s, p384_order); + sp_384_cond_sub_6(ctx->s, ctx->s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_6(ctx->s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_6(ctx->s, ctx->s, ctx->kInv); + sp_384_norm_6(ctx->s); + + /* Check that signature is usable. */ + if (sp_384_iszero_6(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_384_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_384_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 6U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -41356,6 +42593,169 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_384_ctx { + int state; + union { + sp_384_ecc_mulmod_6_ctx mulmod_ctx; + sp_384_mont_inv_order_6_ctx mont_inv_order_ctx; + sp_384_proj_point_dbl_6_ctx dbl_ctx; + sp_384_proj_point_add_6_ctx add_ctx; + }; + sp_digit u1[2*6]; + sp_digit u2[2*6]; + sp_digit s[2*6]; + sp_digit tmp[2*6 * 5]; + sp_point_384 p1; + sp_point_384 p2; +} sp_ecc_verify_384_ctx; + +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->u1, 6, hash, (int)hashLen); + sp_384_from_mp(ctx->u2, 6, r); + sp_384_from_mp(ctx->s, 6, sm); + sp_384_from_mp(ctx->p2.x, 6, pX); + sp_384_from_mp(ctx->p2.y, 6, pY); + sp_384_from_mp(ctx->p2.z, 6, pZ); + sp_384_mul_6(ctx->s, ctx->s, p384_norm_order); + err = sp_384_mod_6(ctx->s, ctx->s, p384_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_384_norm_6(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_384_mont_inv_order_6_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_384_mont_mul_order_6(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_384_mont_mul_order_6(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_384_proj_point_add_6_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_384_iszero_6(ctx->p1.z)) { + if (sp_384_iszero_6(ctx->p1.x) && sp_384_iszero_6(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<6; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_384_proj_point_dbl_6_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(ctx->u2, 6, r); + err = sp_384_mod_mul_norm_6(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_6(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_384_mont_mul_6(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_384_cmp_6(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int64_t c; + + /* Reload r and add order. */ + sp_384_from_mp(ctx->u2, 6, r); + carry = sp_384_add_6(ctx->u2, ctx->u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_6(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_6(ctx->u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_6(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_6(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_6(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { diff --git a/wolfcrypt/src/sp_armthumb.c b/wolfcrypt/src/sp_armthumb.c index b1c23b8d2f..91a4bc367c 100644 --- a/wolfcrypt/src/sp_armthumb.c +++ b/wolfcrypt/src/sp_armthumb.c @@ -4259,11 +4259,11 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, sp_digit a[128], m[64], r[128]; #else sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; #endif - sp_digit *ah; + sp_digit *ah = NULL; sp_digit e[1]; int err = MP_OKAY; @@ -4432,10 +4432,10 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -4494,16 +4494,16 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, sp_digit tmpa[64], tmpb[64]; #else sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* tmpa; - sp_digit* tmpb; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; #endif - sp_digit* r; - sp_digit* qi; - sp_digit* dq; + sp_digit* r = NULL; + sp_digit* qi = NULL; + sp_digit* dq = NULL; sp_digit c; int err = MP_OKAY; @@ -10065,11 +10065,11 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, sp_digit a[192], m[96], r[192]; #else sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; #endif - sp_digit *ah; + sp_digit *ah = NULL; sp_digit e[1]; int err = MP_OKAY; @@ -10238,10 +10238,10 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -10300,16 +10300,16 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, sp_digit tmpa[96], tmpb[96]; #else sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* tmpa; - sp_digit* tmpb; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; #endif - sp_digit* r; - sp_digit* qi; - sp_digit* dq; + sp_digit* r = NULL; + sp_digit* qi = NULL; + sp_digit* dq = NULL; sp_digit c; int err = MP_OKAY; @@ -13952,11 +13952,11 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, sp_digit a[256], m[128], r[256]; #else sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; #endif - sp_digit *ah; + sp_digit *ah = NULL; sp_digit e[1]; int err = MP_OKAY; @@ -14126,10 +14126,10 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -14188,16 +14188,16 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, sp_digit tmpa[128], tmpb[128]; #else sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* tmpa; - sp_digit* tmpb; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; #endif - sp_digit* r; - sp_digit* qi; - sp_digit* dq; + sp_digit* r = NULL; + sp_digit* qi = NULL; + sp_digit* dq = NULL; sp_digit c; int err = MP_OKAY; @@ -17060,6 +17060,141 @@ SP_NOINLINE static void sp_256_div2_8(sp_digit* r, const sp_digit* a, const sp_d * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_8_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_8_ctx; + +static int sp_256_proj_point_dbl_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_8_ctx* ctx = (sp_256_proj_point_dbl_8_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*8; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_8(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_8(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_8(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_8(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_8(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_8(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_8(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_8(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_8(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_8(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_8(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_8(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_8(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_8(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -17225,6 +17360,209 @@ static int sp_256_cmp_equal_8(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_8_ctx { + int state; + sp_256_proj_point_dbl_8_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_8_ctx; + +static int sp_256_proj_point_add_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_8_ctx* ctx = (sp_256_proj_point_add_8_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*8; + ctx->t3 = t + 4*8; + ctx->t4 = t + 6*8; + ctx->t5 = t + 8*8; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_8(ctx->t1, p256_mod, q->y); + sp_256_norm_8(ctx->t1); + if ((sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<8; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<8; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<8; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_8(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_8(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_8(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_8(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_8(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_8(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_8(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_8(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_8(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_8(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_8(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_8(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_8(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_8(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_8(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_8(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_8(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -20479,6 +20817,46 @@ static void sp_256_mont_sqr_n_order_8(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_8_ctx { + int state; + int i; +} sp_256_mont_inv_order_8_ctx; +static int sp_256_mont_inv_order_8_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_8_ctx* ctx = (sp_256_mont_inv_order_8_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 8); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_8(t, t); + if ((p256_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_256_mont_mul_order_8(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 8U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -20594,6 +20972,165 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_256_mont_inv_order_8_ctx mont_inv_order_ctx; + }; + sp_digit e[2*8]; + sp_digit x[2*8]; + sp_digit k[2*8]; + sp_digit r[2*8]; + sp_digit tmp[3 * 2*8]; + sp_point_256 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_256_ctx; + +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + (void)heap; + + switch (ctx->state) { + case 0: /* INIT */ + ctx->s = ctx->e; + ctx->kInv = ctx->k; + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->e, 8, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_256_from_mp(ctx->x, 8, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_8(rng, ctx->k); + } + else { + sp_256_from_mp(ctx->k, 8, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p256_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 8U); + sp_256_norm_8(ctx->r); + c = sp_256_cmp_8(ctx->r, p256_order); + sp_256_cond_sub_8(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(ctx->k, ctx->k, p256_norm_order); + err = sp_256_mod_8(ctx->k, ctx->k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_8(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_256_mont_inv_order_8_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_256_norm_8(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_256_mul_8(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_256_mod_8(ctx->x, ctx->x, p256_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_256_norm_8(ctx->x); + carry = sp_256_add_8(ctx->s, ctx->e, ctx->x); + sp_256_cond_sub_8(ctx->s, ctx->s, p256_order, 0 - carry); + sp_256_norm_8(ctx->s); + c = sp_256_cmp_8(ctx->s, p256_order); + sp_256_cond_sub_8(ctx->s, ctx->s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(ctx->s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(ctx->s, ctx->s, ctx->kInv); + sp_256_norm_8(ctx->s); + + /* Check that signature is usable. */ + if (sp_256_iszero_8(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_256_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_256_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -20765,6 +21302,169 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_256_mont_inv_order_8_ctx mont_inv_order_ctx; + sp_256_proj_point_dbl_8_ctx dbl_ctx; + sp_256_proj_point_add_8_ctx add_ctx; + }; + sp_digit u1[2*8]; + sp_digit u2[2*8]; + sp_digit s[2*8]; + sp_digit tmp[2*8 * 5]; + sp_point_256 p1; + sp_point_256 p2; +} sp_ecc_verify_256_ctx; + +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->u1, 8, hash, (int)hashLen); + sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->s, 8, sm); + sp_256_from_mp(ctx->p2.x, 8, pX); + sp_256_from_mp(ctx->p2.y, 8, pY); + sp_256_from_mp(ctx->p2.z, 8, pZ); + sp_256_mul_8(ctx->s, ctx->s, p256_norm_order); + err = sp_256_mod_8(ctx->s, ctx->s, p256_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_256_norm_8(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_256_mont_inv_order_8_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_256_mont_mul_order_8(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_256_mont_mul_order_8(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_256_proj_point_add_8_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_256_iszero_8(ctx->p1.z)) { + if (sp_256_iszero_8(ctx->p1.x) && sp_256_iszero_8(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<8; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(ctx->u2, 8, r); + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_256_from_mp(ctx->u2, 8, r); + carry = sp_256_add_8(ctx->u2, ctx->u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_8(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(ctx->u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { @@ -22937,6 +23637,141 @@ SP_NOINLINE static void sp_384_div2_12(sp_digit* r, const sp_digit* a, const sp_ * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_12_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_12_ctx; + +static int sp_384_proj_point_dbl_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_12_ctx* ctx = (sp_384_proj_point_dbl_12_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*12; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_12(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_12(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_12(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_12(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_12(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_12(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_12(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_12(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_12(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_12(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_12(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_12(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_12(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_12(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -23012,6 +23847,209 @@ static int sp_384_cmp_equal_12(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_12_ctx { + int state; + sp_384_proj_point_dbl_12_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_12_ctx; + +static int sp_384_proj_point_add_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_12_ctx* ctx = (sp_384_proj_point_add_12_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*12; + ctx->t3 = t + 4*12; + ctx->t4 = t + 6*12; + ctx->t5 = t + 8*12; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_12(ctx->t1, p384_mod, q->y); + sp_384_norm_12(ctx->t1); + if ((sp_384_cmp_equal_12(p->x, q->x) & sp_384_cmp_equal_12(p->z, q->z) & + (sp_384_cmp_equal_12(p->y, q->y) | sp_384_cmp_equal_12(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<12; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<12; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<12; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_12(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_12(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_12(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_12(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_12(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_12(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_12(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_12(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_12(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_12(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_12(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_12(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_12(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_12(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_12(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_12(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_12(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_12(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_12(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -26300,6 +27338,46 @@ static void sp_384_mont_sqr_n_order_12(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_12_ctx { + int state; + int i; +} sp_384_mont_inv_order_12_ctx; +static int sp_384_mont_inv_order_12_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_12_ctx* ctx = (sp_384_mont_inv_order_12_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 12); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_12(t, t); + if ((p384_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_384_mont_mul_order_12(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 12U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -26386,6 +27464,165 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_384_mont_inv_order_12_ctx mont_inv_order_ctx; + }; + sp_digit e[2*12]; + sp_digit x[2*12]; + sp_digit k[2*12]; + sp_digit r[2*12]; + sp_digit tmp[3 * 2*12]; + sp_point_384 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_384_ctx; + +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + (void)heap; + + switch (ctx->state) { + case 0: /* INIT */ + ctx->s = ctx->e; + ctx->kInv = ctx->k; + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->e, 12, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_384_from_mp(ctx->x, 12, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_12(rng, ctx->k); + } + else { + sp_384_from_mp(ctx->k, 12, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p384_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 12U); + sp_384_norm_12(ctx->r); + c = sp_384_cmp_12(ctx->r, p384_order); + sp_384_cond_sub_12(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_12(ctx->k, ctx->k, p384_norm_order); + err = sp_384_mod_12(ctx->k, ctx->k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_12(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_384_mont_inv_order_12_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_384_norm_12(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_384_mul_12(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_384_mod_12(ctx->x, ctx->x, p384_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_384_norm_12(ctx->x); + carry = sp_384_add_12(ctx->s, ctx->e, ctx->x); + sp_384_cond_sub_12(ctx->s, ctx->s, p384_order, 0 - carry); + sp_384_norm_12(ctx->s); + c = sp_384_cmp_12(ctx->s, p384_order); + sp_384_cond_sub_12(ctx->s, ctx->s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(ctx->s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_12(ctx->s, ctx->s, ctx->kInv); + sp_384_norm_12(ctx->s); + + /* Check that signature is usable. */ + if (sp_384_iszero_12(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_384_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_384_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -26557,6 +27794,169 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_384_mont_inv_order_12_ctx mont_inv_order_ctx; + sp_384_proj_point_dbl_12_ctx dbl_ctx; + sp_384_proj_point_add_12_ctx add_ctx; + }; + sp_digit u1[2*12]; + sp_digit u2[2*12]; + sp_digit s[2*12]; + sp_digit tmp[2*12 * 5]; + sp_point_384 p1; + sp_point_384 p2; +} sp_ecc_verify_384_ctx; + +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->u1, 12, hash, (int)hashLen); + sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->s, 12, sm); + sp_384_from_mp(ctx->p2.x, 12, pX); + sp_384_from_mp(ctx->p2.y, 12, pY); + sp_384_from_mp(ctx->p2.z, 12, pZ); + sp_384_mul_12(ctx->s, ctx->s, p384_norm_order); + err = sp_384_mod_12(ctx->s, ctx->s, p384_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_384_norm_12(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_384_mont_inv_order_12_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_384_mont_mul_order_12(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_384_mont_mul_order_12(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_384_proj_point_add_12_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_384_iszero_12(ctx->p1.z)) { + if (sp_384_iszero_12(ctx->p1.x) && sp_384_iszero_12(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<12; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(ctx->u2, 12, r); + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_12(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_384_from_mp(ctx->u2, 12, r); + carry = sp_384_add_12(ctx->u2, ctx->u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_12(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_12(ctx->u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { diff --git a/wolfcrypt/src/sp_c32.c b/wolfcrypt/src/sp_c32.c index 3662ceae2e..4dec2d99ca 100644 --- a/wolfcrypt/src/sp_c32.c +++ b/wolfcrypt/src/sp_c32.c @@ -57,6 +57,10 @@ static const size_t addr_mask[2] = { 0, (size_t)-1 }; #endif +#if defined(WOLFSSL_SP_NONBLOCK) && (!defined(WOLFSSL_SP_NO_MALLOC) || !defined(WOLFSSL_SP_SMALL)) + #error SP non-blocking requires small and no-malloc (WOLFSSL_SP_SMALL and WOLFSSL_SP_NO_MALLOC) +#endif + #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) #ifndef WOLFSSL_SP_NO_2048 /* Read big endian unsigned byte array into r. @@ -2083,7 +2087,7 @@ static int sp_2048_mod_exp_45(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(32 * 90) + 90]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; @@ -3036,7 +3040,7 @@ static int sp_2048_mod_exp_90(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(32 * 180) + 180]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; @@ -3188,10 +3192,10 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, { #ifdef WOLFSSL_SP_SMALL sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; - sp_digit* norm; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; + sp_digit* norm = NULL; sp_digit e[1] = {0}; sp_digit mp; int i; @@ -3285,9 +3289,9 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, #else sp_digit* d = NULL; #endif - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; sp_digit e[1] = {0}; int err = MP_OKAY; @@ -3426,10 +3430,10 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -3526,15 +3530,15 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, #else #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* dq; - sp_digit* qi; - sp_digit* tmpa; - sp_digit* tmpb; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -5924,7 +5928,7 @@ static int sp_3072_mod_exp_67(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(32 * 134) + 134]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; @@ -6913,7 +6917,7 @@ static int sp_3072_mod_exp_134(sp_digit* r, const sp_digit* a, const sp_digit* e sp_digit td[(32 * 268) + 268]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; @@ -7065,10 +7069,10 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, { #ifdef WOLFSSL_SP_SMALL sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; - sp_digit* norm; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; + sp_digit* norm = NULL; sp_digit e[1] = {0}; sp_digit mp; int i; @@ -7162,9 +7166,9 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, #else sp_digit* d = NULL; #endif - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; sp_digit e[1] = {0}; int err = MP_OKAY; @@ -7303,10 +7307,10 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -7403,15 +7407,15 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, #else #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* dq; - sp_digit* qi; - sp_digit* tmpa; - sp_digit* tmpb; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -9988,7 +9992,7 @@ static int sp_4096_mod_exp_98(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(32 * 196) + 196]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; @@ -10954,7 +10958,7 @@ static int sp_4096_mod_exp_196(sp_digit* r, const sp_digit* a, const sp_digit* e sp_digit td[(32 * 392) + 392]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; @@ -11106,10 +11110,10 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, { #ifdef WOLFSSL_SP_SMALL sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; - sp_digit* norm; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; + sp_digit* norm = NULL; sp_digit e[1] = {0}; sp_digit mp; int i; @@ -11203,9 +11207,9 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, #else sp_digit* d = NULL; #endif - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; sp_digit e[1] = {0}; int err = MP_OKAY; @@ -11344,10 +11348,10 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -11444,15 +11448,15 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, #else #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* dq; - sp_digit* qi; - sp_digit* tmpa; - sp_digit* tmpb; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -13847,6 +13851,141 @@ static void sp_256_div2_10(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_10_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_10_ctx; + +static int sp_256_proj_point_dbl_10_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_10_ctx* ctx = (sp_256_proj_point_dbl_10_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_10_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*10; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_10(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_10(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_10(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_10(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_10(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_10(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_10(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_10(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_10(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_10(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_10(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_10(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_10(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_10(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_10(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_10(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_10(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_10(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_10(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -13922,6 +14061,209 @@ static int sp_256_cmp_equal_10(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_10_ctx { + int state; + sp_256_proj_point_dbl_10_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_10_ctx; + +static int sp_256_proj_point_add_10_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_10_ctx* ctx = (sp_256_proj_point_add_10_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_10_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*10; + ctx->t3 = t + 4*10; + ctx->t4 = t + 6*10; + ctx->t5 = t + 8*10; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_10(ctx->t1, p256_mod, q->y); + sp_256_norm_10(ctx->t1); + if ((sp_256_cmp_equal_10(p->x, q->x) & sp_256_cmp_equal_10(p->z, q->z) & + (sp_256_cmp_equal_10(p->y, q->y) | sp_256_cmp_equal_10(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_10_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<10; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<10; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<10; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_10(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_10(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_10(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_10(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_10(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_10(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_10(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_10(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_10(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_10(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_10(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_10(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_10(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_10(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_10(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_10(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_10(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_10(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_10(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_10(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_10(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_10(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_10(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_10(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -14020,6 +14362,118 @@ static void sp_256_proj_point_add_10(sp_point_256* r, const sp_point_256* p, con * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_ecc_mulmod_10_ctx { + int state; + union { + sp_256_proj_point_dbl_10_ctx dbl_ctx; + sp_256_proj_point_add_10_ctx add_ctx; + }; + sp_point_256 t[3]; + sp_digit tmp[2 * 10 * 5]; + sp_digit n; + int i; + int c; + int y; +} sp_256_ecc_mulmod_10_ctx; + +static int sp_256_ecc_mulmod_10_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* g, const sp_digit* k, int map, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_256_ecc_mulmod_10_ctx* ctx = (sp_256_ecc_mulmod_10_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_ecc_mulmod_10_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + XMEMSET(ctx->t, 0, sizeof(sp_point_256) * 3); + ctx->i = 9; + ctx->c = 22; + ctx->n = k[ctx->i--] << (26 - ctx->c); + + /* t[0] = {0, 0, 1} * norm */ + ctx->t[0].infinity = 1; + ctx->state = 1; + break; + case 1: /* T1X */ + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_10(ctx->t[1].x, g->x, p256_mod); + ctx->state = 2; + break; + case 2: /* T1Y */ + err = sp_256_mod_mul_norm_10(ctx->t[1].y, g->y, p256_mod); + ctx->state = 3; + break; + case 3: /* T1Z */ + err = sp_256_mod_mul_norm_10(ctx->t[1].z, g->z, p256_mod); + ctx->state = 4; + break; + case 4: /* ADDPREP */ + if (ctx->c == 0) { + if (ctx->i == -1) { + ctx->state = 7; + break; + } + + ctx->n = k[ctx->i--]; + ctx->c = 26; + } + ctx->y = (ctx->n >> 25) & 1; + ctx->n <<= 1; + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 5; + break; + case 5: /* ADD */ + err = sp_256_proj_point_add_10_nb((sp_ecc_ctx_t*)&ctx->add_ctx, + &ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), + sizeof(sp_point_256)); + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 6; + } + break; + case 6: /* DBL */ + err = sp_256_proj_point_dbl_10_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2], + &ctx->t[2], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2], + sizeof(sp_point_256)); + ctx->state = 4; + ctx->c--; + } + break; + case 7: /* MAP */ + if (map != 0) { + sp_256_map_10(r, &ctx->t[0], ctx->tmp); + } + else { + XMEMCPY(r, &ctx->t[0], sizeof(sp_point_256)); + } + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 7) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + ForceZero(ctx->tmp, sizeof(ctx->tmp)); + ForceZero(ctx->t, sizeof(ctx->t)); + } + + (void)heap; + + return err; +} + +#endif /* WOLFSSL_SP_NONBLOCK */ + static int sp_256_ecc_mulmod_10(sp_point_256* r, const sp_point_256* g, const sp_digit* k, int map, void* heap) { @@ -16826,6 +17280,46 @@ static void sp_256_mont_sqr_n_order_10(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_10_ctx { + int state; + int i; +} sp_256_mont_inv_order_10_ctx; +static int sp_256_mont_inv_order_10_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_10_ctx* ctx = (sp_256_mont_inv_order_10_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_10_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 10); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_10(t, t); + if ((p256_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_256_mont_mul_order_10(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 10U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_10(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -16941,6 +17435,165 @@ static void sp_256_mont_inv_order_10(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_256_ctx { + int state; + union { + sp_256_ecc_mulmod_10_ctx mulmod_ctx; + sp_256_mont_inv_order_10_ctx mont_inv_order_ctx; + }; + sp_digit e[2*10]; + sp_digit x[2*10]; + sp_digit k[2*10]; + sp_digit r[2*10]; + sp_digit tmp[3 * 2*10]; + sp_point_256 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_256_ctx; + +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + (void)heap; + + switch (ctx->state) { + case 0: /* INIT */ + ctx->s = ctx->e; + ctx->kInv = ctx->k; + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->e, 10, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_256_from_mp(ctx->x, 10, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_10(rng, ctx->k); + } + else { + sp_256_from_mp(ctx->k, 10, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_256_ecc_mulmod_10_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p256_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 10U); + sp_256_norm_10(ctx->r); + c = sp_256_cmp_10(ctx->r, p256_order); + sp_256_cond_sub_10(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_10(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_10(ctx->k, ctx->k, p256_norm_order); + err = sp_256_mod_10(ctx->k, ctx->k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_10(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_256_mont_inv_order_10_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_256_norm_10(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_256_mul_10(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_256_mod_10(ctx->x, ctx->x, p256_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_256_norm_10(ctx->x); + carry = sp_256_add_10(ctx->s, ctx->e, ctx->x); + sp_256_cond_sub_10(ctx->s, ctx->s, p256_order, 0 - carry); + sp_256_norm_10(ctx->s); + c = sp_256_cmp_10(ctx->s, p256_order); + sp_256_cond_sub_10(ctx->s, ctx->s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_10(ctx->s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_10(ctx->s, ctx->s, ctx->kInv); + sp_256_norm_10(ctx->s); + + /* Check that signature is usable. */ + if (sp_256_iszero_10(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_256_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_256_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 10U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 10U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 10U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 10U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 10U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -17112,6 +17765,169 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_256_ctx { + int state; + union { + sp_256_ecc_mulmod_10_ctx mulmod_ctx; + sp_256_mont_inv_order_10_ctx mont_inv_order_ctx; + sp_256_proj_point_dbl_10_ctx dbl_ctx; + sp_256_proj_point_add_10_ctx add_ctx; + }; + sp_digit u1[2*10]; + sp_digit u2[2*10]; + sp_digit s[2*10]; + sp_digit tmp[2*10 * 5]; + sp_point_256 p1; + sp_point_256 p2; +} sp_ecc_verify_256_ctx; + +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->u1, 10, hash, (int)hashLen); + sp_256_from_mp(ctx->u2, 10, r); + sp_256_from_mp(ctx->s, 10, sm); + sp_256_from_mp(ctx->p2.x, 10, pX); + sp_256_from_mp(ctx->p2.y, 10, pY); + sp_256_from_mp(ctx->p2.z, 10, pZ); + sp_256_mul_10(ctx->s, ctx->s, p256_norm_order); + err = sp_256_mod_10(ctx->s, ctx->s, p256_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_256_norm_10(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_256_mont_inv_order_10_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_256_mont_mul_order_10(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_256_mont_mul_order_10(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_256_ecc_mulmod_10_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_256_ecc_mulmod_10_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_256_proj_point_add_10_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_256_iszero_10(ctx->p1.z)) { + if (sp_256_iszero_10(ctx->p1.x) && sp_256_iszero_10(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<10; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_256_proj_point_dbl_10_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(ctx->u2, 10, r); + err = sp_256_mod_mul_norm_10(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_10(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_256_mont_mul_10(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_256_cmp_10(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_256_from_mp(ctx->u2, 10, r); + carry = sp_256_add_10(ctx->u2, ctx->u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_10(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_10(ctx->u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_10(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_10(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_10(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { @@ -19472,6 +20288,141 @@ static void sp_384_div2_15(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_15_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_15_ctx; + +static int sp_384_proj_point_dbl_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_15_ctx* ctx = (sp_384_proj_point_dbl_15_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*15; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_15(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_15(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_15(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_15(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_15(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_15(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_15(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_15(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_15(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_15(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_15(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_15(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_15(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_15(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_15(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_15(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_15(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_15(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_15(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -19548,6 +20499,209 @@ static int sp_384_cmp_equal_15(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_15_ctx { + int state; + sp_384_proj_point_dbl_15_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_15_ctx; + +static int sp_384_proj_point_add_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_15_ctx* ctx = (sp_384_proj_point_add_15_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*15; + ctx->t3 = t + 4*15; + ctx->t4 = t + 6*15; + ctx->t5 = t + 8*15; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_15(ctx->t1, p384_mod, q->y); + sp_384_norm_15(ctx->t1); + if ((sp_384_cmp_equal_15(p->x, q->x) & sp_384_cmp_equal_15(p->z, q->z) & + (sp_384_cmp_equal_15(p->y, q->y) | sp_384_cmp_equal_15(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_15_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<15; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<15; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<15; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_15(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_15(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_15(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_15(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_15(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_15(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_15(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_15(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_15(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_15(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_15(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_15(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_15(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_15(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_15(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_15(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_15(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_15(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_15(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_15(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_15(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_15(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_15(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_15(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -19646,6 +20800,118 @@ static void sp_384_proj_point_add_15(sp_point_384* r, const sp_point_384* p, con * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_ecc_mulmod_15_ctx { + int state; + union { + sp_384_proj_point_dbl_15_ctx dbl_ctx; + sp_384_proj_point_add_15_ctx add_ctx; + }; + sp_point_384 t[3]; + sp_digit tmp[2 * 15 * 6]; + sp_digit n; + int i; + int c; + int y; +} sp_384_ecc_mulmod_15_ctx; + +static int sp_384_ecc_mulmod_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* g, const sp_digit* k, int map, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_384_ecc_mulmod_15_ctx* ctx = (sp_384_ecc_mulmod_15_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_ecc_mulmod_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + XMEMSET(ctx->t, 0, sizeof(sp_point_384) * 3); + ctx->i = 14; + ctx->c = 20; + ctx->n = k[ctx->i--] << (26 - ctx->c); + + /* t[0] = {0, 0, 1} * norm */ + ctx->t[0].infinity = 1; + ctx->state = 1; + break; + case 1: /* T1X */ + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_384_mod_mul_norm_15(ctx->t[1].x, g->x, p384_mod); + ctx->state = 2; + break; + case 2: /* T1Y */ + err = sp_384_mod_mul_norm_15(ctx->t[1].y, g->y, p384_mod); + ctx->state = 3; + break; + case 3: /* T1Z */ + err = sp_384_mod_mul_norm_15(ctx->t[1].z, g->z, p384_mod); + ctx->state = 4; + break; + case 4: /* ADDPREP */ + if (ctx->c == 0) { + if (ctx->i == -1) { + ctx->state = 7; + break; + } + + ctx->n = k[ctx->i--]; + ctx->c = 26; + } + ctx->y = (ctx->n >> 25) & 1; + ctx->n <<= 1; + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 5; + break; + case 5: /* ADD */ + err = sp_384_proj_point_add_15_nb((sp_ecc_ctx_t*)&ctx->add_ctx, + &ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), + sizeof(sp_point_384)); + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 6; + } + break; + case 6: /* DBL */ + err = sp_384_proj_point_dbl_15_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2], + &ctx->t[2], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2], + sizeof(sp_point_384)); + ctx->state = 4; + ctx->c--; + } + break; + case 7: /* MAP */ + if (map != 0) { + sp_384_map_15(r, &ctx->t[0], ctx->tmp); + } + else { + XMEMCPY(r, &ctx->t[0], sizeof(sp_point_384)); + } + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 7) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + ForceZero(ctx->tmp, sizeof(ctx->tmp)); + ForceZero(ctx->t, sizeof(ctx->t)); + } + + (void)heap; + + return err; +} + +#endif /* WOLFSSL_SP_NONBLOCK */ + static int sp_384_ecc_mulmod_15(sp_point_384* r, const sp_point_384* g, const sp_digit* k, int map, void* heap) { @@ -22973,6 +24239,46 @@ static void sp_384_mont_sqr_n_order_15(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_15_ctx { + int state; + int i; +} sp_384_mont_inv_order_15_ctx; +static int sp_384_mont_inv_order_15_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_15_ctx* ctx = (sp_384_mont_inv_order_15_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 15); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_15(t, t); + if ((p384_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_384_mont_mul_order_15(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 15U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_15(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -23059,6 +24365,165 @@ static void sp_384_mont_inv_order_15(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_384_ctx { + int state; + union { + sp_384_ecc_mulmod_15_ctx mulmod_ctx; + sp_384_mont_inv_order_15_ctx mont_inv_order_ctx; + }; + sp_digit e[2*15]; + sp_digit x[2*15]; + sp_digit k[2*15]; + sp_digit r[2*15]; + sp_digit tmp[3 * 2*15]; + sp_point_384 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_384_ctx; + +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + (void)heap; + + switch (ctx->state) { + case 0: /* INIT */ + ctx->s = ctx->e; + ctx->kInv = ctx->k; + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->e, 15, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_384_from_mp(ctx->x, 15, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_15(rng, ctx->k); + } + else { + sp_384_from_mp(ctx->k, 15, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p384_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 15U); + sp_384_norm_15(ctx->r); + c = sp_384_cmp_15(ctx->r, p384_order); + sp_384_cond_sub_15(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_15(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_15(ctx->k, ctx->k, p384_norm_order); + err = sp_384_mod_15(ctx->k, ctx->k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_15(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_384_mont_inv_order_15_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_384_norm_15(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_384_mul_15(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_384_mod_15(ctx->x, ctx->x, p384_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_384_norm_15(ctx->x); + carry = sp_384_add_15(ctx->s, ctx->e, ctx->x); + sp_384_cond_sub_15(ctx->s, ctx->s, p384_order, 0 - carry); + sp_384_norm_15(ctx->s); + c = sp_384_cmp_15(ctx->s, p384_order); + sp_384_cond_sub_15(ctx->s, ctx->s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_15(ctx->s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_15(ctx->s, ctx->s, ctx->kInv); + sp_384_norm_15(ctx->s); + + /* Check that signature is usable. */ + if (sp_384_iszero_15(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_384_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_384_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 15U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 15U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 15U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 15U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 15U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -23230,6 +24695,169 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_384_ctx { + int state; + union { + sp_384_ecc_mulmod_15_ctx mulmod_ctx; + sp_384_mont_inv_order_15_ctx mont_inv_order_ctx; + sp_384_proj_point_dbl_15_ctx dbl_ctx; + sp_384_proj_point_add_15_ctx add_ctx; + }; + sp_digit u1[2*15]; + sp_digit u2[2*15]; + sp_digit s[2*15]; + sp_digit tmp[2*15 * 5]; + sp_point_384 p1; + sp_point_384 p2; +} sp_ecc_verify_384_ctx; + +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->u1, 15, hash, (int)hashLen); + sp_384_from_mp(ctx->u2, 15, r); + sp_384_from_mp(ctx->s, 15, sm); + sp_384_from_mp(ctx->p2.x, 15, pX); + sp_384_from_mp(ctx->p2.y, 15, pY); + sp_384_from_mp(ctx->p2.z, 15, pZ); + sp_384_mul_15(ctx->s, ctx->s, p384_norm_order); + err = sp_384_mod_15(ctx->s, ctx->s, p384_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_384_norm_15(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_384_mont_inv_order_15_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_384_mont_mul_order_15(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_384_mont_mul_order_15(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_384_proj_point_add_15_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_384_iszero_15(ctx->p1.z)) { + if (sp_384_iszero_15(ctx->p1.x) && sp_384_iszero_15(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<15; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_384_proj_point_dbl_15_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(ctx->u2, 15, r); + err = sp_384_mod_mul_norm_15(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_15(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_384_mont_mul_15(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_384_cmp_15(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_384_from_mp(ctx->u2, 15, r); + carry = sp_384_add_15(ctx->u2, ctx->u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_15(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_15(ctx->u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_15(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_15(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_15(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { diff --git a/wolfcrypt/src/sp_c64.c b/wolfcrypt/src/sp_c64.c index 74e54f2268..cec1f2eb2d 100644 --- a/wolfcrypt/src/sp_c64.c +++ b/wolfcrypt/src/sp_c64.c @@ -57,6 +57,10 @@ static const size_t addr_mask[2] = { 0, (size_t)-1 }; #endif +#if defined(WOLFSSL_SP_NONBLOCK) && (!defined(WOLFSSL_SP_NO_MALLOC) || !defined(WOLFSSL_SP_SMALL)) + #error SP non-blocking requires small and no-malloc (WOLFSSL_SP_SMALL and WOLFSSL_SP_NO_MALLOC) +#endif + #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) #ifndef WOLFSSL_SP_NO_2048 /* Read big endian unsigned byte array into r. @@ -1731,7 +1735,7 @@ static int sp_2048_mod_exp_18(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(32 * 36) + 36]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; @@ -2676,7 +2680,7 @@ static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(32 * 72) + 72]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; @@ -2828,10 +2832,10 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, { #ifdef WOLFSSL_SP_SMALL sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; - sp_digit* norm; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; + sp_digit* norm = NULL; sp_digit e[1] = {0}; sp_digit mp; int i; @@ -2925,9 +2929,9 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, #else sp_digit* d = NULL; #endif - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; sp_digit e[1] = {0}; int err = MP_OKAY; @@ -3066,10 +3070,10 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -3166,15 +3170,15 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, #else #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* dq; - sp_digit* qi; - sp_digit* tmpa; - sp_digit* tmpb; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -5912,7 +5916,7 @@ static int sp_3072_mod_exp_27(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(32 * 54) + 54]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; @@ -6827,7 +6831,7 @@ static int sp_3072_mod_exp_54(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(32 * 108) + 108]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; @@ -6979,10 +6983,10 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, { #ifdef WOLFSSL_SP_SMALL sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; - sp_digit* norm; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; + sp_digit* norm = NULL; sp_digit e[1] = {0}; sp_digit mp; int i; @@ -7076,9 +7080,9 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, #else sp_digit* d = NULL; #endif - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; sp_digit e[1] = {0}; int err = MP_OKAY; @@ -7217,10 +7221,10 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -7317,15 +7321,15 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, #else #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* dq; - sp_digit* qi; - sp_digit* tmpa; - sp_digit* tmpb; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -10209,7 +10213,7 @@ static int sp_4096_mod_exp_39(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(32 * 78) + 78]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; @@ -11223,7 +11227,7 @@ static int sp_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(32 * 156) + 156]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; @@ -11375,10 +11379,10 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, { #ifdef WOLFSSL_SP_SMALL sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; - sp_digit* norm; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; + sp_digit* norm = NULL; sp_digit e[1] = {0}; sp_digit mp; int i; @@ -11472,9 +11476,9 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, #else sp_digit* d = NULL; #endif - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; sp_digit e[1] = {0}; int err = MP_OKAY; @@ -11613,10 +11617,10 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -11713,15 +11717,15 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, #else #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* dq; - sp_digit* qi; - sp_digit* tmpa; - sp_digit* tmpb; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -13668,6 +13672,141 @@ static void sp_256_div2_5(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_5_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_5_ctx; + +static int sp_256_proj_point_dbl_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_5_ctx* ctx = (sp_256_proj_point_dbl_5_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_5_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*5; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_5(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_5(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_5(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_5(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_5(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_5(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_5(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_5(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_5(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_5(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_5(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_5(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_5(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_5(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_5(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_5(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_5(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_5(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_5(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -13742,6 +13881,209 @@ static int sp_256_cmp_equal_5(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_5_ctx { + int state; + sp_256_proj_point_dbl_5_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_5_ctx; + +static int sp_256_proj_point_add_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_5_ctx* ctx = (sp_256_proj_point_add_5_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_5_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*5; + ctx->t3 = t + 4*5; + ctx->t4 = t + 6*5; + ctx->t5 = t + 8*5; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_5(ctx->t1, p256_mod, q->y); + sp_256_norm_5(ctx->t1); + if ((sp_256_cmp_equal_5(p->x, q->x) & sp_256_cmp_equal_5(p->z, q->z) & + (sp_256_cmp_equal_5(p->y, q->y) | sp_256_cmp_equal_5(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_5_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<5; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<5; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<5; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_5(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_5(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_5(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_5(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_5(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_5(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_5(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_5(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_5(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_5(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_5(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_5(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_5(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_5(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_5(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_5(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_5(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_5(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_5(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_5(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_5(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_5(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_5(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_5(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -13840,6 +14182,118 @@ static void sp_256_proj_point_add_5(sp_point_256* r, const sp_point_256* p, cons * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_ecc_mulmod_5_ctx { + int state; + union { + sp_256_proj_point_dbl_5_ctx dbl_ctx; + sp_256_proj_point_add_5_ctx add_ctx; + }; + sp_point_256 t[3]; + sp_digit tmp[2 * 5 * 5]; + sp_digit n; + int i; + int c; + int y; +} sp_256_ecc_mulmod_5_ctx; + +static int sp_256_ecc_mulmod_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* g, const sp_digit* k, int map, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_256_ecc_mulmod_5_ctx* ctx = (sp_256_ecc_mulmod_5_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_ecc_mulmod_5_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + XMEMSET(ctx->t, 0, sizeof(sp_point_256) * 3); + ctx->i = 4; + ctx->c = 48; + ctx->n = k[ctx->i--] << (52 - ctx->c); + + /* t[0] = {0, 0, 1} * norm */ + ctx->t[0].infinity = 1; + ctx->state = 1; + break; + case 1: /* T1X */ + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_5(ctx->t[1].x, g->x, p256_mod); + ctx->state = 2; + break; + case 2: /* T1Y */ + err = sp_256_mod_mul_norm_5(ctx->t[1].y, g->y, p256_mod); + ctx->state = 3; + break; + case 3: /* T1Z */ + err = sp_256_mod_mul_norm_5(ctx->t[1].z, g->z, p256_mod); + ctx->state = 4; + break; + case 4: /* ADDPREP */ + if (ctx->c == 0) { + if (ctx->i == -1) { + ctx->state = 7; + break; + } + + ctx->n = k[ctx->i--]; + ctx->c = 52; + } + ctx->y = (ctx->n >> 51) & 1; + ctx->n <<= 1; + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 5; + break; + case 5: /* ADD */ + err = sp_256_proj_point_add_5_nb((sp_ecc_ctx_t*)&ctx->add_ctx, + &ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), + sizeof(sp_point_256)); + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 6; + } + break; + case 6: /* DBL */ + err = sp_256_proj_point_dbl_5_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2], + &ctx->t[2], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2], + sizeof(sp_point_256)); + ctx->state = 4; + ctx->c--; + } + break; + case 7: /* MAP */ + if (map != 0) { + sp_256_map_5(r, &ctx->t[0], ctx->tmp); + } + else { + XMEMCPY(r, &ctx->t[0], sizeof(sp_point_256)); + } + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 7) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + ForceZero(ctx->tmp, sizeof(ctx->tmp)); + ForceZero(ctx->t, sizeof(ctx->t)); + } + + (void)heap; + + return err; +} + +#endif /* WOLFSSL_SP_NONBLOCK */ + static int sp_256_ecc_mulmod_5(sp_point_256* r, const sp_point_256* g, const sp_digit* k, int map, void* heap) { @@ -16627,6 +17081,46 @@ static void sp_256_mont_sqr_n_order_5(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_5_ctx { + int state; + int i; +} sp_256_mont_inv_order_5_ctx; +static int sp_256_mont_inv_order_5_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_5_ctx* ctx = (sp_256_mont_inv_order_5_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_5_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 5); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_5(t, t); + if ((p256_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_256_mont_mul_order_5(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 5U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_5(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -16742,6 +17236,165 @@ static void sp_256_mont_inv_order_5(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_256_ctx { + int state; + union { + sp_256_ecc_mulmod_5_ctx mulmod_ctx; + sp_256_mont_inv_order_5_ctx mont_inv_order_ctx; + }; + sp_digit e[2*5]; + sp_digit x[2*5]; + sp_digit k[2*5]; + sp_digit r[2*5]; + sp_digit tmp[3 * 2*5]; + sp_point_256 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_256_ctx; + +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + (void)heap; + + switch (ctx->state) { + case 0: /* INIT */ + ctx->s = ctx->e; + ctx->kInv = ctx->k; + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->e, 5, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_256_from_mp(ctx->x, 5, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_5(rng, ctx->k); + } + else { + sp_256_from_mp(ctx->k, 5, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_256_ecc_mulmod_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p256_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int64_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 5U); + sp_256_norm_5(ctx->r); + c = sp_256_cmp_5(ctx->r, p256_order); + sp_256_cond_sub_5(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_5(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_5(ctx->k, ctx->k, p256_norm_order); + err = sp_256_mod_5(ctx->k, ctx->k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_5(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_256_mont_inv_order_5_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_256_norm_5(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_256_mul_5(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_256_mod_5(ctx->x, ctx->x, p256_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int64_t c; + sp_256_norm_5(ctx->x); + carry = sp_256_add_5(ctx->s, ctx->e, ctx->x); + sp_256_cond_sub_5(ctx->s, ctx->s, p256_order, 0 - carry); + sp_256_norm_5(ctx->s); + c = sp_256_cmp_5(ctx->s, p256_order); + sp_256_cond_sub_5(ctx->s, ctx->s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_5(ctx->s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_5(ctx->s, ctx->s, ctx->kInv); + sp_256_norm_5(ctx->s); + + /* Check that signature is usable. */ + if (sp_256_iszero_5(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_256_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_256_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 5U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 5U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 5U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 5U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 5U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -16913,6 +17566,169 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_256_ctx { + int state; + union { + sp_256_ecc_mulmod_5_ctx mulmod_ctx; + sp_256_mont_inv_order_5_ctx mont_inv_order_ctx; + sp_256_proj_point_dbl_5_ctx dbl_ctx; + sp_256_proj_point_add_5_ctx add_ctx; + }; + sp_digit u1[2*5]; + sp_digit u2[2*5]; + sp_digit s[2*5]; + sp_digit tmp[2*5 * 5]; + sp_point_256 p1; + sp_point_256 p2; +} sp_ecc_verify_256_ctx; + +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->u1, 5, hash, (int)hashLen); + sp_256_from_mp(ctx->u2, 5, r); + sp_256_from_mp(ctx->s, 5, sm); + sp_256_from_mp(ctx->p2.x, 5, pX); + sp_256_from_mp(ctx->p2.y, 5, pY); + sp_256_from_mp(ctx->p2.z, 5, pZ); + sp_256_mul_5(ctx->s, ctx->s, p256_norm_order); + err = sp_256_mod_5(ctx->s, ctx->s, p256_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_256_norm_5(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_256_mont_inv_order_5_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_256_mont_mul_order_5(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_256_mont_mul_order_5(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_256_ecc_mulmod_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_256_ecc_mulmod_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_256_proj_point_add_5_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_256_iszero_5(ctx->p1.z)) { + if (sp_256_iszero_5(ctx->p1.x) && sp_256_iszero_5(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<5; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_256_proj_point_dbl_5_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(ctx->u2, 5, r); + err = sp_256_mod_mul_norm_5(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_5(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_256_mont_mul_5(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_256_cmp_5(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int64_t c; + + /* Reload r and add order. */ + sp_256_from_mp(ctx->u2, 5, r); + carry = sp_256_add_5(ctx->u2, ctx->u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_5(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_5(ctx->u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_5(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_5(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_5(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { @@ -18854,6 +19670,141 @@ static void sp_384_div2_7(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_7_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_7_ctx; + +static int sp_384_proj_point_dbl_7_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_7_ctx* ctx = (sp_384_proj_point_dbl_7_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_7_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*7; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_7(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_7(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_7(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_7(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_7(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_7(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_7(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_7(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_7(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_7(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_7(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_7(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_7(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_7(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_7(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_7(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_7(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_7(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_7(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -18928,6 +19879,209 @@ static int sp_384_cmp_equal_7(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_7_ctx { + int state; + sp_384_proj_point_dbl_7_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_7_ctx; + +static int sp_384_proj_point_add_7_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_7_ctx* ctx = (sp_384_proj_point_add_7_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_7_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*7; + ctx->t3 = t + 4*7; + ctx->t4 = t + 6*7; + ctx->t5 = t + 8*7; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_7(ctx->t1, p384_mod, q->y); + sp_384_norm_7(ctx->t1); + if ((sp_384_cmp_equal_7(p->x, q->x) & sp_384_cmp_equal_7(p->z, q->z) & + (sp_384_cmp_equal_7(p->y, q->y) | sp_384_cmp_equal_7(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_7_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<7; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<7; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<7; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_7(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_7(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_7(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_7(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_7(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_7(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_7(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_7(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_7(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_7(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_7(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_7(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_7(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_7(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_7(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_7(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_7(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_7(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_7(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_7(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_7(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_7(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_7(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_7(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -19026,6 +20180,118 @@ static void sp_384_proj_point_add_7(sp_point_384* r, const sp_point_384* p, cons * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_ecc_mulmod_7_ctx { + int state; + union { + sp_384_proj_point_dbl_7_ctx dbl_ctx; + sp_384_proj_point_add_7_ctx add_ctx; + }; + sp_point_384 t[3]; + sp_digit tmp[2 * 7 * 6]; + sp_digit n; + int i; + int c; + int y; +} sp_384_ecc_mulmod_7_ctx; + +static int sp_384_ecc_mulmod_7_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* g, const sp_digit* k, int map, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_384_ecc_mulmod_7_ctx* ctx = (sp_384_ecc_mulmod_7_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_ecc_mulmod_7_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + XMEMSET(ctx->t, 0, sizeof(sp_point_384) * 3); + ctx->i = 6; + ctx->c = 54; + ctx->n = k[ctx->i--] << (55 - ctx->c); + + /* t[0] = {0, 0, 1} * norm */ + ctx->t[0].infinity = 1; + ctx->state = 1; + break; + case 1: /* T1X */ + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_384_mod_mul_norm_7(ctx->t[1].x, g->x, p384_mod); + ctx->state = 2; + break; + case 2: /* T1Y */ + err = sp_384_mod_mul_norm_7(ctx->t[1].y, g->y, p384_mod); + ctx->state = 3; + break; + case 3: /* T1Z */ + err = sp_384_mod_mul_norm_7(ctx->t[1].z, g->z, p384_mod); + ctx->state = 4; + break; + case 4: /* ADDPREP */ + if (ctx->c == 0) { + if (ctx->i == -1) { + ctx->state = 7; + break; + } + + ctx->n = k[ctx->i--]; + ctx->c = 55; + } + ctx->y = (ctx->n >> 54) & 1; + ctx->n <<= 1; + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 5; + break; + case 5: /* ADD */ + err = sp_384_proj_point_add_7_nb((sp_ecc_ctx_t*)&ctx->add_ctx, + &ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), + sizeof(sp_point_384)); + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 6; + } + break; + case 6: /* DBL */ + err = sp_384_proj_point_dbl_7_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2], + &ctx->t[2], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2], + sizeof(sp_point_384)); + ctx->state = 4; + ctx->c--; + } + break; + case 7: /* MAP */ + if (map != 0) { + sp_384_map_7(r, &ctx->t[0], ctx->tmp); + } + else { + XMEMCPY(r, &ctx->t[0], sizeof(sp_point_384)); + } + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 7) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + ForceZero(ctx->tmp, sizeof(ctx->tmp)); + ForceZero(ctx->t, sizeof(ctx->t)); + } + + (void)heap; + + return err; +} + +#endif /* WOLFSSL_SP_NONBLOCK */ + static int sp_384_ecc_mulmod_7(sp_point_384* r, const sp_point_384* g, const sp_digit* k, int map, void* heap) { @@ -22344,6 +23610,46 @@ static void sp_384_mont_sqr_n_order_7(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_7_ctx { + int state; + int i; +} sp_384_mont_inv_order_7_ctx; +static int sp_384_mont_inv_order_7_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_7_ctx* ctx = (sp_384_mont_inv_order_7_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_7_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 7); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_7(t, t); + if ((p384_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_384_mont_mul_order_7(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 7U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_7(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -22430,6 +23736,165 @@ static void sp_384_mont_inv_order_7(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_384_ctx { + int state; + union { + sp_384_ecc_mulmod_7_ctx mulmod_ctx; + sp_384_mont_inv_order_7_ctx mont_inv_order_ctx; + }; + sp_digit e[2*7]; + sp_digit x[2*7]; + sp_digit k[2*7]; + sp_digit r[2*7]; + sp_digit tmp[3 * 2*7]; + sp_point_384 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_384_ctx; + +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + (void)heap; + + switch (ctx->state) { + case 0: /* INIT */ + ctx->s = ctx->e; + ctx->kInv = ctx->k; + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->e, 7, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_384_from_mp(ctx->x, 7, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_7(rng, ctx->k); + } + else { + sp_384_from_mp(ctx->k, 7, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_384_ecc_mulmod_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p384_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int64_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 7U); + sp_384_norm_7(ctx->r); + c = sp_384_cmp_7(ctx->r, p384_order); + sp_384_cond_sub_7(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_7(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_7(ctx->k, ctx->k, p384_norm_order); + err = sp_384_mod_7(ctx->k, ctx->k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_7(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_384_mont_inv_order_7_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_384_norm_7(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_384_mul_7(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_384_mod_7(ctx->x, ctx->x, p384_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int64_t c; + sp_384_norm_7(ctx->x); + carry = sp_384_add_7(ctx->s, ctx->e, ctx->x); + sp_384_cond_sub_7(ctx->s, ctx->s, p384_order, 0 - carry); + sp_384_norm_7(ctx->s); + c = sp_384_cmp_7(ctx->s, p384_order); + sp_384_cond_sub_7(ctx->s, ctx->s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_7(ctx->s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_7(ctx->s, ctx->s, ctx->kInv); + sp_384_norm_7(ctx->s); + + /* Check that signature is usable. */ + if (sp_384_iszero_7(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_384_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_384_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 7U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 7U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 7U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 7U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 7U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -22601,6 +24066,169 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_384_ctx { + int state; + union { + sp_384_ecc_mulmod_7_ctx mulmod_ctx; + sp_384_mont_inv_order_7_ctx mont_inv_order_ctx; + sp_384_proj_point_dbl_7_ctx dbl_ctx; + sp_384_proj_point_add_7_ctx add_ctx; + }; + sp_digit u1[2*7]; + sp_digit u2[2*7]; + sp_digit s[2*7]; + sp_digit tmp[2*7 * 5]; + sp_point_384 p1; + sp_point_384 p2; +} sp_ecc_verify_384_ctx; + +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->u1, 7, hash, (int)hashLen); + sp_384_from_mp(ctx->u2, 7, r); + sp_384_from_mp(ctx->s, 7, sm); + sp_384_from_mp(ctx->p2.x, 7, pX); + sp_384_from_mp(ctx->p2.y, 7, pY); + sp_384_from_mp(ctx->p2.z, 7, pZ); + sp_384_mul_7(ctx->s, ctx->s, p384_norm_order); + err = sp_384_mod_7(ctx->s, ctx->s, p384_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_384_norm_7(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_384_mont_inv_order_7_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_384_mont_mul_order_7(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_384_mont_mul_order_7(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_384_ecc_mulmod_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_384_ecc_mulmod_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_384_proj_point_add_7_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_384_iszero_7(ctx->p1.z)) { + if (sp_384_iszero_7(ctx->p1.x) && sp_384_iszero_7(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<7; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_384_proj_point_dbl_7_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(ctx->u2, 7, r); + err = sp_384_mod_mul_norm_7(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_7(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_384_mont_mul_7(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_384_cmp_7(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int64_t c; + + /* Reload r and add order. */ + sp_384_from_mp(ctx->u2, 7, r); + carry = sp_384_add_7(ctx->u2, ctx->u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_7(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_7(ctx->u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_7(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_7(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_7(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { diff --git a/wolfcrypt/src/sp_cortexm.c b/wolfcrypt/src/sp_cortexm.c index be01f9757c..e930b34bb9 100644 --- a/wolfcrypt/src/sp_cortexm.c +++ b/wolfcrypt/src/sp_cortexm.c @@ -4013,11 +4013,11 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, sp_digit a[128], m[64], r[128]; #else sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; #endif - sp_digit *ah; + sp_digit *ah = NULL; sp_digit e[1]; int err = MP_OKAY; @@ -4184,10 +4184,10 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -4246,16 +4246,16 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, sp_digit tmpa[64], tmpb[64]; #else sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* tmpa; - sp_digit* tmpb; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; #endif - sp_digit* r; - sp_digit* qi; - sp_digit* dq; + sp_digit* r = NULL; + sp_digit* qi = NULL; + sp_digit* dq = NULL; sp_digit c; int err = MP_OKAY; @@ -8668,11 +8668,11 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, sp_digit a[192], m[96], r[192]; #else sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; #endif - sp_digit *ah; + sp_digit *ah = NULL; sp_digit e[1]; int err = MP_OKAY; @@ -8839,10 +8839,10 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -8901,16 +8901,16 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, sp_digit tmpa[96], tmpb[96]; #else sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* tmpa; - sp_digit* tmpb; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; #endif - sp_digit* r; - sp_digit* qi; - sp_digit* dq; + sp_digit* r = NULL; + sp_digit* qi = NULL; + sp_digit* dq = NULL; sp_digit c; int err = MP_OKAY; @@ -11875,11 +11875,11 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, sp_digit a[256], m[128], r[256]; #else sp_digit* d = NULL; - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; #endif - sp_digit *ah; + sp_digit *ah = NULL; sp_digit e[1]; int err = MP_OKAY; @@ -12047,10 +12047,10 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a; + sp_digit* a = NULL; sp_digit* d = NULL; - sp_digit* m; - sp_digit* r; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -12109,16 +12109,16 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, sp_digit tmpa[128], tmpb[128]; #else sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* tmpa; - sp_digit* tmpb; + sp_digit* a = NULL; + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; #endif - sp_digit* r; - sp_digit* qi; - sp_digit* dq; + sp_digit* r = NULL; + sp_digit* qi = NULL; + sp_digit* dq = NULL; sp_digit c; int err = MP_OKAY; @@ -15902,6 +15902,141 @@ SP_NOINLINE static void sp_256_div2_8(sp_digit* r, const sp_digit* a, const sp_d * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_8_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_8_ctx; + +static int sp_256_proj_point_dbl_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_8_ctx* ctx = (sp_256_proj_point_dbl_8_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*8; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_8(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_8(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_8(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_8(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_8(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_8(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_8(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_8(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_8(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_8(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_8(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_8(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_8(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_8(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -16067,6 +16202,209 @@ static int sp_256_cmp_equal_8(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_8_ctx { + int state; + sp_256_proj_point_dbl_8_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_8_ctx; + +static int sp_256_proj_point_add_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_8_ctx* ctx = (sp_256_proj_point_add_8_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*8; + ctx->t3 = t + 4*8; + ctx->t4 = t + 6*8; + ctx->t5 = t + 8*8; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_8(ctx->t1, p256_mod, q->y); + sp_256_norm_8(ctx->t1); + if ((sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<8; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<8; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<8; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_8(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_8(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_8(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_8(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_8(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_8(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_8(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_8(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_8(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_8(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_8(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_8(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_8(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_8(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_8(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_8(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_8(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -20047,6 +20385,46 @@ static void sp_256_mont_sqr_n_order_8(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_8_ctx { + int state; + int i; +} sp_256_mont_inv_order_8_ctx; +static int sp_256_mont_inv_order_8_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_8_ctx* ctx = (sp_256_mont_inv_order_8_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 8); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_8(t, t); + if ((p256_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_256_mont_mul_order_8(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 8U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -20162,6 +20540,165 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_256_mont_inv_order_8_ctx mont_inv_order_ctx; + }; + sp_digit e[2*8]; + sp_digit x[2*8]; + sp_digit k[2*8]; + sp_digit r[2*8]; + sp_digit tmp[3 * 2*8]; + sp_point_256 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_256_ctx; + +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + (void)heap; + + switch (ctx->state) { + case 0: /* INIT */ + ctx->s = ctx->e; + ctx->kInv = ctx->k; + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->e, 8, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_256_from_mp(ctx->x, 8, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_8(rng, ctx->k); + } + else { + sp_256_from_mp(ctx->k, 8, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p256_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 8U); + sp_256_norm_8(ctx->r); + c = sp_256_cmp_8(ctx->r, p256_order); + sp_256_cond_sub_8(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(ctx->k, ctx->k, p256_norm_order); + err = sp_256_mod_8(ctx->k, ctx->k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_8(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_256_mont_inv_order_8_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_256_norm_8(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_256_mul_8(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_256_mod_8(ctx->x, ctx->x, p256_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_256_norm_8(ctx->x); + carry = sp_256_add_8(ctx->s, ctx->e, ctx->x); + sp_256_cond_sub_8(ctx->s, ctx->s, p256_order, 0 - carry); + sp_256_norm_8(ctx->s); + c = sp_256_cmp_8(ctx->s, p256_order); + sp_256_cond_sub_8(ctx->s, ctx->s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(ctx->s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(ctx->s, ctx->s, ctx->kInv); + sp_256_norm_8(ctx->s); + + /* Check that signature is usable. */ + if (sp_256_iszero_8(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_256_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_256_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -20333,6 +20870,169 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_256_mont_inv_order_8_ctx mont_inv_order_ctx; + sp_256_proj_point_dbl_8_ctx dbl_ctx; + sp_256_proj_point_add_8_ctx add_ctx; + }; + sp_digit u1[2*8]; + sp_digit u2[2*8]; + sp_digit s[2*8]; + sp_digit tmp[2*8 * 5]; + sp_point_256 p1; + sp_point_256 p2; +} sp_ecc_verify_256_ctx; + +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->u1, 8, hash, (int)hashLen); + sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->s, 8, sm); + sp_256_from_mp(ctx->p2.x, 8, pX); + sp_256_from_mp(ctx->p2.y, 8, pY); + sp_256_from_mp(ctx->p2.z, 8, pZ); + sp_256_mul_8(ctx->s, ctx->s, p256_norm_order); + err = sp_256_mod_8(ctx->s, ctx->s, p256_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_256_norm_8(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_256_mont_inv_order_8_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_256_mont_mul_order_8(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_256_mont_mul_order_8(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_256_proj_point_add_8_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_256_iszero_8(ctx->p1.z)) { + if (sp_256_iszero_8(ctx->p1.x) && sp_256_iszero_8(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<8; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(ctx->u2, 8, r); + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_256_from_mp(ctx->u2, 8, r); + carry = sp_256_add_8(ctx->u2, ctx->u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_8(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(ctx->u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { @@ -22356,6 +23056,141 @@ SP_NOINLINE static void sp_384_div2_12(sp_digit* r, const sp_digit* a, const sp_ * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_12_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_12_ctx; + +static int sp_384_proj_point_dbl_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_12_ctx* ctx = (sp_384_proj_point_dbl_12_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*12; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_12(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_12(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_12(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_12(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_12(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_12(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_12(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_12(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_12(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_12(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_12(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_12(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_12(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_12(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -22431,6 +23266,209 @@ static int sp_384_cmp_equal_12(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_12_ctx { + int state; + sp_384_proj_point_dbl_12_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_12_ctx; + +static int sp_384_proj_point_add_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_12_ctx* ctx = (sp_384_proj_point_add_12_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*12; + ctx->t3 = t + 4*12; + ctx->t4 = t + 6*12; + ctx->t5 = t + 8*12; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_12(ctx->t1, p384_mod, q->y); + sp_384_norm_12(ctx->t1); + if ((sp_384_cmp_equal_12(p->x, q->x) & sp_384_cmp_equal_12(p->z, q->z) & + (sp_384_cmp_equal_12(p->y, q->y) | sp_384_cmp_equal_12(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<12; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<12; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<12; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_12(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_12(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_12(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_12(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_12(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_12(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_12(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_12(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_12(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_12(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_12(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_12(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_12(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_12(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_12(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_12(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_12(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_12(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_12(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -25581,6 +26619,46 @@ static void sp_384_mont_sqr_n_order_12(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_12_ctx { + int state; + int i; +} sp_384_mont_inv_order_12_ctx; +static int sp_384_mont_inv_order_12_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_12_ctx* ctx = (sp_384_mont_inv_order_12_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 12); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_12(t, t); + if ((p384_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_384_mont_mul_order_12(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 12U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -25667,6 +26745,165 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_384_mont_inv_order_12_ctx mont_inv_order_ctx; + }; + sp_digit e[2*12]; + sp_digit x[2*12]; + sp_digit k[2*12]; + sp_digit r[2*12]; + sp_digit tmp[3 * 2*12]; + sp_point_384 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_384_ctx; + +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + (void)heap; + + switch (ctx->state) { + case 0: /* INIT */ + ctx->s = ctx->e; + ctx->kInv = ctx->k; + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->e, 12, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_384_from_mp(ctx->x, 12, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_12(rng, ctx->k); + } + else { + sp_384_from_mp(ctx->k, 12, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p384_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 12U); + sp_384_norm_12(ctx->r); + c = sp_384_cmp_12(ctx->r, p384_order); + sp_384_cond_sub_12(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_12(ctx->k, ctx->k, p384_norm_order); + err = sp_384_mod_12(ctx->k, ctx->k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_12(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_384_mont_inv_order_12_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_384_norm_12(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_384_mul_12(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_384_mod_12(ctx->x, ctx->x, p384_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_384_norm_12(ctx->x); + carry = sp_384_add_12(ctx->s, ctx->e, ctx->x); + sp_384_cond_sub_12(ctx->s, ctx->s, p384_order, 0 - carry); + sp_384_norm_12(ctx->s); + c = sp_384_cmp_12(ctx->s, p384_order); + sp_384_cond_sub_12(ctx->s, ctx->s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(ctx->s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_12(ctx->s, ctx->s, ctx->kInv); + sp_384_norm_12(ctx->s); + + /* Check that signature is usable. */ + if (sp_384_iszero_12(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_384_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_384_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -25838,6 +27075,169 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_384_mont_inv_order_12_ctx mont_inv_order_ctx; + sp_384_proj_point_dbl_12_ctx dbl_ctx; + sp_384_proj_point_add_12_ctx add_ctx; + }; + sp_digit u1[2*12]; + sp_digit u2[2*12]; + sp_digit s[2*12]; + sp_digit tmp[2*12 * 5]; + sp_point_384 p1; + sp_point_384 p2; +} sp_ecc_verify_384_ctx; + +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->u1, 12, hash, (int)hashLen); + sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->s, 12, sm); + sp_384_from_mp(ctx->p2.x, 12, pX); + sp_384_from_mp(ctx->p2.y, 12, pY); + sp_384_from_mp(ctx->p2.z, 12, pZ); + sp_384_mul_12(ctx->s, ctx->s, p384_norm_order); + err = sp_384_mod_12(ctx->s, ctx->s, p384_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_384_norm_12(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_384_mont_inv_order_12_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_384_mont_mul_order_12(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_384_mont_mul_order_12(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_384_proj_point_add_12_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_384_iszero_12(ctx->p1.z)) { + if (sp_384_iszero_12(ctx->p1.x) && sp_384_iszero_12(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<12; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(ctx->u2, 12, r); + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_12(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_384_from_mp(ctx->u2, 12, r); + carry = sp_384_add_12(ctx->u2, ctx->u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_12(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_12(ctx->u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index b3194596de..396c57b5ea 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -38,8 +38,10 @@ * WOLFSSL_HAVE_SP_RSA: Enable SP RSA support * WOLFSSL_HAVE_SP_DH: Enable SP DH support * WOLFSSL_HAVE_SP_ECC: Enable SP ECC support - * WOLFSSL_SP_MATH: Use only single precision math and algorithms it supports (no fastmath tfm.c or normal integer.c) - * WOLFSSL_SP_SMALL: Use smaller version of code and avoid large stack variables + * WOLFSSL_SP_MATH: Use only single precision math and algorithms + * it supports (no fastmath tfm.c or normal integer.c) + * WOLFSSL_SP_SMALL: Use smaller version of code and avoid large + * stack variables * WOLFSSL_SP_NO_MALLOC: Always use stack, no heap XMALLOC/XFREE allowed * WOLFSSL_SP_NO_2048: Disable RSA/DH 2048-bit support * WOLFSSL_SP_NO_3072: Disable RSA/DH 3072-bit support @@ -52,8 +54,12 @@ * WOLFSSL_SP_ARM32_ASM Enable Aarch32 assembly speedups * WOLFSSL_SP_ARM64_ASM Enable Aarch64 assembly speedups * WOLFSSL_SP_ARM_CORTEX_M_ASM Enable Cortex-M assembly speedups - * WOLFSSL_SP_ARM_THUMB_ASM Enable ARM Thumb assembly speedups (used with -mthumb) + * WOLFSSL_SP_ARM_THUMB_ASM Enable ARM Thumb assembly speedups + * (used with -mthumb) * SP_WORD_SIZE Force 32 or 64 bit mode + * WOLFSSL_SP_NONBLOCK Enables "non blocking" mode for SP math, which + * will return FP_WOULDBLOCK for long operations and function must be + * called again until complete. */ #ifdef WOLFSSL_SP_MATH diff --git a/wolfcrypt/src/sp_x86_64.c b/wolfcrypt/src/sp_x86_64.c index 435aa22344..67eadecffb 100644 --- a/wolfcrypt/src/sp_x86_64.c +++ b/wolfcrypt/src/sp_x86_64.c @@ -6562,6 +6562,141 @@ extern void sp_256_div2_4(sp_digit* r, const sp_digit* a, const sp_digit* m); * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_4_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_4_ctx; + +static int sp_256_proj_point_dbl_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_4_ctx* ctx = (sp_256_proj_point_dbl_4_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*4; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_4(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_4(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_4(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_4(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_4(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_4(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_4(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_4(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_4(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_4(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_4(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_4(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_4(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_4(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_4(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -6723,6 +6858,209 @@ static int sp_256_cmp_equal_4(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_4_ctx { + int state; + sp_256_proj_point_dbl_4_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_4_ctx; + +static int sp_256_proj_point_add_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_4_ctx* ctx = (sp_256_proj_point_add_4_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*4; + ctx->t3 = t + 4*4; + ctx->t4 = t + 6*4; + ctx->t5 = t + 8*4; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_4(ctx->t1, p256_mod, q->y); + sp_256_norm_4(ctx->t1); + if ((sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & + (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_4_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<4; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<4; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<4; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_4(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_4(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_4(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_4(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_4(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_4(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_4(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_4(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_4(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_4(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_4(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_4(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_4(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_4(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_4(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_4(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_4(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_4(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_4(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_4(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -7286,6 +7624,141 @@ static void sp_256_map_avx2_4(sp_point_256* r, const sp_point_256* p, sp_digit* * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_avx2_4_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_avx2_4_ctx; + +static int sp_256_proj_point_dbl_avx2_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_avx2_4_ctx* ctx = (sp_256_proj_point_dbl_avx2_4_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_avx2_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*4; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_avx2_4(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_avx2_4(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_avx2_4(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_avx2_4(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_avx2_4(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_avx2_4(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_avx2_4(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_avx2_4(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_avx2_4(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_avx2_4(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_avx2_4(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_avx2_4(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_avx2_4(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_avx2_4(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_avx2_4(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_avx2_4(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_avx2_4(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_avx2_4(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_avx2_4(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -7435,6 +7908,209 @@ static void sp_256_proj_point_dbl_n_avx2_4(sp_point_256* p, int n, sp_digit* t) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_avx2_4_ctx { + int state; + sp_256_proj_point_dbl_avx2_4_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_avx2_4_ctx; + +static int sp_256_proj_point_add_avx2_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_avx2_4_ctx* ctx = (sp_256_proj_point_add_avx2_4_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_avx2_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*4; + ctx->t3 = t + 4*4; + ctx->t4 = t + 6*4; + ctx->t5 = t + 8*4; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_avx2_4(ctx->t1, p256_mod, q->y); + sp_256_norm_avx2_4(ctx->t1); + if ((sp_256_cmp_equal_avx2_4(p->x, q->x) & sp_256_cmp_equal_avx2_4(p->z, q->z) & + (sp_256_cmp_equal_avx2_4(p->y, q->y) | sp_256_cmp_equal_avx2_4(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_avx2_4_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<4; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<4; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<4; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_avx2_4(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_avx2_4(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_avx2_4(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_avx2_4(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_avx2_4(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_avx2_4(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_avx2_4(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_avx2_4(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_avx2_4(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_avx2_4(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_avx2_4(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_avx2_4(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_avx2_4(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_avx2_4(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_avx2_4(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_avx2_4(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_avx2_4(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_avx2_4(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_avx2_4(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_avx2_4(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_avx2_4(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_avx2_4(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_avx2_4(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_avx2_4(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -22626,6 +23302,46 @@ static void sp_256_mont_sqr_n_order_4(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_4_ctx { + int state; + int i; +} sp_256_mont_inv_order_4_ctx; +static int sp_256_mont_inv_order_4_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_4_ctx* ctx = (sp_256_mont_inv_order_4_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 4); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_4(t, t); + if ((p256_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_256_mont_mul_order_4(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 4U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_4(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -22772,6 +23488,46 @@ static void sp_256_mont_sqr_n_order_avx2_4(sp_digit* r, const sp_digit* a, int n * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_avx2_4_ctx { + int state; + int i; +} sp_256_mont_inv_order_avx2_4_ctx; +static int sp_256_mont_inv_order_avx2_4_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_avx2_4_ctx* ctx = (sp_256_mont_inv_order_avx2_4_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_avx2_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 4); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_avx2_4(t, t); + if ((p256_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_256_mont_mul_order_avx2_4(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 4U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_avx2_4(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -22888,6 +23644,165 @@ static void sp_256_mont_inv_order_avx2_4(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_256_ctx { + int state; + union { + sp_256_ecc_mulmod_4_ctx mulmod_ctx; + sp_256_mont_inv_order_4_ctx mont_inv_order_ctx; + }; + sp_digit e[2*4]; + sp_digit x[2*4]; + sp_digit k[2*4]; + sp_digit r[2*4]; + sp_digit tmp[3 * 2*4]; + sp_point_256 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_256_ctx; + +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + (void)heap; + + switch (ctx->state) { + case 0: /* INIT */ + ctx->s = ctx->e; + ctx->kInv = ctx->k; + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->e, 4, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_256_from_mp(ctx->x, 4, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_4(rng, ctx->k); + } + else { + sp_256_from_mp(ctx->k, 4, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p256_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int64_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 4U); + sp_256_norm_4(ctx->r); + c = sp_256_cmp_4(ctx->r, p256_order); + sp_256_cond_sub_4(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_4(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_4(ctx->k, ctx->k, p256_norm_order); + err = sp_256_mod_4(ctx->k, ctx->k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_4(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_256_mont_inv_order_4_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_256_norm_4(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_256_mul_4(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_256_mod_4(ctx->x, ctx->x, p256_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int64_t c; + sp_256_norm_4(ctx->x); + carry = sp_256_add_4(ctx->s, ctx->e, ctx->x); + sp_256_cond_sub_4(ctx->s, ctx->s, p256_order, 0 - carry); + sp_256_norm_4(ctx->s); + c = sp_256_cmp_4(ctx->s, p256_order); + sp_256_cond_sub_4(ctx->s, ctx->s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_4(ctx->s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_4(ctx->s, ctx->s, ctx->kInv); + sp_256_norm_4(ctx->s); + + /* Check that signature is usable. */ + if (sp_256_iszero_4(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_256_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_256_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 4U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -23087,6 +24002,169 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_256_ctx { + int state; + union { + sp_256_ecc_mulmod_4_ctx mulmod_ctx; + sp_256_mont_inv_order_4_ctx mont_inv_order_ctx; + sp_256_proj_point_dbl_4_ctx dbl_ctx; + sp_256_proj_point_add_4_ctx add_ctx; + }; + sp_digit u1[2*4]; + sp_digit u2[2*4]; + sp_digit s[2*4]; + sp_digit tmp[2*4 * 5]; + sp_point_256 p1; + sp_point_256 p2; +} sp_ecc_verify_256_ctx; + +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->u1, 4, hash, (int)hashLen); + sp_256_from_mp(ctx->u2, 4, r); + sp_256_from_mp(ctx->s, 4, sm); + sp_256_from_mp(ctx->p2.x, 4, pX); + sp_256_from_mp(ctx->p2.y, 4, pY); + sp_256_from_mp(ctx->p2.z, 4, pZ); + sp_256_mul_4(ctx->s, ctx->s, p256_norm_order); + err = sp_256_mod_4(ctx->s, ctx->s, p256_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_256_norm_4(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_256_mont_inv_order_4_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_256_mont_mul_order_4(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_256_mont_mul_order_4(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_256_proj_point_add_4_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_256_iszero_4(ctx->p1.z)) { + if (sp_256_iszero_4(ctx->p1.x) && sp_256_iszero_4(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<4; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_256_proj_point_dbl_4_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(ctx->u2, 4, r); + err = sp_256_mod_mul_norm_4(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_4(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_256_mont_mul_4(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_256_cmp_4(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int64_t c; + + /* Reload r and add order. */ + sp_256_from_mp(ctx->u2, 4, r); + carry = sp_256_add_4(ctx->u2, ctx->u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_4(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_4(ctx->u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_4(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_4(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_4(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { @@ -24596,6 +25674,141 @@ extern void sp_384_div2_6(sp_digit* r, const sp_digit* a, const sp_digit* m); * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_6_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_6_ctx; + +static int sp_384_proj_point_dbl_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_6_ctx* ctx = (sp_384_proj_point_dbl_6_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*6; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_6(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_6(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_6(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_6(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_6(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_6(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_6(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_6(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_6(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_6(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_6(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_6(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_6(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_6(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -24758,6 +25971,209 @@ static int sp_384_cmp_equal_6(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_6_ctx { + int state; + sp_384_proj_point_dbl_6_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_6_ctx; + +static int sp_384_proj_point_add_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_6_ctx* ctx = (sp_384_proj_point_add_6_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*6; + ctx->t3 = t + 4*6; + ctx->t4 = t + 6*6; + ctx->t5 = t + 8*6; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_6(ctx->t1, p384_mod, q->y); + sp_384_norm_6(ctx->t1); + if ((sp_384_cmp_equal_6(p->x, q->x) & sp_384_cmp_equal_6(p->z, q->z) & + (sp_384_cmp_equal_6(p->y, q->y) | sp_384_cmp_equal_6(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_6_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<6; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<6; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<6; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_6(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_6(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_6(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_6(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_6(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_6(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_6(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_6(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_6(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_6(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_6(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_6(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_6(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_6(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_6(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_6(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_6(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_6(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_6(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_6(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -25373,6 +26789,141 @@ static void sp_384_map_avx2_6(sp_point_384* r, const sp_point_384* p, sp_digit* * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_avx2_6_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_avx2_6_ctx; + +static int sp_384_proj_point_dbl_avx2_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_avx2_6_ctx* ctx = (sp_384_proj_point_dbl_avx2_6_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_avx2_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*6; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_avx2_6(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_avx2_6(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_avx2_6(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_avx2_6(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_avx2_6(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_avx2_6(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_avx2_6(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_avx2_6(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_avx2_6(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_avx2_6(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_avx2_6(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_avx2_6(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_avx2_6(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_avx2_6(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_avx2_6(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_avx2_6(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_avx2_6(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_avx2_6(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_avx2_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -25522,6 +27073,209 @@ static void sp_384_proj_point_dbl_n_avx2_6(sp_point_384* p, int n, sp_digit* t) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_avx2_6_ctx { + int state; + sp_384_proj_point_dbl_avx2_6_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_avx2_6_ctx; + +static int sp_384_proj_point_add_avx2_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_avx2_6_ctx* ctx = (sp_384_proj_point_add_avx2_6_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_avx2_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*6; + ctx->t3 = t + 4*6; + ctx->t4 = t + 6*6; + ctx->t5 = t + 8*6; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_avx2_6(ctx->t1, p384_mod, q->y); + sp_384_norm_avx2_6(ctx->t1); + if ((sp_384_cmp_equal_avx2_6(p->x, q->x) & sp_384_cmp_equal_avx2_6(p->z, q->z) & + (sp_384_cmp_equal_avx2_6(p->y, q->y) | sp_384_cmp_equal_avx2_6(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_avx2_6_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<6; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<6; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<6; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_avx2_6(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_avx2_6(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_avx2_6(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_avx2_6(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_avx2_6(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_avx2_6(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_avx2_6(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_avx2_6(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_avx2_6(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_avx2_6(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_avx2_6(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_avx2_6(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_avx2_6(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_avx2_6(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_avx2_6(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_avx2_6(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_avx2_6(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_avx2_6(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_avx2_6(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_avx2_6(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_avx2_6(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_avx2_6(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_avx2_6(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_avx2_6(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -28483,6 +30237,46 @@ static void sp_384_mont_sqr_n_order_6(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_6_ctx { + int state; + int i; +} sp_384_mont_inv_order_6_ctx; +static int sp_384_mont_inv_order_6_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_6_ctx* ctx = (sp_384_mont_inv_order_6_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 6); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_6(t, t); + if ((p384_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_384_mont_mul_order_6(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 6U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_6(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -28596,6 +30390,46 @@ static void sp_384_mont_sqr_n_order_avx2_6(sp_digit* r, const sp_digit* a, int n * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_avx2_6_ctx { + int state; + int i; +} sp_384_mont_inv_order_avx2_6_ctx; +static int sp_384_mont_inv_order_avx2_6_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_avx2_6_ctx* ctx = (sp_384_mont_inv_order_avx2_6_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_avx2_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 6); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_avx2_6(t, t); + if ((p384_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_384_mont_mul_order_avx2_6(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 6U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_avx2_6(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -28683,6 +30517,165 @@ static void sp_384_mont_inv_order_avx2_6(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_384_ctx { + int state; + union { + sp_384_ecc_mulmod_6_ctx mulmod_ctx; + sp_384_mont_inv_order_6_ctx mont_inv_order_ctx; + }; + sp_digit e[2*6]; + sp_digit x[2*6]; + sp_digit k[2*6]; + sp_digit r[2*6]; + sp_digit tmp[3 * 2*6]; + sp_point_384 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_384_ctx; + +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + (void)heap; + + switch (ctx->state) { + case 0: /* INIT */ + ctx->s = ctx->e; + ctx->kInv = ctx->k; + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->e, 6, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_384_from_mp(ctx->x, 6, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_6(rng, ctx->k); + } + else { + sp_384_from_mp(ctx->k, 6, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p384_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int64_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 6U); + sp_384_norm_6(ctx->r); + c = sp_384_cmp_6(ctx->r, p384_order); + sp_384_cond_sub_6(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_6(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_6(ctx->k, ctx->k, p384_norm_order); + err = sp_384_mod_6(ctx->k, ctx->k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_6(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_384_mont_inv_order_6_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_384_norm_6(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_384_mul_6(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_384_mod_6(ctx->x, ctx->x, p384_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int64_t c; + sp_384_norm_6(ctx->x); + carry = sp_384_add_6(ctx->s, ctx->e, ctx->x); + sp_384_cond_sub_6(ctx->s, ctx->s, p384_order, 0 - carry); + sp_384_norm_6(ctx->s); + c = sp_384_cmp_6(ctx->s, p384_order); + sp_384_cond_sub_6(ctx->s, ctx->s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_6(ctx->s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_6(ctx->s, ctx->s, ctx->kInv); + sp_384_norm_6(ctx->s); + + /* Check that signature is usable. */ + if (sp_384_iszero_6(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_384_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_384_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 6U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -28882,6 +30875,169 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_384_ctx { + int state; + union { + sp_384_ecc_mulmod_6_ctx mulmod_ctx; + sp_384_mont_inv_order_6_ctx mont_inv_order_ctx; + sp_384_proj_point_dbl_6_ctx dbl_ctx; + sp_384_proj_point_add_6_ctx add_ctx; + }; + sp_digit u1[2*6]; + sp_digit u2[2*6]; + sp_digit s[2*6]; + sp_digit tmp[2*6 * 5]; + sp_point_384 p1; + sp_point_384 p2; +} sp_ecc_verify_384_ctx; + +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->u1, 6, hash, (int)hashLen); + sp_384_from_mp(ctx->u2, 6, r); + sp_384_from_mp(ctx->s, 6, sm); + sp_384_from_mp(ctx->p2.x, 6, pX); + sp_384_from_mp(ctx->p2.y, 6, pY); + sp_384_from_mp(ctx->p2.z, 6, pZ); + sp_384_mul_6(ctx->s, ctx->s, p384_norm_order); + err = sp_384_mod_6(ctx->s, ctx->s, p384_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_384_norm_6(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_384_mont_inv_order_6_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_384_mont_mul_order_6(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_384_mont_mul_order_6(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_384_proj_point_add_6_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_384_iszero_6(ctx->p1.z)) { + if (sp_384_iszero_6(ctx->p1.x) && sp_384_iszero_6(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<6; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_384_proj_point_dbl_6_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(ctx->u2, 6, r); + err = sp_384_mod_mul_norm_6(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_6(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_384_mont_mul_6(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_384_cmp_6(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int64_t c; + + /* Reload r and add order. */ + sp_384_from_mp(ctx->u2, 6, r); + carry = sp_384_add_6(ctx->u2, ctx->u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_6(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_6(ctx->u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_6(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_6(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_6(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 2385982210..16468ff9fd 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -3311,9 +3311,9 @@ int fp_is_bit_set (fp_int *a, fp_digit b) fp_digit i; if (b > FP_MAX_BITS) - return 0; - else - i = b/DIGIT_BIT; + return FP_VAL; + + i = b/DIGIT_BIT; if ((fp_digit)a->used < i) return 0; @@ -3327,9 +3327,9 @@ int fp_set_bit (fp_int * a, fp_digit b) fp_digit i; if (b > FP_MAX_BITS) - return 0; - else - i = b/DIGIT_BIT; + return FP_VAL; + + i = b/DIGIT_BIT; /* set the used count of where the bit will go if required */ if (a->used < (int)(i+1)) diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index d660f22926..b30359c957 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -331,8 +331,60 @@ int wolfCrypt_Cleanup(void) return ret; } -#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) && \ - !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) +#ifndef NO_FILESYSTEM + +/* Helpful function to load file into allocated buffer */ +int wc_FileLoad(const char* fname, unsigned char** buf, size_t* bufLen, + void* heap) +{ + int ret; + size_t fileSz; + XFILE f; + + if (fname == NULL || buf == NULL || bufLen == NULL) { + return BAD_FUNC_ARG; + } + + /* set defaults */ + *buf = NULL; + *bufLen = 0; + + /* open file (read-only binary) */ + f = XFOPEN(fname, "rb"); + if (!f) { + WOLFSSL_MSG("wc_LoadFile file load error"); + return BAD_PATH_ERROR; + } + + XFSEEK(f, 0, SEEK_END); + fileSz = XFTELL(f); + XREWIND(f); + if (fileSz > 0) { + *bufLen = fileSz; + *buf = (byte*)XMALLOC(*bufLen, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (*buf == NULL) { + WOLFSSL_MSG("wc_LoadFile memory error"); + ret = MEMORY_E; + } + else { + size_t readLen = XFREAD(*buf, 1, *bufLen, f); + + /* check response code */ + ret = (readLen == *bufLen) ? 0 : -1; + } + } + else { + ret = BUFFER_E; + } + XFCLOSE(f); + + (void)heap; + + return ret; +} + +#if !defined(NO_WOLFSSL_DIR) && \ + !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) /* File Handling Helpers */ /* returns 0 if file found, WC_READDIR_NOFILE if no files or negative error */ @@ -631,7 +683,8 @@ void wc_ReadDirClose(ReadDirCtx* ctx) #endif } -#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */ +#endif /* !NO_WOLFSSL_DIR */ +#endif /* !NO_FILESYSTEM */ #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_ZEPHYR) XFILE z_fs_open(const char* filename, const char* perm) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index b2f871b8bb..d9e653a302 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -10385,7 +10385,10 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) !defined(USE_CERT_BUFFERS_3072) && !defined(USE_CERT_BUFFERS_4096) && \ !defined(NO_ASN) #ifndef NO_DH - static const char* dhKey = CERT_ROOT "dh2048.der"; + static const char* dhParamsFile = CERT_ROOT "dh2048.der"; + #ifdef WOLFSSL_DH_EXTRA + static const char* dhKeyFile = CERT_ROOT "statickeys/dh-ffdhe2048.der"; + #endif #endif #ifndef NO_DSA static const char* dsaKey = CERT_ROOT "dsa2048.der"; @@ -14144,7 +14147,6 @@ static int dh_fips_generate_test(WC_RNG *rng) if (ret != 0) { ERROR_OUT(-7796, exit_gen_test); } - #endif /* WOLFSSL_KEY_GEN */ #endif /* HAVE_SELFTEST */ @@ -14428,7 +14430,7 @@ int dh_test(void) #elif defined(NO_ASN) /* don't use file, no DER parsing */ #elif !defined(NO_FILESYSTEM) - XFILE file = XFOPEN(dhKey, "rb"); + XFILE file = XFOPEN(dhParamsFile, "rb"); if (!file) return -7900; @@ -14545,6 +14547,36 @@ int dh_test(void) } #endif + + + /* Test DH key import / export */ +#ifdef WOLFSSL_DH_EXTRA +#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) + file = XFOPEN(dhKeyFile, "rb"); + if (!file) + return -7950; + bytes = (word32)XFREAD(tmp, 1, sizeof(tmp), file); + XFCLOSE(file); + + idx = 0; + ret = wc_DhKeyDecode(tmp, &idx, &key, bytes); + if (ret != 0) { + return -7951; + } +#endif + + privSz = sizeof(priv); + pubSz = sizeof(pub); + ret = wc_DhExportKeyPair(&key, priv, &privSz, pub, &pubSz); + if (ret != 0) { + return -7952; + } + ret = wc_DhImportKeyPair(&key2, priv, privSz, pub, pubSz); + if (ret != 0) { + return -7953; + } +#endif /* WOLFSSL_DH_EXTRA */ + ret = dh_generate_test(&rng); if (ret == 0) ret = dh_fips_generate_test(&rng); @@ -20051,6 +20083,446 @@ exit: } #endif +/* ECC Non-blocking tests for Sign and Verify */ +/* Requires SP math and supports P384 or P256 */ +/* ./configure --enable-ecc=nonblock --enable-sp=yes,nonblock CFLAGS="-DWOLFSSL_PUBLIC_MP" */ +#if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_PUBLIC_MP) && \ + defined(HAVE_ECC_SIGN) && defined(HAVE_ECC_VERIFY) +/* Test Data - Random */ +static const uint8_t kMsg[] = { + 0x69, 0xbc, 0x9f, 0xce, 0x68, 0x17, 0xc2, 0x10, 0xea, 0xfc, 0x10, 0x65, 0x67, 0x52, 0xed, 0x78, + 0x6e, 0xb8, 0x83, 0x9c, 0x9a, 0xb4, 0x56, 0x0d, 0xc1, 0x0d, 0x1f, 0x78, 0x6e, 0x75, 0xd7, 0xbe, + 0x92, 0x6b, 0x12, 0xf6, 0x76, 0x60, 0x8e, 0xb1, 0xf4, 0x19, 0x0c, 0x81, 0xe7, 0x54, 0x5e, 0xbc, + 0xe0, 0xae, 0xc2, 0x7d, 0x1b, 0xc4, 0x6e, 0xec, 0xb1, 0x99, 0x6c, 0xbf, 0x0e, 0x38, 0xa8, 0x01, + 0xa6, 0x9a, 0x48, 0x12, 0xe4, 0xc9, 0x3b, 0xf0, 0x63, 0x46, 0x15, 0xb4, 0x61, 0xa8, 0x1a, 0x60, + 0x71, 0x87, 0x98, 0xd7, 0x6f, 0x98, 0x7b, 0x2d, 0xb9, 0x19, 0x1b, 0x21, 0x9c, 0x70, 0x58, 0xe8, + 0x0d, 0x0f, 0xe9, 0x2d, 0x9a, 0x9a, 0xf1, 0x55, 0xa0, 0x4c, 0xd3, 0x07, 0xbd, 0x97, 0x48, 0xec, + 0x88, 0x0a, 0xaf, 0xb3, 0x80, 0x78, 0xa4, 0x59, 0x43, 0x57, 0xd3, 0xa7, 0x01, 0x66, 0x0e, 0xfc +}; + +/* ECC Private Key "d" */ +static const uint8_t kPrivKey[] = { +#ifdef HAVE_ECC384 + /* SECP384R1 */ + /* d */ + 0xa4, 0xe5, 0x06, 0xe8, 0x06, 0x16, 0x3e, 0xab, + 0x89, 0xf8, 0x60, 0x43, 0xc0, 0x60, 0x25, 0xdb, + 0xba, 0x7b, 0xfe, 0x19, 0x35, 0x08, 0x55, 0x65, + 0x76, 0xe2, 0xdc, 0xe0, 0x01, 0x8b, 0x6b, 0x68, + 0xdf, 0xcf, 0x6f, 0x80, 0x12, 0xce, 0x79, 0x37, + 0xeb, 0x2b, 0x9c, 0x7b, 0xc4, 0x68, 0x1c, 0x74 +#else + /* SECP256R1 */ + /* d */ + 0x1e, 0xe7, 0x70, 0x07, 0xd3, 0x30, 0x94, 0x39, + 0x28, 0x90, 0xdf, 0x23, 0x88, 0x2c, 0x4a, 0x34, + 0x15, 0xdb, 0x4c, 0x43, 0xcd, 0xfa, 0xe5, 0x1f, + 0x3d, 0x4c, 0x37, 0xfe, 0x59, 0x3b, 0x96, 0xd8 +#endif +}; + +/* ECC public key Qx/Qy */ +static const uint8_t kPubKey[] = { +#ifdef HAVE_ECC384 + /* SECP384R1 */ + /* Qx */ + 0xea, 0xcf, 0x93, 0x4f, 0x2c, 0x09, 0xbb, 0x39, + 0x14, 0x0f, 0x56, 0x64, 0xc3, 0x40, 0xb4, 0xdf, + 0x0e, 0x63, 0xae, 0xe5, 0x71, 0x4b, 0x00, 0xcc, + 0x04, 0x97, 0xff, 0xe1, 0xe9, 0x38, 0x96, 0xbb, + 0x5f, 0x91, 0xb2, 0x6a, 0xcc, 0xb5, 0x39, 0x5f, + 0x8f, 0x70, 0x59, 0xf1, 0x01, 0xf6, 0x5a, 0x2b, + /* Qy */ + 0x01, 0x6c, 0x68, 0x0b, 0xcf, 0x55, 0x25, 0xaf, + 0x6d, 0x98, 0x48, 0x0a, 0xa8, 0x74, 0xc9, 0xa9, + 0x17, 0xa0, 0x0c, 0xc3, 0xfb, 0xd3, 0x23, 0x68, + 0xfe, 0x04, 0x3c, 0x63, 0x50, 0x88, 0x3b, 0xb9, + 0x4f, 0x7c, 0x67, 0x34, 0xf7, 0x3b, 0xa9, 0x73, + 0xe7, 0x1b, 0xc3, 0x51, 0x5e, 0x22, 0x18, 0xec +#else + /* SECP256R1 */ + /* Qx */ + 0x96, 0x93, 0x1c, 0x53, 0x0b, 0x43, 0x6c, 0x42, + 0x0c, 0x52, 0x90, 0xe4, 0xa7, 0xec, 0x98, 0xb1, + 0xaf, 0xd4, 0x14, 0x49, 0xd8, 0xc1, 0x42, 0x82, + 0x04, 0x78, 0xd1, 0x90, 0xae, 0xa0, 0x6c, 0x07, + /* Qy */ + 0xf2, 0x3a, 0xb5, 0x10, 0x32, 0x8d, 0xce, 0x9e, + 0x76, 0xa0, 0xd2, 0x8c, 0xf3, 0xfc, 0xa9, 0x94, + 0x43, 0x24, 0xe6, 0x82, 0x00, 0x40, 0xc6, 0xdb, + 0x1c, 0x2f, 0xcd, 0x38, 0x4b, 0x60, 0xdd, 0x61 +#endif +}; + +/* ECC Curve */ +#ifdef HAVE_ECC384 + /* SECP384R1 */ + #define ECC_CURVE_SZ 48 + #define ECC_CURVE_ID ECC_SECP384R1 +#else + /* SECP256R1 */ + #define ECC_CURVE_SZ 32 + #define ECC_CURVE_ID ECC_SECP256R1 +#endif + +/* Hash Algorithm */ +#if defined(HAVE_ECC384) && defined(WOLFSSL_SHA3) + #define HASH_DIGEST_SZ WC_SHA3_384_DIGEST_SIZE + #define HASH_SHA_VER 3 + #define CRYPTO_HASH_FN crypto_sha3_384 +#elif defined(HAVE_ECC384) && defined(WOLFSSL_SHA384) + #define HASH_DIGEST_SZ WC_SHA384_DIGEST_SIZE + #define HASH_SHA_VER 2 + #define CRYPTO_HASH_FN crypto_sha2_384 +#elif !defined(NO_SHA256) + #define HASH_DIGEST_SZ WC_SHA256_DIGEST_SIZE + #define HASH_SHA_VER 2 + #define CRYPTO_HASH_FN crypto_sha2_256 +#else + #error test configuration not supported +#endif + +#if defined(HAVE_ECC384) && defined(WOLFSSL_SHA3) +/* helper to perform hashing block by block */ +static int crypto_sha3_384(const uint8_t *buf, uint32_t len, uint8_t *hash, + uint32_t hashSz, uint32_t blkSz) +{ + int ret; + uint32_t i = 0, chunk; + wc_Sha3 sha3; + + /* validate arguments */ + if ((buf == NULL && len > 0) || hash == NULL || + hashSz < WC_SHA3_384_DIGEST_SIZE || blkSz == 0) + { + return BAD_FUNC_ARG; + } + + /* Init Sha3_384 structure */ + ret = wc_InitSha3_384(&sha3, NULL, INVALID_DEVID); + if (ret != 0) { + return ret; + } + while (i < len) { + chunk = blkSz; + if ((chunk + i) > len) + chunk = len - i; + /* Perform chunked update */ + ret = wc_Sha3_384_Update(&sha3, (buf + i), chunk); + if (ret != 0) { + break; + } + i += chunk; + } + if (ret == 0) { + /* Get final digest result */ + ret = wc_Sha3_384_Final(&sha3, hash); + } + return ret; +} +#elif defined(HAVE_ECC384) && defined(WOLFSSL_SHA384) +/* helper to perform hashing block by block */ +static int crypto_sha2_384(const uint8_t *buf, uint32_t len, uint8_t *hash, + uint32_t hashSz, uint32_t blkSz) +{ + int ret; + uint32_t i = 0, chunk; + wc_Sha384 sha384; + + /* validate arguments */ + if ((buf == NULL && len > 0) || hash == NULL || + hashSz < WC_SHA384_DIGEST_SIZE || blkSz == 0) + { + return BAD_FUNC_ARG; + } + + /* Init Sha384 structure */ + ret = wc_InitSha384(&sha384); + if (ret != 0) { + return ret; + } + while (i < len) { + chunk = blkSz; + if ((chunk + i) > len) + chunk = len - i; + /* Perform chunked update */ + ret = wc_Sha384Update(&sha384, (buf + i), chunk); + if (ret != 0) { + break; + } + i += chunk; + } + if (ret == 0) { + /* Get final digest result */ + ret = wc_Sha384Final(&sha384, hash); + } + return ret; +} +#elif !defined(NO_SHA256) +/* helper to perform hashing block by block */ +static int crypto_sha2_256(const uint8_t *buf, uint32_t len, uint8_t *hash, + uint32_t hashSz, uint32_t blkSz) +{ + int ret; + uint32_t i = 0, chunk; + wc_Sha256 sha256; + + /* validate arguments */ + if ((buf == NULL && len > 0) || hash == NULL || + hashSz < WC_SHA256_DIGEST_SIZE || blkSz == 0) + { + return BAD_FUNC_ARG; + } + + /* Init Sha256 structure */ + ret = wc_InitSha256(&sha256); + if (ret != 0) { + return ret; + } + while (i < len) { + chunk = blkSz; + if ((chunk + i) > len) + chunk = len - i; + /* Perform chunked update */ + ret = wc_Sha256Update(&sha256, (buf + i), chunk); + if (ret != 0) { + break; + } + i += chunk; + } + if (ret == 0) { + /* Get final digest result */ + ret = wc_Sha256Final(&sha256, hash); + } + return ret; +} +#endif + +/* perform verify of signature and hash using public key */ +/* key is public Qx + public Qy */ +/* sig is r + s */ +static int crypto_ecc_verify(const uint8_t *key, uint32_t keySz, + const uint8_t *hash, uint32_t hashSz, const uint8_t *sig, uint32_t sigSz, + uint32_t curveSz, int curveId) +{ + int ret, verify_res = 0, count = 0; + mp_int r, s; + ecc_key ecc; + ecc_nb_ctx_t nb_ctx; + + /* validate arguments */ + if (key == NULL || hash == NULL || sig == NULL || curveSz == 0 || + hashSz == 0 || keySz < (curveSz*2) || sigSz < (curveSz*2)) + { + return BAD_FUNC_ARG; + } + + /* Setup the ECC key */ + ret = wc_ecc_init(&ecc); + if (ret < 0) { + return ret; + } + + ret = wc_ecc_set_nonblock(&ecc, &nb_ctx); + if (ret != MP_OKAY) { + wc_ecc_free(&ecc); + return ret; + } + + /* Setup the signature r/s variables */ + ret = mp_init(&r); + if (ret != MP_OKAY) { + wc_ecc_free(&ecc); + return ret; + } + ret = mp_init(&s); + if (ret != MP_OKAY) { + mp_clear(&r); + wc_ecc_free(&ecc); + return ret; + } + + /* Import public key x/y */ + ret = wc_ecc_import_unsigned( + &ecc, + (byte*)key, /* Public "x" Coordinate */ + (byte*)(key + curveSz), /* Public "y" Coordinate */ + NULL, /* Private "d" (optional) */ + curveId /* ECC Curve Id */ + ); + /* Make sure it was a public key imported */ + if (ret == 0 && ecc.type != ECC_PUBLICKEY) { + ret = ECC_BAD_ARG_E; + } + + /* Import signature r/s */ + if (ret == 0) { + ret = mp_read_unsigned_bin(&r, sig, curveSz); + } + if (ret == 0) { + ret = mp_read_unsigned_bin(&s, sig + curveSz, curveSz); + } + + /* Verify ECC Signature */ + if (ret == 0) { + do { + ret = wc_ecc_verify_hash_ex( + &r, &s, /* r/s as mp_int */ + hash, hashSz, /* computed hash digest */ + &verify_res, /* verification result 1=success */ + &ecc + ); + count++; + + /* TODO: Real-time work can be called here */ + } while (ret == FP_WOULDBLOCK); + #ifdef DEBUG_WOLFSSL + printf("ECC non-block verify: %d times\n", count); + #endif + } + + /* check verify result */ + if (ret == 0 && verify_res == 0) { + ret = SIG_VERIFY_E; + } + + mp_clear(&r); + mp_clear(&s); + wc_ecc_free(&ecc); + + (void)count; + + return ret; +} + +/* perform signature operation against hash using private key */ +static int crypto_ecc_sign(const uint8_t *key, uint32_t keySz, + const uint8_t *hash, uint32_t hashSz, uint8_t *sig, uint32_t* sigSz, + uint32_t curveSz, int curveId, WC_RNG* rng) +{ + int ret, count = 0; + mp_int r, s; + ecc_key ecc; + ecc_nb_ctx_t nb_ctx; + + /* validate arguments */ + if (key == NULL || hash == NULL || sig == NULL || sigSz == NULL || + curveSz == 0 || hashSz == 0 || keySz < curveSz || *sigSz < (curveSz*2)) + { + return BAD_FUNC_ARG; + } + + /* Initialize signature result */ + memset(sig, 0, curveSz*2); + + /* Setup the ECC key */ + ret = wc_ecc_init(&ecc); + if (ret < 0) { + return ret; + } + + ret = wc_ecc_set_nonblock(&ecc, &nb_ctx); + if (ret != MP_OKAY) { + wc_ecc_free(&ecc); + return ret; + } + + /* Setup the signature r/s variables */ + ret = mp_init(&r); + if (ret != MP_OKAY) { + wc_ecc_free(&ecc); + return ret; + } + ret = mp_init(&s); + if (ret != MP_OKAY) { + mp_clear(&r); + wc_ecc_free(&ecc); + return ret; + } + + /* Import private key "k" */ + ret = wc_ecc_import_private_key_ex( + key, keySz, /* private key "d" */ + NULL, 0, /* public (optional) */ + &ecc, + curveId /* ECC Curve Id */ + ); + + if (ret == 0) { + do { + /* Verify ECC Signature */ + ret = wc_ecc_sign_hash_ex( + hash, hashSz, /* computed hash digest */ + rng, &ecc, /* random and key context */ + &r, &s /* r/s as mp_int */ + ); + count++; + + /* TODO: Real-time work can be called here */ + } while (ret == FP_WOULDBLOCK); + + #ifdef DEBUG_WOLFSSL + printf("ECC non-block sign: %d times\n", count); + #endif + } + + if (ret == 0) { + /* export r/s */ + mp_to_unsigned_bin(&r, sig); + mp_to_unsigned_bin(&s, sig + curveSz); + } + + mp_clear(&r); + mp_clear(&s); + wc_ecc_free(&ecc); + + (void)count; + + return ret; +} + +static int ecc_test_nonblock(WC_RNG* rng) +{ + int ret; + uint8_t hash[HASH_DIGEST_SZ]; + uint8_t sig[ECC_CURVE_SZ*2]; + uint32_t sigSz = sizeof(sig); + + ret = CRYPTO_HASH_FN( + kMsg, sizeof(kMsg), /* input message */ + hash, sizeof(hash), /* hash digest result */ + 32 /* configurable block / chunk size */ + ); + if (ret == 0) { + /* Sign hash using private key */ + /* Note: result of an ECC sign varies for each call even with same + private key and hash. This is because a new random public key is + used for each operation. */ + ret = crypto_ecc_sign( + kPrivKey, sizeof(kPrivKey), /* private key */ + hash, sizeof(hash), /* computed hash digest */ + sig, &sigSz, /* signature r/s */ + ECC_CURVE_SZ, /* curve size in bytes */ + ECC_CURVE_ID, /* curve id */ + rng + ); + } + + if (ret == 0) { + /* Verify generated signature is valid */ + ret = crypto_ecc_verify( + kPubKey, sizeof(kPubKey), /* public key point x/y */ + hash, sizeof(hash), /* computed hash digest */ + sig, sigSz, /* signature r/s */ + ECC_CURVE_SZ, /* curve size in bytes */ + ECC_CURVE_ID /* curve id */ + ); + } + + return ret; +} +#endif /* WC_ECC_NONBLOCK && WOLFSSL_PUBLIC_MP && HAVE_ECC_SIGN && HAVE_ECC_VERIFY */ + int ecc_test(void) { int ret; @@ -20193,6 +20665,14 @@ int ecc_test(void) } #endif +#if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_PUBLIC_MP) && \ + defined(HAVE_ECC_SIGN) && defined(HAVE_ECC_VERIFY) + ret = ecc_test_nonblock(&rng); + if (ret != 0) { + printf("ecc_test_nonblock failed!: %d\n", ret); + } +#endif + done: wc_FreeRng(&rng); @@ -28013,12 +28493,15 @@ int mutex_test(void) XFREE(mm, NULL, DYNAMIC_TYPE_MUTEX); #endif + /* Can optionally enable advanced pthread tests using "ENABLE_PTHREAD_LOCKFREE_TESTS" */ #ifdef WOLFSSL_PTHREADS if (wc_InitMutex(&m) != 0) return -12701; if (wc_LockMutex(&m) != 0) return -12702; -#if !defined(WOLFSSL_SOLARIS) +#if !defined(WOLFSSL_SOLARIS) && defined(ENABLE_PTHREAD_LOCKFREE_TESTS) + /* trying to free a locked mutex is not portable behavior with pthread */ + /* Attempting to destroy a locked mutex results in undefined behavior */ if (wc_FreeMutex(&m) != BAD_MUTEX_E) return -12703; #endif @@ -28026,7 +28509,8 @@ int mutex_test(void) return -12704; if (wc_FreeMutex(&m) != 0) return -12705; -#if !defined(WOLFSSL_NO_MUTEXLOCK_AFTER_FREE) +#if !defined(WOLFSSL_SOLARIS) && defined(ENABLE_PTHREAD_LOCKFREE_TESTS) + /* Trying to use a pthread after free'ing is not portable behavior */ if (wc_LockMutex(&m) != BAD_MUTEX_E) return -12706; if (wc_UnLockMutex(&m) != BAD_MUTEX_E) diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 9b44326e7f..c6870d96c4 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -167,6 +167,8 @@ enum wolfSSL_ErrorCodes { CLIENT_CERT_CB_ERROR = -436, /* Client cert callback error */ SSL_SHUTDOWN_ALREADY_DONE_E = -437, /* Shutdown called redundantly */ TLS13_SECRET_CB_E = -438, /* TLS1.3 secret Cb fcn failure */ + DTLS_SIZE_ERROR = -439, /* Trying to send too much data */ + NO_CERT_ERROR = -440, /* TLS1.3 - no cert set error */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index a7ad54fc05..f1d3a2868f 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1657,6 +1657,10 @@ WOLFSSL_LOCAL int InitSSL_Side(WOLFSSL* ssl, word16 side); /* for sniffer */ WOLFSSL_LOCAL int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, word32 totalSz, int sniff); +#ifdef WOLFSSL_TLS13 +WOLFSSL_LOCAL int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 size, word32 totalSz, int sniff); +#endif WOLFSSL_LOCAL int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx); /* TLS v1.3 needs these */ WOLFSSL_LOCAL int HandleTlsResumption(WOLFSSL* ssl, int bogusID, @@ -1692,10 +1696,11 @@ WOLFSSL_LOCAL int CheckAltNames(DecodedCert* dCert, char* domain); WOLFSSL_LOCAL int CheckIPAddr(DecodedCert* dCert, const char* ipasc); #endif WOLFSSL_LOCAL int CreateTicket(WOLFSSL* ssl); -WOLFSSL_LOCAL int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz); +WOLFSSL_LOCAL int HashRaw(WOLFSSL* ssl, const byte* output, int sz); WOLFSSL_LOCAL int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz); WOLFSSL_LOCAL int HashInput(WOLFSSL* ssl, const byte* input, int sz); + #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) WOLFSSL_LOCAL int SNI_Callback(WOLFSSL* ssl); #endif @@ -2150,13 +2155,14 @@ typedef enum { TLSX_SUPPORTED_GROUPS = 0x000a, /* a.k.a. Supported Curves */ TLSX_EC_POINT_FORMATS = 0x000b, #if !defined(WOLFSSL_NO_SIGALG) - TLSX_SIGNATURE_ALGORITHMS = 0x000d, + TLSX_SIGNATURE_ALGORITHMS = 0x000d, /* HELLO_EXT_SIG_ALGO */ #endif TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */ TLSX_STATUS_REQUEST_V2 = 0x0011, /* a.k.a. OCSP stapling v2 */ #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) TLSX_ENCRYPT_THEN_MAC = 0x0016, /* RFC 7366 */ #endif + TLSX_EXTENDED_MASTER_SECRET = 0x0017, /* HELLO_EXT_EXTMS */ TLSX_QUANTUM_SAFE_HYBRID = 0x0018, /* a.k.a. QSH */ TLSX_SESSION_TICKET = 0x0023, #ifdef WOLFSSL_TLS13 @@ -2579,6 +2585,13 @@ enum DeriveKeyType { update_traffic_key }; +WOLFSSL_LOCAL int DeriveEarlySecret(WOLFSSL* ssl); +WOLFSSL_LOCAL int DeriveHandshakeSecret(WOLFSSL* ssl); +WOLFSSL_LOCAL int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store); +WOLFSSL_LOCAL int DeriveMasterSecret(WOLFSSL* ssl); +WOLFSSL_LOCAL int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret); +WOLFSSL_LOCAL int DeriveResumptionSecret(WOLFSSL* ssl, byte* key); + /* The key update request values for KeyUpdate message. */ enum KeyUpdateRequest { update_not_requested, @@ -2595,6 +2608,14 @@ enum SetCBIO { }; #endif +#ifdef WOLFSSL_STATIC_EPHEMERAL +typedef struct { + int keyAlgo; + DerBuffer* key; +} StaticKeyExchangeInfo_t; +#endif + + /* wolfSSL context type */ struct WOLFSSL_CTX { WOLFSSL_METHOD* method; @@ -2868,16 +2889,19 @@ struct WOLFSSL_CTX { #endif /* NO_RSA */ #endif /* HAVE_PK_CALLBACKS */ #ifdef HAVE_WOLF_EVENT - WOLF_EVENT_QUEUE event_queue; + WOLF_EVENT_QUEUE event_queue; #endif /* HAVE_WOLF_EVENT */ #ifdef HAVE_EXT_CACHE - WOLFSSL_SESSION*(*get_sess_cb)(WOLFSSL*, unsigned char*, int, int*); - int (*new_sess_cb)(WOLFSSL*, WOLFSSL_SESSION*); - void (*rem_sess_cb)(WOLFSSL_CTX*, WOLFSSL_SESSION*); + WOLFSSL_SESSION*(*get_sess_cb)(WOLFSSL*, unsigned char*, int, int*); + int (*new_sess_cb)(WOLFSSL*, WOLFSSL_SESSION*); + void (*rem_sess_cb)(WOLFSSL_CTX*, WOLFSSL_SESSION*); #endif #if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) - Srp* srp; /* TLS Secure Remote Password Protocol*/ - byte* srp_password; + Srp* srp; /* TLS Secure Remote Password Protocol*/ + byte* srp_password; +#endif +#ifdef WOLFSSL_STATIC_EPHEMERAL + StaticKeyExchangeInfo_t staticKE; #endif }; @@ -2942,7 +2966,6 @@ enum KeyExchangeAlgorithm { ecc_static_diffie_hellman_kea /* for verify suite only */ }; - /* Supported Authentication Schemes */ enum SignatureAlgorithm { anonymous_sa_algo = 0, @@ -4220,6 +4243,9 @@ struct WOLFSSL { WOLFSSL_STACK* supportedCiphers; /* Used in wolfSSL_get_ciphers_compat */ WOLFSSL_STACK* peerCertChain; /* Used in wolfSSL_get_peer_cert_chain */ #endif +#ifdef WOLFSSL_STATIC_EPHEMERAL + StaticKeyExchangeInfo_t staticKE; +#endif }; diff --git a/wolfssl/sniffer.h b/wolfssl/sniffer.h index 8c31b024d6..f18415a9ea 100644 --- a/wolfssl/sniffer.h +++ b/wolfssl/sniffer.h @@ -49,18 +49,19 @@ SSL_SNIFFER_API int ssl_SetPrivateKey(const char* address, int port, const char* keyFile, int typeK, const char* password, char* error); -WOLFSSL_API -SSL_SNIFFER_API int ssl_SetNamedPrivateKey(const char* name, - const char* address, int port, - const char* keyFile, int typeK, - const char* password, char* error); - WOLFSSL_API SSL_SNIFFER_API int ssl_SetPrivateKeyBuffer(const char* address, int port, const char* keyBuf, int keySz, int typeK, const char* password, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetNamedPrivateKey(const char* name, + const char* address, int port, + const char* keyFile, int typeK, + const char* password, char* error); + WOLFSSL_API SSL_SNIFFER_API int ssl_SetNamedPrivateKeyBuffer(const char* name, const char* address, int port, @@ -68,6 +69,29 @@ SSL_SNIFFER_API int ssl_SetNamedPrivateKeyBuffer(const char* name, int typeK, const char* password, char* error); +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetEphemeralKey(const char* address, int port, + const char* keyFile, int typeKey, + const char* password, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetEphemeralKeyBuffer(const char* address, int port, + const char* keyBuf, int keySz, int typeKey, + const char* password, char* error); + + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetNamedEphemeralKey(const char* name, + const char* address, int port, + const char* keyFile, int typeKey, + const char* password, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetNamedEphemeralKeyBuffer(const char* name, + const char* address, int port, + const char* keyBuf, int keySz, int typeKey, + const char* password, char* error); + WOLFSSL_API SSL_SNIFFER_API int ssl_DecodePacket(const unsigned char* packet, int length, unsigned char** data, char* error); diff --git a/wolfssl/sniffer_error.h b/wolfssl/sniffer_error.h index d4e8369273..882aaeae7b 100644 --- a/wolfssl/sniffer_error.h +++ b/wolfssl/sniffer_error.h @@ -130,6 +130,7 @@ #define NO_DATA_DEST_STR 91 #define STORE_DATA_FAIL_STR 92 #define CHAIN_INPUT_STR 93 +#define GOT_ENC_EXT_STR 94 /* !!!! also add to msgTable in sniffer.c and .rc file !!!! */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 8714786cb3..d0abe090b4 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -2541,7 +2541,7 @@ struct DhKey; typedef int (*CallbackDhAgree)(WOLFSSL* ssl, struct DhKey* key, const unsigned char* priv, unsigned int privSz, const unsigned char* otherPubKeyDer, unsigned int otherPubKeySz, - unsigned char* out, unsigned int* outlen, + unsigned char* out, word32* outlen, void* ctx); WOLFSSL_API void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX*, CallbackDhAgree); WOLFSSL_API void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx); @@ -2639,7 +2639,7 @@ WOLFSSL_API void* wolfSSL_GetX448SharedSecretCtx(WOLFSSL* ssl); #ifndef NO_RSA typedef int (*CallbackRsaSign)(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, - unsigned char* out, unsigned int* outSz, + unsigned char* out, word32* outSz, const unsigned char* keyDer, unsigned int keySz, void* ctx); WOLFSSL_API void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX*, CallbackRsaSign); @@ -2684,7 +2684,7 @@ WOLFSSL_API void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl); /* RSA Public Encrypt cb */ typedef int (*CallbackRsaEnc)(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, - unsigned char* out, unsigned int* outSz, + unsigned char* out, word32* outSz, const unsigned char* keyDer, unsigned int keySz, void* ctx); WOLFSSL_API void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX*, CallbackRsaEnc); @@ -3898,7 +3898,7 @@ WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey( WOLFSSL_API unsigned long wolfSSL_X509_subject_name_hash(const WOLFSSL_X509* x509); -#endif /* OPENSSL_EXTRA */ +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ #ifdef HAVE_PK_CALLBACKS WOLFSSL_API int wolfSSL_IsPrivatePkSet(WOLFSSL* ssl); @@ -3910,6 +3910,15 @@ WOLFSSL_API int wolfSSL_CTX_AllowEncryptThenMac(WOLFSSL_CTX *, int); WOLFSSL_API int wolfSSL_AllowEncryptThenMac(WOLFSSL *s, int); #endif +/* This feature is used to set a fixed ephemeral key and is for testing only */ +/* Currently allows ECDHE and DHE only */ +#ifdef WOLFSSL_STATIC_EPHEMERAL +WOLFSSL_API int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, + const char* key, unsigned int keySz, int format); +WOLFSSL_API int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo, + const char* key, unsigned int keySz, int format); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/test.h b/wolfssl/test.h index 385a3be211..9e192c040c 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -55,6 +55,7 @@ #endif #define SOCKET_T SOCKET #define SNPRINTF _snprintf + #define XSLEEP_MS(t) Sleep(t) #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) #include #include "rl_net.h" @@ -69,9 +70,9 @@ return(ret) ; } #if defined(HAVE_KEIL_RTX) - #define sleep(t) os_dly_wait(t/1000+1); + #define XSLEEP_MS(t) os_dly_wait(t) #elif defined(WOLFSSL_CMSIS_RTOS) || defined(WOLFSSL_CMSIS_RTOSv2) - #define sleep(t) osDelay(t/1000+1); + #define XSLEEP_MS(t) osDelay(t) #endif #elif defined(WOLFSSL_TIRTOS) #include @@ -88,6 +89,7 @@ char **h_addr_list; /* list of addresses from name server */ }; #define SOCKET_T int + #define XSLEEP_MS(t) Task_sleep(t/1000) #elif defined(WOLFSSL_VXWORKS) #include #include @@ -148,8 +150,19 @@ #include /* ignore SIGPIPE */ #endif #define SNPRINTF snprintf + + #define XSELECT_WAIT(x,y) do { \ + struct timeval tv = {(x),(y)}; \ + select(0, NULL, NULL, NULL, &tv); \ + } while (0) + #define XSLEEP_US(u) XSELECT_WAIT(0,u) + #define XSLEEP_MS(m) XSELECT_WAIT(0,(m)*1000) #endif /* USE_WINDOWS_API */ +#ifndef XSLEEP_MS + #define XSLEEP_MS(t) sleep(t/1000) +#endif + #ifdef WOLFSSL_ASYNC_CRYPT #include #endif @@ -1684,7 +1697,7 @@ enum { VERIFY_USE_PREVERFIY, VERIFY_OVERRIDE_DATE_ERR, }; -static int myVerifyAction = VERIFY_OVERRIDE_ERROR; +static THREAD_LS_T int myVerifyAction = VERIFY_OVERRIDE_ERROR; /* The verify callback is called for every certificate only when * --enable-opensslextra is defined because it sets WOLFSSL_ALWAYS_VERIFY_CB and @@ -3601,15 +3614,16 @@ static WC_INLINE const char* mymktemp(char *tempfn, int len, int num) int enc, byte* ticket, int inLen, int* outLen, void* userCtx) { - (void)ssl; - (void)userCtx; - int ret; word16 sLen = XHTONS(inLen); byte aad[WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2]; int aadSz = WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2; byte* tmp = aad; + (void)ssl; + (void)userCtx; + + /* encrypt */ if (enc) { XMEMCPY(key_name, myKey_ctx.name, WOLFSSL_TICKET_NAME_SZ); @@ -3630,8 +3644,9 @@ static WC_INLINE const char* mymktemp(char *tempfn, int len, int num) mac); if (ret != 0) return WOLFSSL_TICKET_RET_REJECT; *outLen = inLen; /* no padding in this mode */ - } else { - /* decrypt */ + } + /* decrypt */ + else { /* see if we know this key */ if (XMEMCMP(key_name, myKey_ctx.name, WOLFSSL_TICKET_NAME_SZ) != 0){ @@ -3658,7 +3673,7 @@ static WC_INLINE const char* mymktemp(char *tempfn, int len, int num) return WOLFSSL_TICKET_RET_OK; } -#endif /* HAVE_SESSION_TICKET && CHACHA20 && POLY1305 */ +#endif /* HAVE_SESSION_TICKET && HAVE_CHACHA && HAVE_POLY1305 */ static WC_INLINE word16 GetRandomPort(void) { diff --git a/wolfssl/wolfcrypt/dh.h b/wolfssl/wolfcrypt/dh.h index a69232cc09..a92d7b3ce1 100644 --- a/wolfssl/wolfcrypt/dh.h +++ b/wolfssl/wolfcrypt/dh.h @@ -45,11 +45,19 @@ #ifdef WOLFSSL_ASYNC_CRYPT #include #endif + +/* Optional support extended DH public / private keys */ +#if !defined(WOLFSSL_DH_EXTRA) && (defined(WOLFSSL_QT) || \ + defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH) || \ + defined(WOLFSSL_STATIC_EPHEMERAL)) + #define WOLFSSL_DH_EXTRA +#endif + typedef struct DhParams { - #ifdef HAVE_FFDHE_Q +#ifdef HAVE_FFDHE_Q const byte* q; word32 q_len; - #endif /* HAVE_FFDHE_Q */ +#endif /* HAVE_FFDHE_Q */ const byte* p; word32 p_len; const byte* g; @@ -58,8 +66,8 @@ typedef struct DhParams { /* Diffie-Hellman Key */ struct DhKey { - mp_int p, g, q; /* group parameters */ -#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH) + mp_int p, g, q; /* group parameters */ +#ifdef WOLFSSL_DH_EXTRA mp_int pub; mp_int priv; #endif @@ -101,15 +109,20 @@ WOLFSSL_API int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, word32 pubSz); WOLFSSL_API int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, - word32); + word32); /* wc_DhKeyDecode is in asn.c */ + WOLFSSL_API int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz); WOLFSSL_API int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz, const byte* q, word32 qSz); -#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) -WOLFSSL_LOCAL int wc_DhSetFullKeys(DhKey* key,const byte* priv_key,word32 privSz, - const byte* pub_key, word32 pubSz); -#endif + +#ifdef WOLFSSL_DH_EXTRA +WOLFSSL_API int wc_DhImportKeyPair(DhKey* key, const byte* priv, word32 privSz, + const byte* pub, word32 pubSz); +WOLFSSL_API int wc_DhExportKeyPair(DhKey* key, byte* priv, word32* pPrivSz, + byte* pub, word32* pPubSz); +#endif /* WOLFSSL_DH_EXTRA */ + WOLFSSL_API int wc_DhSetCheckKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz, const byte* q, word32 qSz, int trusted, WC_RNG* rng); @@ -136,4 +149,3 @@ WOLFSSL_API int wc_DhExportParamsRaw(DhKey* dh, byte* p, word32* pSz, #endif /* NO_DH */ #endif /* WOLF_CRYPT_DH_H */ - diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 3dc0f32532..930b96199e 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -58,6 +58,11 @@ #include #endif +#ifdef WOLFSSL_HAVE_SP_ECC + #include +#endif + + #ifdef __cplusplus extern "C" { #endif @@ -353,6 +358,19 @@ enum { #endif }; +/* ECC non-blocking */ +#ifdef WC_ECC_NONBLOCK + typedef struct ecc_nb_ctx { + #if defined(WOLFSSL_HAVE_SP_ECC) && defined(WOLFSSL_SP_NONBLOCK) + sp_ecc_ctx_t sp_ctx; + #else + /* build configuration not supported */ + #error ECC non-blocking only supports SP (--enable-sp=nonblock) + #endif + } ecc_nb_ctx_t; +#endif /* WC_ECC_NONBLOCK */ + + /* An ECC Key */ struct ecc_key { int type; /* Public or Private */ @@ -413,6 +431,9 @@ struct ecc_key { #ifdef WOLFSSL_DSP remote_handle64 handle; #endif +#ifdef WC_ECC_NONBLOCK + ecc_nb_ctx_t* nb_ctx; +#endif }; @@ -757,6 +778,10 @@ int sp_dsp_ecc_verify_256(remote_handle64 handle, const byte* hash, word32 hashL mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap); #endif +#ifdef WC_ECC_NONBLOCK + WOLFSSL_API int wc_ecc_set_nonblock(ecc_key *key, ecc_nb_ctx_t* ctx); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 87f1ab396b..cbca49131b 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -388,7 +388,9 @@ #ifdef WOLFSSL_ATECC508A /* backwards compatibility */ +#ifndef WOLFSSL_ATECC_NO_ECDH_ENC #define WOLFSSL_ATECC_ECDH_ENC +#endif #ifdef WOLFSSL_ATECC508A_DEBUG #define WOLFSSL_ATECC_DEBUG #endif @@ -919,6 +921,19 @@ extern void uITRON4_free(void *p) ; #define TFM_TIMING_RESISTANT #endif +/* To support storing some of the large constant tables in flash memory rather than SRAM. + Useful for processors that have limited SRAM, such as the AVR family of microtrollers. */ +#ifdef WOLFSSL_USE_FLASHMEM + /* This is supported on the avr-gcc compiler, for more information see: + https://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html */ + #define FLASH_QUALIFIER __flash + + /* Copy data out of flash memory and into SRAM */ + #define XMEMCPY_P(pdest, psrc, size) memcpy_P((pdest), (psrc), (size)) +#else + #define FLASH_QUALIFIER +#endif + #ifdef FREESCALE_MQX_5_0 /* use normal Freescale MQX port, but with minor changes for 5.0 */ #define FREESCALE_MQX @@ -1450,7 +1465,6 @@ extern void uITRON4_free(void *p) ; #endif #ifdef WOLFSSL_SOLARIS - #define WOLFSSL_NO_MUTEXLOCK_AFTER_FREE /* Avoid naming clash with fp_zero from math.h > ieefp.h */ #define WOLFSSL_DH_CONST #endif diff --git a/wolfssl/wolfcrypt/sp.h b/wolfssl/wolfcrypt/sp.h index e468a06fa4..5e01b82a82 100644 --- a/wolfssl/wolfcrypt/sp.h +++ b/wolfssl/wolfcrypt/sp.h @@ -141,7 +141,18 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ); int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym); -#endif /*ifdef WOLFSSL_HAVE_SP_ECC */ +#ifdef WOLFSSL_SP_NONBLOCK +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap); +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, + mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap); +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap); +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, + mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap); +#endif /* WOLFSSL_SP_NONBLOCK */ + +#endif /* WOLFSSL_HAVE_SP_ECC */ #ifdef __cplusplus diff --git a/wolfssl/wolfcrypt/sp_int.h b/wolfssl/wolfcrypt/sp_int.h index e3cc191bec..ef0ebbb0a3 100644 --- a/wolfssl/wolfcrypt/sp_int.h +++ b/wolfssl/wolfcrypt/sp_int.h @@ -109,6 +109,17 @@ #define SP_MASK (sp_digit)(-1) + +#if defined(WOLFSSL_HAVE_SP_ECC) && defined(WOLFSSL_SP_NONBLOCK) +typedef struct sp_ecc_ctx { + #ifdef WOLFSSL_SP_384 + byte data[48*80]; /* stack data */ + #else + byte data[32*80]; /* stack data */ + #endif +} sp_ecc_ctx_t; +#endif + #ifdef WOLFSSL_SP_MATH #include @@ -216,7 +227,6 @@ MP_API void sp_rshb(sp_int* a, int n, sp_int* r); MP_API int sp_mul_d(sp_int* a, sp_int_digit n, sp_int* r); -#define MP_OKAY 0 #define MP_NO 0 #define MP_YES 1 @@ -226,8 +236,10 @@ MP_API int sp_mul_d(sp_int* a, sp_int_digit n, sp_int* r); #define MP_EQ 0 #define MP_LT -1 +#define MP_OKAY 0 #define MP_MEM -2 #define MP_VAL -3 +#define FP_WOULDBLOCK -4 #define DIGIT_BIT SP_WORD_SIZE #define MP_MASK SP_MASK diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 362784b38b..c5329164a7 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -342,9 +342,9 @@ #else /* just use plain C stdlib stuff if desired */ #include - #define XMALLOC(s, h, t) malloc((s)) + #define XMALLOC(s, h, t) malloc((size_t)(s)) #define XFREE(p, h, t) {void* xp = (p); if((xp)) free((xp));} - #define XREALLOC(p, n, h, t) realloc((p), (n)) + #define XREALLOC(p, n, h, t) realloc((p), (size_t)(n)) #endif #elif !defined(MICRIUM_MALLOC) && !defined(EBSNET) \ && !defined(WOLFSSL_SAFERTOS) && !defined(FREESCALE_MQX) \ diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index 41e8bfe6df..617a9e34e0 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -455,6 +455,9 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define MAX_PATH 256 #endif + WOLFSSL_LOCAL int wc_FileLoad(const char* fname, unsigned char** buf, + size_t* bufLen, void* heap); + #if !defined(NO_WOLFSSL_DIR) && !defined(WOLFSSL_NUCLEUS) && \ !defined(WOLFSSL_NUCLEUS_1_2) typedef struct ReadDirCtx {