summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Source/WolfSSL/src/ssl.c
diff options
context:
space:
mode:
authorlundinc <lundinc@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2020-08-12 19:11:51 +0000
committerlundinc <lundinc@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2020-08-12 19:11:51 +0000
commit42255af1e27a3157d541f0812eaca447c569ca49 (patch)
tree5c8702c2f0dc1cb9be1a4d5ff285897d96b97dd2 /FreeRTOS-Plus/Source/WolfSSL/src/ssl.c
parentf5221dff43de249079c2da081723cb7a456f981f (diff)
downloadfreertos-master.tar.gz
commit 70dcbe4527a45ab4fea6d58c016e7d3032f31e8cHEADmaster
Author: Ming Yue <mingyue86010@gmail.com> Date: Tue Aug 11 17:06:59 2020 -0700 Remove unused wolfSSL files. (#197) * Remove unused wolfSSL files. * Add back some removed ciphers. * Update VS project file. commit 0e0edd96e8236b2ea4a6e6018812807be828c77f Author: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Date: Tue Aug 11 10:50:30 2020 -0700 Use new QEMU test project to improve stream/message buffer tests (#168) * Add Eclipse/GCC project that targets the LM3S8962 QEMU model. * Get the Cortex-M QEMU project working. * Continue working on making stream buffer demo more robust and QEMU project. * Rename directory CORTEX_LM3S8986_QEMU to CORTEX_LM3S6965_QEMU. Work on making the Stream Buffer tests more robust. Check in before adding in the trace recorder. * Rename CORTEX_LM3S6969_QEMU to CORTEX_LM3S6969_GCC_QEMU. * Make the StreamBufferDemo.c common demo file (test file) more robust to other test tasks running at an equally high priority. * Work in progress checkin only - comments in main.c are incorrect. * Correct comments at the top of FreeRTOS/Demo/CORTEX_LM3S6965_GCC_QEMU/main.c Make the message buffer tests more robust in the case the a message buffer becomes full when prvSenderTask() has a higher priority than the reader task. * Disable trace recorder in the LM3S6965 QEMU demo. * I'm dropping FreeRTOS-Kernel reference update, since this seems to break the CMBC CI. Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit 157a7fc39f19583ac8481e93fa3e1c91b1e1860c Author: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Date: Sun Aug 9 22:21:44 2020 -0700 Use chacheable RAM in IAR project for MPU_M7_NUCLEO_H743ZI2 project (#193) This change updates the IAR project for Nucleo H743ZI2 to use the cacheable DTC RAM and enables L1 cache. In order to ensure the correct functioning of cache, the project sets configTEX_S_C_B_SRAM in FreeRTOSConfig.h to not mark the RAM as shareable. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> commit f3e43556f90f01b82918ad533b0c616489331919 Author: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Date: Sun Aug 9 16:23:53 2020 -0700 Add MPU demo projects for NUCLEO-H743ZI2 board (#155) * Add MPU demo projects for NUCLEO-H743ZI2 board It contains projects for Keil uVision, STM32CubeIDE and IAR EW. This demo shows the use of newly added support for 16 MPU regions. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Delete not needed CMSIS files Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> commit 94aa31c3cbae7c929b8a412768b74631f4a6b461 Author: TakayukiMatsuo <62984531+TakayukiMatsuo@users.noreply.github.com> Date: Sat Aug 8 07:58:14 2020 +0900 Update wolfSSL to the latest version(v.4.4.0) (#186) * deleted old version wolfSSL before updating * updated wolfSSL to the latest version(v4.4.0) * updated wolfSSL to the latest version(v4.4.0) * added macros for timing resistance Co-authored-by: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Co-authored-by: Ming Yue <mingyue86010@gmail.com> commit 68518f5866aac58793c737d9a46dd07a6a816aaf Author: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Date: Fri Aug 7 14:59:24 2020 -0700 Removed a 16MByte flash image file that was checked in by mistake (several years ago). (#173) Remove the copies of lwIP that are no longer reference from demo projects. Co-authored-by: Carl Lundin <53273776+lundinc2@users.noreply.github.com> commit d4bf09480a2c77b1a25cce35b32293be61ab586f Author: m17336 <45935231+m17336@users.noreply.github.com> Date: Thu Aug 6 22:37:08 2020 +0300 Update previous AVR ATmega0 and AVR Dx projecs + addition of equivalent projects in MPLAB.X and IAR (#180) * Updated indentation in AVR_ATMega4809_Atmel_Studio and AVR_Dx_Atmel_Studio projects, plus small fixes in their readme files. * Added AVR_ATMega4809_IAR, AVR_ATMega4809_MPLAB.X, AVR_Dx_IAR and AVR_Dx_MPLAB.X demo projects. * Removed build artefacts and added .gitignore files in AVR_ATMega4809_MPLAB.X and AVR_Dx_MPLAB.X projects. Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit f32a0647c8228ddd066f5d69a85b2e49086e4c95 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Mon Aug 3 16:45:10 2020 -0700 Remove CBMC patch which is not used anymore (#187) * Delete 0002-Change-FreeRTOS_IP_Private.h-union-to-struct.patch * Delete 0002-Change-FreeRTOS_IP_Private.h-union-to-struct.patch commit 08af68ef9049279b265c3d00e9c48fb9594129a8 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Sat Aug 1 16:38:23 2020 -0700 Remove dependency of CBMC on Patches (#181) * Changes to DHCP * CBMC DNS changes * Changes for TCP_IP * Changes to TCP_WIN * Define away static to nothing * Remove patches * Changes after Mark's comments v1 * Update MakefileCommon.json * Correction! commit a7fec906a415363338449447daf10d7517b78848 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 29 17:39:36 2020 -0700 Misc changes (#183) commit 07cf5e07e4a05d6775a2f9e753269f43f82cf6ba Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 29 16:15:38 2020 -0700 MISRA compliance changes for FreeRTOS+TCP headers (#165) * misra changes * Update FreeRTOS_IP_Private.h * Update FreeRTOS_IP_Private.h commit e903ac0fed7ce59916899e404f3e5ae5b08d1478 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 29 16:03:14 2020 -0700 UPD MISRA changes (#164) Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit 97551bf44e7dc7dc1e4484a8fd30f699255e8569 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 29 15:52:00 2020 -0700 MISRA changes in FreeRTOS_TCP_WIN.c (#162) commit f2611cc5e5999c4c87e040a8c2d2e6b5e77a16a6 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 29 15:38:37 2020 -0700 MISRA compliance changes in FreeRTOS_Sockets{.c/.h} (#161) * MISRA changes Sockets * add other changes * Update FreeRTOSIPConfig.h * Update FreeRTOSIPConfig.h * Update FreeRTOSIPConfig.h * Update FreeRTOSIPConfig.h * correction * Add 'U' * Update FreeRTOS_Sockets.h * Update FreeRTOS_Sockets.h * Update FreeRTOS_Sockets.c * Update FreeRTOS_Sockets.h * Update after Gary's comments * Correction reverted commit ae4d4d38d9b2685bae159b4c87619cdb157c0bf7 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 29 13:56:57 2020 -0700 MISRA compliance changes for FreeRTOS_TCP_IP.c (#160) * MISRA tcp-ip changes * Changes after Hein's comments on original PR * Update FreeRTOS_TCP_IP.c Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit a457f43c66eb0f4be9d8f8678c0e3fb8d7ebd57b Author: Carl Lundin <53273776+lundinc2@users.noreply.github.com> Date: Tue Jul 28 13:01:38 2020 -0700 Add missing error state assignment. (#166) commit 915af50524e15a78ceb6c62b3d33f6562621ee46 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Mon Jul 27 17:30:53 2020 -0700 Add Atmel Studio projects for ATMega4809 and AVR128DA48 (#159) * Added explicit cast to allow roll over and avoid integer promotion during cycles counters comparison in recmutex.c. * Fixed type mismatch between declaration and definition of function xAreSemaphoreTasksStillRunning( void ). * Added Atmel Studio demo projects for ATMega4809 and AVR128DA48. * Per https://www.freertos.org/upgrading-to-FreeRTOS-V8.html, I'm updating portBASE_TYPE to BaseType_t. Signed-off-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> * Update register test for ATmega4809 - to cover r28, r29, r31. - call public API taskYIELD() instead of portYIELD(). * Update ATmega4809 readme.md to include info for serial port setup, and minor wording fix. Co-authored-by: Alexandru Niculae - M17336 <alexandru.niculae@microchip.com> commit 4a7a48790d64127f85cc763721b575c51c452833 Author: Carl Lundin <53273776+lundinc2@users.noreply.github.com> Date: Thu Jul 23 10:22:33 2020 -0700 Add Uncrustify file used for Kernel. (#163) commit e0d62163b08769fd74f020709c398f994088ca96 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 22 18:06:23 2020 -0700 Sync with +TCP amazon-FreeRTOS (#158) * DNS.c commit * IP.c commit * Add various source & header files commit 8e36bee30eef2107e128edb58e83ee46e8241a91 Author: Nathan Chong <52972368+nchong-at-aws@users.noreply.github.com> Date: Tue Jul 21 12:51:20 2020 -0400 Prove buffer lemmas (#124) * Prove buffer lemmas * Update queue proofs to latest kernel source All changes were syntactic due to uncrustify code-formatting * Strengthen prvCopyDataToQueue proof * Add extract script for diff comparison Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit c720c18ada40b502436ea811e8d03dca919726d8 Author: Hein Tibosch <hein_tibosch@yahoo.es> Date: Tue Jul 14 05:35:44 2020 +0800 FreeRTOS+TCP Adding the combined driver for SAM4E and SAME70 v2 (#78) * Adding a combined +TCP driver for SAM4E and SAME70 * Changes after review from Aniruddha Co-authored-by: Hein Tibosch <hein@htibosch.net> Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> commit 4237049b12d9bb6b03694fecf6ea26a353e637c8 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Mon Jul 13 12:07:56 2020 -0700 Add changes from 2225-2227 amazon-FreeRTOS (#134) commit 7caa32863458c4470d3c620945c30824199f524c Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri Jul 10 23:32:30 2020 -0700 Add Full TCP test suite - not using secure sockets (#131) * Add Full-TCP suite * delete unnecessary files * Change after Joshua's comments commit d7667a0034841f2968f9f9f805030cc608bfbce1 Author: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Date: Fri Jul 3 15:45:44 2020 -0700 Remove unnecessary semicolon from the linker file (#121) This was creating problem with the onboard LPCLink debug probe. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> commit 529c481c39506d0b331bfd0cdea35e5d1aeaaad0 Author: Nathan Chong <52972368+nchong-at-aws@users.noreply.github.com> Date: Thu Jul 2 15:55:20 2020 -0400 Add VeriFast kernel queue proofs (#117) commit d5fedeaa96b5b1d3c0f6b9b52a8064ab72ff2821 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 1 13:56:27 2020 -0700 Add checks in FreeRTOS_Socket.c (#104) * Add fail-safes to FreeRTOS_Socket.c * Use all 'pd' errors * Correction after Hein's comments * Correction after Hein's comments v2 * Changes after Hein's comments * Update after Gary's comments commit a9b2aac4e9fda2a259380156df9cc0af51384d2d Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri Jun 26 12:09:36 2020 -0700 Folder structure change + Fix broken Projects (#103) * Update folder structure * Correct project files * Move test folder * Some changes after Yuki's comments commit 98bfc38bf3404414878dc68ea41753bea4e24c8e Author: Hein Tibosch <hein_tibosch@yahoo.es> Date: Thu Jun 25 13:01:45 2020 +0800 FreeRTOS+TCP : add memory statistics and dump packets, v3 (#83) * FreeRTOS+TCP : add memory statistics and dump packets, v3 * Two changes as requested by Aniruddha Co-authored-by: Hein Tibosch <hein@htibosch.net> Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> commit 072a173c9df31c75ff64bde440f3f316cedb9033 Author: S.Burch <8697966+wholl0p@users.noreply.github.com> Date: Mon Jun 22 23:39:26 2020 +0200 Fixed Imports for Infineon XMC1100 Board (#88) Co-authored-by: RichardBarry <3073890+RichardBarry@users.noreply.github.com> commit 2df5eeef5763045c4c74ff0e2a4091b7d19bea89 Author: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Date: Mon Jun 8 14:22:46 2020 -0700 Feature/multiple direct to task notifications (#73) * Add TaskNotifyArray.c with the single task tests updated to use the task notification array up to the point where the timer is created. * Continue working on TaskNotifyArray.c to test the new task notification indexes. Next TaskNotifyArray.c will be refactored to break the tests up a bit. * Refactor and update the comments in TaskNotifyArray.c - no functional changes. * Change from the task notify "array" to task notification "indexed" nomenclature in the new task notification API functions that work on one particular task notification with the array of task notifications. * Update the implementation of the taskNOTIFY_TAKE() and taskNOTIFY_WAIT() trace macros to take the array index of the task notification they are acting on. Rename configNUMBER_OF_TASK_NOTIFICATIONS to configTASK_NOTIFICATION_ARRAY_ENTRIES. Add FreeRTOS/Demo/Common/Minimal/TaskNotifyArray.c to the Visual Studio project - the file implements tests specific to the behaviour of the indexed task notification functions and should be used in addition to the tests already provided in FreeRTOS/Demo/Common/Minimal/TaskNotify.c. commit b9e4ecfaf7286d8493d4a96a93fbb325534ad97b Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri Jun 5 11:10:58 2020 -0700 Remove Empty and Un-referenced folder from Demo (#86) commit f11bcc8acc57a23fb03603762e758c25b9d0efb7 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jun 3 16:52:31 2020 -0700 Fix a Bug and corresponding CBMC patch (#84) * Update remove-static-in-freertos-tcp-ip.patch * Update FreeRTOS_TCP_IP.c * Update remove-static-in-freertos-tcp-ip.patch * Update remove-static-in-freertos-tcp-ip.patch Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit bb9f92f771e5f6ea2b9b09c7e89130a75e562eb7 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Wed Jun 3 10:46:55 2020 -0700 Submodule FreeRTOS/Source 10bbbcf0b..6199b72fb (#82) commit 6efc39f44be5b269168836e95aebbdb8ae77dce3 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Tue Jun 2 15:09:25 2020 -0700 Add Project for running integration tests v2 (#80) * Project for integration tests * relative paths in project files * relative paths in project files-1 * relative paths in project files-2 * addressed comments * addressed comments v2 Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit 0eb5909fb02bac9dc074ff1bc2fe338d77f73764 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Thu May 28 17:05:24 2020 -0700 readme.md for ATmega328PB Xplained Mini. (#76) readme.md to get users jump started. commit cb7edd2323a77f3dbea144c1f48f95582becc99e Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Thu May 28 10:11:58 2020 -0700 Sync with a:FR (#75) * AFR sync * AFR sync: CBMC * AFR sync: CBMC: remove .bak files * AFR sync: CBMC: more cleanup * Corrected CBMC proofs * Corrected CBMC patches * Corrected CBMC patches-1 * Corrected CBMC patches-2 * remove .bak files (3) Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit 6557291e5407ca7ec6beca53fced1aaa620c5c02 Author: alfred gedeon <alfred2g@hotmail.com> Date: Wed May 27 14:44:33 2020 -0700 Test: Add Linux Networking support with demo application (#71) * Test: Add Linux Networking support with demo application * Test: revert files affected by uncrustify * Test: revert files affected by uncrustify Co-authored-by: Alfred Gedeon <gedeonag@amazon.com> Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit 8b079bc394e7b205d72210ce9e052404d782938f Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Wed May 27 10:44:03 2020 -0700 ATmega328PB Xplained Mini -- demo project for ATmega port. (#70) * Bootstrap a demo from START. No driver is added in this commit. * Add FreeRTOS source code to project. Remove unnecessary folder nesting. Heap_4 is used here. * Copy over main.c, FreeRTOSConfig.h, and regtest.{c, h}. This commit compiles, but will need some work on timer used. * This port has 2KB RAM. We are using 1KB for heap. Further decreasing minimum stack size, and also use stack overflow check 1 to save some stack space. * Preserve EEPROM set to false. * End of the line. * Reduce register test stack size. 32 8-bit register + 10 bytes for stack frame cost. Round up to 50. * Adding Queue test in Integer test. - g3 to easy debugging. - mainCHECK_PERIOD is set to 1000 ticks. Note that this port for now use WDT as tick timer, and period is set to 15ms. - vErrorChecks, is of highest priority. So if this task gets run before other tasks, the very first check will fail. * Avoid false alarm. Since we don't know in which order the tasks are scheduled, clearing any error for the first entry of vErrorChecks. Signed-off-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> * ParTest.c to init, set, toggle onboard user LED at PB5. * Added a task to blink onboard user LED. Need a magic number for stack size. Signed-off-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> * Explicitly setting timing slicing to 0. This is to avoid unecessary context switch when multiple tasks are of the same priority. Signed-off-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> * Add taskYIELD() at the end of the loop in each register test task. This is to give other tasks of the same priority a chance to run, regardless of scheduling algorithm. Signed-off-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> * minor, update comment in main.c. commit 95a3a02f95749fb7a600723076e291f9dee7426c Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri May 22 16:26:59 2020 -0700 FreeRTOS-Plus: Unit testing Infrastructure and examples (#72) * Added CMock as submodule * Makefile added * Removed TEMP from Makefile * Added configuration files and header files * Update Makefile * Test runner working * make clean * Example added with README * Update README.md * Restored +TCP files * Cleared +TCP changes * removed comments from Makefile * Update README.md * Update README.md * Update README.md * Updated Test/Unit-test/readme.md commit 5003d17feda25490e655c0f1c15d2b13e395c9f7 Author: Hein Tibosch <hein_tibosch@yahoo.es> Date: Wed May 6 14:16:56 2020 -0400 FreeRTOS+TCP : renewing DHCP lease while network is down (#53) Co-authored-by: Hein Tibosch <hein@htibosch.net> Co-authored-by: Gary Wicker <14828980+gkwicker@users.noreply.github.com> commit d95624c5d6ba95ec0474867d7165de2c28ed41b7 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Tue May 5 09:57:18 2020 -0700 Move CBMC proofs to FreeRTOS+ directory (#64) * move CBMC proofs to FreeRTOS+ directory * Failing proofs corrected * ParseDNSReply proof added back * removed queue_init.h from -Plus/Test Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit 95ae7c65758a9473ea16ab08182f056f72331de2 Author: markrtuttle <tuttle@acm.org> Date: Wed Apr 29 04:27:45 2020 +0000 Change cbmc-viewer invocation in CBMC makefile (#63) * Exclude FreeRTOS/Demo from CBMC proof reports. The script cbmc-viewer generates the CBMC proof reports. The script searches source files for symbol definitions and annotates source files with coverage information. This patch causes cbmc-viewer to ignore the directory FreeRTOS/Demo containing 348M of data. The script now terminates in a few seconds. * Make report default target for CBMC Makefile. Modify the Makefile for CBMC proofs to generate the report by default (and not just property checking) and modify property checking to ignore failures (due to property assertions failing) and terminating report generation. Co-authored-by: Mark R. Tuttle <mrtuttle@amazon.com> commit d421ccc89f6f6473dfdd566a00567b0e1fd4cfc3 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Sat Apr 25 16:57:35 2020 -0700 Reword readme.md under ./Test. (#61) commit 38412865985235b90dbd9da9708b68c4de5918f5 Author: Carl Lundin <53273776+lundinc2@users.noreply.github.com> Date: Sat Apr 25 16:56:54 2020 -0700 Removed a:FR reference. (#60) commit 4db195c916c7b13c82ab3a34a499fe606f266810 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Tue Apr 21 15:40:08 2020 -0700 Adding FreeRTOS+TCP CBMC proofs to FreeRTOS/FreeRTOS (#56) ParseDNSReply is to be added in the next PR. commit 40a31b6d35a866a3a6c551d95bf08dae855da5bd Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Mon Apr 13 13:58:33 2020 -0700 'uL' -> 'UL' commit 5b3a289b69fc92089aa8bd4d1b44ab816f326f73 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Mon Apr 13 13:50:53 2020 -0700 Changes after Gary's comments commit edf68637dd22470a8d4f59fecc15b51379bcfeda Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri Apr 10 16:26:03 2020 -0700 Update FreeRTOS_ARP.c commit 35f3ac32a8899dd714a8a48952a4224fbcebc4aa Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri Apr 10 15:56:18 2020 -0700 correct debug output commit 5e12a70db4b6a8e68a434489683306f040252efa Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri Apr 10 15:44:45 2020 -0700 Debugging flag check added commit 4e8ac8de25ac4088b9c789b88a77cd39df4d9167 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Thu Apr 9 16:57:19 2020 -0700 Comment style consistency and Yuhui's suggestions commit e43f7cd086096ad60491fedba69927a1e1a82f20 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Thu Apr 9 16:47:41 2020 -0700 Cleanup commit ab3b51c7a0d880a6bf453ec63ae604e15050f310 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Thu Apr 9 16:33:03 2020 -0700 Update after Gary's comments commit 97f7009699ffb972c0745dfdb526d1fa4e0faf84 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Apr 8 14:30:15 2020 -0700 Update after richard's comments commit a9fcafc074cec559dd67961ef44273df6180c2db Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Apr 8 14:07:39 2020 -0700 Corrected the formatting - visual studio had messed up the formatting commit c381861014a8043ce30723fc5a8cf5107719c8df Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Apr 8 13:01:12 2020 -0700 commit 2 after gary's comments commit 75677a8d85fa802cca9058d6e23796d5043a0982 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Apr 8 12:51:10 2020 -0700 Commit after Gary's comments commit 666c0da366030109db2c0c5e7253cebb2f899db7 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Apr 8 10:56:01 2020 -0700 Update after Yuhui's comments - removed (void) from before memcpy, memset etc. - corrected memcpy style as suggested by Yuhui - Added logging for xNetworkInterfaceOutput. No need to configASSERT commit 4a1148d15b6b8169d2412f8179f734683b179795 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Apr 1 16:05:36 2020 -0700 Coverity + MISRA compliance Modified code to conform to the MISRA directives more closely. commit fa74f7dccf6b1a356993c6a894f8e1173b8c8157 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Thu Apr 2 20:26:10 2020 -0700 Removing writes to read-only PLIC interrupt pending registers. Signed-off-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit 5b9777e11e16609648fb98d2f9a47553ab238950 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Mar 31 10:45:23 2020 -0700 A readme file to introduce what ./Test directory is about. commit 211bb4cbd9ae6dfa95e8d8501f37d272bde5ab26 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Mar 24 15:14:24 2020 -0700 Ignore whitespace when working with patches. commit 8156f64d1c45dd59ef12279f19a99f03e79e1f8a Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Feb 25 18:04:23 2020 -0800 Copying CBMC proofs from aws/amazon-freertos repo ./tools/cbmc to this repo ./FreeRTOS/Test/CBMC as is. The commit ID in aws/amazon-freertos is 0c8e0217f2a43bdeb364b58ae01c6c259e03ef1b. commit 9f316c246baafa15c542a5aea81a94f26e3d6507 Author: David Vrabel <david.vrabel@cambridgeconsultants.com> Date: Mon Mar 16 11:21:46 2020 +0000 Demo/Posix_GCC: add demo application for Posix port using GCC This is largely a copy of the Windows demo application with a few key changes: - heap_3 (use malloc()/free()) so tools like valgrind "just work". - printf() wrapped in a mutex to prevent deadlocks on the internal pthread mutexes inside printf(). SCons (https://scons.org/) is used as the build system. This will be built as a 64-bit application, but note that the memory allocation trace points only record the lower 32-bits of the address. commit f78f919b3e2f0d707531a301a8ca07cd02bc4778 Author: Markus Rinne <markus.ka.rinne@gmail.com> Date: Thu Mar 19 21:00:24 2020 +0200 Fix function comments commit 1cd2d38d960a3576addb224582c88489bade5141 Author: David Chalco <david@chalco.io> Date: Fri Mar 20 10:29:05 2020 -0700 unix separators for path and remove .exe suffix from risc compiler (works on windows/mac) commit 938b19419eded12817737ab0644e94ed2ba7e95d Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Thu Mar 19 18:23:09 2020 -0700 Removing ./FreeRTOS-Labs directory, since: - IoT libraries are now in LTS branch. - FAT/POSIX/Light-weight MQTT are in https://github.com/FreeRTOS/FreeRTOS-Labs. commit 1a4abbc9e91b13fd6394464ade59d5e048320c7c Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Mar 17 19:30:02 2020 -0700 Maintenance -- clean up readme.txt and add url to GitHub. (#38) * Removing readme.txt, as now we have README.md in place. The only information missing from README.md is about FAQ. * Adding FAQ information in README.md. * Adding a .url to root to redict user to FreeRTOS github home page. commit 47bb466aa19395b7785bcb830e2e4dd35f6bafc5 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Mar 17 13:07:44 2020 -0700 Update issue templates Template maintenance. - adding title prefix. - adding examples to "additional context" section. commit f506290041f56867765f8efa70ed2862125bdb7c Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Mar 17 10:15:07 2020 -0700 Create SECURITY.md Apply the recommended SECURITY.md from AWS to our repo. commit 8982a2f80a80a2a0a47cf82de07b52101bd9d606 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Fri Mar 13 12:50:10 2020 -0700 Add ./lib directory to make sure Zynq project compiles. commit ecf0f12aa14ad6fdafe1ef37257cbb4e03e2abd5 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Mar 11 10:19:48 2020 -0700 Sync up with Amazon-freertos repo (10th March 2020) (#34) * Sync up with amazon-freertos * Sync up with amazon-freertos * Sync up with amazon-freertos commit 0acffef047973e2e61c2201fd69cd9bbd317f674 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Mar 10 10:20:48 2020 -0700 GitHub PR template. (#29) commit c40a6da2e4cb8042b56d1b174051cbbe9813781a Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Mon Mar 9 11:18:48 2020 -0700 pass payload length when calling UDP callback (#30) * pass payload length when calling UDP callback commit 12d580e93d4d9074b9a867632f0681a511b4ad12 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Fri Mar 6 18:16:51 2020 -0800 Update issue templates Initial issue template. Created following https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository#configuring-the-template-chooser. If change is needed, we could go another round. commit 9debffb5e0e42ff716f58b2270b3af09652294af Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Fri Mar 6 17:27:46 2020 -0800 Update README.md to remove dead link. See the conversation https://github.com/FreeRTOS/FreeRTOS/commit/42c627b2b88cb3b487fea983d8b566a8bbae54fa#comments . Linkage for both ```./FreeRTOS/Source``` and ```./FreeRTOS/Demo``` are removed, since it looks weird to only provide linkage to Demo. commit 7e1a4bf563240501fc45167aee9d929c533939dd Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri Mar 6 15:18:09 2020 -0800 Fix DHCP option Client-identifier (#28) commit 42c627b2b88cb3b487fea983d8b566a8bbae54fa Author: Yuhui.Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Fri Mar 6 09:15:11 2020 -0800 Update readme and revert relative URL. (#27) * Reordering: bumping cloning instruction up. * Rewording readme.md to be clear kernel code is a submodule of this repository. * Reverting relative URL, since user cannot click through on GitHub page. (With URL, user could still download the correct version of the code. Reverting simply due to UI issue.) commit 5751ae9b60e248ebd0b4dd7c58df54364d2bb9d5 Author: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Date: Fri Mar 6 09:11:42 2020 -0800 Update CORTEX_MPU_M33F_NXP_LPC55S69_MCUXpresso project (#26) This commit updates the project for LPC55S69 so that it works with the latest version of MCUXpresso and SDK. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> commit a9ffffe1f01f45f79e127c15727784984077932f Author: Carl Lundin <53273776+lundinc2@users.noreply.github.com> Date: Thu Mar 5 17:16:13 2020 -0800 Using Relative URL For Submoduling. (#24) commit 52c82076b38fe73d1dc46c97abf74ae9b803696c Author: Carl Lundin <53273776+lundinc2@users.noreply.github.com> Date: Thu Mar 5 09:16:31 2020 -0800 use relative path to point to bundled toolchain instead (#25) commit b877e4ec478de2c24d07ab46241070d7c66f375c Author: lundinc2 <53273776+lundinc2@users.noreply.github.com> Date: Tue Feb 25 13:18:38 2020 -0800 Moved vulnerability reporting and code of conduct to top of CONTRIBUTING.md (#20) commit bef165d46799fb8faa58aaa224f80c16b6538e69 Author: Yuhui.Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Feb 18 22:06:38 2020 -0800 Linking test source file from relative path. (#19) commit 89e7bbe292afd3912d1f0b2402cc506878bad869 Author: Yuhui.Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Feb 18 17:47:55 2020 -0800 A preliminary .gitignore file, to prevent us checking in files unnecessary. (#18) https://github.com/github/gitignore. commit c2a98127acb48c4562233230e66ca5c282688579 Author: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Date: Sun Feb 16 13:19:53 2020 -0800 Minor wording changes in the 'previous releases' section of the readme.me file. (#17) commit 24c772d1439e5c291c0a29fce0a46996ca8afaa9 Author: Yuhui.Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Fri Feb 14 12:47:01 2020 -0800 Submodule kernel directory. (#16) * Removing FreeRTOS/Source in readiness for submoduling. * Submoduling kernel. * README.md update due to submoduling. When releasing, please follow these steps: 1. in local directory, clean directory and check "git status" shows "nothing to commit, working tree clean" for ALL subdirectories. 2. copy source code and instructions only to an empty folder. Git related should not be in this folder -- this covers .git, .gitignore, .github, .gitmodules, gitmessages, ...... 3. zip the folder from step 2. (create both .zip and .7z) 4. attach .zip and .7z to the release. (e.g. attach these two in new release -- https://github.com/FreeRTOS/FreeRTOS/releases/new) 5. PLEASE download both, unzip, diff with your local git repo. (should not see any difference other than git related.) And, sanity check a couple of projects. commit c3f8b91652392dc55e0d7067b90a40de5f5f0837 Author: Rashed Talukder <9218468+rashedtalukder@users.noreply.github.com> Date: Thu Feb 13 17:47:14 2020 -0800 Update readme. Fixed typos and cli commands (#14) commit 4723b825f2989213c1cdb2ebf4d6793e0292e363 Author: Julian Poidevin <julian-poidevin@users.noreply.github.com> Date: Fri Feb 14 02:43:36 2020 +0100 Fixed wrong git clone SSH command (#13) Replaced bad https URL with proper SSH URL commit fc819b821715c42602819e58499846147a6394f5 Author: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Date: Thu Feb 13 17:42:22 2020 -0800 Correct the xTimerCreate() documentation which said NULL was returned if the timer period was passed into the function as 0, whereas that is not the case. (#15) Add a note to the documentation for both the xTimerCreate() and xTimerCreateStatic() functions that the timer period must be greater than 0. commit 1c711ab530b5f0dbd811d7d62e0a3763706ffff4 Author: Rashed Talukder <9218468+rashedtalukder@users.noreply.github.com> Date: Wed Feb 12 23:00:18 2020 -0800 Updated contributions guidelines (#12) commit 84fcc0d5317d96c6b086034093c8c1c83e050819 Author: Cobus van Eeden <35851496+cobusve@users.noreply.github.com> Date: Wed Feb 12 15:05:06 2020 -0800 Updates to Markdown files and readme.txt (#11) git-svn-id: http://svn.code.sf.net/p/freertos/code/trunk@2826 1d2547de-c912-0410-9cb9-b8ca96c0e9e2
Diffstat (limited to 'FreeRTOS-Plus/Source/WolfSSL/src/ssl.c')
-rw-r--r--FreeRTOS-Plus/Source/WolfSSL/src/ssl.c44808
1 files changed, 39789 insertions, 5019 deletions
diff --git a/FreeRTOS-Plus/Source/WolfSSL/src/ssl.c b/FreeRTOS-Plus/Source/WolfSSL/src/ssl.c
index 139e343f9..58569f3e9 100644
--- a/FreeRTOS-Plus/Source/WolfSSL/src/ssl.c
+++ b/FreeRTOS-Plus/Source/WolfSSL/src/ssl.c
@@ -1,8 +1,8 @@
/* ssl.c
*
- * Copyright (C) 2006-2015 wolfSSL Inc.
+ * Copyright (C) 2006-2020 wolfSSL Inc.
*
- * This file is part of wolfSSL. (formerly known as CyaSSL)
+ * 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
@@ -16,14 +16,23 @@
*
* 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-1301, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
+#if defined(OPENSSL_EXTRA) && !defined(_WIN32)
+ /* turn on GNU extensions for XVASPRINTF with wolfSSL_BIO_printf */
+ #undef _GNU_SOURCE
+ #define _GNU_SOURCE
+#endif
+
+#if !defined(WOLFCRYPT_ONLY) || defined(OPENSSL_EXTRA) || \
+ defined(OPENSSL_EXTRA_X509_SMALL)
#ifdef HAVE_ERRNO_H
#include <errno.h>
@@ -32,20 +41,62 @@
#include <wolfssl/internal.h>
#include <wolfssl/error-ssl.h>
#include <wolfssl/wolfcrypt/coding.h>
+#ifdef NO_INLINE
+ #include <wolfssl/wolfcrypt/misc.h>
+#else
+ #define WOLFSSL_MISC_INCLUDED
+ #include <wolfcrypt/src/misc.c>
+#endif
-#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+
+#if !defined(WOLFSSL_ALLOW_NO_SUITES) && !defined(WOLFCRYPT_ONLY)
+ #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA) \
+ && !defined(WOLFSSL_STATIC_DH) && !defined(WOLFSSL_STATIC_PSK) \
+ && !defined(HAVE_ED25519) && !defined(HAVE_ED448)
+ #error "No cipher suites defined because DH disabled, ECC disabled, and no static suites defined. Please see top of README"
+ #endif
+ #ifdef WOLFSSL_CERT_GEN
+ /* need access to Cert struct for creating certificate */
+ #include <wolfssl/wolfcrypt/asn_public.h>
+ #endif
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
+ defined(HAVE_WEBSERVER) || defined(WOLFSSL_KEY_GEN)
#include <wolfssl/openssl/evp.h>
+ /* openssl headers end, wolfssl internal headers next */
+#endif
+
+#include <wolfssl/wolfcrypt/wc_encrypt.h>
+
+#ifndef NO_RSA
+ #include <wolfssl/wolfcrypt/rsa.h>
#endif
#ifdef OPENSSL_EXTRA
/* openssl headers begin */
+ #include <wolfssl/openssl/aes.h>
#include <wolfssl/openssl/hmac.h>
#include <wolfssl/openssl/crypto.h>
#include <wolfssl/openssl/des.h>
#include <wolfssl/openssl/bn.h>
+ #include <wolfssl/openssl/buffer.h>
#include <wolfssl/openssl/dh.h>
#include <wolfssl/openssl/rsa.h>
#include <wolfssl/openssl/pem.h>
+ #include <wolfssl/openssl/ec.h>
+ #include <wolfssl/openssl/ec25519.h>
+ #include <wolfssl/openssl/ed25519.h>
+ #include <wolfssl/openssl/ec448.h>
+ #include <wolfssl/openssl/ed448.h>
+ #include <wolfssl/openssl/ecdsa.h>
+ #include <wolfssl/openssl/ecdh.h>
+ #include <wolfssl/openssl/err.h>
+ #include <wolfssl/openssl/opensslv.h>
+ #include <wolfssl/openssl/rc4.h>
+ #include <wolfssl/openssl/stack.h>
+ #include <wolfssl/openssl/x509v3.h>
+ #include <wolfssl/openssl/x509_vfy.h>
/* openssl headers end, wolfssl internal headers next */
#include <wolfssl/wolfcrypt/hmac.h>
#include <wolfssl/wolfcrypt/random.h>
@@ -53,118 +104,432 @@
#include <wolfssl/wolfcrypt/md4.h>
#include <wolfssl/wolfcrypt/md5.h>
#include <wolfssl/wolfcrypt/arc4.h>
- #ifdef WOLFSSL_SHA512
+ #include <wolfssl/wolfcrypt/idea.h>
+ #include <wolfssl/wolfcrypt/curve25519.h>
+ #include <wolfssl/wolfcrypt/ed25519.h>
+ #include <wolfssl/wolfcrypt/curve448.h>
+ #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL)
+ #include <wolfssl/openssl/ocsp.h>
+ #endif /* WITH_STUNNEL */
+ #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
#include <wolfssl/wolfcrypt/sha512.h>
#endif
-#endif
-
-#ifndef NO_FILESYSTEM
- #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) \
- && !defined(EBSNET)
- #include <dirent.h>
- #include <sys/stat.h>
+ #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \
+ && !defined(WC_NO_RNG)
+ #include <wolfssl/wolfcrypt/srp.h>
#endif
- #ifdef EBSNET
- #include "vfapi.h"
- #include "vfile.h"
+ #if defined(HAVE_FIPS) || defined(HAVE_SELFTEST)
+ #include <wolfssl/wolfcrypt/pkcs7.h>
#endif
-#endif /* NO_FILESYSTEM */
+ #if defined(OPENSSL_ALL) && defined(HAVE_PKCS7)
+ #include <wolfssl/openssl/pkcs7.h>
+ #endif /* OPENSSL_ALL && HAVE_PKCS7 */
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi);
+ int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi);
+ int oid2nid(word32 oid, int grp);
+#endif
-#ifndef TRUE
- #define TRUE 1
+#if defined(WOLFSSL_QT)
+ #include <wolfssl/wolfcrypt/sha.h>
#endif
-#ifndef FALSE
- #define FALSE 0
+
+#ifdef NO_ASN
+ #include <wolfssl/wolfcrypt/dh.h>
#endif
+#endif /* !WOLFCRYPT_ONLY || OPENSSL_EXTRA */
-#ifndef WOLFSSL_HAVE_MIN
-#define WOLFSSL_HAVE_MIN
+#define WOLFSSL_EVP_INCLUDED
+#include "wolfcrypt/src/evp.c"
- static INLINE word32 min(word32 a, word32 b)
- {
- return a > b ? b : a;
- }
+#ifdef OPENSSL_EXTRA
+/* Global pointer to constant BN on */
+static WOLFSSL_BIGNUM* bn_one = NULL;
+#endif
-#endif /* WOLFSSSL_HAVE_MIN */
+#ifndef WOLFCRYPT_ONLY
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
+const WOLF_EC_NIST_NAME kNistCurves[] = {
+ {XSTR_SIZEOF("P-192"), "P-192", NID_X9_62_prime192v1},
+ {XSTR_SIZEOF("P-256"), "P-256", NID_X9_62_prime256v1},
+ {XSTR_SIZEOF("P-112"), "P-112", NID_secp112r1},
+ {XSTR_SIZEOF("P-112-2"), "P-112-2", NID_secp112r2},
+ {XSTR_SIZEOF("P-128"), "P-128", NID_secp128r1},
+ {XSTR_SIZEOF("P-128-2"), "P-128-2", NID_secp128r2},
+ {XSTR_SIZEOF("P-160"), "P-160", NID_secp160r1},
+ {XSTR_SIZEOF("P-160-2"), "P-160-2", NID_secp160r2},
+ {XSTR_SIZEOF("P-224"), "P-224", NID_secp224r1},
+ {XSTR_SIZEOF("P-384"), "P-384", NID_secp384r1},
+ {XSTR_SIZEOF("P-521"), "P-521", NID_secp521r1},
+ {XSTR_SIZEOF("K-160"), "K-160", NID_secp160k1},
+ {XSTR_SIZEOF("K-192"), "K-192", NID_secp192k1},
+ {XSTR_SIZEOF("K-224"), "K-224", NID_secp224k1},
+ {XSTR_SIZEOF("K-256"), "K-256", NID_secp256k1},
+ {XSTR_SIZEOF("B-160"), "B-160", NID_brainpoolP160r1},
+ {XSTR_SIZEOF("B-192"), "B-192", NID_brainpoolP192r1},
+ {XSTR_SIZEOF("B-224"), "B-224", NID_brainpoolP224r1},
+ {XSTR_SIZEOF("B-256"), "B-256", NID_brainpoolP256r1},
+ {XSTR_SIZEOF("B-320"), "B-320", NID_brainpoolP320r1},
+ {XSTR_SIZEOF("B-384"), "B-384", NID_brainpoolP384r1},
+ {XSTR_SIZEOF("B-512"), "B-512", NID_brainpoolP512r1},
+ {0, NULL, 0},
+};
+#endif
-#ifndef WOLFSSL_HAVE_MAX
-#define WOLFSSL_HAVE_MAX
+#if defined(WOLFSSL_RENESAS_TSIP_TLS)
+ /* for root ca verification */
+int tsip_tls_RootCertVerify(const byte *cert, word32 cert_len,
+ word32 key_n_start, word32 key_n_len,
+ word32 key_e_start, word32 key_e_len,
+ word32 cm_row);
+byte tsip_rootCAverified( );
+#endif
+#ifdef WOLFSSL_SESSION_EXPORT
#ifdef WOLFSSL_DTLS
- static INLINE word32 max(word32 a, word32 b)
- {
- return a > b ? a : b;
+int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, unsigned int sz)
+{
+ WOLFSSL_ENTER("wolfSSL_session_import");
+
+ if (ssl == NULL || buf == NULL) {
+ return BAD_FUNC_ARG;
}
-#endif /* WOLFSSL_DTLS */
-#endif /* WOLFSSL_HAVE_MAX */
+ /* sanity checks on buffer and protocol are done in internal function */
+ return wolfSSL_dtls_import_internal(ssl, buf, sz);
+}
-#ifndef WOLFSSL_LEANPSK
-char* mystrnstr(const char* s1, const char* s2, unsigned int n)
+/* Sets the function to call for serializing the session. This function is
+ * called right after the handshake is completed. */
+int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, wc_dtls_export func)
{
- unsigned int s2_len = (unsigned int)XSTRLEN(s2);
- if (s2_len == 0)
- return (char*)s1;
+ WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_export");
- while (n >= s2_len && s1[0]) {
- if (s1[0] == s2[0])
- if (XMEMCMP(s1, s2, s2_len) == 0)
- return (char*)s1;
- s1++;
- n--;
+ /* purposefully allow func to be NULL */
+ if (ctx == NULL) {
+ return BAD_FUNC_ARG;
}
- return NULL;
+ ctx->dtls_export = func;
+
+ return WOLFSSL_SUCCESS;
}
-#endif
-/* prevent multiple mutex initializations */
-static volatile int initRefCount = 0;
-static wolfSSL_Mutex count_mutex; /* init ref count mutex */
+/* Sets the function in WOLFSSL struct to call for serializing the session. This
+ * function is called right after the handshake is completed. */
+int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func)
+{
+ WOLFSSL_ENTER("wolfSSL_dtls_set_export");
-WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method)
+ /* purposefully allow func to be NULL */
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ ssl->dtls_export = func;
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+/* This function allows for directly serializing a session rather than using
+ * callbacks. It has less overhead by removing a temporary buffer and gives
+ * control over when the session gets serialized. When using callbacks the
+ * session is always serialized immediately after the handshake is finished.
+ *
+ * buf is the argument to contain the serialized session
+ * sz is the size of the buffer passed in
+ * ssl is the WOLFSSL struct to serialize
+ * returns the size of serialized session on success, 0 on no action, and
+ * negative value on error */
+int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz)
+{
+ WOLFSSL_ENTER("wolfSSL_dtls_export");
+
+ if (ssl == NULL || sz == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (buf == NULL) {
+ *sz = MAX_EXPORT_BUFFER;
+ return 0;
+ }
+
+ /* if not DTLS do nothing */
+ if (!ssl->options.dtls) {
+ WOLFSSL_MSG("Currently only DTLS export is supported");
+ return 0;
+ }
+
+ /* copy over keys, options, and dtls state struct */
+ return wolfSSL_dtls_export_internal(ssl, buf, *sz);
+}
+
+
+/* This function is similar to wolfSSL_dtls_export but only exports the portion
+ * of the WOLFSSL structure related to the state of the connection, i.e. peer
+ * sequence number, epoch, AEAD state etc.
+ *
+ * buf is the argument to contain the serialized state, if null then set "sz" to
+ * buffer size required
+ * sz is the size of the buffer passed in
+ * ssl is the WOLFSSL struct to serialize
+ * returns the size of serialized session on success, 0 on no action, and
+ * negative value on error */
+int wolfSSL_dtls_export_state_only(WOLFSSL* ssl, unsigned char* buf,
+ unsigned int* sz)
+{
+ WOLFSSL_ENTER("wolfSSL_dtls_export_state_only");
+
+ if (ssl == NULL || sz == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (buf == NULL) {
+ *sz = MAX_EXPORT_STATE_BUFFER;
+ return 0;
+ }
+
+ /* if not DTLS do nothing */
+ if (!ssl->options.dtls) {
+ WOLFSSL_MSG("Currently only DTLS export state is supported");
+ return 0;
+ }
+
+ /* copy over keys, options, and dtls state struct */
+ return wolfSSL_dtls_export_state_internal(ssl, buf, *sz);
+}
+
+
+/* returns 0 on success */
+int wolfSSL_send_session(WOLFSSL* ssl)
+{
+ int ret;
+ byte* buf;
+ word16 bufSz = MAX_EXPORT_BUFFER;
+
+ WOLFSSL_ENTER("wolfSSL_send_session");
+
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ buf = (byte*)XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (buf == NULL) {
+ return MEMORY_E;
+ }
+
+ /* if not DTLS do nothing */
+ if (!ssl->options.dtls) {
+ XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ WOLFSSL_MSG("Currently only DTLS export is supported");
+ return 0;
+ }
+
+ /* copy over keys, options, and dtls state struct */
+ ret = wolfSSL_dtls_export_internal(ssl, buf, bufSz);
+ if (ret < 0) {
+ XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+
+ /* if no error ret has size of buffer */
+ ret = ssl->dtls_export(ssl, buf, ret, NULL);
+ if (ret != WOLFSSL_SUCCESS) {
+ XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+
+ XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return 0;
+}
+#endif /* WOLFSSL_DTLS */
+#endif /* WOLFSSL_SESSION_EXPORT */
+
+/* prevent multiple mutex initializations */
+static volatile WOLFSSL_GLOBAL int initRefCount = 0;
+static WOLFSSL_GLOBAL wolfSSL_Mutex count_mutex; /* init ref count mutex */
+
+/* Create a new WOLFSSL_CTX struct and return the pointer to created struct.
+ WOLFSSL_METHOD pointer passed in is given to ctx to manage.
+ This function frees the passed in WOLFSSL_METHOD struct on failure and on
+ success is freed when ctx is freed.
+ */
+WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap)
{
WOLFSSL_CTX* ctx = NULL;
- WOLFSSL_ENTER("WOLFSSL_CTX_new");
+ WOLFSSL_ENTER("wolfSSL_CTX_new_ex");
- if (initRefCount == 0)
- wolfSSL_Init(); /* user no longer forced to call Init themselves */
+ if (initRefCount == 0) {
+ /* user no longer forced to call Init themselves */
+ int ret = wolfSSL_Init();
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("wolfSSL_Init failed");
+ WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0);
+ if (method != NULL) {
+ XFREE(method, heap, DYNAMIC_TYPE_METHOD);
+ }
+ return NULL;
+ }
+ }
if (method == NULL)
return ctx;
- ctx = (WOLFSSL_CTX*) XMALLOC(sizeof(WOLFSSL_CTX), 0, DYNAMIC_TYPE_CTX);
+ ctx = (WOLFSSL_CTX*) XMALLOC(sizeof(WOLFSSL_CTX), heap, DYNAMIC_TYPE_CTX);
if (ctx) {
- if (InitSSL_Ctx(ctx, method) < 0) {
+ int ret;
+
+ ret = InitSSL_Ctx(ctx, method, heap);
+ #ifdef WOLFSSL_STATIC_MEMORY
+ if (heap != NULL) {
+ ctx->onHeap = 1; /* free the memory back to heap when done */
+ }
+ #endif
+ if (ret < 0) {
WOLFSSL_MSG("Init CTX failed");
wolfSSL_CTX_free(ctx);
ctx = NULL;
}
+#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
+ && !defined(NO_SHA256) && !defined(WC_NO_RNG)
+ else {
+ ctx->srp = (Srp*) XMALLOC(sizeof(Srp), heap, DYNAMIC_TYPE_SRP);
+ if (ctx->srp == NULL){
+ WOLFSSL_MSG("Init CTX failed");
+ wolfSSL_CTX_free(ctx);
+ return NULL;
+ }
+ XMEMSET(ctx->srp, 0, sizeof(Srp));
+ }
+#endif
}
else {
WOLFSSL_MSG("Alloc CTX failed, method freed");
- XFREE(method, NULL, DYNAMIC_TYPE_METHOD);
+ XFREE(method, heap, DYNAMIC_TYPE_METHOD);
}
+
WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0);
return ctx;
}
+WOLFSSL_ABI
+WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method)
+{
+#ifdef WOLFSSL_HEAP_TEST
+ /* if testing the heap hint then set top level CTX to have test value */
+ return wolfSSL_CTX_new_ex(method, (void*)WOLFSSL_HEAP_TEST);
+#else
+ return wolfSSL_CTX_new_ex(method, NULL);
+#endif
+}
+
+#ifdef OPENSSL_EXTRA
+/* increases CTX reference count to track proper time to "free" */
+int wolfSSL_CTX_up_ref(WOLFSSL_CTX* ctx)
+{
+ int refCount = SSL_CTX_RefCount(ctx, 1);
+ return ((refCount > 1) ? 1 : 0);
+}
+#endif
+
+WOLFSSL_ABI
void wolfSSL_CTX_free(WOLFSSL_CTX* ctx)
{
WOLFSSL_ENTER("SSL_CTX_free");
- if (ctx)
+ if (ctx) {
+#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
+&& !defined(NO_SHA256) && !defined(WC_NO_RNG)
+ if (ctx->srp != NULL){
+ if (ctx->srp_password != NULL){
+ XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
+ ctx->srp_password = NULL;
+ }
+ wc_SrpTerm(ctx->srp);
+ XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
+ ctx->srp = NULL;
+ }
+#endif
FreeSSL_Ctx(ctx);
+ }
+
WOLFSSL_LEAVE("SSL_CTX_free", 0);
}
+#ifdef HAVE_ENCRYPT_THEN_MAC
+/**
+ * Sets whether Encrypt-Then-MAC extension can be negotiated against context.
+ * The default value: enabled.
+ *
+ * ctx SSL/TLS context.
+ * set Whether to allow or not: 1 is allow and 0 is disallow.
+ * returns WOLFSSL_SUCCESS
+ */
+int wolfSSL_CTX_AllowEncryptThenMac(WOLFSSL_CTX *ctx, int set)
+{
+ ctx->disallowEncThenMac = !set;
+ return WOLFSSL_SUCCESS;
+}
+
+/**
+ * Sets whether Encrypt-Then-MAC extension can be negotiated against context.
+ * The default value comes from context.
+ *
+ * ctx SSL/TLS context.
+ * set Whether to allow or not: 1 is allow and 0 is disallow.
+ * returns WOLFSSL_SUCCESS
+ */
+int wolfSSL_AllowEncryptThenMac(WOLFSSL *ssl, int set)
+{
+ ssl->options.disallowEncThenMac = !set;
+ return WOLFSSL_SUCCESS;
+}
+#endif
+
+#ifdef SINGLE_THREADED
+/* no locking in single threaded mode, allow a CTX level rng to be shared with
+ * WOLFSSL objects, WOLFSSL_SUCCESS on ok */
+int wolfSSL_CTX_new_rng(WOLFSSL_CTX* ctx)
+{
+ WC_RNG* rng;
+ int ret;
+
+ if (ctx == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ctx->heap, DYNAMIC_TYPE_RNG);
+ if (rng == NULL) {
+ return MEMORY_E;
+ }
+
+#ifndef HAVE_FIPS
+ ret = wc_InitRng_ex(rng, ctx->heap, ctx->devId);
+#else
+ ret = wc_InitRng(rng);
+#endif
+ if (ret != 0) {
+ XFREE(rng, ctx->heap, DYNAMIC_TYPE_RNG);
+ return ret;
+ }
+
+ ctx->rng = rng;
+ return WOLFSSL_SUCCESS;
+}
+#endif
+
+
+WOLFSSL_ABI
WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx)
{
WOLFSSL* ssl = NULL;
@@ -176,10 +541,10 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx)
if (ctx == NULL)
return ssl;
- ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ctx->heap,DYNAMIC_TYPE_SSL);
+ ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ctx->heap, DYNAMIC_TYPE_SSL);
if (ssl)
- if ( (ret = InitSSL(ssl, ctx)) < 0) {
- FreeSSL(ssl);
+ if ( (ret = InitSSL(ssl, ctx, 0)) < 0) {
+ FreeSSL(ssl, ctx->heap);
ssl = 0;
}
@@ -188,277 +553,1204 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx)
}
+WOLFSSL_ABI
void wolfSSL_free(WOLFSSL* ssl)
{
WOLFSSL_ENTER("SSL_free");
if (ssl)
- FreeSSL(ssl);
+ FreeSSL(ssl, ssl->ctx->heap);
WOLFSSL_LEAVE("SSL_free", 0);
}
+
+int wolfSSL_is_server(WOLFSSL* ssl)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+ return ssl->options.side == WOLFSSL_SERVER_END;
+}
+
+#ifdef HAVE_WRITE_DUP
+
+/*
+ * Release resources around WriteDup object
+ *
+ * ssl WOLFSSL object
+ *
+ * no return, destruction so make best attempt
+*/
+void FreeWriteDup(WOLFSSL* ssl)
+{
+ int doFree = 0;
+
+ WOLFSSL_ENTER("FreeWriteDup");
+
+ if (ssl->dupWrite) {
+ if (wc_LockMutex(&ssl->dupWrite->dupMutex) == 0) {
+ ssl->dupWrite->dupCount--;
+ if (ssl->dupWrite->dupCount == 0) {
+ doFree = 1;
+ } else {
+ WOLFSSL_MSG("WriteDup count not zero, no full free");
+ }
+ wc_UnLockMutex(&ssl->dupWrite->dupMutex);
+ }
+ }
+
+ if (doFree) {
+ WOLFSSL_MSG("Doing WriteDup full free, count to zero");
+ wc_FreeMutex(&ssl->dupWrite->dupMutex);
+ XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
+ }
+}
+
+
+/*
+ * duplicate existing ssl members into dup needed for writing
+ *
+ * dup write only WOLFSSL
+ * ssl existing WOLFSSL
+ *
+ * 0 on success
+*/
+static int DupSSL(WOLFSSL* dup, WOLFSSL* ssl)
+{
+ /* shared dupWrite setup */
+ ssl->dupWrite = (WriteDup*)XMALLOC(sizeof(WriteDup), ssl->heap,
+ DYNAMIC_TYPE_WRITEDUP);
+ if (ssl->dupWrite == NULL) {
+ return MEMORY_E;
+ }
+ XMEMSET(ssl->dupWrite, 0, sizeof(WriteDup));
+
+ if (wc_InitMutex(&ssl->dupWrite->dupMutex) != 0) {
+ XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
+ ssl->dupWrite = NULL;
+ return BAD_MUTEX_E;
+ }
+ ssl->dupWrite->dupCount = 2; /* both sides have a count to start */
+ dup->dupWrite = ssl->dupWrite; /* each side uses */
+
+ /* copy write parts over to dup writer */
+ XMEMCPY(&dup->specs, &ssl->specs, sizeof(CipherSpecs));
+ XMEMCPY(&dup->options, &ssl->options, sizeof(Options));
+ XMEMCPY(&dup->keys, &ssl->keys, sizeof(Keys));
+ XMEMCPY(&dup->encrypt, &ssl->encrypt, sizeof(Ciphers));
+ /* dup side now owns encrypt/write ciphers */
+ XMEMSET(&ssl->encrypt, 0, sizeof(Ciphers));
+
+ dup->IOCB_WriteCtx = ssl->IOCB_WriteCtx;
+ dup->wfd = ssl->wfd;
+ dup->wflags = ssl->wflags;
+ dup->hmac = ssl->hmac;
+#ifdef HAVE_TRUNCATED_HMAC
+ dup->truncated_hmac = ssl->truncated_hmac;
+#endif
+
+ /* unique side dup setup */
+ dup->dupSide = WRITE_DUP_SIDE;
+ ssl->dupSide = READ_DUP_SIDE;
+
+ return 0;
+}
+
+
+/*
+ * duplicate a WOLFSSL object post handshake for writing only
+ * turn existing object into read only. Allows concurrent access from two
+ * different threads.
+ *
+ * ssl existing WOLFSSL object
+ *
+ * return dup'd WOLFSSL object on success
+*/
+WOLFSSL* wolfSSL_write_dup(WOLFSSL* ssl)
+{
+ WOLFSSL* dup = NULL;
+ int ret = 0;
+
+ (void)ret;
+ WOLFSSL_ENTER("wolfSSL_write_dup");
+
+ if (ssl == NULL) {
+ return ssl;
+ }
+
+ if (ssl->options.handShakeDone == 0) {
+ WOLFSSL_MSG("wolfSSL_write_dup called before handshake complete");
+ return NULL;
+ }
+
+ if (ssl->dupWrite) {
+ WOLFSSL_MSG("wolfSSL_write_dup already called once");
+ return NULL;
+ }
+
+ dup = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ssl->ctx->heap, DYNAMIC_TYPE_SSL);
+ if (dup) {
+ if ( (ret = InitSSL(dup, ssl->ctx, 1)) < 0) {
+ FreeSSL(dup, ssl->ctx->heap);
+ dup = NULL;
+ } else if ( (ret = DupSSL(dup, ssl)) < 0) {
+ FreeSSL(dup, ssl->ctx->heap);
+ dup = NULL;
+ }
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_write_dup", ret);
+
+ return dup;
+}
+
+
+/*
+ * Notify write dup side of fatal error or close notify
+ *
+ * ssl WOLFSSL object
+ * err Notify err
+ *
+ * 0 on success
+*/
+int NotifyWriteSide(WOLFSSL* ssl, int err)
+{
+ int ret;
+
+ WOLFSSL_ENTER("NotifyWriteSide");
+
+ ret = wc_LockMutex(&ssl->dupWrite->dupMutex);
+ if (ret == 0) {
+ ssl->dupWrite->dupErr = err;
+ ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex);
+ }
+
+ return ret;
+}
+
+
+#endif /* HAVE_WRITE_DUP */
+
+
#ifdef HAVE_POLY1305
/* set if to use old poly 1 for yes 0 to use new poly */
int wolfSSL_use_old_poly(WOLFSSL* ssl, int value)
{
+ (void)ssl;
+ (void)value;
+
+#ifndef WOLFSSL_NO_TLS12
WOLFSSL_ENTER("SSL_use_old_poly");
- ssl->options.oldPoly = value;
+ WOLFSSL_MSG("Warning SSL connection auto detects old/new and this function"
+ "is depreciated");
+ ssl->options.oldPoly = (word16)value;
WOLFSSL_LEAVE("SSL_use_old_poly", 0);
+#endif
return 0;
}
#endif
+
+WOLFSSL_ABI
int wolfSSL_set_fd(WOLFSSL* ssl, int fd)
{
+ int ret;
+
WOLFSSL_ENTER("SSL_set_fd");
- ssl->rfd = fd; /* not used directly to allow IO callbacks */
- ssl->wfd = fd;
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ ret = wolfSSL_set_read_fd(ssl, fd);
+ if (ret == WOLFSSL_SUCCESS) {
+ ret = wolfSSL_set_write_fd(ssl, fd);
+ }
+
+ return ret;
+}
+
+
+int wolfSSL_set_read_fd(WOLFSSL* ssl, int fd)
+{
+ WOLFSSL_ENTER("SSL_set_read_fd");
+
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ ssl->rfd = fd; /* not used directly to allow IO callbacks */
ssl->IOCB_ReadCtx = &ssl->rfd;
- ssl->IOCB_WriteCtx = &ssl->wfd;
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx;
+ ssl->buffers.dtlsCtx.rfd = fd;
+ }
+ #endif
+
+ WOLFSSL_LEAVE("SSL_set_read_fd", WOLFSSL_SUCCESS);
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_set_write_fd(WOLFSSL* ssl, int fd)
+{
+ WOLFSSL_ENTER("SSL_set_write_fd");
+
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ ssl->wfd = fd; /* not used directly to allow IO callbacks */
+ ssl->IOCB_WriteCtx = &ssl->wfd;
+
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx;
- ssl->buffers.dtlsCtx.fd = fd;
+ ssl->buffers.dtlsCtx.wfd = fd;
}
#endif
- WOLFSSL_LEAVE("SSL_set_fd", SSL_SUCCESS);
- return SSL_SUCCESS;
+ WOLFSSL_LEAVE("SSL_set_write_fd", WOLFSSL_SUCCESS);
+ return WOLFSSL_SUCCESS;
}
/**
- * Get the name of cipher at priotity level passed in.
+ * Get the name of cipher at priority level passed in.
*/
char* wolfSSL_get_cipher_list(int priority)
{
- const char* const* ciphers = GetCipherNames();
+ const CipherSuiteInfo* ciphers = GetCipherNames();
if (priority >= GetCipherNamesSize() || priority < 0) {
return 0;
}
- return (char*)ciphers[priority];
+ return (char*)ciphers[priority].name;
+}
+
+
+/**
+ * Get the name of cipher at priority level passed in.
+ */
+char* wolfSSL_get_cipher_list_ex(WOLFSSL* ssl, int priority)
+{
+
+ if (ssl == NULL) {
+ return NULL;
+ }
+ else {
+ const char* cipher;
+
+ if ((cipher = wolfSSL_get_cipher_name_internal(ssl)) != NULL) {
+ if (priority == 0) {
+ return (char*)cipher;
+ }
+ else {
+ return NULL;
+ }
+ }
+ else {
+ return wolfSSL_get_cipher_list(priority);
+ }
+ }
}
int wolfSSL_get_ciphers(char* buf, int len)
{
- const char* const* ciphers = GetCipherNames();
- int totalInc = 0;
- int step = 0;
- char delim = ':';
- int size = GetCipherNamesSize();
- int i;
+ const CipherSuiteInfo* ciphers = GetCipherNames();
+ int ciphersSz = GetCipherNamesSize();
+ int i;
+ int cipherNameSz;
if (buf == NULL || len <= 0)
return BAD_FUNC_ARG;
- /* Add each member to the buffer delimitted by a : */
- for (i = 0; i < size; i++) {
- step = (int)(XSTRLEN(ciphers[i]) + 1); /* delimiter */
- totalInc += step;
+ /* Add each member to the buffer delimited by a : */
+ for (i = 0; i < ciphersSz; i++) {
+ cipherNameSz = (int)XSTRLEN(ciphers[i].name);
+ if (cipherNameSz + 1 < len) {
+ XSTRNCPY(buf, ciphers[i].name, len);
+ buf += cipherNameSz;
- /* Check to make sure buf is large enough and will not overflow */
- if (totalInc < len) {
- XSTRNCPY(buf, ciphers[i], XSTRLEN(ciphers[i]));
- buf += XSTRLEN(ciphers[i]);
+ if (i < ciphersSz - 1)
+ *buf++ = ':';
+ *buf = 0;
- if (i < size - 1)
- *buf++ = delim;
+ len -= cipherNameSz + 1;
}
else
return BUFFER_E;
}
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
-int wolfSSL_get_fd(const WOLFSSL* ssl)
+#ifndef NO_ERROR_STRINGS
+/* places a list of all supported cipher suites in TLS_* format into "buf"
+ * return WOLFSSL_SUCCESS on success */
+int wolfSSL_get_ciphers_iana(char* buf, int len)
{
- WOLFSSL_ENTER("SSL_get_fd");
- WOLFSSL_LEAVE("SSL_get_fd", ssl->rfd);
- return ssl->rfd;
+ const CipherSuiteInfo* ciphers = GetCipherNames();
+ int ciphersSz = GetCipherNamesSize();
+ int i;
+ int cipherNameSz;
+
+ if (buf == NULL || len <= 0)
+ return BAD_FUNC_ARG;
+
+ /* Add each member to the buffer delimited by a : */
+ for (i = 0; i < ciphersSz; i++) {
+ cipherNameSz = (int)XSTRLEN(ciphers[i].name_iana);
+ if (cipherNameSz + 1 < len) {
+ XSTRNCPY(buf, ciphers[i].name_iana, len);
+ buf += cipherNameSz;
+
+ if (i < ciphersSz - 1)
+ *buf++ = ':';
+ *buf = 0;
+
+ len -= cipherNameSz + 1;
+ }
+ else
+ return BUFFER_E;
+ }
+ return WOLFSSL_SUCCESS;
}
+#endif /* NO_ERROR_STRINGS */
-int wolfSSL_get_using_nonblock(WOLFSSL* ssl)
+const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, int len)
{
- WOLFSSL_ENTER("wolfSSL_get_using_nonblock");
- WOLFSSL_LEAVE("wolfSSL_get_using_nonblock", ssl->options.usingNonblock);
- return ssl->options.usingNonblock;
+ const char* cipher;
+
+ if (ssl == NULL)
+ return NULL;
+
+ cipher = wolfSSL_get_cipher_name_iana(ssl);
+ len = min(len, (int)(XSTRLEN(cipher) + 1));
+ XMEMCPY(buf, cipher, len);
+ return buf;
+}
+
+int wolfSSL_get_fd(const WOLFSSL* ssl)
+{
+ int fd = -1;
+ WOLFSSL_ENTER("SSL_get_fd");
+ if (ssl) {
+ fd = ssl->rfd;
+ }
+ WOLFSSL_LEAVE("SSL_get_fd", fd);
+ return fd;
}
int wolfSSL_dtls(WOLFSSL* ssl)
{
- return ssl->options.dtls;
+ int dtlsOpt = 0;
+ if (ssl)
+ dtlsOpt = ssl->options.dtls;
+ return dtlsOpt;
}
-
-#ifndef WOLFSSL_LEANPSK
-void wolfSSL_set_using_nonblock(WOLFSSL* ssl, int nonblock)
+#if !defined(NO_CERTS)
+/* Set whether mutual authentication is required for connections.
+ * Server side only.
+ *
+ * ctx The SSL/TLS CTX object.
+ * req 1 to indicate required and 0 when not.
+ * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and
+ * 0 on success.
+ */
+int wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req)
{
- WOLFSSL_ENTER("wolfSSL_set_using_nonblock");
- ssl->options.usingNonblock = (nonblock != 0);
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+ if (ctx->method->side == WOLFSSL_CLIENT_END)
+ return SIDE_ERROR;
+
+ ctx->mutualAuth = (byte)req;
+
+ return 0;
}
+/* Set whether mutual authentication is required for the connection.
+ * Server side only.
+ *
+ * ssl The SSL/TLS object.
+ * req 1 to indicate required and 0 when not.
+ * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
+ * SIDE_ERROR when not a client and 0 on success.
+ */
+int wolfSSL_mutual_auth(WOLFSSL* ssl, int req)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+ if (ssl->options.side == WOLFSSL_SERVER_END)
+ return SIDE_ERROR;
+
+ ssl->options.mutualAuth = (word16)req;
+ return 0;
+}
+#endif /* NO_CERTS */
+
+#ifndef WOLFSSL_LEANPSK
int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
{
#ifdef WOLFSSL_DTLS
- void* sa = (void*)XMALLOC(peerSz, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
+ void* sa;
+
+ if (ssl == NULL)
+ return WOLFSSL_FAILURE;
+
+ sa = (void*)XMALLOC(peerSz, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
if (sa != NULL) {
- if (ssl->buffers.dtlsCtx.peer.sa != NULL)
+ if (ssl->buffers.dtlsCtx.peer.sa != NULL) {
XFREE(ssl->buffers.dtlsCtx.peer.sa,ssl->heap,DYNAMIC_TYPE_SOCKADDR);
+ ssl->buffers.dtlsCtx.peer.sa = NULL;
+ }
XMEMCPY(sa, peer, peerSz);
ssl->buffers.dtlsCtx.peer.sa = sa;
ssl->buffers.dtlsCtx.peer.sz = peerSz;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
#else
(void)ssl;
(void)peer;
(void)peerSz;
- return SSL_NOT_IMPLEMENTED;
+ return WOLFSSL_NOT_IMPLEMENTED;
#endif
}
int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz)
{
#ifdef WOLFSSL_DTLS
+ if (ssl == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
if (peer != NULL && peerSz != NULL
- && *peerSz >= ssl->buffers.dtlsCtx.peer.sz) {
+ && *peerSz >= ssl->buffers.dtlsCtx.peer.sz
+ && ssl->buffers.dtlsCtx.peer.sa != NULL) {
*peerSz = ssl->buffers.dtlsCtx.peer.sz;
XMEMCPY(peer, ssl->buffers.dtlsCtx.peer.sa, *peerSz);
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
#else
(void)ssl;
(void)peer;
(void)peerSz;
- return SSL_NOT_IMPLEMENTED;
+ return WOLFSSL_NOT_IMPLEMENTED;
#endif
}
+
+
+#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
+
+int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_sctp()");
+
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ ctx->dtlsSctp = 1;
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_dtls_set_sctp(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_dtls_set_sctp()");
+
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ ssl->options.dtlsSctp = 1;
+ return WOLFSSL_SUCCESS;
+}
+
+#endif /* WOLFSSL_DTLS && WOLFSSL_SCTP */
+
+#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \
+ defined(WOLFSSL_DTLS)
+
+int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX* ctx, word16 newMtu)
+{
+ if (ctx == NULL || newMtu > MAX_RECORD_SIZE)
+ return BAD_FUNC_ARG;
+
+ ctx->dtlsMtuSz = newMtu;
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ if (newMtu > MAX_RECORD_SIZE) {
+ ssl->error = BAD_FUNC_ARG;
+ return WOLFSSL_FAILURE;
+ }
+
+ ssl->dtlsMtuSz = newMtu;
+ return WOLFSSL_SUCCESS;
+}
+
+#endif /* WOLFSSL_DTLS && (WOLFSSL_SCTP || WOLFSSL_DTLS_MTU) */
+
+
+#ifdef WOLFSSL_DTLS_DROP_STATS
+
+int wolfSSL_dtls_get_drop_stats(WOLFSSL* ssl,
+ word32* macDropCount, word32* replayDropCount)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_dtls_get_drop_stats()");
+
+ if (ssl == NULL)
+ ret = BAD_FUNC_ARG;
+ else {
+ ret = WOLFSSL_SUCCESS;
+ if (macDropCount != NULL)
+ *macDropCount = ssl->macDropCount;
+ if (replayDropCount != NULL)
+ *replayDropCount = ssl->replayDropCount;
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_dtls_get_drop_stats()", ret);
+ return ret;
+}
+
+#endif /* WOLFSSL_DTLS_DROP_STATS */
+
+
+#if defined(WOLFSSL_MULTICAST)
+
+int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id)
+{
+ int ret = 0;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_mcast_set_member_id()");
+
+ if (ctx == NULL || id > 255)
+ ret = BAD_FUNC_ARG;
+
+ if (ret == 0) {
+ ctx->haveEMS = 0;
+ ctx->haveMcast = 1;
+ ctx->mcastID = (byte)id;
+#ifndef WOLFSSL_USER_IO
+ ctx->CBIORecv = EmbedReceiveFromMcast;
+#endif /* WOLFSSL_USER_IO */
+
+ ret = WOLFSSL_SUCCESS;
+ }
+ WOLFSSL_LEAVE("wolfSSL_CTX_mcast_set_member_id()", ret);
+ return ret;
+}
+
+int wolfSSL_mcast_get_max_peers(void)
+{
+ return WOLFSSL_MULTICAST_PEERS;
+}
+
+#ifdef WOLFSSL_DTLS
+static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
+ word32 second, word32 max)
+{
+ word32 newCur = 0;
+
+ if (cur < first)
+ newCur = first;
+ else if (cur < second)
+ newCur = second;
+ else if (cur < max)
+ newCur = max;
+
+ return newCur;
+}
+#endif /* WOLFSSL_DTLS */
+
+
+int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch,
+ const byte* preMasterSecret, word32 preMasterSz,
+ const byte* clientRandom, const byte* serverRandom,
+ const byte* suite)
+{
+ int ret = 0;
+
+ WOLFSSL_ENTER("wolfSSL_set_secret()");
+
+ if (ssl == NULL || preMasterSecret == NULL ||
+ preMasterSz == 0 || preMasterSz > ENCRYPT_LEN ||
+ clientRandom == NULL || serverRandom == NULL || suite == NULL) {
+
+ ret = BAD_FUNC_ARG;
+ }
+
+ if (ret == 0) {
+ XMEMCPY(ssl->arrays->preMasterSecret, preMasterSecret, preMasterSz);
+ ssl->arrays->preMasterSz = preMasterSz;
+ XMEMCPY(ssl->arrays->clientRandom, clientRandom, RAN_LEN);
+ XMEMCPY(ssl->arrays->serverRandom, serverRandom, RAN_LEN);
+ ssl->options.cipherSuite0 = suite[0];
+ ssl->options.cipherSuite = suite[1];
+
+ ret = SetCipherSpecs(ssl);
+ }
+
+ if (ret == 0)
+ ret = MakeTlsMasterSecret(ssl);
+
+ if (ret == 0) {
+ ssl->keys.encryptionOn = 1;
+ ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
+ }
+
+ if (ret == 0) {
+ if (ssl->options.dtls) {
+ #ifdef WOLFSSL_DTLS
+ WOLFSSL_DTLS_PEERSEQ* peerSeq;
+ int i;
+
+ ssl->keys.dtls_epoch = epoch;
+ for (i = 0, peerSeq = ssl->keys.peerSeq;
+ i < WOLFSSL_DTLS_PEERSEQ_SZ;
+ i++, peerSeq++) {
+
+ peerSeq->nextEpoch = epoch;
+ peerSeq->prevSeq_lo = peerSeq->nextSeq_lo;
+ peerSeq->prevSeq_hi = peerSeq->nextSeq_hi;
+ peerSeq->nextSeq_lo = 0;
+ peerSeq->nextSeq_hi = 0;
+ XMEMCPY(peerSeq->prevWindow, peerSeq->window, DTLS_SEQ_SZ);
+ XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ);
+ peerSeq->highwaterMark = UpdateHighwaterMark(0,
+ ssl->ctx->mcastFirstSeq,
+ ssl->ctx->mcastSecondSeq,
+ ssl->ctx->mcastMaxSeq);
+ }
+ #else
+ (void)epoch;
+ #endif
+ }
+ FreeHandshakeResources(ssl);
+ ret = WOLFSSL_SUCCESS;
+ }
+ else {
+ if (ssl)
+ ssl->error = ret;
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ WOLFSSL_LEAVE("wolfSSL_set_secret()", ret);
+ return ret;
+}
+
+
+#ifdef WOLFSSL_DTLS
+
+int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove)
+{
+ WOLFSSL_DTLS_PEERSEQ* p = NULL;
+ int ret = WOLFSSL_SUCCESS;
+ int i;
+
+ WOLFSSL_ENTER("wolfSSL_mcast_peer_add()");
+ if (ssl == NULL || peerId > 255)
+ return BAD_FUNC_ARG;
+
+ if (!remove) {
+ /* Make sure it isn't already present, while keeping the first
+ * open spot. */
+ for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
+ if (ssl->keys.peerSeq[i].peerId == INVALID_PEER_ID)
+ p = &ssl->keys.peerSeq[i];
+ if (ssl->keys.peerSeq[i].peerId == peerId) {
+ WOLFSSL_MSG("Peer ID already in multicast peer list.");
+ p = NULL;
+ }
+ }
+
+ if (p != NULL) {
+ XMEMSET(p, 0, sizeof(WOLFSSL_DTLS_PEERSEQ));
+ p->peerId = peerId;
+ p->highwaterMark = UpdateHighwaterMark(0,
+ ssl->ctx->mcastFirstSeq,
+ ssl->ctx->mcastSecondSeq,
+ ssl->ctx->mcastMaxSeq);
+ }
+ else {
+ WOLFSSL_MSG("No room in peer list.");
+ ret = -1;
+ }
+ }
+ else {
+ for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
+ if (ssl->keys.peerSeq[i].peerId == peerId)
+ p = &ssl->keys.peerSeq[i];
+ }
+
+ if (p != NULL) {
+ p->peerId = INVALID_PEER_ID;
+ }
+ else {
+ WOLFSSL_MSG("Peer not found in list.");
+ }
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_mcast_peer_add()", ret);
+ return ret;
+}
+
+
+/* If peerId is in the list of peers and its last sequence number is non-zero,
+ * return 1, otherwise return 0. */
+int wolfSSL_mcast_peer_known(WOLFSSL* ssl, unsigned short peerId)
+{
+ int known = 0;
+ int i;
+
+ WOLFSSL_ENTER("wolfSSL_mcast_peer_known()");
+
+ if (ssl == NULL || peerId > 255) {
+ return BAD_FUNC_ARG;
+ }
+
+ for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
+ if (ssl->keys.peerSeq[i].peerId == peerId) {
+ if (ssl->keys.peerSeq[i].nextSeq_hi ||
+ ssl->keys.peerSeq[i].nextSeq_lo) {
+
+ known = 1;
+ }
+ break;
+ }
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_mcast_peer_known()", known);
+ return known;
+}
+
+
+int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX* ctx, word32 maxSeq,
+ word32 first, word32 second,
+ CallbackMcastHighwater cb)
+{
+ if (ctx == NULL || (second && first > second) ||
+ first > maxSeq || second > maxSeq || cb == NULL) {
+
+ return BAD_FUNC_ARG;
+ }
+
+ ctx->mcastHwCb = cb;
+ ctx->mcastFirstSeq = first;
+ ctx->mcastSecondSeq = second;
+ ctx->mcastMaxSeq = maxSeq;
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_mcast_set_highwater_ctx(WOLFSSL* ssl, void* ctx)
+{
+ if (ssl == NULL || ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ ssl->mcastHwCbCtx = ctx;
+
+ return WOLFSSL_SUCCESS;
+}
+
+#endif /* WOLFSSL_DTLS */
+
+#endif /* WOLFSSL_MULTICAST */
+
+
#endif /* WOLFSSL_LEANPSK */
-/* return underlyig connect or accept, SSL_SUCCESS on ok */
+/* return underlying connect or accept, WOLFSSL_SUCCESS on ok */
int wolfSSL_negotiate(WOLFSSL* ssl)
{
- int err = SSL_FATAL_ERROR;
+ int err = WOLFSSL_FATAL_ERROR;
WOLFSSL_ENTER("wolfSSL_negotiate");
#ifndef NO_WOLFSSL_SERVER
- if (ssl->options.side == WOLFSSL_SERVER_END)
- err = wolfSSL_accept(ssl);
+ if (ssl->options.side == WOLFSSL_SERVER_END) {
+#ifdef WOLFSSL_TLS13
+ if (IsAtLeastTLSv1_3(ssl->version))
+ err = wolfSSL_accept_TLSv13(ssl);
+ else
+#endif
+ err = wolfSSL_accept(ssl);
+ }
#endif
#ifndef NO_WOLFSSL_CLIENT
- if (ssl->options.side == WOLFSSL_CLIENT_END)
- err = wolfSSL_connect(ssl);
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+#ifdef WOLFSSL_TLS13
+ if (IsAtLeastTLSv1_3(ssl->version))
+ err = wolfSSL_connect_TLSv13(ssl);
+ else
+#endif
+ err = wolfSSL_connect(ssl);
+ }
#endif
+ (void)ssl;
+
WOLFSSL_LEAVE("wolfSSL_negotiate", err);
return err;
}
+WOLFSSL_ABI
+WC_RNG* wolfSSL_GetRNG(WOLFSSL* ssl)
+{
+ if (ssl) {
+ return ssl->rng;
+ }
+
+ return NULL;
+}
+
+
#ifndef WOLFSSL_LEANPSK
/* object size based on build */
int wolfSSL_GetObjectSize(void)
{
#ifdef SHOW_SIZES
- printf("sizeof suites = %lu\n", sizeof(Suites));
- printf("sizeof ciphers(2) = %lu\n", sizeof(Ciphers));
+ printf("sizeof suites = %lu\n", (unsigned long)sizeof(Suites));
+ printf("sizeof ciphers(2) = %lu\n", (unsigned long)sizeof(Ciphers));
#ifndef NO_RC4
- printf(" sizeof arc4 = %lu\n", sizeof(Arc4));
+ printf("\tsizeof arc4 = %lu\n", (unsigned long)sizeof(Arc4));
#endif
- printf(" sizeof aes = %lu\n", sizeof(Aes));
+ printf("\tsizeof aes = %lu\n", (unsigned long)sizeof(Aes));
#ifndef NO_DES3
- printf(" sizeof des3 = %lu\n", sizeof(Des3));
+ printf("\tsizeof des3 = %lu\n", (unsigned long)sizeof(Des3));
#endif
#ifndef NO_RABBIT
- printf(" sizeof rabbit = %lu\n", sizeof(Rabbit));
+ printf("\tsizeof rabbit = %lu\n", (unsigned long)sizeof(Rabbit));
#endif
#ifdef HAVE_CHACHA
- printf(" sizeof chacha = %lu\n", sizeof(Chacha));
+ printf("\tsizeof chacha = %lu\n", (unsigned long)sizeof(ChaCha));
#endif
- printf("sizeof cipher specs = %lu\n", sizeof(CipherSpecs));
- printf("sizeof keys = %lu\n", sizeof(Keys));
- printf("sizeof Hashes(2) = %lu\n", sizeof(Hashes));
+ printf("sizeof cipher specs = %lu\n", (unsigned long)sizeof(CipherSpecs));
+ printf("sizeof keys = %lu\n", (unsigned long)sizeof(Keys));
+ printf("sizeof Hashes(2) = %lu\n", (unsigned long)sizeof(Hashes));
#ifndef NO_MD5
- printf(" sizeof MD5 = %lu\n", sizeof(Md5));
+ printf("\tsizeof MD5 = %lu\n", (unsigned long)sizeof(wc_Md5));
#endif
#ifndef NO_SHA
- printf(" sizeof SHA = %lu\n", sizeof(Sha));
+ printf("\tsizeof SHA = %lu\n", (unsigned long)sizeof(wc_Sha));
+#endif
+#ifdef WOLFSSL_SHA224
+ printf("\tsizeof SHA224 = %lu\n", (unsigned long)sizeof(wc_Sha224));
#endif
#ifndef NO_SHA256
- printf(" sizeof SHA256 = %lu\n", sizeof(Sha256));
+ printf("\tsizeof SHA256 = %lu\n", (unsigned long)sizeof(wc_Sha256));
#endif
#ifdef WOLFSSL_SHA384
- printf(" sizeof SHA384 = %lu\n", sizeof(Sha384));
+ printf("\tsizeof SHA384 = %lu\n", (unsigned long)sizeof(wc_Sha384));
#endif
#ifdef WOLFSSL_SHA384
- printf(" sizeof SHA512 = %lu\n", sizeof(Sha512));
+ printf("\tsizeof SHA512 = %lu\n", (unsigned long)sizeof(wc_Sha512));
#endif
- printf("sizeof Buffers = %lu\n", sizeof(Buffers));
- printf("sizeof Options = %lu\n", sizeof(Options));
- printf("sizeof Arrays = %lu\n", sizeof(Arrays));
+ printf("sizeof Buffers = %lu\n", (unsigned long)sizeof(Buffers));
+ printf("sizeof Options = %lu\n", (unsigned long)sizeof(Options));
+ printf("sizeof Arrays = %lu\n", (unsigned long)sizeof(Arrays));
#ifndef NO_RSA
- printf("sizeof RsaKey = %lu\n", sizeof(RsaKey));
+ printf("sizeof RsaKey = %lu\n", (unsigned long)sizeof(RsaKey));
#endif
#ifdef HAVE_ECC
- printf("sizeof ecc_key = %lu\n", sizeof(ecc_key));
+ printf("sizeof ecc_key = %lu\n", (unsigned long)sizeof(ecc_key));
#endif
- printf("sizeof WOLFSSL_CIPHER = %lu\n", sizeof(WOLFSSL_CIPHER));
- printf("sizeof WOLFSSL_SESSION = %lu\n", sizeof(WOLFSSL_SESSION));
- printf("sizeof WOLFSSL = %lu\n", sizeof(WOLFSSL));
- printf("sizeof WOLFSSL_CTX = %lu\n", sizeof(WOLFSSL_CTX));
+ printf("sizeof WOLFSSL_CIPHER = %lu\n", (unsigned long)sizeof(WOLFSSL_CIPHER));
+ printf("sizeof WOLFSSL_SESSION = %lu\n", (unsigned long)sizeof(WOLFSSL_SESSION));
+ printf("sizeof WOLFSSL = %lu\n", (unsigned long)sizeof(WOLFSSL));
+ printf("sizeof WOLFSSL_CTX = %lu\n", (unsigned long)sizeof(WOLFSSL_CTX));
#endif
return sizeof(WOLFSSL);
}
+
+int wolfSSL_CTX_GetObjectSize(void)
+{
+ return sizeof(WOLFSSL_CTX);
+}
+
+int wolfSSL_METHOD_GetObjectSize(void)
+{
+ return sizeof(WOLFSSL_METHOD);
+}
+#endif
+
+
+#ifdef WOLFSSL_STATIC_MEMORY
+
+int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method,
+ unsigned char* buf, unsigned int sz,
+ int flag, int max)
+{
+ WOLFSSL_HEAP* heap;
+ WOLFSSL_HEAP_HINT* hint;
+ word32 idx = 0;
+
+ if (ctx == NULL || buf == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (*ctx == NULL && method == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (*ctx == NULL || (*ctx)->heap == NULL) {
+ if (sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT) > sz - idx) {
+ return BUFFER_E; /* not enough memory for structures */
+ }
+ heap = (WOLFSSL_HEAP*)buf;
+ idx += sizeof(WOLFSSL_HEAP);
+ if (wolfSSL_init_memory_heap(heap) != 0) {
+ return WOLFSSL_FAILURE;
+ }
+ hint = (WOLFSSL_HEAP_HINT*)(buf + idx);
+ idx += sizeof(WOLFSSL_HEAP_HINT);
+ XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT));
+ hint->memory = heap;
+
+ if (*ctx && (*ctx)->heap == NULL) {
+ (*ctx)->heap = (void*)hint;
+ }
+ }
+ else {
+#ifdef WOLFSSL_HEAP_TEST
+ /* do not load in memory if test has been set */
+ if ((*ctx)->heap == (void*)WOLFSSL_HEAP_TEST) {
+ return WOLFSSL_SUCCESS;
+ }
#endif
+ hint = (WOLFSSL_HEAP_HINT*)((*ctx)->heap);
+ heap = hint->memory;
+ }
+
+ if (wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap) != 1) {
+ WOLFSSL_MSG("Error partitioning memory");
+ return WOLFSSL_FAILURE;
+ }
+ /* create ctx if needed */
+ if (*ctx == NULL) {
+ *ctx = wolfSSL_CTX_new_ex(method(hint), hint);
+ if (*ctx == NULL) {
+ WOLFSSL_MSG("Error creating ctx");
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ /* determine what max applies too */
+ if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
+ heap->maxIO = max;
+ }
+ else { /* general memory used in handshakes */
+ heap->maxHa = max;
+ }
+
+ heap->flag |= flag;
+
+ (void)max;
+ (void)method;
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats)
+{
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+ WOLFSSL_ENTER("wolfSSL_is_static_memory");
+
+ /* fill out statistics if wanted and WOLFMEM_TRACK_STATS flag */
+ if (mem_stats != NULL && ssl->heap != NULL) {
+ WOLFSSL_HEAP_HINT* hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap));
+ WOLFSSL_HEAP* heap = hint->memory;
+ if (heap->flag & WOLFMEM_TRACK_STATS && hint->stats != NULL) {
+ XMEMCPY(mem_stats, hint->stats, sizeof(WOLFSSL_MEM_CONN_STATS));
+ }
+ }
+
+ return (ssl->heap) ? 1 : 0;
+}
+
+
+int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, WOLFSSL_MEM_STATS* mem_stats)
+{
+ if (ctx == NULL) {
+ return BAD_FUNC_ARG;
+ }
+ WOLFSSL_ENTER("wolfSSL_CTX_is_static_memory");
+
+ /* fill out statistics if wanted */
+ if (mem_stats != NULL && ctx->heap != NULL) {
+ WOLFSSL_HEAP* heap = ((WOLFSSL_HEAP_HINT*)(ctx->heap))->memory;
+ if (wolfSSL_GetMemStats(heap, mem_stats) != 1) {
+ return MEMORY_E;
+ }
+ }
+
+ return (ctx->heap) ? 1 : 0;
+}
+
+#endif /* WOLFSSL_STATIC_MEMORY */
+
+
+/* return max record layer size plaintext input size */
+int wolfSSL_GetMaxOutputSize(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_GetMaxOutputSize");
+
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ if (ssl->options.handShakeState != HANDSHAKE_DONE) {
+ WOLFSSL_MSG("Handshake not complete yet");
+ return BAD_FUNC_ARG;
+ }
+
+ return wolfSSL_GetMaxRecordSize(ssl, OUTPUT_RECORD_SIZE);
+}
+
+
+/* return record layer size of plaintext input size */
+int wolfSSL_GetOutputSize(WOLFSSL* ssl, int inSz)
+{
+ int maxSize;
+
+ WOLFSSL_ENTER("wolfSSL_GetOutputSize");
+
+ if (inSz < 0)
+ return BAD_FUNC_ARG;
+
+ maxSize = wolfSSL_GetMaxOutputSize(ssl);
+ if (maxSize < 0)
+ return maxSize; /* error */
+ if (inSz > maxSize)
+ return INPUT_SIZE_E;
+
+ return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0);
+}
+
+
+#ifdef HAVE_ECC
+int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX* ctx, short keySz)
+{
+ if (ctx == NULL || keySz < 0 || keySz % 8 != 0) {
+ WOLFSSL_MSG("Key size must be divisible by 8 or ctx was null");
+ return BAD_FUNC_ARG;
+ }
+
+ ctx->minEccKeySz = keySz / 8;
+#ifndef NO_CERTS
+ ctx->cm->minEccKeySz = keySz / 8;
+#endif
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_SetMinEccKey_Sz(WOLFSSL* ssl, short keySz)
+{
+ if (ssl == NULL || keySz < 0 || keySz % 8 != 0) {
+ WOLFSSL_MSG("Key size must be divisible by 8 or ssl was null");
+ return BAD_FUNC_ARG;
+ }
+
+ ssl->options.minEccKeySz = keySz / 8;
+ return WOLFSSL_SUCCESS;
+}
+
+#endif /* !NO_RSA */
+
+#ifndef NO_RSA
+int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX* ctx, short keySz)
+{
+ if (ctx == NULL || keySz < 0 || keySz % 8 != 0) {
+ WOLFSSL_MSG("Key size must be divisible by 8 or ctx was null");
+ return BAD_FUNC_ARG;
+ }
+
+ ctx->minRsaKeySz = keySz / 8;
+ ctx->cm->minRsaKeySz = keySz / 8;
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_SetMinRsaKey_Sz(WOLFSSL* ssl, short keySz)
+{
+ if (ssl == NULL || keySz < 0 || keySz % 8 != 0) {
+ WOLFSSL_MSG("Key size must be divisible by 8 or ssl was null");
+ return BAD_FUNC_ARG;
+ }
+
+ ssl->options.minRsaKeySz = keySz / 8;
+ return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_RSA */
#ifndef NO_DH
-/* server Diffie-Hellman parameters, SSL_SUCCESS on ok */
+/* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz,
const unsigned char* g, int gSz)
{
- byte havePSK = 0;
- byte haveRSA = 1;
-
WOLFSSL_ENTER("wolfSSL_SetTmpDH");
- if (ssl == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG;
- if (pSz < ssl->options.minDhKeySz)
+ if (ssl == NULL || p == NULL || g == NULL)
+ return BAD_FUNC_ARG;
+
+ if ((word16)pSz < ssl->options.minDhKeySz)
+ return DH_KEY_SIZE_E;
+ if ((word16)pSz > ssl->options.maxDhKeySz)
return DH_KEY_SIZE_E;
- if (ssl->options.side != WOLFSSL_SERVER_END)
+ /* this function is for server only */
+ if (ssl->options.side == WOLFSSL_CLIENT_END)
return SIDE_ERROR;
- if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH)
- XFREE(ssl->buffers.serverDH_P.buffer, ssl->ctx->heap, DYNAMIC_TYPE_DH);
- if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH)
- XFREE(ssl->buffers.serverDH_G.buffer, ssl->ctx->heap, DYNAMIC_TYPE_DH);
+ #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
+ !defined(HAVE_SELFTEST)
+ ssl->options.dhKeyTested = 0;
+ ssl->options.dhDoKeyTest = 1;
+ #endif
+
+ if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) {
+ XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ ssl->buffers.serverDH_P.buffer = NULL;
+ }
+ if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) {
+ XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ ssl->buffers.serverDH_G.buffer = NULL;
+ }
ssl->buffers.weOwnDH = 1; /* SSL owns now */
- ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(pSz, ssl->ctx->heap,
- DYNAMIC_TYPE_DH);
+ ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(pSz, ssl->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
if (ssl->buffers.serverDH_P.buffer == NULL)
- return MEMORY_E;
+ return MEMORY_E;
- ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(gSz, ssl->ctx->heap,
- DYNAMIC_TYPE_DH);
+ ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(gSz, ssl->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
if (ssl->buffers.serverDH_G.buffer == NULL) {
- XFREE(ssl->buffers.serverDH_P.buffer, ssl->ctx->heap, DYNAMIC_TYPE_DH);
+ XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ ssl->buffers.serverDH_P.buffer = NULL;
return MEMORY_E;
}
@@ -469,40 +1761,108 @@ int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz,
XMEMCPY(ssl->buffers.serverDH_G.buffer, g, gSz);
ssl->options.haveDH = 1;
+
+ if (ssl->options.side != WOLFSSL_NEITHER_END) {
+ word16 havePSK;
+ word16 haveRSA;
+ int keySz = 0;
+
#ifndef NO_PSK
havePSK = ssl->options.havePSK;
+ #else
+ havePSK = 0;
#endif
#ifdef NO_RSA
haveRSA = 0;
+ #else
+ haveRSA = 1;
#endif
- InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, ssl->options.haveDH,
- ssl->options.haveNTRU, ssl->options.haveECDSAsig,
- ssl->options.haveStaticECC, ssl->options.side);
+ #ifndef NO_CERTS
+ keySz = ssl->buffers.keySz;
+ #endif
+ InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+ ssl->options.haveDH, ssl->options.haveNTRU,
+ ssl->options.haveECDSAsig, ssl->options.haveECC,
+ ssl->options.haveStaticECC, ssl->options.side);
+ }
WOLFSSL_LEAVE("wolfSSL_SetTmpDH", 0);
- return SSL_SUCCESS;
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+#if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
+ !defined(HAVE_SELFTEST)
+/* Enables or disables the session's DH key prime test. */
+int wolfSSL_SetEnableDhKeyTest(WOLFSSL* ssl, int enable)
+{
+ WOLFSSL_ENTER("wolfSSL_SetEnableDhKeyTest");
+
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ if (!enable)
+ ssl->options.dhDoKeyTest = 0;
+ else
+ ssl->options.dhDoKeyTest = 1;
+
+ WOLFSSL_LEAVE("wolfSSL_SetEnableDhKeyTest", WOLFSSL_SUCCESS);
+ return WOLFSSL_SUCCESS;
}
+#endif
+
-/* server ctx Diffie-Hellman parameters, SSL_SUCCESS on ok */
+/* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz,
const unsigned char* g, int gSz)
{
WOLFSSL_ENTER("wolfSSL_CTX_SetTmpDH");
if (ctx == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG;
- if (pSz < ctx->minDhKeySz)
+ if ((word16)pSz < ctx->minDhKeySz)
return DH_KEY_SIZE_E;
+ if ((word16)pSz > ctx->maxDhKeySz)
+ return DH_KEY_SIZE_E;
+
+ #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
+ !defined(HAVE_SELFTEST)
+ {
+ DhKey checkKey;
+ WC_RNG rng;
+ int error, freeKey = 0;
+
+ error = wc_InitRng(&rng);
+ if (!error)
+ error = wc_InitDhKey(&checkKey);
+ if (!error) {
+ freeKey = 1;
+ error = wc_DhSetCheckKey(&checkKey,
+ p, pSz, g, gSz, NULL, 0, 0, &rng);
+ }
+ if (freeKey)
+ wc_FreeDhKey(&checkKey);
+ wc_FreeRng(&rng);
+ if (error)
+ return error;
+
+ ctx->dhKeyTested = 1;
+ }
+ #endif
- XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH);
- XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH);
+ XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ ctx->serverDH_P.buffer = NULL;
+ XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ ctx->serverDH_G.buffer = NULL;
- ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap,DYNAMIC_TYPE_DH);
+ ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if (ctx->serverDH_P.buffer == NULL)
return MEMORY_E;
- ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap,DYNAMIC_TYPE_DH);
+ ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if (ctx->serverDH_G.buffer == NULL) {
- XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH);
+ XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ ctx->serverDH_P.buffer = NULL;
return MEMORY_E;
}
@@ -515,12 +1875,62 @@ int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz,
ctx->haveDH = 1;
WOLFSSL_LEAVE("wolfSSL_CTX_SetTmpDH", 0);
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz)
+{
+ if (ctx == NULL || keySz > 16000 || keySz % 8 != 0)
+ return BAD_FUNC_ARG;
+
+ ctx->minDhKeySz = keySz / 8;
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_SetMinDhKey_Sz(WOLFSSL* ssl, word16 keySz)
+{
+ if (ssl == NULL || keySz > 16000 || keySz % 8 != 0)
+ return BAD_FUNC_ARG;
+
+ ssl->options.minDhKeySz = keySz / 8;
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz)
+{
+ if (ctx == NULL || keySz > 16000 || keySz % 8 != 0)
+ return BAD_FUNC_ARG;
+
+ ctx->maxDhKeySz = keySz / 8;
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_SetMaxDhKey_Sz(WOLFSSL* ssl, word16 keySz)
+{
+ if (ssl == NULL || keySz > 16000 || keySz % 8 != 0)
+ return BAD_FUNC_ARG;
+
+ ssl->options.maxDhKeySz = keySz / 8;
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_GetDhKey_Sz(WOLFSSL* ssl)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ return (ssl->options.dhKeySz * 8);
}
#endif /* !NO_DH */
+WOLFSSL_ABI
int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
{
int ret;
@@ -530,21 +1940,64 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
if (ssl == NULL || data == NULL || sz < 0)
return BAD_FUNC_ARG;
+#ifdef WOLFSSL_EARLY_DATA
+ if (ssl->earlyData != no_early_data && (ret = wolfSSL_negotiate(ssl)) < 0) {
+ ssl->error = ret;
+ return WOLFSSL_FATAL_ERROR;
+ }
+ ssl->earlyData = no_early_data;
+#endif
+
+#ifdef HAVE_WRITE_DUP
+ { /* local variable scope */
+ int dupErr = 0; /* local copy */
+
+ ret = 0;
+
+ if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) {
+ WOLFSSL_MSG("Read dup side cannot write");
+ return WRITE_DUP_WRITE_E;
+ }
+ if (ssl->dupWrite) {
+ if (wc_LockMutex(&ssl->dupWrite->dupMutex) != 0) {
+ return BAD_MUTEX_E;
+ }
+ dupErr = ssl->dupWrite->dupErr;
+ ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex);
+ }
+
+ if (ret != 0) {
+ ssl->error = ret; /* high priority fatal error */
+ return WOLFSSL_FATAL_ERROR;
+ }
+ if (dupErr != 0) {
+ WOLFSSL_MSG("Write dup error from other side");
+ ssl->error = dupErr;
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+#endif
+
#ifdef HAVE_ERRNO_H
errno = 0;
#endif
+ #ifdef OPENSSL_EXTRA
+ if (ssl->CBIS != NULL) {
+ ssl->CBIS(ssl, SSL_CB_WRITE, SSL_SUCCESS);
+ ssl->cbmode = SSL_CB_WRITE;
+ }
+ #endif
ret = SendData(ssl, data, sz);
WOLFSSL_LEAVE("SSL_write()", ret);
if (ret < 0)
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
else
return ret;
}
-
static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek)
{
int ret;
@@ -554,25 +2007,55 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek)
if (ssl == NULL || data == NULL || sz < 0)
return BAD_FUNC_ARG;
+#ifdef HAVE_WRITE_DUP
+ if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) {
+ WOLFSSL_MSG("Write dup side cannot read");
+ return WRITE_DUP_READ_E;
+ }
+#endif
+
#ifdef HAVE_ERRNO_H
errno = 0;
#endif
+
#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls)
+ if (ssl->options.dtls) {
ssl->dtls_expected_rx = max(sz + 100, MAX_MTU);
+#ifdef WOLFSSL_SCTP
+ if (ssl->options.dtlsSctp)
+#endif
+#if defined(WOLLSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)
+ ssl->dtls_expected_rx = max(ssl->dtls_expected_rx, ssl->dtlsMtuSz);
+#endif
+ }
#endif
-#ifdef HAVE_MAX_FRAGMENT
- ret = ReceiveData(ssl, (byte*)data,
- min(sz, min(ssl->max_fragment, OUTPUT_RECORD_SIZE)), peek);
-#else
- ret = ReceiveData(ssl, (byte*)data, min(sz, OUTPUT_RECORD_SIZE), peek);
+ sz = wolfSSL_GetMaxRecordSize(ssl, sz);
+
+ ret = ReceiveData(ssl, (byte*)data, sz, peek);
+
+#ifdef HAVE_WRITE_DUP
+ if (ssl->dupWrite) {
+ if (ssl->error != 0 && ssl->error != WANT_READ
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ && ssl->error != WC_PENDING_E
+ #endif
+ ) {
+ int notifyErr;
+
+ WOLFSSL_MSG("Notifying write side of fatal read error");
+ notifyErr = NotifyWriteSide(ssl, ssl->error);
+ if (notifyErr < 0) {
+ ret = ssl->error = notifyErr;
+ }
+ }
+ }
#endif
WOLFSSL_LEAVE("wolfSSL_read_internal()", ret);
if (ret < 0)
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
else
return ret;
}
@@ -586,58 +2069,106 @@ int wolfSSL_peek(WOLFSSL* ssl, void* data, int sz)
}
+WOLFSSL_ABI
int wolfSSL_read(WOLFSSL* ssl, void* data, int sz)
{
WOLFSSL_ENTER("wolfSSL_read()");
+ #ifdef OPENSSL_EXTRA
+ if (ssl->CBIS != NULL) {
+ ssl->CBIS(ssl, SSL_CB_READ, SSL_SUCCESS);
+ ssl->cbmode = SSL_CB_READ;
+ }
+ #endif
return wolfSSL_read_internal(ssl, data, sz, FALSE);
}
-#ifdef HAVE_CAVIUM
+#ifdef WOLFSSL_MULTICAST
+
+int wolfSSL_mcast_read(WOLFSSL* ssl, word16* id, void* data, int sz)
+{
+ int ret = 0;
+
+ WOLFSSL_ENTER("wolfSSL_mcast_read()");
+
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ ret = wolfSSL_read_internal(ssl, data, sz, FALSE);
+ if (ssl->options.dtls && ssl->options.haveMcast && id != NULL)
+ *id = ssl->keys.curPeerId;
+ return ret;
+}
+
+#endif /* WOLFSSL_MULTICAST */
+
-/* let's use cavium, SSL_SUCCESS on ok */
-int wolfSSL_UseCavium(WOLFSSL* ssl, int devId)
+/* helpers to set the device id, WOLFSSL_SUCCESS on ok */
+WOLFSSL_ABI
+int wolfSSL_SetDevId(WOLFSSL* ssl, int devId)
{
if (ssl == NULL)
return BAD_FUNC_ARG;
ssl->devId = devId;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
-
-/* let's use cavium, SSL_SUCCESS on ok */
-int wolfSSL_CTX_UseCavium(WOLFSSL_CTX* ctx, int devId)
+WOLFSSL_ABI
+int wolfSSL_CTX_SetDevId(WOLFSSL_CTX* ctx, int devId)
{
if (ctx == NULL)
return BAD_FUNC_ARG;
ctx->devId = devId;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
+/* helpers to get device id and heap */
+WOLFSSL_ABI
+int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
+{
+ int devId = INVALID_DEVID;
+ if (ctx != NULL)
+ devId = ctx->devId;
+ else if (ssl != NULL)
+ devId = ssl->devId;
+ return devId;
+}
+void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
+{
+ void* heap = NULL;
+ if (ctx != NULL)
+ heap = ctx->heap;
+ else if (ssl != NULL)
+ heap = ssl->heap;
+ return heap;
+}
-#endif /* HAVE_CAVIUM */
#ifdef HAVE_SNI
+WOLFSSL_ABI
int wolfSSL_UseSNI(WOLFSSL* ssl, byte type, const void* data, word16 size)
{
if (ssl == NULL)
return BAD_FUNC_ARG;
- return TLSX_UseSNI(&ssl->extensions, type, data, size);
+ return TLSX_UseSNI(&ssl->extensions, type, data, size, ssl->heap);
}
-int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, byte type, const void* data, word16 size)
+
+WOLFSSL_ABI
+int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, byte type, const void* data,
+ word16 size)
{
if (ctx == NULL)
return BAD_FUNC_ARG;
- return TLSX_UseSNI(&ctx->extensions, type, data, size);
+ return TLSX_UseSNI(&ctx->extensions, type, data, size, ctx->heap);
}
#ifndef NO_WOLFSSL_SERVER
@@ -648,17 +2179,20 @@ void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, byte type, byte options)
TLSX_SNI_SetOptions(ssl->extensions, type, options);
}
+
void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx, byte type, byte options)
{
if (ctx && ctx->extensions)
TLSX_SNI_SetOptions(ctx->extensions, type, options);
}
+
byte wolfSSL_SNI_Status(WOLFSSL* ssl, byte type)
{
return TLSX_SNI_Status(ssl ? ssl->extensions : NULL, type);
}
+
word16 wolfSSL_SNI_GetRequest(WOLFSSL* ssl, byte type, void** data)
{
if (data)
@@ -670,8 +2204,9 @@ word16 wolfSSL_SNI_GetRequest(WOLFSSL* ssl, byte type, void** data)
return 0;
}
-int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, byte type,
- byte* sni, word32* inOutSz)
+
+int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
+ byte type, byte* sni, word32* inOutSz)
{
if (clientHello && helloSz > 0 && sni && inOutSz && *inOutSz > 0)
return TLSX_SNI_GetFromBuffer(clientHello, helloSz, type, sni, inOutSz);
@@ -684,49 +2219,155 @@ int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, byte type
#endif /* HAVE_SNI */
+#ifdef HAVE_TRUSTED_CA
+
+WOLFSSL_API int wolfSSL_UseTrustedCA(WOLFSSL* ssl, byte type,
+ const byte* certId, word32 certIdSz)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ if (type == WOLFSSL_TRUSTED_CA_PRE_AGREED) {
+ if (certId != NULL || certIdSz != 0)
+ return BAD_FUNC_ARG;
+ }
+ else if (type == WOLFSSL_TRUSTED_CA_X509_NAME) {
+ if (certId == NULL || certIdSz == 0)
+ return BAD_FUNC_ARG;
+ }
+ #ifndef NO_SHA
+ else if (type == WOLFSSL_TRUSTED_CA_KEY_SHA1 ||
+ type == WOLFSSL_TRUSTED_CA_CERT_SHA1) {
+ if (certId == NULL || certIdSz != WC_SHA_DIGEST_SIZE)
+ return BAD_FUNC_ARG;
+ }
+ #endif
+ else
+ return BAD_FUNC_ARG;
+
+ return TLSX_UseTrustedCA(&ssl->extensions,
+ type, certId, certIdSz, ssl->heap);
+}
+
+#endif /* HAVE_TRUSTED_CA */
+
+
#ifdef HAVE_MAX_FRAGMENT
#ifndef NO_WOLFSSL_CLIENT
+
int wolfSSL_UseMaxFragment(WOLFSSL* ssl, byte mfl)
{
if (ssl == NULL)
return BAD_FUNC_ARG;
- return TLSX_UseMaxFragment(&ssl->extensions, mfl);
+#ifdef WOLFSSL_ALLOW_MAX_FRAGMENT_ADJUST
+ /* The following is a non-standard way to reconfigure the max packet size
+ post-handshake for wolfSSL_write/woflSSL_read */
+ if (ssl->options.handShakeState == HANDSHAKE_DONE) {
+ switch (mfl) {
+ case WOLFSSL_MFL_2_8 : ssl->max_fragment = 256; break;
+ case WOLFSSL_MFL_2_9 : ssl->max_fragment = 512; break;
+ case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break;
+ case WOLFSSL_MFL_2_11: ssl->max_fragment = 2048; break;
+ case WOLFSSL_MFL_2_12: ssl->max_fragment = 4096; break;
+ case WOLFSSL_MFL_2_13: ssl->max_fragment = 8192; break;
+ default: ssl->max_fragment = MAX_RECORD_SIZE; break;
+ }
+ return WOLFSSL_SUCCESS;
+ }
+#endif /* WOLFSSL_MAX_FRAGMENT_ADJUST */
+
+ /* This call sets the max fragment TLS extension, which gets sent to server.
+ The server_hello response is what sets the `ssl->max_fragment` in
+ TLSX_MFL_Parse */
+ return TLSX_UseMaxFragment(&ssl->extensions, mfl, ssl->heap);
}
+
int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, byte mfl)
{
if (ctx == NULL)
return BAD_FUNC_ARG;
- return TLSX_UseMaxFragment(&ctx->extensions, mfl);
+ return TLSX_UseMaxFragment(&ctx->extensions, mfl, ctx->heap);
}
+
#endif /* NO_WOLFSSL_CLIENT */
#endif /* HAVE_MAX_FRAGMENT */
#ifdef HAVE_TRUNCATED_HMAC
#ifndef NO_WOLFSSL_CLIENT
+
int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl)
{
if (ssl == NULL)
return BAD_FUNC_ARG;
- return TLSX_UseTruncatedHMAC(&ssl->extensions);
+ return TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap);
}
+
int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx)
{
if (ctx == NULL)
return BAD_FUNC_ARG;
- return TLSX_UseTruncatedHMAC(&ctx->extensions);
+ return TLSX_UseTruncatedHMAC(&ctx->extensions, ctx->heap);
}
+
#endif /* NO_WOLFSSL_CLIENT */
#endif /* HAVE_TRUNCATED_HMAC */
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+
+int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, byte status_type, byte options)
+{
+ if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
+ return BAD_FUNC_ARG;
+
+ return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type,
+ options, NULL, ssl->heap, ssl->devId);
+}
+
+
+int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, byte status_type,
+ byte options)
+{
+ if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
+ return BAD_FUNC_ARG;
+
+ return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type,
+ options, NULL, ctx->heap, ctx->devId);
+}
+
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+
+int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, byte status_type, byte options)
+{
+ if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
+ return BAD_FUNC_ARG;
+
+ return TLSX_UseCertificateStatusRequestV2(&ssl->extensions, status_type,
+ options, ssl->heap, ssl->devId);
+}
+
+
+int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, byte status_type,
+ byte options)
+{
+ if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
+ return BAD_FUNC_ARG;
+
+ return TLSX_UseCertificateStatusRequestV2(&ctx->extensions, status_type,
+ options, ctx->heap, ctx->devId);
+}
+
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+
/* Elliptic Curves */
-#ifdef HAVE_SUPPORTED_CURVES
-#ifndef NO_WOLFSSL_CLIENT
+#if defined(HAVE_SUPPORTED_CURVES) && !defined(NO_WOLFSSL_CLIENT)
int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name)
{
@@ -734,44 +2375,238 @@ int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name)
return BAD_FUNC_ARG;
switch (name) {
+ case WOLFSSL_ECC_SECP160K1:
case WOLFSSL_ECC_SECP160R1:
+ case WOLFSSL_ECC_SECP160R2:
+ case WOLFSSL_ECC_SECP192K1:
case WOLFSSL_ECC_SECP192R1:
+ case WOLFSSL_ECC_SECP224K1:
case WOLFSSL_ECC_SECP224R1:
+ case WOLFSSL_ECC_SECP256K1:
case WOLFSSL_ECC_SECP256R1:
case WOLFSSL_ECC_SECP384R1:
case WOLFSSL_ECC_SECP521R1:
+ case WOLFSSL_ECC_BRAINPOOLP256R1:
+ case WOLFSSL_ECC_BRAINPOOLP384R1:
+ case WOLFSSL_ECC_BRAINPOOLP512R1:
+ case WOLFSSL_ECC_X25519:
+ case WOLFSSL_ECC_X448:
+
+ case WOLFSSL_FFDHE_2048:
+ case WOLFSSL_FFDHE_3072:
+ case WOLFSSL_FFDHE_4096:
+ case WOLFSSL_FFDHE_6144:
+ case WOLFSSL_FFDHE_8192:
break;
default:
return BAD_FUNC_ARG;
}
- return TLSX_UseSupportedCurve(&ssl->extensions, name);
+ ssl->options.userCurves = 1;
+
+ return TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap);
}
+
int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name)
{
if (ctx == NULL)
return BAD_FUNC_ARG;
switch (name) {
+ case WOLFSSL_ECC_SECP160K1:
case WOLFSSL_ECC_SECP160R1:
+ case WOLFSSL_ECC_SECP160R2:
+ case WOLFSSL_ECC_SECP192K1:
case WOLFSSL_ECC_SECP192R1:
+ case WOLFSSL_ECC_SECP224K1:
case WOLFSSL_ECC_SECP224R1:
+ case WOLFSSL_ECC_SECP256K1:
case WOLFSSL_ECC_SECP256R1:
case WOLFSSL_ECC_SECP384R1:
case WOLFSSL_ECC_SECP521R1:
+ case WOLFSSL_ECC_BRAINPOOLP256R1:
+ case WOLFSSL_ECC_BRAINPOOLP384R1:
+ case WOLFSSL_ECC_BRAINPOOLP512R1:
+ case WOLFSSL_ECC_X25519:
+ case WOLFSSL_ECC_X448:
+ case WOLFSSL_FFDHE_2048:
+ case WOLFSSL_FFDHE_3072:
+ case WOLFSSL_FFDHE_4096:
+ case WOLFSSL_FFDHE_6144:
+ case WOLFSSL_FFDHE_8192:
break;
default:
return BAD_FUNC_ARG;
}
- return TLSX_UseSupportedCurve(&ctx->extensions, name);
+ ctx->userCurves = 1;
+
+ return TLSX_UseSupportedCurve(&ctx->extensions, name, ctx->heap);
+}
+
+#endif /* HAVE_SUPPORTED_CURVES && !NO_WOLFSSL_CLIENT */
+
+/* QSH quantum safe handshake */
+#ifdef HAVE_QSH
+/* returns 1 if QSH has been used 0 otherwise */
+int wolfSSL_isQSH(WOLFSSL* ssl)
+{
+ /* if no ssl struct than QSH was not used */
+ if (ssl == NULL)
+ return 0;
+
+ return ssl->isQSH;
}
+
+int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, word16 name)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ switch (name) {
+ #ifdef HAVE_NTRU
+ case WOLFSSL_NTRU_EESS439:
+ case WOLFSSL_NTRU_EESS593:
+ case WOLFSSL_NTRU_EESS743:
+ break;
+ #endif
+ default:
+ return BAD_FUNC_ARG;
+ }
+
+ ssl->user_set_QSHSchemes = 1;
+
+ return TLSX_UseQSHScheme(&ssl->extensions, name, NULL, 0, ssl->heap);
+}
+
+#ifndef NO_WOLFSSL_CLIENT
+ /* user control over sending client public key in hello
+ when flag = 1 will send keys if flag is 0 or function is not called
+ then will not send keys in the hello extension
+ return 0 on success
+ */
+ int wolfSSL_UseClientQSHKeys(WOLFSSL* ssl, unsigned char flag)
+ {
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ ssl->sendQSHKeys = flag;
+
+ return 0;
+ }
#endif /* NO_WOLFSSL_CLIENT */
-#endif /* HAVE_SUPPORTED_CURVES */
+#endif /* HAVE_QSH */
+
+/* Application-Layer Protocol Negotiation */
+#ifdef HAVE_ALPN
+
+WOLFSSL_ABI
+int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
+ word32 protocol_name_listSz, byte options)
+{
+ char *list, *ptr, *token[WOLFSSL_MAX_ALPN_NUMBER]={NULL};
+ word16 len;
+ int idx = 0;
+ int ret = WOLFSSL_FAILURE;
+
+ WOLFSSL_ENTER("wolfSSL_UseALPN");
+
+ if (ssl == NULL || protocol_name_list == NULL)
+ return BAD_FUNC_ARG;
+
+ if (protocol_name_listSz > (WOLFSSL_MAX_ALPN_NUMBER *
+ WOLFSSL_MAX_ALPN_PROTO_NAME_LEN +
+ WOLFSSL_MAX_ALPN_NUMBER)) {
+ WOLFSSL_MSG("Invalid arguments, protocol name list too long");
+ return BAD_FUNC_ARG;
+ }
+
+ if (!(options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) &&
+ !(options & WOLFSSL_ALPN_FAILED_ON_MISMATCH)) {
+ WOLFSSL_MSG("Invalid arguments, options not supported");
+ return BAD_FUNC_ARG;
+ }
+
+
+ list = (char *)XMALLOC(protocol_name_listSz+1, ssl->heap,
+ DYNAMIC_TYPE_ALPN);
+ if (list == NULL) {
+ WOLFSSL_MSG("Memory failure");
+ return MEMORY_ERROR;
+ }
+
+ XSTRNCPY(list, protocol_name_list, protocol_name_listSz);
+ list[protocol_name_listSz] = '\0';
+
+ /* read all protocol name from the list */
+ token[idx] = XSTRTOK(list, ",", &ptr);
+ while (idx < WOLFSSL_MAX_ALPN_NUMBER && token[idx] != NULL)
+ token[++idx] = XSTRTOK(NULL, ",", &ptr);
+
+ /* add protocol name list in the TLS extension in reverse order */
+ while ((idx--) > 0) {
+ len = (word16)XSTRLEN(token[idx]);
+
+ ret = TLSX_UseALPN(&ssl->extensions, token[idx], len, options,
+ ssl->heap);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("TLSX_UseALPN failure");
+ break;
+ }
+ }
+
+ XFREE(list, ssl->heap, DYNAMIC_TYPE_ALPN);
+
+ return ret;
+}
+
+int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name, word16 *size)
+{
+ return TLSX_ALPN_GetRequest(ssl ? ssl->extensions : NULL,
+ (void **)protocol_name, size);
+}
+
+int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, word16 *listSz)
+{
+ if (list == NULL || listSz == NULL)
+ return BAD_FUNC_ARG;
+
+ if (ssl->alpn_client_list == NULL)
+ return BUFFER_ERROR;
+
+ *listSz = (word16)XSTRLEN(ssl->alpn_client_list);
+ if (*listSz == 0)
+ return BUFFER_ERROR;
+
+ *list = (char *)XMALLOC((*listSz)+1, ssl->heap, DYNAMIC_TYPE_TLSX);
+ if (*list == NULL)
+ return MEMORY_ERROR;
+
+ XSTRNCPY(*list, ssl->alpn_client_list, (*listSz)+1);
+ (*list)[*listSz] = 0;
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+/* used to free memory allocated by wolfSSL_ALPN_GetPeerProtocol */
+int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list)
+{
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ XFREE(*list, ssl->heap, DYNAMIC_TYPE_TLSX);
+ *list = NULL;
+
+ return WOLFSSL_SUCCESS;
+}
+
+#endif /* HAVE_ALPN */
/* Secure Renegotiation */
#ifdef HAVE_SECURE_RENEGOTIATION
@@ -782,11 +2617,11 @@ int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl)
int ret = BAD_FUNC_ARG;
if (ssl)
- ret = TLSX_UseSecureRenegotiation(&ssl->extensions);
+ ret = TLSX_UseSecureRenegotiation(&ssl->extensions, ssl->heap);
+
+ if (ret == WOLFSSL_SUCCESS) {
+ TLSX* extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO);
- if (ret == SSL_SUCCESS) {
- TLSX* extension = TLSX_Find(ssl->extensions, SECURE_RENEGOTIATION);
-
if (extension)
ssl->secure_renegotiation = (SecureRenegotiation*)extension->data;
}
@@ -794,9 +2629,18 @@ int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl)
return ret;
}
+int wolfSSL_CTX_UseSecureRenegotiation(WOLFSSL_CTX* ctx)
+{
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ ctx->useSecureReneg = 1;
+ return WOLFSSL_SUCCESS;
+}
+
/* do a secure renegotiation handshake, user forced, we discourage */
-int wolfSSL_Rehandshake(WOLFSSL* ssl)
+static int _Rehandshake(WOLFSSL* ssl)
{
int ret;
@@ -813,67 +2657,120 @@ int wolfSSL_Rehandshake(WOLFSSL* ssl)
return SECURE_RENEGOTIATION_E;
}
- if (ssl->options.handShakeState != HANDSHAKE_DONE) {
- WOLFSSL_MSG("Can't renegotiate until previous handshake complete");
- return SECURE_RENEGOTIATION_E;
- }
+ /* If the client started the renegotiation, the server will already
+ * have processed the client's hello. */
+ if (ssl->options.side != WOLFSSL_SERVER_END ||
+ ssl->options.acceptState != ACCEPT_FIRST_REPLY_DONE) {
+
+ if (ssl->options.handShakeState != HANDSHAKE_DONE) {
+ WOLFSSL_MSG("Can't renegotiate until previous handshake complete");
+ return SECURE_RENEGOTIATION_E;
+ }
#ifndef NO_FORCE_SCR_SAME_SUITE
- /* force same suite */
- if (ssl->suites) {
- ssl->suites->suiteSz = SUITE_LEN;
- ssl->suites->suites[0] = ssl->options.cipherSuite0;
- ssl->suites->suites[1] = ssl->options.cipherSuite;
- }
+ /* force same suite */
+ if (ssl->suites) {
+ ssl->suites->suiteSz = SUITE_LEN;
+ ssl->suites->suites[0] = ssl->options.cipherSuite0;
+ ssl->suites->suites[1] = ssl->options.cipherSuite;
+ }
#endif
- /* reset handshake states */
- ssl->options.serverState = NULL_STATE;
- ssl->options.clientState = NULL_STATE;
- ssl->options.connectState = CONNECT_BEGIN;
- ssl->options.acceptState = ACCEPT_BEGIN;
- ssl->options.handShakeState = NULL_STATE;
- ssl->options.processReply = 0; /* TODO, move states in internal.h */
+ /* reset handshake states */
+ ssl->options.sendVerify = 0;
+ ssl->options.serverState = NULL_STATE;
+ ssl->options.clientState = NULL_STATE;
+ ssl->options.connectState = CONNECT_BEGIN;
+ ssl->options.acceptState = ACCEPT_BEGIN_RENEG;
+ ssl->options.handShakeState = NULL_STATE;
+ ssl->options.processReply = 0; /* TODO, move states in internal.h */
+
+ XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
+
+ ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED;
+
+#if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SERVER_RENEGOTIATION_INFO)
+ if (ssl->options.side == WOLFSSL_SERVER_END) {
+ ret = SendHelloRequest(ssl);
+ if (ret != 0) {
+ ssl->error = ret;
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+#endif /* NO_WOLFSSL_SERVER && HAVE_SERVER_RENEGOTIATION_INFO */
- XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
+ ret = InitHandshakeHashes(ssl);
+ if (ret != 0) {
+ ssl->error = ret;
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+ ret = wolfSSL_negotiate(ssl);
+ ssl->secure_rene_count++;
+ return ret;
+}
- ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED;
-#ifndef NO_OLD_TLS
-#ifndef NO_MD5
- wc_InitMd5(&ssl->hsHashes->hashMd5);
-#endif
-#ifndef NO_SHA
- ret = wc_InitSha(&ssl->hsHashes->hashSha);
- if (ret !=0)
- return ret;
-#endif
-#endif /* NO_OLD_TLS */
-#ifndef NO_SHA256
- ret = wc_InitSha256(&ssl->hsHashes->hashSha256);
- if (ret !=0)
- return ret;
-#endif
-#ifdef WOLFSSL_SHA384
- ret = wc_InitSha384(&ssl->hsHashes->hashSha384);
- if (ret !=0)
- return ret;
-#endif
-#ifdef WOLFSSL_SHA512
- ret = wc_InitSha512(&ssl->hsHashes->hashSha512);
- if (ret !=0)
- return ret;
-#endif
+/* do a secure renegotiation handshake, user forced, we discourage */
+int wolfSSL_Rehandshake(WOLFSSL* ssl)
+{
+ int ret = WOLFSSL_SUCCESS;
+ WOLFSSL_ENTER("wolfSSL_Rehandshake");
+
+ if (ssl->options.side == WOLFSSL_SERVER_END) {
+ /* Reset option to send certificate verify. */
+ ssl->options.sendVerify = 0;
+ }
+ else {
+ /* Reset resuming flag to do full secure handshake. */
+ ssl->options.resuming = 0;
+ #ifdef HAVE_SESSION_TICKET
+ /* Clearing the ticket. */
+ ret = wolfSSL_UseSessionTicket(ssl);
+ #endif
+ }
+
+ if (ret == WOLFSSL_SUCCESS)
+ ret = _Rehandshake(ssl);
- ret = wolfSSL_negotiate(ssl);
return ret;
}
+
+#ifndef NO_WOLFSSL_CLIENT
+
+/* do a secure resumption handshake, user forced, we discourage */
+int wolfSSL_SecureResume(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_SecureResume");
+
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ if (ssl->options.side == WOLFSSL_SERVER_END) {
+ ssl->error = SIDE_ERROR;
+ return SSL_FATAL_ERROR;
+ }
+
+ return _Rehandshake(ssl);
+}
+
+#endif /* NO_WOLFSSL_CLIENT */
+
+long wolfSSL_SSL_get_secure_renegotiation_support(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_SSL_get_secure_renegotiation_support");
+
+ if (!ssl || !ssl->secure_renegotiation)
+ return WOLFSSL_FAILURE;
+ return ssl->secure_renegotiation->enabled;
+}
+
#endif /* HAVE_SECURE_RENEGOTIATION */
/* Session Ticket */
#if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SESSION_TICKET)
-/* SSL_SUCCESS on ok */
+/* WOLFSSL_SUCCESS on ok */
int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx, SessionTicketEncCb cb)
{
if (ctx == NULL)
@@ -881,10 +2778,10 @@ int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx, SessionTicketEncCb cb)
ctx->ticketEncCb = cb;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
-/* set hint interval, SSL_SUCCESS on ok */
+/* set hint interval, WOLFSSL_SUCCESS on ok */
int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int hint)
{
if (ctx == NULL)
@@ -892,10 +2789,10 @@ int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int hint)
ctx->ticketHint = hint;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
-/* set user context, SSL_SUCCESS on ok */
+/* set user context, WOLFSSL_SUCCESS on ok */
int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void* userCtx)
{
if (ctx == NULL)
@@ -903,7 +2800,7 @@ int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void* userCtx)
ctx->ticketEncCtx = userCtx;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
#endif /* !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET) */
@@ -915,7 +2812,7 @@ int wolfSSL_UseSessionTicket(WOLFSSL* ssl)
if (ssl == NULL)
return BAD_FUNC_ARG;
- return TLSX_UseSessionTicket(&ssl->extensions, NULL);
+ return TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
}
int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx)
@@ -923,10 +2820,11 @@ int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx)
if (ctx == NULL)
return BAD_FUNC_ARG;
- return TLSX_UseSessionTicket(&ctx->extensions, NULL);
+ return TLSX_UseSessionTicket(&ctx->extensions, NULL, ctx->heap);
}
-WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl, byte* buf, word32* bufSz)
+WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl,
+ byte* buf, word32* bufSz)
{
if (ssl == NULL || buf == NULL || bufSz == NULL || *bufSz == 0)
return BAD_FUNC_ARG;
@@ -938,19 +2836,43 @@ WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl, byte* buf, word32* bufSz
else
*bufSz = 0;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
-WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, byte* buf, word32 bufSz)
+WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf,
+ word32 bufSz)
{
if (ssl == NULL || (buf == NULL && bufSz > 0))
return BAD_FUNC_ARG;
- if (bufSz > 0)
+ if (bufSz > 0) {
+ /* Ticket will fit into static ticket */
+ if(bufSz <= SESSION_TICKET_LEN) {
+ if (ssl->session.isDynamic) {
+ XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+ ssl->session.isDynamic = 0;
+ ssl->session.ticket = ssl->session.staticTicket;
+ }
+ } else { /* Ticket requires dynamic ticket storage */
+ if (ssl->session.ticketLen < bufSz) { /* is dyn buffer big enough */
+ if(ssl->session.isDynamic)
+ XFREE(ssl->session.ticket, ssl->heap,
+ DYNAMIC_TYPE_SESSION_TICK);
+ ssl->session.ticket = (byte*)XMALLOC(bufSz, ssl->heap,
+ DYNAMIC_TYPE_SESSION_TICK);
+ if(!ssl->session.ticket) {
+ ssl->session.ticket = ssl->session.staticTicket;
+ ssl->session.isDynamic = 0;
+ return MEMORY_ERROR;
+ }
+ ssl->session.isDynamic = 1;
+ }
+ }
XMEMCPY(ssl->session.ticket, buf, bufSz);
+ }
ssl->session.ticketLen = (word16)bufSz;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
@@ -963,10 +2885,39 @@ WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL* ssl,
ssl->session_ticket_cb = cb;
ssl->session_ticket_ctx = ctx;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
+}
+#endif
+
+
+#ifdef HAVE_EXTENDED_MASTER
+#ifndef NO_WOLFSSL_CLIENT
+
+int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx)
+{
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ ctx->haveEMS = 0;
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ ssl->options.haveEMS = 0;
+
+ return WOLFSSL_SUCCESS;
}
+
+#endif
#endif
+
#ifndef WOLFSSL_LEANPSK
int wolfSSL_send(WOLFSSL* ssl, const void* data, int sz, int flags)
@@ -1014,50 +2965,72 @@ int wolfSSL_recv(WOLFSSL* ssl, void* data, int sz, int flags)
#endif
-/* SSL_SUCCESS on ok */
+/* WOLFSSL_SUCCESS on ok */
+WOLFSSL_ABI
int wolfSSL_shutdown(WOLFSSL* ssl)
{
- int ret = SSL_FATAL_ERROR;
- byte tmp;
+ int ret = WOLFSSL_FATAL_ERROR;
WOLFSSL_ENTER("SSL_shutdown()");
if (ssl == NULL)
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
if (ssl->options.quietShutdown) {
WOLFSSL_MSG("quiet shutdown, no close notify sent");
- return SSL_SUCCESS;
+ ret = WOLFSSL_SUCCESS;
}
+ else {
+ /* try to send close notify, not an error if can't */
+ if (!ssl->options.isClosed && !ssl->options.connReset &&
+ !ssl->options.sentNotify) {
+ ssl->error = SendAlert(ssl, alert_warning, close_notify);
+ if (ssl->error < 0) {
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ ssl->options.sentNotify = 1; /* don't send close_notify twice */
+ if (ssl->options.closeNotify)
+ ret = WOLFSSL_SUCCESS;
+ else {
+ ret = WOLFSSL_SHUTDOWN_NOT_DONE;
+ WOLFSSL_LEAVE("SSL_shutdown()", ret);
+ return ret;
+ }
+ }
- /* try to send close notify, not an error if can't */
- if (!ssl->options.isClosed && !ssl->options.connReset &&
- !ssl->options.sentNotify) {
- ssl->error = SendAlert(ssl, alert_warning, close_notify);
- if (ssl->error < 0) {
- WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+#ifdef WOLFSSL_SHUTDOWNONCE
+ if (ssl->options.isClosed || ssl->options.connReset) {
+ /* Shutdown has already occurred.
+ * Caller is free to ignore this error. */
+ return SSL_SHUTDOWN_ALREADY_DONE_E;
}
- ssl->options.sentNotify = 1; /* don't send close_notify twice */
- if (ssl->options.closeNotify)
- ret = SSL_SUCCESS;
- else
- ret = SSL_SHUTDOWN_NOT_DONE;
+#endif
- WOLFSSL_LEAVE("SSL_shutdown()", ret);
- return ret;
+ /* call wolfSSL_shutdown again for bidirectional shutdown */
+ if (ssl->options.sentNotify && !ssl->options.closeNotify) {
+ ret = ProcessReply(ssl);
+ if (ret == ZERO_RETURN) {
+ /* simulate OpenSSL behavior */
+ ssl->error = WOLFSSL_ERROR_SYSCALL;
+ ret = WOLFSSL_SUCCESS;
+ } else if (ssl->error == WOLFSSL_ERROR_NONE) {
+ ret = WOLFSSL_SHUTDOWN_NOT_DONE;
+ } else {
+ WOLFSSL_ERROR(ssl->error);
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
}
- /* call wolfSSL_shutdown again for bidirectional shudown */
- if (ssl->options.sentNotify && !ssl->options.closeNotify) {
- ret = wolfSSL_read(ssl, &tmp, 0);
- if (ret < 0) {
- WOLFSSL_ERROR(ssl->error);
- ret = SSL_FATAL_ERROR;
- } else if (ssl->options.closeNotify) {
- ssl->error = SSL_ERROR_SYSCALL; /* simulate OpenSSL behavior */
- ret = SSL_SUCCESS;
+#ifdef OPENSSL_EXTRA
+ /* reset WOLFSSL structure state for possible re-use */
+ if (ret == WOLFSSL_SUCCESS) {
+ if (wolfSSL_clear(ssl) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("could not clear WOLFSSL");
+ ret = WOLFSSL_FATAL_ERROR;
}
}
+#endif
WOLFSSL_LEAVE("SSL_shutdown()", ret);
@@ -1065,12 +3038,24 @@ int wolfSSL_shutdown(WOLFSSL* ssl)
}
+/* get current error state value */
+int wolfSSL_state(WOLFSSL* ssl)
+{
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ return ssl->error;
+}
+
+
+WOLFSSL_ABI
int wolfSSL_get_error(WOLFSSL* ssl, int ret)
{
WOLFSSL_ENTER("SSL_get_error");
if (ret > 0)
- return SSL_ERROR_NONE;
+ return WOLFSSL_ERROR_NONE;
if (ssl == NULL)
return BAD_FUNC_ARG;
@@ -1078,24 +3063,38 @@ int wolfSSL_get_error(WOLFSSL* ssl, int ret)
/* make sure converted types are handled in SetErrorString() too */
if (ssl->error == WANT_READ)
- return SSL_ERROR_WANT_READ; /* convert to OpenSSL type */
+ return WOLFSSL_ERROR_WANT_READ; /* convert to OpenSSL type */
else if (ssl->error == WANT_WRITE)
- return SSL_ERROR_WANT_WRITE; /* convert to OpenSSL type */
+ return WOLFSSL_ERROR_WANT_WRITE; /* convert to OpenSSL type */
else if (ssl->error == ZERO_RETURN)
- return SSL_ERROR_ZERO_RETURN; /* convert to OpenSSL type */
+ return WOLFSSL_ERROR_ZERO_RETURN; /* convert to OpenSSL type */
return ssl->error;
}
-/* retrive alert history, SSL_SUCCESS on ok */
+/* retrieve alert history, WOLFSSL_SUCCESS on ok */
int wolfSSL_get_alert_history(WOLFSSL* ssl, WOLFSSL_ALERT_HISTORY *h)
{
if (ssl && h) {
*h = ssl->alert_history;
}
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
+#ifdef OPENSSL_EXTRA
+/* returns SSL_WRITING, SSL_READING or SSL_NOTHING */
+int wolfSSL_want(WOLFSSL* ssl)
+{
+ int rw_state = SSL_NOTHING;
+ if (ssl) {
+ if (ssl->error == WANT_READ)
+ rw_state = SSL_READING;
+ else if (ssl->error == WANT_WRITE)
+ rw_state = SSL_WRITING;
+ }
+ return rw_state;
+}
+#endif
/* return TRUE if current error is want read */
int wolfSSL_want_read(WOLFSSL* ssl)
@@ -1121,7 +3120,7 @@ int wolfSSL_want_write(WOLFSSL* ssl)
char* wolfSSL_ERR_error_string(unsigned long errNumber, char* data)
{
- static const char* msg = "Please supply a buffer for error string";
+ static wcchar msg = "Please supply a buffer for error string";
WOLFSSL_ENTER("ERR_error_string");
if (data) {
@@ -1168,9 +3167,70 @@ void wolfSSL_FreeArrays(WOLFSSL* ssl)
}
}
+/* Set option to indicate that the resources are not to be freed after
+ * handshake.
+ *
+ * ssl The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
+ */
+int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ ssl->options.keepResources = 1;
+
+ return 0;
+}
+
+/* Free the handshake resources after handshake.
+ *
+ * ssl The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
+ */
+int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ FreeHandshakeResources(ssl);
+
+ return 0;
+}
+
+/* Use the client's order of preference when matching cipher suites.
+ *
+ * ssl The SSL/TLS context object.
+ * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
+ */
+int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx)
+{
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ ctx->useClientOrder = 1;
+
+ return 0;
+}
+
+/* Use the client's order of preference when matching cipher suites.
+ *
+ * ssl The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
+ */
+int wolfSSL_UseClientSuites(WOLFSSL* ssl)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ ssl->options.useClientOrder = 1;
+
+ return 0;
+}
const byte* wolfSSL_GetMacSecret(WOLFSSL* ssl, int verify)
{
+#ifndef WOLFSSL_AEAD_ONLY
if (ssl == NULL)
return NULL;
@@ -1179,6 +3239,12 @@ const byte* wolfSSL_GetMacSecret(WOLFSSL* ssl, int verify)
return ssl->keys.client_write_MAC_secret;
else
return ssl->keys.server_write_MAC_secret;
+#else
+ (void)ssl;
+ (void)verify;
+
+ return NULL;
+#endif
}
@@ -1229,6 +3295,86 @@ void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl)
return NULL;
}
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+/**
+ * Set the callback, against the context, that encrypts then MACs.
+ *
+ * ctx SSL/TLS context.
+ * cb Callback function to use with Encrypt-Then-MAC.
+ */
+void wolfSSL_CTX_SetEncryptMacCb(WOLFSSL_CTX* ctx, CallbackEncryptMac cb)
+{
+ if (ctx)
+ ctx->EncryptMacCb = cb;
+}
+
+/**
+ * Set the context to use with callback that encrypts then MACs.
+ *
+ * ssl SSL/TLS object.
+ * ctx Callback function's context.
+ */
+void wolfSSL_SetEncryptMacCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->EncryptMacCtx = ctx;
+}
+
+/**
+ * Get the context being used with callback that encrypts then MACs.
+ *
+ * ssl SSL/TLS object.
+ * returns callback function's context or NULL if SSL/TLS object is NULL.
+ */
+void* wolfSSL_GetEncryptMacCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->EncryptMacCtx;
+
+ return NULL;
+}
+
+
+/**
+ * Set the callback, against the context, that MAC verifies then decrypts.
+ *
+ * ctx SSL/TLS context.
+ * cb Callback function to use with Encrypt-Then-MAC.
+ */
+void wolfSSL_CTX_SetVerifyDecryptCb(WOLFSSL_CTX* ctx, CallbackVerifyDecrypt cb)
+{
+ if (ctx)
+ ctx->VerifyDecryptCb = cb;
+}
+
+/**
+ * Set the context to use with callback that MAC verifies then decrypts.
+ *
+ * ssl SSL/TLS object.
+ * ctx Callback function's context.
+ */
+void wolfSSL_SetVerifyDecryptCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->VerifyDecryptCtx = ctx;
+}
+
+/**
+ * Get the context being used with callback that MAC verifies then decrypts.
+ *
+ * ssl SSL/TLS object.
+ * returns callback function's context or NULL if SSL/TLS object is NULL.
+ */
+void* wolfSSL_GetVerifyDecryptCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->VerifyDecryptCtx;
+
+ return NULL;
+}
+#endif /* HAVE_ENCRYPT_THEN_MAC !WOLFSSL_AEAD_ONLY */
+
+
const byte* wolfSSL_GetClientWriteKey(WOLFSSL* ssl)
{
@@ -1265,7 +3411,6 @@ const byte* wolfSSL_GetServerWriteIV(WOLFSSL* ssl)
return NULL;
}
-
int wolfSSL_GetKeySize(WOLFSSL* ssl)
{
if (ssl)
@@ -1298,10 +3443,12 @@ int wolfSSL_GetCipherType(WOLFSSL* ssl)
if (ssl == NULL)
return BAD_FUNC_ARG;
+#ifndef WOLFSSL_AEAD_ONLY
if (ssl->specs.cipher_type == block)
return WOLFSSL_BLOCK_TYPE;
if (ssl->specs.cipher_type == stream)
return WOLFSSL_STREAM_TYPE;
+#endif
if (ssl->specs.cipher_type == aead)
return WOLFSSL_AEAD_TYPE;
@@ -1361,28 +3508,59 @@ int wolfSSL_GetHmacSize(WOLFSSL* ssl)
#ifndef NO_CERTS
-WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void)
+WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX* ctx)
{
WOLFSSL_CERT_MANAGER* cm = NULL;
+ if (ctx)
+ cm = ctx->cm;
+ return cm;
+}
+
+WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap)
+{
+ WOLFSSL_CERT_MANAGER* cm;
WOLFSSL_ENTER("wolfSSL_CertManagerNew");
- cm = (WOLFSSL_CERT_MANAGER*) XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), 0,
- DYNAMIC_TYPE_CERT_MANAGER);
+ cm = (WOLFSSL_CERT_MANAGER*) XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), heap,
+ DYNAMIC_TYPE_CERT_MANAGER);
if (cm) {
XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER));
- if (InitMutex(&cm->caLock) != 0) {
+ if (wc_InitMutex(&cm->caLock) != 0) {
+ WOLFSSL_MSG("Bad mutex init");
+ wolfSSL_CertManagerFree(cm);
+ return NULL;
+ }
+
+ #ifdef WOLFSSL_TRUST_PEER_CERT
+ if (wc_InitMutex(&cm->tpLock) != 0) {
WOLFSSL_MSG("Bad mutex init");
wolfSSL_CertManagerFree(cm);
return NULL;
}
+ #endif
+
+ /* set default minimum key size allowed */
+ #ifndef NO_RSA
+ cm->minRsaKeySz = MIN_RSAKEY_SZ;
+ #endif
+ #ifdef HAVE_ECC
+ cm->minEccKeySz = MIN_ECCKEY_SZ;
+ #endif
+ cm->heap = heap;
}
return cm;
}
+WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void)
+{
+ return wolfSSL_CertManagerNew_ex(NULL);
+}
+
+
void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
{
WOLFSSL_ENTER("wolfSSL_CertManagerFree");
@@ -1395,201 +3573,268 @@ void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
#ifdef HAVE_OCSP
if (cm->ocsp)
FreeOCSP(cm->ocsp, 1);
+ XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
+ #if !defined(NO_WOLFSSL_SERVER) && \
+ (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+ defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
+ if (cm->ocsp_stapling)
+ FreeOCSP(cm->ocsp_stapling, 1);
+ #endif
+ #endif
+ FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
+ wc_FreeMutex(&cm->caLock);
+
+ #ifdef WOLFSSL_TRUST_PEER_CERT
+ FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
+ wc_FreeMutex(&cm->tpLock);
#endif
- FreeSignerTable(cm->caTable, CA_TABLE_SIZE, NULL);
- FreeMutex(&cm->caLock);
- XFREE(cm, NULL, DYNAMIC_TYPE_CERT_MANAGER);
+
+ XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER);
}
}
-
-/* Unload the CA signer list */
-int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm)
+#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM)
+#if defined(WOLFSSL_SIGNER_DER_CERT)
+/******************************************************************************
+* wolfSSL_CertManagerGetCerts - retrieve stack of X509 certificates in a
+* certificate manager (CM).
+*
+* RETURNS:
+* returns stack of X509 certs on success, otherwise returns a NULL.
+*/
+WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm)
{
- WOLFSSL_ENTER("wolfSSL_CertManagerUnloadCAs");
+ WOLFSSL_STACK* sk = NULL;
+ Signer* signers = NULL;
+ word32 row = 0;
+ DecodedCert* dCert = NULL;
+ WOLFSSL_X509* x509 = NULL;
+ int found = 0;
if (cm == NULL)
- return BAD_FUNC_ARG;
+ return NULL;
- if (LockMutex(&cm->caLock) != 0)
- return BAD_MUTEX_E;
+ sk = wolfSSL_sk_X509_new();
- FreeSignerTable(cm->caTable, CA_TABLE_SIZE, NULL);
+ if (sk == NULL) {
+ return NULL;
+ }
- UnLockMutex(&cm->caLock);
+ if (wc_LockMutex(&cm->caLock) != 0) {
+ goto error_init;
+ }
+ for (row = 0; row < CA_TABLE_SIZE; row++) {
+ signers = cm->caTable[row];
+ while (signers && signers->derCert && signers->derCert->buffer) {
- return SSL_SUCCESS;
-}
+ dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
+ DYNAMIC_TYPE_DCERT);
+ if (dCert == NULL) {
+ goto error;
+ }
+ XMEMSET(dCert, 0, sizeof(DecodedCert));
-/* Return bytes written to buff or < 0 for error */
-int wolfSSL_CertPemToDer(const unsigned char* pem, int pemSz,
- unsigned char* buff, int buffSz,
- int type)
-{
- int eccKey = 0;
- int ret;
- buffer der;
-#ifdef WOLFSSL_SMALL_STACK
- EncryptedInfo* info = NULL;
-#else
- EncryptedInfo info[1];
-#endif
+ InitDecodedCert(dCert, signers->derCert->buffer,
+ signers->derCert->length, cm->heap);
- WOLFSSL_ENTER("wolfSSL_CertPemToDer");
+ /* Parse Certificate */
+ if (ParseCert(dCert, CERT_TYPE, NO_VERIFY, cm)) {
+ goto error;
+ }
- if (pem == NULL || buff == NULL || buffSz <= 0) {
- WOLFSSL_MSG("Bad pem der args");
- return BAD_FUNC_ARG;
- }
+ x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), cm->heap,
+ DYNAMIC_TYPE_X509);
- if (type != CERT_TYPE && type != CA_TYPE && type != CERTREQ_TYPE) {
- WOLFSSL_MSG("Bad cert type");
- return BAD_FUNC_ARG;
- }
+ if (x509 == NULL) {
+ goto error;
+ }
-#ifdef WOLFSSL_SMALL_STACK
- info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (info == NULL)
- return MEMORY_E;
-#endif
+ InitX509(x509, 1, NULL);
- info->set = 0;
- info->ctx = NULL;
- info->consumed = 0;
- der.buffer = NULL;
+ if (CopyDecodedToX509(x509, dCert) == 0) {
- ret = PemToDer(pem, pemSz, type, &der, NULL, info, &eccKey);
+ if (wolfSSL_sk_X509_push(sk, x509) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Unable to load x509 into stack");
+ FreeX509(x509);
+ XFREE(x509, cm->heap, DYNAMIC_TYPE_X509);
+ goto error;
+ }
+ }
+ else {
+ goto error;
+ }
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ found = 1;
- if (ret < 0) {
- WOLFSSL_MSG("Bad Pem To Der");
- }
- else {
- if (der.length <= (word32)buffSz) {
- XMEMCPY(buff, der.buffer, der.length);
- ret = der.length;
- }
- else {
- WOLFSSL_MSG("Bad der length");
- ret = BAD_FUNC_ARG;
+ signers = signers->next;
+
+ FreeDecodedCert(dCert);
+ XFREE(dCert, cm->heap, DYNAMIC_TYPE_DCERT);
+ dCert = NULL;
}
}
+ wc_UnLockMutex(&cm->caLock);
- XFREE(der.buffer, NULL, DYNAMIC_TYPE_KEY);
+ if (!found) {
+ goto error_init;
+ }
- return ret;
-}
+ return sk;
+error:
+ wc_UnLockMutex(&cm->caLock);
-#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+error_init:
-/* our KeyPemToDer password callback, password in userData */
-static INLINE int OurPasswordCb(char* passwd, int sz, int rw, void* userdata)
-{
- (void)rw;
+ if (dCert) {
+ FreeDecodedCert(dCert);
+ XFREE(dCert, cm->heap, DYNAMIC_TYPE_DCERT);
+ }
- if (userdata == NULL)
- return 0;
+ if (sk)
+ wolfSSL_sk_X509_free(sk);
- XSTRNCPY(passwd, (char*)userdata, sz);
- return min((word32)sz, (word32)XSTRLEN((char*)userdata));
+ return NULL;
}
+#endif /* WOLFSSL_SIGNER_DER_CERT */
-#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
-
-
-/* Return bytes written to buff or < 0 for error */
-int wolfSSL_KeyPemToDer(const unsigned char* pem, int pemSz, unsigned char* buff,
- int buffSz, const char* pass)
+/******************************************************************************
+* wolfSSL_X509_STORE_GetCerts - retrieve stack of X509 in a certificate store ctx
+*
+* This API can be used in SSL verify callback function to view cert chain
+* See examples/client/client.c and myVerify() function in test.h
+*
+* RETURNS:
+* returns stack of X509 certs on success, otherwise returns a NULL.
+*/
+WOLFSSL_STACK* wolfSSL_X509_STORE_GetCerts(WOLFSSL_X509_STORE_CTX* s)
{
- int eccKey = 0;
- int ret;
- buffer der;
-#ifdef WOLFSSL_SMALL_STACK
- EncryptedInfo* info = NULL;
-#else
- EncryptedInfo info[1];
-#endif
+ int certIdx = 0;
+ WOLFSSL_BUFFER_INFO* cert = NULL;
+ DecodedCert* dCert = NULL;
+ WOLFSSL_X509* x509 = NULL;
+ WOLFSSL_STACK* sk = NULL;
+ int found = 0;
- (void)pass;
+ if (s == NULL) {
+ return NULL;
+ }
- WOLFSSL_ENTER("wolfSSL_KeyPemToDer");
+ sk = wolfSSL_sk_X509_new();
- if (pem == NULL || buff == NULL || buffSz <= 0) {
- WOLFSSL_MSG("Bad pem der args");
- return BAD_FUNC_ARG;
+ if (sk == NULL) {
+ return NULL;
}
-#ifdef WOLFSSL_SMALL_STACK
- info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (info == NULL)
- return MEMORY_E;
-#endif
+ for (certIdx = s->totalCerts - 1; certIdx >= 0; certIdx--) {
+ /* get certificate buffer */
+ cert = &s->certs[certIdx];
- info->set = 0;
- info->ctx = NULL;
- info->consumed = 0;
- der.buffer = NULL;
+ dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
-#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- if (pass) {
- info->ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
- if (info->ctx == NULL) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return MEMORY_E;
+ if (dCert == NULL) {
+ goto error;
}
+ XMEMSET(dCert, 0, sizeof(DecodedCert));
- wolfSSL_CTX_set_default_passwd_cb(info->ctx, OurPasswordCb);
- wolfSSL_CTX_set_default_passwd_cb_userdata(info->ctx, (void*)pass);
- }
-#endif
+ InitDecodedCert(dCert, cert->buffer, cert->length, NULL);
- ret = PemToDer(pem, pemSz, PRIVATEKEY_TYPE, &der, NULL, info, &eccKey);
+ /* Parse Certificate */
+ if (ParseCert(dCert, CERT_TYPE, NO_VERIFY, NULL)){
+ goto error;
+ }
+ x509 = wolfSSL_X509_new();
- if (info->ctx)
- wolfSSL_CTX_free(info->ctx);
+ if (x509 == NULL) {
+ goto error;
+ }
+ InitX509(x509, 1, NULL);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ if (CopyDecodedToX509(x509, dCert) == 0) {
- if (ret < 0) {
- WOLFSSL_MSG("Bad Pem To Der");
- }
- else {
- if (der.length <= (word32)buffSz) {
- XMEMCPY(buff, der.buffer, der.length);
- ret = der.length;
+ if (wolfSSL_sk_X509_push(sk, x509) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Unable to load x509 into stack");
+ wolfSSL_X509_free(x509);
+ goto error;
+ }
}
else {
- WOLFSSL_MSG("Bad der length");
- ret = BAD_FUNC_ARG;
+ goto error;
}
+ found = 1;
+
+ FreeDecodedCert(dCert);
+ XFREE(dCert, NULL, DYNAMIC_TYPE_DCERT);
+ dCert = NULL;
}
- XFREE(der.buffer, NULL, DYNAMIC_TYPE_KEY);
+ if (!found) {
+ wolfSSL_sk_X509_free(sk);
+ sk = NULL;
+ }
+ return sk;
- return ret;
+error:
+ if (dCert) {
+ FreeDecodedCert(dCert);
+ XFREE(dCert, NULL, DYNAMIC_TYPE_DCERT);
+ }
+
+ if (sk)
+ wolfSSL_sk_X509_free(sk);
+
+ return NULL;
}
+#endif /* OPENSSL_EXTRA && !NO_FILESYSTEM */
+/* Unload the CA signer list */
+int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm)
+{
+ WOLFSSL_ENTER("wolfSSL_CertManagerUnloadCAs");
-#endif /* !NO_CERTS */
+ if (cm == NULL)
+ return BAD_FUNC_ARG;
+ if (wc_LockMutex(&cm->caLock) != 0)
+ return BAD_MUTEX_E;
+ FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
+
+ wc_UnLockMutex(&cm->caLock);
+
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm)
+{
+ WOLFSSL_ENTER("wolfSSL_CertManagerUnload_trust_peers");
+
+ if (cm == NULL)
+ return BAD_FUNC_ARG;
+
+ if (wc_LockMutex(&cm->tpLock) != 0)
+ return BAD_MUTEX_E;
+
+ FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
+
+ wc_UnLockMutex(&cm->tpLock);
+
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+#endif /* NO_CERTS */
#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
-void wolfSSL_ERR_print_errors_fp(FILE* fp, int err)
+void wolfSSL_ERR_print_errors_fp(XFILE fp, int err)
{
char data[WOLFSSL_MAX_ERROR_SZ + 1];
@@ -1598,9 +3843,21 @@ void wolfSSL_ERR_print_errors_fp(FILE* fp, int err)
fprintf(fp, "%s", data);
}
-#endif
+#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
+void wolfSSL_ERR_dump_errors_fp(XFILE fp)
+{
+ wc_ERR_print_errors_fp(fp);
+}
+void wolfSSL_ERR_print_errors_cb (int (*cb)(const char *str, size_t len,
+ void *u), void *u)
+{
+ wc_ERR_print_errors_cb(cb, u);
+}
+#endif
+#endif
+WOLFSSL_ABI
int wolfSSL_pending(WOLFSSL* ssl)
{
WOLFSSL_ENTER("SSL_pending");
@@ -1609,7 +3866,7 @@ int wolfSSL_pending(WOLFSSL* ssl)
#ifndef WOLFSSL_LEANPSK
-/* trun on handshake group messages for context */
+/* turn on handshake group messages for context */
int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX* ctx)
{
if (ctx == NULL)
@@ -1617,7 +3874,7 @@ int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX* ctx)
ctx->groupMessages = 1;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
#endif
@@ -1629,7 +3886,7 @@ int wolfSSL_connect_cert(WOLFSSL* ssl)
int ret;
if (ssl == NULL)
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
ssl->options.certOnly = 1;
ret = wolfSSL_connect(ssl);
@@ -1641,7 +3898,7 @@ int wolfSSL_connect_cert(WOLFSSL* ssl)
#ifndef WOLFSSL_LEANPSK
-/* trun on handshake group messages for ssl object */
+/* turn on handshake group messages for ssl object */
int wolfSSL_set_group_messages(WOLFSSL* ssl)
{
if (ssl == NULL)
@@ -1649,15 +3906,19 @@ int wolfSSL_set_group_messages(WOLFSSL* ssl)
ssl->options.groupMessages = 1;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
-/* make minVersion the internal equivilant SSL version */
+/* make minVersion the internal equivalent SSL version */
static int SetMinVersionHelper(byte* minVersion, int version)
{
+#ifdef NO_TLS
+ (void)minVersion;
+#endif
+
switch (version) {
-#ifndef NO_OLD_TLS
+#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
case WOLFSSL_SSLV3:
*minVersion = SSLv3_MINOR;
break;
@@ -1665,29 +3926,39 @@ static int SetMinVersionHelper(byte* minVersion, int version)
#ifndef NO_TLS
#ifndef NO_OLD_TLS
+ #ifdef WOLFSSL_ALLOW_TLSV10
case WOLFSSL_TLSV1:
*minVersion = TLSv1_MINOR;
break;
+ #endif
case WOLFSSL_TLSV1_1:
*minVersion = TLSv1_1_MINOR;
break;
#endif
+ #ifndef WOLFSSL_NO_TLS12
case WOLFSSL_TLSV1_2:
*minVersion = TLSv1_2_MINOR;
break;
+ #endif
#endif
+ #ifdef WOLFSSL_TLS13
+ case WOLFSSL_TLSV1_3:
+ *minVersion = TLSv1_3_MINOR;
+ break;
+ #endif
default:
WOLFSSL_MSG("Bad function argument");
return BAD_FUNC_ARG;
}
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
-/* Set minimum downgrade version allowed, SSL_SUCCESS on ok */
+/* Set minimum downgrade version allowed, WOLFSSL_SUCCESS on ok */
+WOLFSSL_ABI
int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version)
{
WOLFSSL_ENTER("wolfSSL_CTX_SetMinVersion");
@@ -1701,7 +3972,7 @@ int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version)
}
-/* Set minimum downgrade version allowed, SSL_SUCCESS on ok */
+/* Set minimum downgrade version allowed, WOLFSSL_SUCCESS on ok */
int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version)
{
WOLFSSL_ENTER("wolfSSL_SetMinVersion");
@@ -1715,10 +3986,37 @@ int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version)
}
+/* Function to get version as WOLFSSL_ enum value for wolfSSL_SetVersion */
+int wolfSSL_GetVersion(WOLFSSL* ssl)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ if (ssl->version.major == SSLv3_MAJOR) {
+ switch (ssl->version.minor) {
+ case SSLv3_MINOR :
+ return WOLFSSL_SSLV3;
+ case TLSv1_MINOR :
+ return WOLFSSL_TLSV1;
+ case TLSv1_1_MINOR :
+ return WOLFSSL_TLSV1_1;
+ case TLSv1_2_MINOR :
+ return WOLFSSL_TLSV1_2;
+ case TLSv1_3_MINOR :
+ return WOLFSSL_TLSV1_3;
+ default:
+ break;
+ }
+ }
+
+ return VERSION_ERROR;
+}
+
int wolfSSL_SetVersion(WOLFSSL* ssl, int version)
{
- byte haveRSA = 1;
- byte havePSK = 0;
+ word16 haveRSA = 1;
+ word16 havePSK = 0;
+ int keySz = 0;
WOLFSSL_ENTER("wolfSSL_SetVersion");
@@ -1728,7 +4026,7 @@ int wolfSSL_SetVersion(WOLFSSL* ssl, int version)
}
switch (version) {
-#ifndef NO_OLD_TLS
+#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
case WOLFSSL_SSLV3:
ssl->version = MakeSSLv3();
break;
@@ -1736,17 +4034,27 @@ int wolfSSL_SetVersion(WOLFSSL* ssl, int version)
#ifndef NO_TLS
#ifndef NO_OLD_TLS
+ #ifdef WOLFSSL_ALLOW_TLSV10
case WOLFSSL_TLSV1:
ssl->version = MakeTLSv1();
break;
+ #endif
case WOLFSSL_TLSV1_1:
ssl->version = MakeTLSv1_1();
break;
#endif
+ #ifndef WOLFSSL_NO_TLS12
case WOLFSSL_TLSV1_2:
ssl->version = MakeTLSv1_2();
break;
+ #endif
+#endif
+#ifdef WOLFSSL_TLS13
+ case WOLFSSL_TLSV1_3:
+ ssl->version = MakeTLSv1_3();
+ break;
+
#endif
default:
@@ -1760,12 +4068,16 @@ int wolfSSL_SetVersion(WOLFSSL* ssl, int version)
#ifndef NO_PSK
havePSK = ssl->options.havePSK;
#endif
+ #ifndef NO_CERTS
+ keySz = ssl->buffers.keySz;
+ #endif
- InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, ssl->options.haveDH,
- ssl->options.haveNTRU, ssl->options.haveECDSAsig,
- ssl->options.haveStaticECC, ssl->options.side);
+ InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+ ssl->options.haveDH, ssl->options.haveNTRU,
+ ssl->options.haveECDSAsig, ssl->options.haveECC,
+ ssl->options.haveStaticECC, ssl->options.side);
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
#endif /* !leanpsk */
@@ -1773,10 +4085,10 @@ int wolfSSL_SetVersion(WOLFSSL* ssl, int version)
#if !defined(NO_CERTS) || !defined(NO_SESSION_CACHE)
/* Make a work from the front of random hash */
-static INLINE word32 MakeWordFromHash(const byte* hashID)
+static WC_INLINE word32 MakeWordFromHash(const byte* hashID)
{
- return (hashID[0] << 24) | (hashID[1] << 16) | (hashID[2] << 8) |
- hashID[3];
+ return ((word32)hashID[0] << 24) | ((word32)hashID[1] << 16) |
+ (hashID[2] << 8) | hashID[3];
}
#endif /* !NO_CERTS || !NO_SESSION_CACHE */
@@ -1785,7 +4097,7 @@ static INLINE word32 MakeWordFromHash(const byte* hashID)
#ifndef NO_CERTS
/* hash is the SHA digest of name, just use first 32 bits as hash */
-static INLINE word32 HashSigner(const byte* hash)
+static WC_INLINE word32 HashSigner(const byte* hash)
{
return MakeWordFromHash(hash) % CA_TABLE_SIZE;
}
@@ -1796,30 +4108,145 @@ int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash)
{
Signer* signers;
int ret = 0;
- word32 row = HashSigner(hash);
+ word32 row;
- if (LockMutex(&cm->caLock) != 0)
- return ret;
+ if (cm == NULL || hash == NULL) {
+ return ret;
+ }
+
+ row = HashSigner(hash);
+
+ if (wc_LockMutex(&cm->caLock) != 0) {
+ return ret;
+ }
signers = cm->caTable[row];
while (signers) {
byte* subjectHash;
+
+ #ifndef NO_SKID
+ subjectHash = signers->subjectKeyIdHash;
+ #else
+ subjectHash = signers->subjectNameHash;
+ #endif
+
+ if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
+ ret = 1; /* success */
+ break;
+ }
+ signers = signers->next;
+ }
+ wc_UnLockMutex(&cm->caLock);
+
+ return ret;
+}
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* hash is the SHA digest of name, just use first 32 bits as hash */
+static WC_INLINE word32 TrustedPeerHashSigner(const byte* hash)
+{
+ return MakeWordFromHash(hash) % TP_TABLE_SIZE;
+}
+
+/* does trusted peer already exist on signer list */
+int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash)
+{
+ TrustedPeerCert* tp;
+ int ret = 0;
+ word32 row = TrustedPeerHashSigner(hash);
+
+ if (wc_LockMutex(&cm->tpLock) != 0)
+ return ret;
+ tp = cm->tpTable[row];
+ while (tp) {
+ byte* subjectHash;
#ifndef NO_SKID
- subjectHash = signers->subjectKeyIdHash;
+ subjectHash = tp->subjectKeyIdHash;
#else
- subjectHash = signers->subjectNameHash;
+ subjectHash = tp->subjectNameHash;
#endif
if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
ret = 1;
break;
}
- signers = signers->next;
+ tp = tp->next;
}
- UnLockMutex(&cm->caLock);
+ wc_UnLockMutex(&cm->tpLock);
return ret;
}
+/* return Trusted Peer if found, otherwise NULL
+ type is what to match on
+ */
+TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash, int type)
+{
+ WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+ TrustedPeerCert* ret = NULL;
+ TrustedPeerCert* tp = NULL;
+ word32 row;
+
+ if (cm == NULL || hash == NULL)
+ return NULL;
+
+ row = TrustedPeerHashSigner(hash);
+
+ if (wc_LockMutex(&cm->tpLock) != 0)
+ return ret;
+
+ tp = cm->tpTable[row];
+ while (tp) {
+ byte* subjectHash;
+ switch (type) {
+ #ifndef NO_SKID
+ case WC_MATCH_SKID:
+ subjectHash = tp->subjectKeyIdHash;
+ break;
+ #endif
+ case WC_MATCH_NAME:
+ subjectHash = tp->subjectNameHash;
+ break;
+ default:
+ WOLFSSL_MSG("Unknown search type");
+ wc_UnLockMutex(&cm->tpLock);
+ return NULL;
+ }
+ if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
+ ret = tp;
+ break;
+ }
+ tp = tp->next;
+ }
+ wc_UnLockMutex(&cm->tpLock);
+
+ return ret;
+}
+
+
+int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert)
+{
+ if (tp == NULL || cert == NULL)
+ return BAD_FUNC_ARG;
+
+ /* subject key id or subject hash has been compared when searching
+ tpTable for the cert from function GetTrustedPeer */
+
+ /* compare signatures */
+ if (tp->sigLen == cert->sigLength) {
+ if (XMEMCMP(tp->sig, cert->signature, cert->sigLength)) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+ else {
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+
/* return CA if found, otherwise NULL */
Signer* GetCA(void* vp, byte* hash)
{
@@ -1831,7 +4258,7 @@ Signer* GetCA(void* vp, byte* hash)
if (cm == NULL)
return NULL;
- if (LockMutex(&cm->caLock) != 0)
+ if (wc_LockMutex(&cm->caLock) != 0)
return ret;
signers = cm->caTable[row];
@@ -1848,7 +4275,7 @@ Signer* GetCA(void* vp, byte* hash)
}
signers = signers->next;
}
- UnLockMutex(&cm->caLock);
+ wc_UnLockMutex(&cm->caLock);
return ret;
}
@@ -1866,33 +4293,163 @@ Signer* GetCAByName(void* vp, byte* hash)
if (cm == NULL)
return NULL;
- if (LockMutex(&cm->caLock) != 0)
+ if (wc_LockMutex(&cm->caLock) != 0)
return ret;
for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
signers = cm->caTable[row];
while (signers && ret == NULL) {
- if (XMEMCMP(hash,
- signers->subjectNameHash, SIGNER_DIGEST_SIZE) == 0) {
+ if (XMEMCMP(hash, signers->subjectNameHash,
+ SIGNER_DIGEST_SIZE) == 0) {
ret = signers;
}
signers = signers->next;
}
}
- UnLockMutex(&cm->caLock);
+ wc_UnLockMutex(&cm->caLock);
return ret;
}
#endif
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* add a trusted peer cert to linked list */
+int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify)
+{
+ int ret, row;
+ TrustedPeerCert* peerCert;
+ DecodedCert* cert;
+ DerBuffer* der = *pDer;
+ byte* subjectHash = NULL;
+
+ WOLFSSL_MSG("Adding a Trusted Peer Cert");
+
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
+ DYNAMIC_TYPE_DCERT);
+ if (cert == NULL)
+ return MEMORY_E;
+
+ InitDecodedCert(cert, der->buffer, der->length, cm->heap);
+ if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) {
+ FreeDecodedCert(cert);
+ XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+ return ret;
+ }
+ WOLFSSL_MSG("\tParsed new trusted peer cert");
+
+ peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), cm->heap,
+ DYNAMIC_TYPE_CERT);
+ if (peerCert == NULL) {
+ FreeDecodedCert(cert);
+ XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+ return MEMORY_E;
+ }
+ XMEMSET(peerCert, 0, sizeof(TrustedPeerCert));
+
+#ifndef NO_SKID
+ if (cert->extAuthKeyIdSet) {
+ subjectHash = cert->extSubjKeyId;
+ }
+ else {
+ subjectHash = cert->subjectHash;
+ }
+#else
+ subjectHash = cert->subjectHash;
+#endif
+
+ #ifndef IGNORE_NAME_CONSTRAINTS
+ if (peerCert->permittedNames)
+ FreeNameSubtrees(peerCert->permittedNames, cm->heap);
+ if (peerCert->excludedNames)
+ FreeNameSubtrees(peerCert->excludedNames, cm->heap);
+ #endif
+
+ if (AlreadyTrustedPeer(cm, subjectHash)) {
+ WOLFSSL_MSG("\tAlready have this CA, not adding again");
+ FreeTrustedPeer(peerCert, cm->heap);
+ (void)ret;
+ }
+ else {
+ /* add trusted peer signature */
+ peerCert->sigLen = cert->sigLength;
+ peerCert->sig = XMALLOC(cert->sigLength, cm->heap,
+ DYNAMIC_TYPE_SIGNATURE);
+ if (peerCert->sig == NULL) {
+ FreeDecodedCert(cert);
+ XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+ FreeTrustedPeer(peerCert, cm->heap);
+ return MEMORY_E;
+ }
+ XMEMCPY(peerCert->sig, cert->signature, cert->sigLength);
+
+ /* add trusted peer name */
+ peerCert->nameLen = cert->subjectCNLen;
+ peerCert->name = cert->subjectCN;
+ #ifndef IGNORE_NAME_CONSTRAINTS
+ peerCert->permittedNames = cert->permittedNames;
+ peerCert->excludedNames = cert->excludedNames;
+ #endif
+
+ /* add SKID when available and hash of name */
+ #ifndef NO_SKID
+ XMEMCPY(peerCert->subjectKeyIdHash, cert->extSubjKeyId,
+ SIGNER_DIGEST_SIZE);
+ #endif
+ XMEMCPY(peerCert->subjectNameHash, cert->subjectHash,
+ SIGNER_DIGEST_SIZE);
+ peerCert->next = NULL; /* If Key Usage not set, all uses valid. */
+ cert->subjectCN = 0;
+ #ifndef IGNORE_NAME_CONSTRAINTS
+ cert->permittedNames = NULL;
+ cert->excludedNames = NULL;
+ #endif
+
+ #ifndef NO_SKID
+ if (cert->extAuthKeyIdSet) {
+ row = TrustedPeerHashSigner(peerCert->subjectKeyIdHash);
+ }
+ else {
+ row = TrustedPeerHashSigner(peerCert->subjectNameHash);
+ }
+ #else
+ row = TrustedPeerHashSigner(peerCert->subjectNameHash);
+ #endif
+
+ if (wc_LockMutex(&cm->tpLock) == 0) {
+ peerCert->next = cm->tpTable[row];
+ cm->tpTable[row] = peerCert; /* takes ownership */
+ wc_UnLockMutex(&cm->tpLock);
+ }
+ else {
+ WOLFSSL_MSG("\tTrusted Peer Cert Mutex Lock failed");
+ FreeDecodedCert(cert);
+ XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+ FreeTrustedPeer(peerCert, cm->heap);
+ return BAD_MUTEX_E;
+ }
+ }
+
+ WOLFSSL_MSG("\tFreeing parsed trusted peer cert");
+ FreeDecodedCert(cert);
+ XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+ WOLFSSL_MSG("\tFreeing der trusted peer cert");
+ FreeDer(&der);
+ WOLFSSL_MSG("\t\tOK Freeing der trusted peer cert");
+ WOLFSSL_LEAVE("AddTrustedPeer", ret);
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+
/* owns der, internal now uses too */
/* type flag ids from user or from chain received during verify
don't allow chain ones to be added w/o isCA extension */
-int AddCA(WOLFSSL_CERT_MANAGER* cm, buffer der, int type, int verify)
+int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
{
int ret;
- Signer* signer = 0;
+ Signer* signer = NULL;
word32 row;
byte* subjectHash;
#ifdef WOLFSSL_SMALL_STACK
@@ -1900,19 +4457,27 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, buffer der, int type, int verify)
#else
DecodedCert cert[1];
#endif
+ DerBuffer* der = *pDer;
WOLFSSL_MSG("Adding a CA");
+ if (cm == NULL) {
+ FreeDer(pDer);
+ return BAD_FUNC_ARG;
+ }
+
#ifdef WOLFSSL_SMALL_STACK
cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (cert == NULL)
+ DYNAMIC_TYPE_DCERT);
+ if (cert == NULL) {
+ FreeDer(pDer);
return MEMORY_E;
+ }
#endif
- InitDecodedCert(cert, der.buffer, der.length, cm->heap);
+ InitDecodedCert(cert, der->buffer, der->length, cm->heap);
ret = ParseCert(cert, CA_TYPE, verify, cm);
- WOLFSSL_MSG(" Parsed new CA");
+ WOLFSSL_MSG("\tParsed new CA");
#ifndef NO_SKID
subjectHash = cert->extSubjKeyId;
@@ -1920,21 +4485,67 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, buffer der, int type, int verify)
subjectHash = cert->subjectHash;
#endif
+ /* check CA key size */
+ if (verify) {
+ switch (cert->keyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ if (cm->minRsaKeySz < 0 ||
+ cert->pubKeySize < (word16)cm->minRsaKeySz) {
+ ret = RSA_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA RSA key size error");
+ }
+ break;
+ #endif /* !NO_RSA */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ if (cm->minEccKeySz < 0 ||
+ cert->pubKeySize < (word16)cm->minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA ECC key size error");
+ }
+ break;
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ if (cm->minEccKeySz < 0 ||
+ ED25519_KEY_SIZE < (word16)cm->minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA ECC key size error");
+ }
+ break;
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ED448k:
+ if (cm->minEccKeySz < 0 ||
+ ED448_KEY_SIZE < (word16)cm->minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA ECC key size error");
+ }
+ break;
+ #endif /* HAVE_ED448 */
+
+ default:
+ WOLFSSL_MSG("\tNo key size check done on CA");
+ break; /* no size check if key type is not in switch */
+ }
+ }
+
if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA) {
- WOLFSSL_MSG(" Can't add as CA if not actually one");
+ WOLFSSL_MSG("\tCan't add as CA if not actually one");
ret = NOT_CA_ERROR;
}
#ifndef ALLOW_INVALID_CERTSIGN
else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA &&
- (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
+ !cert->selfSigned && (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
/* Intermediate CA certs are required to have the keyCertSign
* extension set. User loaded root certs are not. */
- WOLFSSL_MSG(" Doesn't have key usage certificate signing");
+ WOLFSSL_MSG("\tDoesn't have key usage certificate signing");
ret = NOT_CA_ERROR;
}
#endif
else if (ret == 0 && AlreadySigner(cm, subjectHash)) {
- WOLFSSL_MSG(" Already have this CA, not adding again");
+ WOLFSSL_MSG("\tAlready have this CA, not adding again");
(void)ret;
}
else if (ret == 0) {
@@ -1942,65 +4553,102 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, buffer der, int type, int verify)
signer = MakeSigner(cm->heap);
if (!signer)
ret = MEMORY_ERROR;
- else {
- signer->keyOID = cert->keyOID;
+ }
+ if (ret == 0 && signer != NULL) {
+ #ifdef WOLFSSL_SIGNER_DER_CERT
+ ret = AllocDer(&signer->derCert, der->length, der->type, NULL);
+ }
+ if (ret == 0 && signer != NULL) {
+ XMEMCPY(signer->derCert->buffer, der->buffer, der->length);
+ #endif
+ signer->keyOID = cert->keyOID;
+ if (cert->pubKeyStored) {
signer->publicKey = cert->publicKey;
signer->pubKeySize = cert->pubKeySize;
+ }
+ if (cert->subjectCNStored) {
signer->nameLen = cert->subjectCNLen;
signer->name = cert->subjectCN;
- #ifndef IGNORE_NAME_CONSTRAINTS
- signer->permittedNames = cert->permittedNames;
- signer->excludedNames = cert->excludedNames;
- #endif
- #ifndef NO_SKID
- XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId,
- SIGNER_DIGEST_SIZE);
- #endif
- XMEMCPY(signer->subjectNameHash, cert->subjectHash,
- SIGNER_DIGEST_SIZE);
- signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage
- : 0xFFFF;
- signer->next = NULL; /* If Key Usage not set, all uses valid. */
- cert->publicKey = 0; /* in case lock fails don't free here. */
- cert->subjectCN = 0;
- #ifndef IGNORE_NAME_CONSTRAINTS
- cert->permittedNames = NULL;
- cert->excludedNames = NULL;
- #endif
+ }
+ signer->pathLength = cert->pathLength;
+ signer->maxPathLen = cert->maxPathLen;
+ signer->pathLengthSet = cert->pathLengthSet;
+ signer->selfSigned = cert->selfSigned;
+ #ifndef IGNORE_NAME_CONSTRAINTS
+ signer->permittedNames = cert->permittedNames;
+ signer->excludedNames = cert->excludedNames;
+ #endif
+ #ifndef NO_SKID
+ XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId,
+ SIGNER_DIGEST_SIZE);
+ #endif
+ XMEMCPY(signer->subjectNameHash, cert->subjectHash,
+ SIGNER_DIGEST_SIZE);
+ #ifdef HAVE_OCSP
+ XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash,
+ KEYID_SIZE);
+ #endif
+ signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage
+ : 0xFFFF;
+ signer->next = NULL; /* If Key Usage not set, all uses valid. */
+ cert->publicKey = 0; /* in case lock fails don't free here. */
+ cert->subjectCN = 0;
+ #ifndef IGNORE_NAME_CONSTRAINTS
+ cert->permittedNames = NULL;
+ cert->excludedNames = NULL;
+ #endif
- #ifndef NO_SKID
- row = HashSigner(signer->subjectKeyIdHash);
- #else
- row = HashSigner(signer->subjectNameHash);
- #endif
+ #ifndef NO_SKID
+ row = HashSigner(signer->subjectKeyIdHash);
+ #else
+ row = HashSigner(signer->subjectNameHash);
+ #endif
- if (LockMutex(&cm->caLock) == 0) {
- signer->next = cm->caTable[row];
- cm->caTable[row] = signer; /* takes ownership */
- UnLockMutex(&cm->caLock);
- if (cm->caCacheCallback)
- cm->caCacheCallback(der.buffer, (int)der.length, type);
- }
- else {
- WOLFSSL_MSG(" CA Mutex Lock failed");
- ret = BAD_MUTEX_E;
- FreeSigner(signer, cm->heap);
- }
+ if (wc_LockMutex(&cm->caLock) == 0) {
+ signer->next = cm->caTable[row];
+ cm->caTable[row] = signer; /* takes ownership */
+ wc_UnLockMutex(&cm->caLock);
+ if (cm->caCacheCallback)
+ cm->caCacheCallback(der->buffer, (int)der->length, type);
+ }
+ else {
+ WOLFSSL_MSG("\tCA Mutex Lock failed");
+ ret = BAD_MUTEX_E;
+ FreeSigner(signer, cm->heap);
}
}
-
- WOLFSSL_MSG(" Freeing Parsed CA");
+#if defined(WOLFSSL_RENESAS_TSIP_TLS)
+ /* Verify CA by TSIP so that generated tsip key is going to be able to */
+ /* be used for peer's cert verification */
+ /* TSIP is only able to handle USER CA, and only one CA. */
+ /* Therefore, it doesn't need to call TSIP again if there is already */
+ /* verified CA. */
+ if ( ret == 0 && signer != NULL ) {
+ signer->cm_idx = row;
+ if (type == WOLFSSL_USER_CA && tsip_rootCAverified() == 0 ) {
+ if ((ret = tsip_tls_RootCertVerify(cert->source, cert->maxIdx,
+ cert->sigCtx.pubkey_n_start, cert->sigCtx.pubkey_n_len - 1,
+ cert->sigCtx.pubkey_e_start, cert->sigCtx.pubkey_e_len - 1,
+ row/* cm index */))
+ != 0)
+ WOLFSSL_MSG("tsip_tls_RootCertVerify() failed");
+ else
+ WOLFSSL_MSG("tsip_tls_RootCertVerify() succeed");
+ }
+ }
+#endif
+ WOLFSSL_MSG("\tFreeing Parsed CA");
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
#endif
- WOLFSSL_MSG(" Freeing der CA");
- XFREE(der.buffer, cm->heap, DYNAMIC_TYPE_CA);
- WOLFSSL_MSG(" OK Freeing der CA");
+ WOLFSSL_MSG("\tFreeing der CA");
+ FreeDer(pDer);
+ WOLFSSL_MSG("\t\tOK Freeing der CA");
WOLFSSL_LEAVE("AddCA", ret);
- return ret == 0 ? SSL_SUCCESS : ret;
+ return ret == 0 ? WOLFSSL_SUCCESS : ret;
}
#endif /* !NO_CERTS */
@@ -2011,22 +4659,29 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, buffer der, int type, int verify)
/* basic config gives a cache with 33 sessions, adequate for clients and
embedded servers
- MEDIUM_SESSION_CACHE allows 1055 sessions, adequate for servers that
- aren't under heavy load, basically allows 200 new sessions per minute
-
- BIG_SESSION_CACHE yields 20,027 sessions
+ TITAN_SESSION_CACHE allows just over 2 million sessions, for servers
+ with titanic amounts of memory with long session ID timeouts and high
+ levels of traffic.
HUGE_SESSION_CACHE yields 65,791 sessions, for servers under heavy load,
allows over 13,000 new sessions per minute or over 200 new sessions per
second
+ BIG_SESSION_CACHE yields 20,027 sessions
+
+ MEDIUM_SESSION_CACHE allows 1055 sessions, adequate for servers that
+ aren't under heavy load, basically allows 200 new sessions per minute
+
SMALL_SESSION_CACHE only stores 6 sessions, good for embedded clients
or systems where the default of nearly 3kB is too much RAM, this define
uses less than 500 bytes RAM
default SESSION_CACHE stores 33 sessions (no XXX_SESSION_CACHE defined)
*/
- #ifdef HUGE_SESSION_CACHE
+ #if defined(TITAN_SESSION_CACHE)
+ #define SESSIONS_PER_ROW 31
+ #define SESSION_ROWS 64937
+ #elif defined(HUGE_SESSION_CACHE)
#define SESSIONS_PER_ROW 11
#define SESSION_ROWS 5981
#elif defined(BIG_SESSION_CACHE)
@@ -2049,13 +4704,13 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, buffer der, int type, int verify)
WOLFSSL_SESSION Sessions[SESSIONS_PER_ROW];
} SessionRow;
- static SessionRow SessionCache[SESSION_ROWS];
+ static WOLFSSL_GLOBAL SessionRow SessionCache[SESSION_ROWS];
#if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS)
- static word32 PeakSessions;
+ static WOLFSSL_GLOBAL word32 PeakSessions;
#endif
- static wolfSSL_Mutex session_mutex; /* SessionCache mutex */
+ static WOLFSSL_GLOBAL wolfSSL_Mutex session_mutex; /* SessionCache mutex */
#ifndef NO_CLIENT_CACHE
@@ -2070,707 +4725,1049 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, buffer der, int type, int verify)
ClientSession Clients[SESSIONS_PER_ROW];
} ClientRow;
- static ClientRow ClientCache[SESSION_ROWS]; /* Client Cache */
+ static WOLFSSL_GLOBAL ClientRow ClientCache[SESSION_ROWS];
+ /* Client Cache */
/* uses session mutex */
#endif /* NO_CLIENT_CACHE */
#endif /* NO_SESSION_CACHE */
-
+WOLFSSL_ABI
int wolfSSL_Init(void)
{
- int ret = SSL_SUCCESS;
-
WOLFSSL_ENTER("wolfSSL_Init");
if (initRefCount == 0) {
+ /* Initialize crypto for use with TLS connection */
+ if (wolfCrypt_Init() != 0) {
+ WOLFSSL_MSG("Bad wolfCrypt Init");
+ return WC_INIT_E;
+ }
+
+#ifdef OPENSSL_EXTRA
+ if (wolfSSL_RAND_seed(NULL, 0) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("wolfSSL_RAND_Seed failed");
+ return WC_INIT_E;
+ }
+#endif
+
#ifndef NO_SESSION_CACHE
- if (InitMutex(&session_mutex) != 0)
- ret = BAD_MUTEX_E;
+ if (wc_InitMutex(&session_mutex) != 0) {
+ WOLFSSL_MSG("Bad Init Mutex session");
+ return BAD_MUTEX_E;
+ }
#endif
- if (InitMutex(&count_mutex) != 0)
- ret = BAD_MUTEX_E;
- }
- if (ret == SSL_SUCCESS) {
- if (LockMutex(&count_mutex) != 0) {
- WOLFSSL_MSG("Bad Lock Mutex count");
+ if (wc_InitMutex(&count_mutex) != 0) {
+ WOLFSSL_MSG("Bad Init Mutex count");
return BAD_MUTEX_E;
}
- initRefCount++;
- UnLockMutex(&count_mutex);
}
- return ret;
+ if (wc_LockMutex(&count_mutex) != 0) {
+ WOLFSSL_MSG("Bad Lock Mutex count");
+ return BAD_MUTEX_E;
+ }
+
+ initRefCount++;
+ wc_UnLockMutex(&count_mutex);
+
+ return WOLFSSL_SUCCESS;
}
+
#ifndef NO_CERTS
-static const char* BEGIN_CERT = "-----BEGIN CERTIFICATE-----";
-static const char* END_CERT = "-----END CERTIFICATE-----";
-static const char* BEGIN_CERT_REQ = "-----BEGIN CERTIFICATE REQUEST-----";
-static const char* END_CERT_REQ = "-----END CERTIFICATE REQUEST-----";
-static const char* BEGIN_DH_PARAM = "-----BEGIN DH PARAMETERS-----";
-static const char* END_DH_PARAM = "-----END DH PARAMETERS-----";
-static const char* BEGIN_X509_CRL = "-----BEGIN X509 CRL-----";
-static const char* END_X509_CRL = "-----END X509 CRL-----";
-static const char* BEGIN_RSA_PRIV = "-----BEGIN RSA PRIVATE KEY-----";
-static const char* END_RSA_PRIV = "-----END RSA PRIVATE KEY-----";
-static const char* BEGIN_PRIV_KEY = "-----BEGIN PRIVATE KEY-----";
-static const char* END_PRIV_KEY = "-----END PRIVATE KEY-----";
-static const char* BEGIN_ENC_PRIV_KEY = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
-static const char* END_ENC_PRIV_KEY = "-----END ENCRYPTED PRIVATE KEY-----";
-static const char* BEGIN_EC_PRIV = "-----BEGIN EC PRIVATE KEY-----";
-static const char* END_EC_PRIV = "-----END EC PRIVATE KEY-----";
-static const char* BEGIN_DSA_PRIV = "-----BEGIN DSA PRIVATE KEY-----";
-static const char* END_DSA_PRIV = "-----END DSA PRIVATE KEY-----";
-
-/* Remove PEM header/footer, convert to ASN1, store any encrypted data
- info->consumed tracks of PEM bytes consumed in case multiple parts */
-int PemToDer(const unsigned char* buff, long longSz, int type,
- buffer* der, void* heap, EncryptedInfo* info, int* eccKey)
-{
- const char* header = NULL;
- const char* footer = NULL;
- char* headerEnd;
- char* footerEnd;
- char* consumedEnd;
- char* bufferEnd = (char*)(buff + longSz);
- long neededSz;
- int ret = 0;
- int dynamicType = 0;
- int sz = (int)longSz;
+/* process user cert chain to pass during the handshake */
+static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff,
+ long sz, int format, int type, WOLFSSL* ssl,
+ long* used, EncryptedInfo* info, int verify)
+{
+ int ret = 0;
+ void* heap = wolfSSL_CTX_GetHeap(ctx, ssl);
+#ifdef WOLFSSL_TLS13
+ int cnt = 0;
+#endif
- switch (type) {
- case CA_TYPE: /* same as below */
- case CERT_TYPE: header= BEGIN_CERT; footer= END_CERT; break;
- case CRL_TYPE: header= BEGIN_X509_CRL; footer= END_X509_CRL; break;
- case DH_PARAM_TYPE: header= BEGIN_DH_PARAM; footer= END_DH_PARAM; break;
- case CERTREQ_TYPE: header= BEGIN_CERT_REQ; footer= END_CERT_REQ; break;
- default: header= BEGIN_RSA_PRIV; footer= END_RSA_PRIV; break;
- }
-
- switch (type) {
- case CA_TYPE: dynamicType = DYNAMIC_TYPE_CA; break;
- case CERT_TYPE: dynamicType = DYNAMIC_TYPE_CERT; break;
- case CRL_TYPE: dynamicType = DYNAMIC_TYPE_CRL; break;
- default: dynamicType = DYNAMIC_TYPE_KEY; break;
- }
-
- /* find header */
- for (;;) {
- headerEnd = XSTRNSTR((char*)buff, header, sz);
-
- if (headerEnd || type != PRIVATEKEY_TYPE) {
- break;
- } else if (header == BEGIN_RSA_PRIV) {
- header = BEGIN_PRIV_KEY; footer = END_PRIV_KEY;
- } else if (header == BEGIN_PRIV_KEY) {
- header = BEGIN_ENC_PRIV_KEY; footer = END_ENC_PRIV_KEY;
- } else if (header == BEGIN_ENC_PRIV_KEY) {
- header = BEGIN_EC_PRIV; footer = END_EC_PRIV;
- } else if (header == BEGIN_EC_PRIV) {
- header = BEGIN_DSA_PRIV; footer = END_DSA_PRIV;
- } else
- break;
+ if ((type == CA_TYPE) && (ctx == NULL)) {
+ WOLFSSL_MSG("Need context for CA load");
+ return BAD_FUNC_ARG;
}
- if (!headerEnd) {
- WOLFSSL_MSG("Couldn't find PEM header");
- return SSL_NO_PEM_HEADER;
- }
+ /* we may have a user cert chain, try to consume */
+ if ((type == CERT_TYPE || type == CA_TYPE) && (info->consumed < sz)) {
+ #ifdef WOLFSSL_SMALL_STACK
+ byte staticBuffer[1]; /* force heap usage */
+ #else
+ byte staticBuffer[FILE_BUFFER_SIZE]; /* tmp chain buffer */
+ #endif
+ byte* chainBuffer = staticBuffer;
+ int dynamicBuffer = 0;
+ word32 bufferSz;
+ long consumed = info->consumed;
+ word32 idx = 0;
+ int gotOne = 0;
+
+ /* Calculate max possible size, including max headers */
+ bufferSz = (word32)(sz - consumed) + (CERT_HEADER_SZ * MAX_CHAIN_DEPTH);
+ if (bufferSz > sizeof(staticBuffer)) {
+ WOLFSSL_MSG("Growing Tmp Chain Buffer");
+ /* will shrink to actual size */
+ chainBuffer = (byte*)XMALLOC(bufferSz, heap, DYNAMIC_TYPE_FILE);
+ if (chainBuffer == NULL) {
+ return MEMORY_E;
+ }
+ dynamicBuffer = 1;
+ }
- headerEnd += XSTRLEN(header);
+ WOLFSSL_MSG("Processing Cert Chain");
+ while (consumed < sz) {
+ DerBuffer* part = NULL;
+ word32 remain = (word32)(sz - consumed);
+ info->consumed = 0;
- /* eat end of line */
- if (headerEnd[0] == '\n')
- headerEnd++;
- else if (headerEnd[1] == '\n')
- headerEnd += 2;
- else
- return SSL_BAD_FILE;
+ if (format == WOLFSSL_FILETYPE_PEM) {
+ #ifdef WOLFSSL_PEM_TO_DER
+ ret = PemToDer(buff + consumed, remain, type, &part,
+ heap, info, NULL);
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif
+ }
+ else {
+ int length = remain;
+ if (format == WOLFSSL_FILETYPE_ASN1) {
+ /* get length of der (read sequence) */
+ word32 inOutIdx = 0;
+ if (GetSequence(buff + consumed, &inOutIdx, &length,
+ remain) < 0) {
+ ret = ASN_NO_PEM_HEADER;
+ }
+ length += inOutIdx; /* include leading sequence */
+ }
+ info->consumed = length;
+ if (ret == 0) {
+ ret = AllocDer(&part, length, type, heap);
+ if (ret == 0) {
+ XMEMCPY(part->buffer, buff + consumed, length);
+ }
+ }
+ }
+ if (ret == 0) {
+ gotOne = 1;
+#ifdef WOLFSSL_TLS13
+ cnt++;
+#endif
+ if ((idx + part->length + CERT_HEADER_SZ) > bufferSz) {
+ WOLFSSL_MSG(" Cert Chain bigger than buffer");
+ ret = BUFFER_E;
+ }
+ else {
+ c32to24(part->length, &chainBuffer[idx]);
+ idx += CERT_HEADER_SZ;
+ XMEMCPY(&chainBuffer[idx], part->buffer, part->length);
+ idx += part->length;
+ consumed += info->consumed;
+ if (used)
+ *used += info->consumed;
+ }
+
+ /* add CA's to certificate manager */
+ if (type == CA_TYPE) {
+ /* verify CA unless user set to no verify */
+ ret = AddCA(ctx->cm, &part, WOLFSSL_USER_CA, verify);
+ gotOne = 0; /* don't exit loop for CA type */
+ }
+ }
+
+ FreeDer(&part);
+
+ if (ret == ASN_NO_PEM_HEADER && gotOne) {
+ WOLFSSL_MSG("We got one good cert, so stuff at end ok");
+ break;
+ }
+
+ if (ret < 0) {
+ WOLFSSL_MSG(" Error in Cert in Chain");
+ if (dynamicBuffer)
+ XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
+ return ret;
+ }
+ WOLFSSL_MSG(" Consumed another Cert in Chain");
+ }
+ WOLFSSL_MSG("Finished Processing Cert Chain");
+
+ /* only retain actual size used */
+ ret = 0;
+ if (idx > 0) {
+ if (ssl) {
+ if (ssl->buffers.weOwnCertChain) {
+ FreeDer(&ssl->buffers.certChain);
+ }
+ ret = AllocDer(&ssl->buffers.certChain, idx, type, heap);
+ if (ret == 0) {
+ XMEMCPY(ssl->buffers.certChain->buffer, chainBuffer,
+ idx);
+ ssl->buffers.weOwnCertChain = 1;
+ }
+ #ifdef WOLFSSL_TLS13
+ ssl->buffers.certChainCnt = cnt;
+ #endif
+ } else if (ctx) {
+ FreeDer(&ctx->certChain);
+ ret = AllocDer(&ctx->certChain, idx, type, heap);
+ if (ret == 0) {
+ XMEMCPY(ctx->certChain->buffer, chainBuffer, idx);
+ }
+ #ifdef WOLFSSL_TLS13
+ ctx->certChainCnt = cnt;
+ #endif
+ }
+ }
- if (type == PRIVATEKEY_TYPE) {
- if (eccKey)
- *eccKey = header == BEGIN_EC_PRIV;
+ if (dynamicBuffer)
+ XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
}
-#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- {
- /* remove encrypted header if there */
- char encHeader[] = "Proc-Type";
- char* line = XSTRNSTR(headerEnd, encHeader, PEM_LINE_LEN);
- if (line) {
- char* newline;
- char* finish;
- char* start = XSTRNSTR(line, "DES", PEM_LINE_LEN);
+ return ret;
+}
- if (!start)
- start = XSTRNSTR(line, "AES", PEM_LINE_LEN);
+static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der,
+ int* keySz, word32* idx, int* resetSuites, int* keyFormat, void* heap, int devId)
+{
+ int ret = 0;
- if (!start) return SSL_BAD_FILE;
- if (!info) return SSL_BAD_FILE;
+ (void)heap;
+ (void)devId;
- finish = XSTRNSTR(start, ",", PEM_LINE_LEN);
+ if (ctx == NULL && ssl == NULL)
+ ret = BAD_FUNC_ARG;
+ if (!der || !keySz || !idx || !resetSuites || !keyFormat)
+ ret = BAD_FUNC_ARG;
- if (start && finish && (start < finish)) {
- newline = XSTRNSTR(finish, "\r", PEM_LINE_LEN);
+#ifndef NO_RSA
+ if (ret == 0 && (*keyFormat == 0 || *keyFormat == RSAk)) {
+ /* make sure RSA key can be used */
+ #ifdef WOLFSSL_SMALL_STACK
+ RsaKey* key;
+ #else
+ RsaKey key[1];
+ #endif
- XMEMCPY(info->name, start, finish - start);
- info->name[finish - start] = 0;
- XMEMCPY(info->iv, finish + 1, sizeof(info->iv));
+ #ifdef WOLFSSL_SMALL_STACK
+ key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA);
+ if (key == NULL)
+ return MEMORY_E;
+ #endif
- if (!newline) newline = XSTRNSTR(finish, "\n", PEM_LINE_LEN);
- if (newline && (newline > finish)) {
- info->ivSz = (word32)(newline - (finish + 1));
- info->set = 1;
+ ret = wc_InitRsaKey_ex(key, heap, devId);
+ if (ret == 0) {
+ *idx = 0;
+ if (wc_RsaPrivateKeyDecode(der->buffer, idx, key, der->length)
+ != 0) {
+ #if !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \
+ !defined(HAVE_ED448)
+ WOLFSSL_MSG("RSA decode failed and ECC/ED25519/ED448 not "
+ "enabled to try");
+ ret = WOLFSSL_BAD_FILE;
+ #endif
+ }
+ else {
+ /* check that the size of the RSA key is enough */
+ int minRsaSz = ssl ? ssl->options.minRsaKeySz :
+ ctx->minRsaKeySz;
+ *keySz = wc_RsaEncryptSize((RsaKey*)key);
+ if (*keySz < minRsaSz) {
+ ret = RSA_KEY_SIZE_E;
+ WOLFSSL_MSG("Private Key size too small");
+ }
+
+ if (ssl) {
+ ssl->buffers.keyType = rsa_sa_algo;
+ ssl->buffers.keySz = *keySz;
+ }
+ else {
+ ctx->privateKeyType = rsa_sa_algo;
+ ctx->privateKeySz = *keySz;
+ }
+
+ *keyFormat = RSAk;
+
+ if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
+ ssl->options.haveStaticECC = 0;
+ *resetSuites = 1;
}
- else
- return SSL_BAD_FILE;
}
- else
- return SSL_BAD_FILE;
- /* eat blank line */
- while (*newline == '\r' || *newline == '\n')
- newline++;
- headerEnd = newline;
+ wc_FreeRsaKey(key);
}
+
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(key, heap, DYNAMIC_TYPE_RSA);
+ #endif
}
-#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
+#endif
+#ifdef HAVE_ECC
+ if (ret == 0 && (*keyFormat == 0 || *keyFormat == ECDSAk)) {
+ /* make sure ECC key can be used */
+ #ifdef WOLFSSL_SMALL_STACK
+ ecc_key* key;
+ #else
+ ecc_key key[1];
+ #endif
- /* find footer */
- footerEnd = XSTRNSTR((char*)buff, footer, sz);
- if (!footerEnd)
- return SSL_BAD_FILE;
+ #ifdef WOLFSSL_SMALL_STACK
+ key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC);
+ if (key == NULL)
+ return MEMORY_E;
+ #endif
- consumedEnd = footerEnd + XSTRLEN(footer);
+ if (wc_ecc_init_ex(key, heap, devId) == 0) {
+ *idx = 0;
+ if (wc_EccPrivateKeyDecode(der->buffer, idx, key,
+ der->length) == 0) {
+ /* check for minimum ECC key size and then free */
+ int minKeySz = ssl ? ssl->options.minEccKeySz :
+ ctx->minEccKeySz;
+ *keySz = wc_ecc_size(key);
+ if (*keySz < minKeySz) {
+ WOLFSSL_MSG("ECC private key too small");
+ ret = ECC_KEY_SIZE_E;
+ }
- if (consumedEnd < bufferEnd) { /* handle no end of line on last line */
- /* eat end of line */
- if (consumedEnd[0] == '\n')
- consumedEnd++;
- else if (consumedEnd[1] == '\n')
- consumedEnd += 2;
- else
- return SSL_BAD_FILE;
- }
+ *keyFormat = ECDSAk;
+ if (ssl) {
+ ssl->options.haveStaticECC = 1;
+ ssl->buffers.keyType = ecc_dsa_sa_algo;
+ ssl->buffers.keySz = *keySz;
+ }
+ else {
+ ctx->haveStaticECC = 1;
+ ctx->privateKeyType = ecc_dsa_sa_algo;
+ ctx->privateKeySz = *keySz;
+ }
- if (info)
- info->consumed = (long)(consumedEnd - (char*)buff);
+ if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
+ *resetSuites = 1;
+ }
+ }
- /* set up der buffer */
- neededSz = (long)(footerEnd - headerEnd);
- if (neededSz > sz || neededSz < 0)
- return SSL_BAD_FILE;
+ wc_ecc_free(key);
+ }
- der->buffer = (byte*)XMALLOC(neededSz, heap, dynamicType);
- if (!der->buffer)
- return MEMORY_ERROR;
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(key, heap, DYNAMIC_TYPE_ECC);
+ #endif
+ }
+#endif /* HAVE_ECC */
+#ifdef HAVE_ED25519
+ if (ret == 0 && (*keyFormat == 0 || *keyFormat == ED25519k)) {
+ /* make sure Ed25519 key can be used */
+ #ifdef WOLFSSL_SMALL_STACK
+ ed25519_key* key;
+ #else
+ ed25519_key key[1];
+ #endif
- der->length = (word32)neededSz;
+ #ifdef WOLFSSL_SMALL_STACK
+ key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap,
+ DYNAMIC_TYPE_ED25519);
+ if (key == NULL)
+ return MEMORY_E;
+ #endif
- if (Base64_Decode((byte*)headerEnd, (word32)neededSz, der->buffer,
- &der->length) < 0)
- return SSL_BAD_FILE;
+ ret = wc_ed25519_init(key);
+ if (ret == 0) {
+ *idx = 0;
+ if (wc_Ed25519PrivateKeyDecode(der->buffer, idx, key,
+ der->length) == 0) {
+ /* check for minimum key size and then free */
+ int minKeySz = ssl ? ssl->options.minEccKeySz :
+ ctx->minEccKeySz;
+ *keySz = ED25519_KEY_SIZE;
+ if (*keySz < minKeySz) {
+ WOLFSSL_MSG("ED25519 private key too small");
+ ret = ECC_KEY_SIZE_E;
+ }
+ if (ret == 0) {
+ if (ssl) {
+ ssl->buffers.keyType = ed25519_sa_algo;
+ ssl->buffers.keySz = *keySz;
+ }
+ else if (ctx) {
+ ctx->privateKeyType = ed25519_sa_algo;
+ ctx->privateKeySz = *keySz;
+ }
- if (header == BEGIN_PRIV_KEY) {
- /* pkcs8 key, convert and adjust length */
- if ((ret = ToTraditional(der->buffer, der->length)) < 0)
- return ret;
+ *keyFormat = ED25519k;
+ if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
+ *resetSuites = 1;
+ }
+ }
+ }
- der->length = ret;
- return 0;
- }
+ wc_ed25519_free(key);
+ }
-#if (defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)) && !defined(NO_PWDBASED)
- if (header == BEGIN_ENC_PRIV_KEY) {
- int passwordSz;
#ifdef WOLFSSL_SMALL_STACK
- char* password = NULL;
+ XFREE(key, heap, DYNAMIC_TYPE_ED25519);
+ #endif
+ }
+#endif /* HAVE_ED25519 */
+#ifdef HAVE_ED448
+ if (ret == 0 && (*keyFormat == 0 || *keyFormat == ED448k)) {
+ /* make sure Ed448 key can be used */
+ #ifdef WOLFSSL_SMALL_STACK
+ ed448_key* key = NULL;
#else
- char password[80];
+ ed448_key key[1];
#endif
- if (!info || !info->ctx || !info->ctx->passwd_cb)
- return SSL_BAD_FILE; /* no callback error */
-
#ifdef WOLFSSL_SMALL_STACK
- password = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (password == NULL)
+ key = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448);
+ if (key == NULL)
return MEMORY_E;
#endif
- passwordSz = info->ctx->passwd_cb(password, sizeof(password), 0,
- info->ctx->userdata);
- /* convert and adjust length */
- ret = ToTraditionalEnc(der->buffer, der->length, password, passwordSz);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(password, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
+ ret = wc_ed448_init(key);
+ if (ret == 0) {
+ *idx = 0;
+ if (wc_Ed448PrivateKeyDecode(der->buffer, idx, key,
+ der->length) != 0) {
+ ret = WOLFSSL_BAD_FILE;
+ }
- if (ret < 0)
- return ret;
+ if (ret == 0) {
+ /* check for minimum key size and then free */
+ int minKeySz = ssl ? ssl->options.minEccKeySz :
+ ctx->minEccKeySz;
+ *keySz = ED448_KEY_SIZE;
+ if (*keySz < minKeySz) {
+ WOLFSSL_MSG("ED448 private key too small");
+ ret = ECC_KEY_SIZE_E;
+ }
+ }
+ if (ret == 0) {
+ if (ssl) {
+ ssl->buffers.keyType = ed448_sa_algo;
+ ssl->buffers.keySz = *keySz;
+ }
+ else if (ctx) {
+ ctx->privateKeyType = ed448_sa_algo;
+ ctx->privateKeySz = *keySz;
+ }
- der->length = ret;
- return 0;
- }
-#endif
+ *keyFormat = ED448k;
+ if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
+ *resetSuites = 1;
+ }
+ }
- return 0;
-}
+ wc_ed448_free(key);
+ }
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(key, heap, DYNAMIC_TYPE_ED448);
+ #endif
+ }
+#endif /* HAVE_ED448 */
+ return ret;
+}
-/* process the buffer buff, legnth sz, into ctx of format and type
+/* process the buffer buff, length sz, into ctx of format and type
used tracks bytes consumed, userChain specifies a user cert chain
to pass during the handshake */
-static int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
+int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
long sz, int format, int type, WOLFSSL* ssl,
- long* used, int userChain)
-{
- buffer der; /* holds DER or RAW (for NTRU) */
- int ret;
- int dynamicType = 0;
- int eccKey = 0;
- int rsaKey = 0;
- void* heap = ctx ? ctx->heap : NULL;
+ long* used, int userChain, int verify)
+{
+ DerBuffer* der = NULL; /* holds DER or RAW (for NTRU) */
+ int ret = 0;
+ int done = 0;
+ int keyFormat = 0;
+ int resetSuites = 0;
+ void* heap = wolfSSL_CTX_GetHeap(ctx, ssl);
+ int devId = wolfSSL_CTX_GetDevId(ctx, ssl);
+ word32 idx = 0;
+ int keySz = 0;
+#if (defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)) || \
+ defined(HAVE_PKCS8)
+ word32 algId = 0;
+#endif
#ifdef WOLFSSL_SMALL_STACK
EncryptedInfo* info = NULL;
#else
EncryptedInfo info[1];
#endif
- (void)dynamicType;
- (void)rsaKey;
+ (void)devId;
+ (void)idx;
+ (void)keySz;
if (used)
*used = sz; /* used bytes default to sz, PEM chain may shorten*/
- if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM
- && format != SSL_FILETYPE_RAW)
- return SSL_BAD_FILETYPE;
+ /* check args */
+ if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM
+ && format != WOLFSSL_FILETYPE_RAW)
+ return WOLFSSL_BAD_FILETYPE;
if (ctx == NULL && ssl == NULL)
return BAD_FUNC_ARG;
- if (type == CA_TYPE)
- dynamicType = DYNAMIC_TYPE_CA;
- else if (type == CERT_TYPE)
- dynamicType = DYNAMIC_TYPE_CERT;
- else
- dynamicType = DYNAMIC_TYPE_KEY;
-
#ifdef WOLFSSL_SMALL_STACK
- info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
+ info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap,
+ DYNAMIC_TYPE_ENCRYPTEDINFO);
if (info == NULL)
return MEMORY_E;
#endif
- info->set = 0;
- info->ctx = ctx;
- info->consumed = 0;
- der.buffer = 0;
-
- if (format == SSL_FILETYPE_PEM) {
- ret = PemToDer(buff, sz, type, &der, heap, info, &eccKey);
- if (ret < 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- XFREE(der.buffer, heap, dynamicType);
- return ret;
- }
-
- if (used)
- *used = info->consumed;
+ XMEMSET(info, 0, sizeof(EncryptedInfo));
+#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
+ if (ctx) {
+ info->passwd_cb = ctx->passwd_cb;
+ info->passwd_userdata = ctx->passwd_userdata;
+ }
+#endif
- /* we may have a user cert chain, try to consume */
- if (userChain && type == CERT_TYPE && info->consumed < sz) {
- #ifdef WOLFSSL_SMALL_STACK
- byte staticBuffer[1]; /* force heap usage */
- #else
- byte staticBuffer[FILE_BUFFER_SIZE]; /* tmp chain buffer */
- #endif
- byte* chainBuffer = staticBuffer;
- byte* shrinked = NULL; /* shrinked to size chainBuffer
- * or staticBuffer */
- int dynamicBuffer = 0;
- word32 bufferSz = sizeof(staticBuffer);
- long consumed = info->consumed;
- word32 idx = 0;
- int gotOne = 0;
-
- if ( (sz - consumed) > (int)bufferSz) {
- WOLFSSL_MSG("Growing Tmp Chain Buffer");
- bufferSz = (word32)(sz - consumed);
- /* will shrink to actual size */
- chainBuffer = (byte*)XMALLOC(bufferSz, heap, DYNAMIC_TYPE_FILE);
- if (chainBuffer == NULL) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- XFREE(der.buffer, heap, dynamicType);
- return MEMORY_E;
- }
- dynamicBuffer = 1;
+ if (format == WOLFSSL_FILETYPE_PEM) {
+ #ifdef WOLFSSL_PEM_TO_DER
+ ret = PemToDer(buff, sz, type, &der, heap, info, &keyFormat);
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif
+ }
+ else {
+ /* ASN1 (DER) or RAW (NTRU) */
+ int length = (int)sz;
+ if (format == WOLFSSL_FILETYPE_ASN1) {
+ /* get length of der (read sequence or octet string) */
+ word32 inOutIdx = 0;
+ if (GetSequence(buff, &inOutIdx, &length, (word32)sz) >= 0) {
+ length += inOutIdx; /* include leading sequence */
}
+ /* get length using octect string (allowed for private key types) */
+ else if (type == PRIVATEKEY_TYPE &&
+ GetOctetString(buff, &inOutIdx, &length, (word32)sz) >= 0) {
+ length += inOutIdx; /* include leading oct string */
+ }
+ else {
+ ret = ASN_PARSE_E;
+ }
+ }
- WOLFSSL_MSG("Processing Cert Chain");
- while (consumed < sz) {
- buffer part;
- info->consumed = 0;
- part.buffer = 0;
-
- ret = PemToDer(buff + consumed, sz - consumed, type, &part,
- heap, info, &eccKey);
- if (ret == 0) {
- gotOne = 1;
- if ( (idx + part.length) > bufferSz) {
- WOLFSSL_MSG(" Cert Chain bigger than buffer");
- ret = BUFFER_E;
- }
- else {
- c32to24(part.length, &chainBuffer[idx]);
- idx += CERT_HEADER_SZ;
- XMEMCPY(&chainBuffer[idx], part.buffer,part.length);
- idx += part.length;
- consumed += info->consumed;
- if (used)
- *used += info->consumed;
- }
- }
-
- XFREE(part.buffer, heap, dynamicType);
-
- if (ret == SSL_NO_PEM_HEADER && gotOne) {
- WOLFSSL_MSG("We got one good PEM so stuff at end ok");
- break;
- }
+ info->consumed = length;
- if (ret < 0) {
- WOLFSSL_MSG(" Error in Cert in Chain");
- if (dynamicBuffer)
- XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- XFREE(der.buffer, heap, dynamicType);
- return ret;
- }
- WOLFSSL_MSG(" Consumed another Cert in Chain");
+ if (ret == 0) {
+ ret = AllocDer(&der, (word32)length, type, heap);
+ if (ret == 0) {
+ XMEMCPY(der->buffer, buff, length);
}
- WOLFSSL_MSG("Finished Processing Cert Chain");
- /* only retain actual size used */
- shrinked = (byte*)XMALLOC(idx, heap, dynamicType);
- if (shrinked) {
- if (ssl) {
- if (ssl->buffers.certChain.buffer &&
- ssl->buffers.weOwnCertChain) {
- XFREE(ssl->buffers.certChain.buffer, heap,
- dynamicType);
- }
- ssl->buffers.certChain.buffer = shrinked;
- ssl->buffers.certChain.length = idx;
- XMEMCPY(ssl->buffers.certChain.buffer, chainBuffer,idx);
- ssl->buffers.weOwnCertChain = 1;
- } else if (ctx) {
- if (ctx->certChain.buffer)
- XFREE(ctx->certChain.buffer, heap, dynamicType);
- ctx->certChain.buffer = shrinked;
- ctx->certChain.length = idx;
- XMEMCPY(ctx->certChain.buffer, chainBuffer, idx);
+ #ifdef HAVE_PKCS8
+ /* if private key try and remove PKCS8 header */
+ if (type == PRIVATEKEY_TYPE) {
+ if ((ret = ToTraditional_ex(der->buffer, der->length, &algId)) > 0) {
+ /* Found PKCS8 header */
+ /* ToTraditional_ex moves buff and returns adjusted length */
+ der->length = ret;
}
+ ret = 0; /* failures should be ignored */
}
-
- if (dynamicBuffer)
- XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
-
- if (shrinked == NULL) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- XFREE(der.buffer, heap, dynamicType);
- return MEMORY_E;
- }
- }
- }
- else { /* ASN1 (DER) or RAW (NTRU) */
- der.buffer = (byte*) XMALLOC(sz, heap, dynamicType);
- if (!der.buffer) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- return MEMORY_ERROR;
}
-
- XMEMCPY(der.buffer, buff, sz);
- der.length = (word32)sz;
}
-#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- if (info->set) {
- /* decrypt */
- int passwordSz;
-#ifdef WOLFSSL_SMALL_STACK
- char* password = NULL;
- byte* key = NULL;
- byte* iv = NULL;
-#else
- char password[80];
- byte key[AES_256_KEY_SIZE];
- #ifndef NO_MD5
- byte iv[AES_IV_SIZE];
- #endif
-#endif
-
- #ifdef WOLFSSL_SMALL_STACK
- password = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- key = (byte*)XMALLOC(AES_256_KEY_SIZE, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- iv = (byte*)XMALLOC(AES_IV_SIZE, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
-
- if (password == NULL || key == NULL || iv == NULL) {
- XFREE(password, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(iv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- ret = MEMORY_E;
- }
- else
- #endif
- if (!ctx || !ctx->passwd_cb) {
- ret = NO_PASSWORD;
- }
- else {
- passwordSz = ctx->passwd_cb(password, sizeof(password), 0,
- ctx->userdata);
+ if (used) {
+ *used = info->consumed;
+ }
- /* use file's salt for key derivation, hex decode first */
- if (Base16_Decode(info->iv, info->ivSz, info->iv, &info->ivSz)
- != 0) {
- ret = ASN_INPUT_E;
- }
-#ifndef NO_MD5
- else if ((ret = EVP_BytesToKey(info->name, "MD5", info->iv,
- (byte*)password, passwordSz, 1, key, iv)) <= 0) {
- /* empty */
- }
-#endif
-#ifndef NO_DES3
- else if (XSTRNCMP(info->name, "DES-CBC", 7) == 0) {
- ret = wc_Des_CbcDecryptWithKey(der.buffer, der.buffer, der.length,
- key, info->iv);
- }
- else if (XSTRNCMP(info->name, "DES-EDE3-CBC", 13) == 0) {
- ret = wc_Des3_CbcDecryptWithKey(der.buffer, der.buffer, der.length,
- key, info->iv);
- }
-#endif
-#ifndef NO_AES
- else if (XSTRNCMP(info->name, "AES-128-CBC", 13) == 0) {
- ret = wc_AesCbcDecryptWithKey(der.buffer, der.buffer, der.length,
- key, AES_128_KEY_SIZE, info->iv);
- }
- else if (XSTRNCMP(info->name, "AES-192-CBC", 13) == 0) {
- ret = wc_AesCbcDecryptWithKey(der.buffer, der.buffer, der.length,
- key, AES_192_KEY_SIZE, info->iv);
- }
- else if (XSTRNCMP(info->name, "AES-256-CBC", 13) == 0) {
- ret = wc_AesCbcDecryptWithKey(der.buffer, der.buffer, der.length,
- key, AES_256_KEY_SIZE, info->iv);
- }
-#endif
- else {
- ret = SSL_BAD_FILE;
- }
+ /* process user chain */
+ if (ret >= 0) {
+ /* Chain should have server cert first, then intermediates, then root.
+ * First certificate in chain is processed below after ProcessUserChain
+ * and is loaded into ssl->buffers.certificate.
+ * Remainder are processed using ProcessUserChain and are loaded into
+ * ssl->buffers.certChain. */
+ if (userChain) {
+ ret = ProcessUserChain(ctx, buff, sz, format, type, ssl, used, info,
+ verify);
}
+ }
+ /* info is only used for private key with DER or PEM, so free now */
+ if (ret < 0 || type != PRIVATEKEY_TYPE || format == WOLFSSL_FILETYPE_RAW) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(password, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(iv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
#endif
-
- if (ret != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- XFREE(der.buffer, heap, dynamicType);
- return ret;
- }
}
-#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ /* check for error */
+ if (ret < 0) {
+ FreeDer(&der);
+ done = 1;
+ }
- if (type == CA_TYPE) {
+ if (done == 1) {
+ /* No operation, just skip the next section */
+ }
+ /* Handle DER owner */
+ else if (type == CA_TYPE) {
if (ctx == NULL) {
WOLFSSL_MSG("Need context for CA load");
- XFREE(der.buffer, heap, dynamicType);
+ FreeDer(&der);
return BAD_FUNC_ARG;
}
- return AddCA(ctx->cm, der, WOLFSSL_USER_CA, ctx->verifyPeer);
- /* takes der over */
+ /* verify CA unless user set to no verify */
+ ret = AddCA(ctx->cm, &der, WOLFSSL_USER_CA, verify);
+ done = 1;
}
+#ifdef WOLFSSL_TRUST_PEER_CERT
+ else if (type == TRUSTED_PEER_TYPE) {
+ if (ctx == NULL) {
+ WOLFSSL_MSG("Need context for trusted peer cert load");
+ FreeDer(&der);
+ return BAD_FUNC_ARG;
+ }
+ /* add trusted peer cert */
+ ret = AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone);
+ done = 1;
+ }
+#endif /* WOLFSSL_TRUST_PEER_CERT */
else if (type == CERT_TYPE) {
if (ssl) {
- if (ssl->buffers.weOwnCert && ssl->buffers.certificate.buffer)
- XFREE(ssl->buffers.certificate.buffer, heap, dynamicType);
+ /* Make sure previous is free'd */
+ if (ssl->buffers.weOwnCert) {
+ FreeDer(&ssl->buffers.certificate);
+ #ifdef KEEP_OUR_CERT
+ FreeX509(ssl->ourCert);
+ if (ssl->ourCert) {
+ XFREE(ssl->ourCert, ssl->heap, DYNAMIC_TYPE_X509);
+ ssl->ourCert = NULL;
+ }
+ #endif
+ }
ssl->buffers.certificate = der;
+ #ifdef KEEP_OUR_CERT
+ ssl->keepCert = 1; /* hold cert for ssl lifetime */
+ #endif
ssl->buffers.weOwnCert = 1;
}
else if (ctx) {
- if (ctx->certificate.buffer)
- XFREE(ctx->certificate.buffer, heap, dynamicType);
- ctx->certificate = der; /* takes der over */
+ FreeDer(&ctx->certificate); /* Make sure previous is free'd */
+ #ifdef KEEP_OUR_CERT
+ if (ctx->ourCert) {
+ if (ctx->ownOurCert) {
+ FreeX509(ctx->ourCert);
+ XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509);
+ }
+ ctx->ourCert = NULL;
+ }
+ #endif
+ ctx->certificate = der;
}
}
else if (type == PRIVATEKEY_TYPE) {
if (ssl) {
- if (ssl->buffers.weOwnKey && ssl->buffers.key.buffer)
- XFREE(ssl->buffers.key.buffer, heap, dynamicType);
+ /* Make sure previous is free'd */
+ if (ssl->buffers.weOwnKey) {
+ FreeDer(&ssl->buffers.key);
+ }
ssl->buffers.key = der;
ssl->buffers.weOwnKey = 1;
}
else if (ctx) {
- if (ctx->privateKey.buffer)
- XFREE(ctx->privateKey.buffer, heap, dynamicType);
- ctx->privateKey = der; /* takes der over */
+ FreeDer(&ctx->privateKey);
+ ctx->privateKey = der;
}
}
else {
- XFREE(der.buffer, heap, dynamicType);
- return SSL_BAD_CERTTYPE;
+ FreeDer(&der);
+ return WOLFSSL_BAD_CERTTYPE;
}
- if (type == PRIVATEKEY_TYPE && format != SSL_FILETYPE_RAW) {
- #ifndef NO_RSA
- if (!eccKey) {
- /* make sure RSA key can be used */
- word32 idx = 0;
- #ifdef WOLFSSL_SMALL_STACK
- RsaKey* key = NULL;
- #else
- RsaKey key[1];
- #endif
+ if (done == 1) {
+ /* No operation, just skip the next section */
+ }
+ else if (type == PRIVATEKEY_TYPE && format != WOLFSSL_FILETYPE_RAW) {
+ #if defined(WOLFSSL_ENCRYPTED_KEYS) || defined(HAVE_PKCS8)
+ keyFormat = algId;
+ #endif
- #ifdef WOLFSSL_SMALL_STACK
- key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (key == NULL)
+ ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx, &resetSuites,
+ &keyFormat, heap, devId);
+
+ #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
+ /* for WOLFSSL_FILETYPE_PEM, PemToDer manages the decryption */
+ /* If private key type PKCS8 header wasn't already removed (algoId == 0) */
+ if ((ret != 0 || keyFormat == 0)
+ && format != WOLFSSL_FILETYPE_PEM && info->passwd_cb && algId == 0)
+ {
+ int passwordSz = NAME_SZ;
+ #ifndef WOLFSSL_SMALL_STACK
+ char password[NAME_SZ];
+ #else
+ char* password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING);
+ if (password == NULL) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
+ #endif
+ FreeDer(&der);
return MEMORY_E;
+ }
#endif
-
- ret = wc_InitRsaKey(key, 0);
- if (ret == 0) {
- if (wc_RsaPrivateKeyDecode(der.buffer, &idx, key, der.length) !=
- 0) {
- #ifdef HAVE_ECC
- /* could have DER ECC (or pkcs8 ecc), no easy way to tell */
- eccKey = 1; /* so try it out */
- #endif
- if (!eccKey)
- ret = SSL_BAD_FILE;
- } else {
- rsaKey = 1;
- (void)rsaKey; /* for no ecc builds */
+ /* get password */
+ ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ,
+ info->passwd_userdata);
+ if (ret >= 0) {
+ passwordSz = ret;
+
+ /* PKCS8 decrypt */
+ ret = ToTraditionalEnc(der->buffer, der->length,
+ password, passwordSz, &algId);
+ if (ret >= 0) {
+ der->length = ret;
}
- }
+ /* ignore failures and try parsing as unencrypted */
- wc_FreeRsaKey(key);
+ ForceZero(password, passwordSz);
+ }
#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(password, heap, DYNAMIC_TYPE_STRING);
#endif
-
- if (ret != 0)
- return ret;
+ ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx,
+ &resetSuites, &keyFormat, heap, devId);
}
+ #endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */
+
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
#endif
- #ifdef HAVE_ECC
- if (!rsaKey) {
- /* make sure ECC key can be used */
- word32 idx = 0;
- ecc_key key;
- wc_ecc_init(&key);
- if (wc_EccPrivateKeyDecode(der.buffer,&idx,&key,der.length) != 0) {
- wc_ecc_free(&key);
- return SSL_BAD_FILE;
- }
- wc_ecc_free(&key);
- eccKey = 1;
- if (ctx)
- ctx->haveStaticECC = 1;
- if (ssl)
- ssl->options.haveStaticECC = 1;
- }
- #endif /* HAVE_ECC */
+ if (ret != 0)
+ return ret;
+ if (keyFormat == 0)
+ return WOLFSSL_BAD_FILE;
+
+ (void)devId;
}
else if (type == CERT_TYPE) {
#ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert = NULL;
+ DecodedCert* cert;
#else
DecodedCert cert[1];
#endif
+ #ifdef HAVE_PK_CALLBACKS
+ int keyType = 0;
+ #endif
#ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap,
+ DYNAMIC_TYPE_DCERT);
if (cert == NULL)
return MEMORY_E;
#endif
WOLFSSL_MSG("Checking cert signature type");
- InitDecodedCert(cert, der.buffer, der.length, heap);
+ InitDecodedCert(cert, der->buffer, der->length, heap);
if (DecodeToKey(cert, 0) < 0) {
WOLFSSL_MSG("Decode to key failed");
+ FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(cert, heap, DYNAMIC_TYPE_DCERT);
#endif
- return SSL_BAD_FILE;
+ return WOLFSSL_BAD_FILE;
+ }
+
+ if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
+ resetSuites = 1;
+ }
+ if (ssl && ssl->ctx->haveECDSAsig) {
+ WOLFSSL_MSG("SSL layer setting cert, CTX had ECDSA, turning off");
+ ssl->options.haveECDSAsig = 0; /* may turn back on next */
}
+
switch (cert->signatureOID) {
case CTC_SHAwECDSA:
case CTC_SHA256wECDSA:
case CTC_SHA384wECDSA:
case CTC_SHA512wECDSA:
WOLFSSL_MSG("ECDSA cert signature");
- if (ctx)
+ if (ssl)
+ ssl->options.haveECDSAsig = 1;
+ else if (ctx)
+ ctx->haveECDSAsig = 1;
+ break;
+ case CTC_ED25519:
+ WOLFSSL_MSG("ED25519 cert signature");
+ if (ssl)
+ ssl->options.haveECDSAsig = 1;
+ else if (ctx)
ctx->haveECDSAsig = 1;
+ break;
+ case CTC_ED448:
+ WOLFSSL_MSG("ED448 cert signature");
if (ssl)
ssl->options.haveECDSAsig = 1;
+ else if (ctx)
+ ctx->haveECDSAsig = 1;
break;
default:
WOLFSSL_MSG("Not ECDSA cert signature");
break;
}
- #ifdef HAVE_ECC
- if (ctx)
- ctx->pkCurveOID = cert->pkCurveOID;
- if (ssl)
+ #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+ if (ssl) {
ssl->pkCurveOID = cert->pkCurveOID;
+ #ifndef WC_STRICT_SIG
+ if (cert->keyOID == ECDSAk) {
+ ssl->options.haveECC = 1;
+ }
+ #ifdef HAVE_ED25519
+ else if (cert->keyOID == ED25519k) {
+ ssl->options.haveECC = 1;
+ }
+ #endif
+ #ifdef HAVE_ED448
+ else if (cert->keyOID == ED448k) {
+ ssl->options.haveECC = 1;
+ }
+ #endif
+ #else
+ ssl->options.haveECC = ssl->options.haveECDSAsig;
+ #endif
+ }
+ else if (ctx) {
+ ctx->pkCurveOID = cert->pkCurveOID;
+ #ifndef WC_STRICT_SIG
+ if (cert->keyOID == ECDSAk) {
+ ctx->haveECC = 1;
+ }
+ #ifdef HAVE_ED25519
+ else if (cert->keyOID == ED25519k) {
+ ctx->haveECC = 1;
+ }
+ #endif
+ #ifdef HAVE_ED448
+ else if (cert->keyOID == ED448k) {
+ ctx->haveECC = 1;
+ }
+ #endif
+ #else
+ ctx->haveECC = ctx->haveECDSAsig;
+ #endif
+ }
+ #endif
+
+ /* check key size of cert unless specified not to */
+ switch (cert->keyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ #ifdef HAVE_PK_CALLBACKS
+ keyType = rsa_sa_algo;
+ #endif
+ #ifdef HAVE_PKCS11
+ if (ctx) {
+ ctx->privateKeyType = rsa_sa_algo;
+ }
+ else {
+ ssl->buffers.keyType = rsa_sa_algo;
+ }
+ #endif
+ /* Determine RSA key size by parsing public key */
+ idx = 0;
+ ret = wc_RsaPublicKeyDecode_ex(cert->publicKey, &idx,
+ cert->pubKeySize, NULL, (word32*)&keySz, NULL, NULL);
+ if (ret < 0)
+ break;
+
+ if (ssl && !ssl->options.verifyNone) {
+ if (ssl->options.minRsaKeySz < 0 ||
+ keySz < (int)ssl->options.minRsaKeySz) {
+ ret = RSA_KEY_SIZE_E;
+ WOLFSSL_MSG("Certificate RSA key size too small");
+ }
+ }
+ else if (ctx && !ctx->verifyNone) {
+ if (ctx->minRsaKeySz < 0 ||
+ keySz < (int)ctx->minRsaKeySz) {
+ ret = RSA_KEY_SIZE_E;
+ WOLFSSL_MSG("Certificate RSA key size too small");
+ }
+ }
+ break;
+ #endif /* !NO_RSA */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ #ifdef HAVE_PK_CALLBACKS
+ keyType = ecc_dsa_sa_algo;
+ #endif
+ #ifdef HAVE_PKCS11
+ if (ctx) {
+ ctx->privateKeyType = ecc_dsa_sa_algo;
+ }
+ else {
+ ssl->buffers.keyType = ecc_dsa_sa_algo;
+ }
+ #endif
+ /* Determine ECC key size based on curve */
+ keySz = wc_ecc_get_curve_size_from_id(
+ wc_ecc_get_oid(cert->pkCurveOID, NULL, NULL));
+
+ if (ssl && !ssl->options.verifyNone) {
+ if (ssl->options.minEccKeySz < 0 ||
+ keySz < (int)ssl->options.minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG("Certificate ECC key size error");
+ }
+ }
+ else if (ctx && !ctx->verifyNone) {
+ if (ctx->minEccKeySz < 0 ||
+ keySz < (int)ctx->minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG("Certificate ECC key size error");
+ }
+ }
+ break;
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ #ifdef HAVE_PK_CALLBACKS
+ keyType = ed25519_sa_algo;
+ #endif
+ #ifdef HAVE_PKCS11
+ if (ctx) {
+ ctx->privateKeyType = ed25519_sa_algo;
+ }
+ else {
+ ssl->buffers.keyType = ed25519_sa_algo;
+ }
+ #endif
+ /* ED25519 is fixed key size */
+ keySz = ED25519_KEY_SIZE;
+ if (ssl && !ssl->options.verifyNone) {
+ if (ssl->options.minEccKeySz < 0 ||
+ keySz < (int)ssl->options.minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG("Certificate Ed key size error");
+ }
+ }
+ else if (ctx && !ctx->verifyNone) {
+ if (ctx->minEccKeySz < 0 ||
+ keySz < (int)ctx->minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG("Certificate ECC key size error");
+ }
+ }
+ break;
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ED448k:
+ #ifdef HAVE_PK_CALLBACKS
+ keyType = ed448_sa_algo;
+ #endif
+ #ifdef HAVE_PKCS11
+ if (ctx) {
+ ctx->privateKeyType = ed448_sa_algo;
+ }
+ else {
+ ssl->buffers.keyType = ed448_sa_algo;
+ }
+ #endif
+ /* ED448 is fixed key size */
+ keySz = ED448_KEY_SIZE;
+ if (ssl && !ssl->options.verifyNone) {
+ if (ssl->options.minEccKeySz < 0 ||
+ keySz < (int)ssl->options.minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG("Certificate Ed key size error");
+ }
+ }
+ else if (ctx && !ctx->verifyNone) {
+ if (ctx->minEccKeySz < 0 ||
+ keySz < (int)ctx->minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG("Certificate ECC key size error");
+ }
+ }
+ break;
+ #endif /* HAVE_ED448 */
+
+ default:
+ WOLFSSL_MSG("No key size check done on certificate");
+ break; /* do no check if not a case for the key */
+ }
+
+ #ifdef HAVE_PK_CALLBACKS
+ if (ssl && ssl->buffers.keyType == 0) {
+ ssl->buffers.keyType = keyType;
+ ssl->buffers.keySz = keySz;
+ }
+ else if (ctx && ctx->privateKeyType == 0) {
+ ctx->privateKeyType = keyType;
+ ctx->privateKeySz = keySz;
+ }
#endif
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(cert, heap, DYNAMIC_TYPE_DCERT);
#endif
+
+ if (ret != 0) {
+ done = 1;
+ }
}
- return SSL_SUCCESS;
+ if (done == 1) {
+ #ifndef NO_WOLFSSL_CM_VERIFY
+ if ((type == CA_TYPE) || (type == CERT_TYPE)) {
+ /* Call to over-ride status */
+ if ((ctx != NULL) && (ctx->cm != NULL) &&
+ (ctx->cm->verifyCallback != NULL)) {
+ ret = CM_VerifyBuffer_ex(ctx->cm, buff,
+ sz, format, (ret == WOLFSSL_SUCCESS ? 0 : ret));
+ }
+ }
+ #endif /* NO_WOLFSSL_CM_VERIFY */
+
+ return ret;
+ }
+
+
+ if (ssl && resetSuites) {
+ word16 havePSK = 0;
+ word16 haveRSA = 0;
+
+ #ifndef NO_PSK
+ if (ssl->options.havePSK) {
+ havePSK = 1;
+ }
+ #endif
+ #ifndef NO_RSA
+ haveRSA = 1;
+ #endif
+ #ifndef NO_CERTS
+ keySz = ssl->buffers.keySz;
+ #endif
+
+ /* let's reset suites */
+ InitSuites(ssl->suites, ssl->version, keySz, haveRSA,
+ havePSK, ssl->options.haveDH, ssl->options.haveNTRU,
+ ssl->options.haveECDSAsig, ssl->options.haveECC,
+ ssl->options.haveStaticECC, ssl->options.side);
+ }
+
+ return WOLFSSL_SUCCESS;
}
/* CA PEM file for verification, may have multiple/chain certs to process */
static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
- long sz, int format, int type, WOLFSSL* ssl)
+ long sz, int format, int type, WOLFSSL* ssl, int verify)
{
long used = 0;
int ret = 0;
@@ -2781,34 +5778,248 @@ static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
long consumed = 0;
ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl,
- &consumed, 0);
+ &consumed, 0, verify);
- if (ret == SSL_NO_PEM_HEADER && gotOne) {
- WOLFSSL_MSG("We got one good PEM file so stuff at end ok");
- ret = SSL_SUCCESS;
- break;
+ if (ret < 0) {
+#if defined(WOLFSSL_WPAS) && defined(HAVE_CRL)
+ DerBuffer* der = NULL;
+ EncryptedInfo info;
+
+ WOLFSSL_MSG("Trying a CRL");
+ if (PemToDer(buff + used, sz - used, CRL_TYPE, &der, NULL, &info,
+ NULL) == 0) {
+ WOLFSSL_MSG(" Processed a CRL");
+ wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer,
+ der->length, WOLFSSL_FILETYPE_ASN1);
+ FreeDer(&der);
+ used += info.consumed;
+ continue;
+ }
+#endif
+
+ if (consumed > 0) { /* Made progress in file */
+ WOLFSSL_ERROR(ret);
+ WOLFSSL_MSG("CA Parse failed, with progress in file.");
+ WOLFSSL_MSG("Search for other certs in file");
+ }
+ else {
+ WOLFSSL_MSG("CA Parse failed, no progress in file.");
+ WOLFSSL_MSG("Do not continue search for other certs in file");
+ break;
+ }
}
+ else {
+ WOLFSSL_MSG(" Processed a CA");
+ gotOne = 1;
+ }
+ used += consumed;
+ }
- if (ret < 0)
- break;
+ if (gotOne) {
+ WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK");
+ return WOLFSSL_SUCCESS;
+ }
+ return ret;
+}
- WOLFSSL_MSG(" Processed a CA");
- gotOne = 1;
- used += consumed;
+
+static WC_INLINE WOLFSSL_METHOD* cm_pick_method(void)
+{
+ #ifndef NO_WOLFSSL_CLIENT
+ #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3)
+ return wolfSSLv3_client_method();
+ #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10)
+ return wolfTLSv1_client_method();
+ #elif !defined(NO_OLD_TLS)
+ return wolfTLSv1_1_client_method();
+ #elif !defined(WOLFSSL_NO_TLS12)
+ return wolfTLSv1_2_client_method();
+ #elif defined(WOLFSSL_TLS13)
+ return wolfTLSv1_3_client_method();
+ #else
+ return NULL;
+ #endif
+ #elif !defined(NO_WOLFSSL_SERVER)
+ #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3)
+ return wolfSSLv3_server_method();
+ #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10)
+ return wolfTLSv1_server_method();
+ #elif !defined(NO_OLD_TLS)
+ return wolfTLSv1_1_server_method();
+ #elif !defined(WOLFSSL_NO_TLS12)
+ return wolfTLSv1_2_server_method();
+ #elif defined(WOLFSSL_TLS13)
+ return wolfTLSv1_3_server_method();
+ #else
+ return NULL;
+ #endif
+ #else
+ return NULL;
+ #endif
+}
+
+
+/* like load verify locations, 1 for success, < 0 for error */
+int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER* cm,
+ const unsigned char* in, long sz, int format)
+{
+ int ret = WOLFSSL_FATAL_ERROR;
+ WOLFSSL_CTX* tmp;
+
+ WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABuffer");
+
+ if (cm == NULL) {
+ WOLFSSL_MSG("No CertManager error");
+ return ret;
+ }
+ tmp = wolfSSL_CTX_new(cm_pick_method());
+
+ if (tmp == NULL) {
+ WOLFSSL_MSG("CTX new failed");
+ return ret;
}
+ /* for tmp use */
+ wolfSSL_CertManagerFree(tmp->cm);
+ tmp->cm = cm;
+
+ ret = wolfSSL_CTX_load_verify_buffer(tmp, in, sz, format);
+
+ /* don't loose our good one */
+ tmp->cm = NULL;
+ wolfSSL_CTX_free(tmp);
+
return ret;
}
+#ifdef HAVE_CRL
-/* Verify the ceritficate, SSL_SUCCESS for ok, < 0 for error */
-int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
- long sz, int format)
+int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm,
+ const unsigned char* buff, long sz, int type)
+{
+ WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLBuffer");
+ if (cm == NULL)
+ return BAD_FUNC_ARG;
+
+ if (cm->crl == NULL) {
+ if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Enable CRL failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ return BufferLoadCRL(cm->crl, buff, sz, type, VERIFY);
+}
+
+int wolfSSL_CertManagerFreeCRL(WOLFSSL_CERT_MANAGER* cm)
+{
+ WOLFSSL_ENTER("wolfSSL_CertManagerFreeCRL");
+ if (cm == NULL)
+ return BAD_FUNC_ARG;
+ if (cm->crl != NULL){
+ FreeCRL(cm->crl, 1);
+ cm->crl = NULL;
+ }
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
+ long sz, int type)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_LoadCRLBuffer");
+
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type);
+}
+
+
+int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff,
+ long sz, int type)
+{
+ WOLFSSL_ENTER("wolfSSL_LoadCRLBuffer");
+
+ if (ssl == NULL || ssl->ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ return wolfSSL_CertManagerLoadCRLBuffer(ssl->ctx->cm, buff, sz, type);
+}
+
+
+#endif /* HAVE_CRL */
+
+/* turn on CRL if off and compiled in, set options */
+int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options)
+{
+ int ret = WOLFSSL_SUCCESS;
+
+ (void)options;
+
+ WOLFSSL_ENTER("wolfSSL_CertManagerEnableCRL");
+ if (cm == NULL)
+ return BAD_FUNC_ARG;
+
+ #ifdef HAVE_CRL
+ if (cm->crl == NULL) {
+ cm->crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap,
+ DYNAMIC_TYPE_CRL);
+ if (cm->crl == NULL)
+ return MEMORY_E;
+
+ if (InitCRL(cm->crl, cm) != 0) {
+ WOLFSSL_MSG("Init CRL failed");
+ FreeCRL(cm->crl, 1);
+ cm->crl = NULL;
+ return WOLFSSL_FAILURE;
+ }
+
+ #ifdef HAVE_CRL_IO
+ cm->crl->crlIOCb = EmbedCrlLookup;
+ #endif
+ }
+
+ cm->crlEnabled = 1;
+ if (options & WOLFSSL_CRL_CHECKALL)
+ cm->crlCheckAll = 1;
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif
+
+ return ret;
+}
+
+
+int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm)
+{
+ WOLFSSL_ENTER("wolfSSL_CertManagerDisableCRL");
+ if (cm == NULL)
+ return BAD_FUNC_ARG;
+
+ cm->crlEnabled = 0;
+
+ return WOLFSSL_SUCCESS;
+}
+
+#ifndef NO_WOLFSSL_CM_VERIFY
+void wolfSSL_CertManagerSetVerify(WOLFSSL_CERT_MANAGER* cm, VerifyCallback vc)
+{
+ WOLFSSL_ENTER("wolfSSL_CertManagerSetVerify");
+ if (cm == NULL)
+ return;
+
+ cm->verifyCallback = vc;
+}
+#endif /* NO_WOLFSSL_CM_VERIFY */
+
+/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
+int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
+ long sz, int format, int err_val)
{
int ret = 0;
- buffer der;
+ DerBuffer* der = NULL;
#ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert = NULL;
+ DecodedCert* cert;
#else
DecodedCert cert[1];
#endif
@@ -2816,71 +6027,101 @@ int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
WOLFSSL_ENTER("wolfSSL_CertManagerVerifyBuffer");
#ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
+ DYNAMIC_TYPE_DCERT);
if (cert == NULL)
return MEMORY_E;
#endif
- der.buffer = NULL;
- der.length = 0;
+ if (format == WOLFSSL_FILETYPE_PEM) {
+#ifdef WOLFSSL_PEM_TO_DER
+ ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, NULL, NULL);
+ if (ret != 0) {
+ FreeDer(&der);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+ #endif
+ return ret;
+ }
+ InitDecodedCert(cert, der->buffer, der->length, cm->heap);
+#else
+ ret = NOT_COMPILED_IN;
+#endif
+ }
+ else {
+ InitDecodedCert(cert, (byte*)buff, (word32)sz, cm->heap);
+ }
- if (format == SSL_FILETYPE_PEM) {
- int eccKey = 0; /* not used */
- #ifdef WOLFSSL_SMALL_STACK
- EncryptedInfo* info = NULL;
- #else
- EncryptedInfo info[1];
- #endif
+ if (ret == 0)
+ ret = ParseCertRelative(cert, CERT_TYPE, 1, cm);
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ /* ret needs to be self-singer error for Qt compat */
+ if (ret == ASN_NO_SIGNER_E && cert->selfSigned)
+ ret = ASN_SELF_SIGNED_E;
+#endif
+#ifdef HAVE_CRL
+ if (ret == 0 && cm->crlEnabled)
+ ret = CheckCertCRL(cm->crl, cert);
+#endif
+
+#ifndef NO_WOLFSSL_CM_VERIFY
+ /* if verify callback has been set */
+ if (cm->verifyCallback) {
+ buffer certBuf;
#ifdef WOLFSSL_SMALL_STACK
- info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (info == NULL) {
- XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ ProcPeerCertArgs* args;
+ args = (ProcPeerCertArgs*)XMALLOC(
+ sizeof(ProcPeerCertArgs), cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (args == NULL) {
+ XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
return MEMORY_E;
}
+ #else
+ ProcPeerCertArgs args[1];
#endif
- info->set = 0;
- info->ctx = NULL;
- info->consumed = 0;
+ certBuf.buffer = (byte*)buff;
+ certBuf.length = (unsigned int)sz;
+ XMEMSET(args, 0, sizeof(ProcPeerCertArgs));
- ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, info, &eccKey);
-
- if (ret == 0)
- InitDecodedCert(cert, der.buffer, der.length, cm->heap);
+ args->totalCerts = 1;
+ args->certs = &certBuf;
+ args->dCert = cert;
+ args->dCertInit = 1;
+ if (err_val != 0) {
+ ret = err_val;
+ }
+ ret = DoVerifyCallback(cm, NULL, ret, args);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(args, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
}
- else
- InitDecodedCert(cert, (byte*)buff, (word32)sz, cm->heap);
-
- if (ret == 0)
- ret = ParseCertRelative(cert, CERT_TYPE, 1, cm);
-
-#ifdef HAVE_CRL
- if (ret == 0 && cm->crlEnabled)
- ret = CheckCertCRL(cm->crl, cert);
+#else
+ (void)err_val;
#endif
FreeDecodedCert(cert);
-
- XFREE(der.buffer, cm->heap, DYNAMIC_TYPE_CERT);
+ FreeDer(&der);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
#endif
- return ret == 0 ? SSL_SUCCESS : ret;
+ return ret == 0 ? WOLFSSL_SUCCESS : ret;
}
-
+/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
+int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
+ long sz, int format)
+{
+ return CM_VerifyBuffer_ex(cm, buff, sz, format, 0);
+}
/* turn on OCSP if off and compiled in, set options */
int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
{
- int ret = SSL_SUCCESS;
+ int ret = WOLFSSL_SUCCESS;
(void)options;
@@ -2891,7 +6132,7 @@ int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
#ifdef HAVE_OCSP
if (cm->ocsp == NULL) {
cm->ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm->heap,
- DYNAMIC_TYPE_OCSP);
+ DYNAMIC_TYPE_OCSP);
if (cm->ocsp == NULL)
return MEMORY_E;
@@ -2899,7 +6140,7 @@ int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
WOLFSSL_MSG("Init OCSP failed");
FreeOCSP(cm->ocsp, 1);
cm->ocsp = NULL;
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
}
}
cm->ocspEnabled = 1;
@@ -2914,6 +6155,7 @@ int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
#ifndef WOLFSSL_USER_IO
cm->ocspIOCb = EmbedOcspLookup;
cm->ocspRespFreeCb = EmbedOcspRespFree;
+ cm->ocspIOCtx = cm->heap;
#endif /* WOLFSSL_USER_IO */
#else
ret = NOT_COMPILED_IN;
@@ -2931,14 +6173,70 @@ int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER* cm)
cm->ocspEnabled = 0;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
+/* turn on OCSP Stapling if off and compiled in, set options */
+int wolfSSL_CertManagerEnableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
+{
+ int ret = WOLFSSL_SUCCESS;
-#ifdef HAVE_OCSP
+ WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPStapling");
+
+ if (cm == NULL)
+ return BAD_FUNC_ARG;
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+ #ifndef NO_WOLFSSL_SERVER
+ if (cm->ocsp_stapling == NULL) {
+ cm->ocsp_stapling = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP),
+ cm->heap, DYNAMIC_TYPE_OCSP);
+ if (cm->ocsp_stapling == NULL)
+ return MEMORY_E;
+ if (InitOCSP(cm->ocsp_stapling, cm) != 0) {
+ WOLFSSL_MSG("Init OCSP failed");
+ FreeOCSP(cm->ocsp_stapling, 1);
+ cm->ocsp_stapling = NULL;
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ #ifndef WOLFSSL_USER_IO
+ cm->ocspIOCb = EmbedOcspLookup;
+ cm->ocspRespFreeCb = EmbedOcspRespFree;
+ cm->ocspIOCtx = cm->heap;
+ #endif /* WOLFSSL_USER_IO */
+ #endif /* NO_WOLFSSL_SERVER */
+ cm->ocspStaplingEnabled = 1;
+#else
+ ret = NOT_COMPILED_IN;
+#endif
+
+ return ret;
+}
-/* check CRL if enabled, SSL_SUCCESS */
+int wolfSSL_CertManagerDisableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
+{
+ int ret = WOLFSSL_SUCCESS;
+
+ WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPStapling");
+
+ if (cm == NULL)
+ return BAD_FUNC_ARG;
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+ cm->ocspStaplingEnabled = 0;
+#else
+ ret = NOT_COMPILED_IN;
+#endif
+ return ret;
+}
+
+#ifdef HAVE_OCSP
+/* check CRL if enabled, WOLFSSL_SUCCESS */
int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz)
{
int ret;
@@ -2954,44 +6252,60 @@ int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz)
return BAD_FUNC_ARG;
if (cm->ocspEnabled == 0)
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
#ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
if (cert == NULL)
return MEMORY_E;
#endif
InitDecodedCert(cert, der, sz, NULL);
- if ((ret = ParseCertRelative(cert, CERT_TYPE, NO_VERIFY, cm)) != 0) {
+ if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm)) != 0) {
WOLFSSL_MSG("ParseCert failed");
}
- else if ((ret = CheckCertOCSP(cm->ocsp, cert)) != 0) {
+ else if ((ret = CheckCertOCSP(cm->ocsp, cert, NULL)) != 0) {
WOLFSSL_MSG("CheckCertOCSP failed");
}
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
#endif
- return ret == 0 ? SSL_SUCCESS : ret;
+ return ret == 0 ? WOLFSSL_SUCCESS : ret;
}
+WOLFSSL_API int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *cm,
+ byte *response, int responseSz, buffer *responseBuffer,
+ CertStatus *status, OcspEntry *entry, OcspRequest *ocspRequest)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP_Staple");
+ if (cm == NULL || response == NULL)
+ return BAD_FUNC_ARG;
+ if (cm->ocspEnabled == 0)
+ return WOLFSSL_SUCCESS;
+
+ ret = CheckOcspResponse(cm->ocsp, response, responseSz, responseBuffer, status,
+ entry, ocspRequest);
+
+ return ret == 0 ? WOLFSSL_SUCCESS : ret;
+}
int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm,
- const char* url)
+ const char* url)
{
WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSPOverrideURL");
if (cm == NULL)
return BAD_FUNC_ARG;
- XFREE(cm->ocspOverrideURL, cm->heap, 0);
+ XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
if (url != NULL) {
int urlSz = (int)XSTRLEN(url) + 1;
- cm->ocspOverrideURL = (char*)XMALLOC(urlSz, cm->heap, 0);
+ cm->ocspOverrideURL = (char*)XMALLOC(urlSz, cm->heap, DYNAMIC_TYPE_URL);
if (cm->ocspOverrideURL != NULL) {
XMEMCPY(cm->ocspOverrideURL, url, urlSz);
}
@@ -3001,7 +6315,7 @@ int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm,
else
cm->ocspOverrideURL = NULL;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
@@ -3016,7 +6330,7 @@ int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm,
cm->ocspRespFreeCb = respFreeCb;
cm->ocspIOCtx = ioCbCtx;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
@@ -3029,7 +6343,6 @@ int wolfSSL_EnableOCSP(WOLFSSL* ssl, int options)
return BAD_FUNC_ARG;
}
-
int wolfSSL_DisableOCSP(WOLFSSL* ssl)
{
WOLFSSL_ENTER("wolfSSL_DisableOCSP");
@@ -3040,6 +6353,24 @@ int wolfSSL_DisableOCSP(WOLFSSL* ssl)
}
+int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling");
+ if (ssl)
+ return wolfSSL_CertManagerEnableOCSPStapling(ssl->ctx->cm);
+ else
+ return BAD_FUNC_ARG;
+}
+
+int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling");
+ if (ssl)
+ return wolfSSL_CertManagerDisableOCSPStapling(ssl->ctx->cm);
+ else
+ return BAD_FUNC_ARG;
+}
+
int wolfSSL_SetOCSP_OverrideURL(WOLFSSL* ssl, const char* url)
{
WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL");
@@ -3054,9 +6385,11 @@ int wolfSSL_SetOCSP_Cb(WOLFSSL* ssl,
CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx)
{
WOLFSSL_ENTER("wolfSSL_SetOCSP_Cb");
- if (ssl)
+ if (ssl) {
+ ssl->ocspIOCtx = ioCbCtx; /* use SSL specific ioCbCtx */
return wolfSSL_CertManagerSetOCSP_Cb(ssl->ctx->cm,
- ioCb, respFreeCb, ioCbCtx);
+ ioCb, respFreeCb, NULL);
+ }
else
return BAD_FUNC_ARG;
}
@@ -3092,33 +6425,52 @@ int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX* ctx, const char* url)
}
-int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX* ctx,
- CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx)
+int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX* ctx, CbOCSPIO ioCb,
+ CbOCSPRespFree respFreeCb, void* ioCbCtx)
{
WOLFSSL_ENTER("wolfSSL_CTX_SetOCSP_Cb");
if (ctx)
- return wolfSSL_CertManagerSetOCSP_Cb(ctx->cm, ioCb, respFreeCb, ioCbCtx);
+ return wolfSSL_CertManagerSetOCSP_Cb(ctx->cm, ioCb,
+ respFreeCb, ioCbCtx);
+ else
+ return BAD_FUNC_ARG;
+}
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPStapling");
+ if (ctx)
+ return wolfSSL_CertManagerEnableOCSPStapling(ctx->cm);
else
return BAD_FUNC_ARG;
}
+int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling");
+ if (ctx)
+ return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm);
+ else
+ return BAD_FUNC_ARG;
+}
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST || HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
#endif /* HAVE_OCSP */
+/* macro to get verify settings for AddCA */
+#define GET_VERIFY_SETTING_CTX(ctx) \
+ (ctx && ctx->verifyNone ? NO_VERIFY : VERIFY)
+#define GET_VERIFY_SETTING_SSL(ssl) \
+ (ssl && ssl->options.verifyNone ? NO_VERIFY : VERIFY)
#ifndef NO_FILESYSTEM
- #if defined(WOLFSSL_MDK_ARM)
- extern FILE * wolfSSL_fopen(const char *name, const char *mode) ;
- #define XFOPEN wolfSSL_fopen
- #else
- #define XFOPEN fopen
- #endif
-
/* process a file with name fname into ctx of format and type
userChain specifies a user certificate chain to pass during handshake */
int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type,
- WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl)
+ WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl, int verify)
{
#ifdef WOLFSSL_SMALL_STACK
byte staticBuffer[1]; /* force heap usage */
@@ -3130,45 +6482,79 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type,
int ret;
long sz = 0;
XFILE file;
- void* heapHint = ctx ? ctx->heap : NULL;
+ void* heapHint = wolfSSL_CTX_GetHeap(ctx, ssl);
+ const char* header = NULL;
+ const char* footer = NULL;
(void)crl;
(void)heapHint;
- if (fname == NULL) return SSL_BAD_FILE;
+ if (fname == NULL) return WOLFSSL_BAD_FILE;
file = XFOPEN(fname, "rb");
- if (file == XBADFILE) return SSL_BAD_FILE;
- XFSEEK(file, 0, XSEEK_END);
+ if (file == XBADFILE) return WOLFSSL_BAD_FILE;
+ if (XFSEEK(file, 0, XSEEK_END) != 0) {
+ XFCLOSE(file);
+ return WOLFSSL_BAD_FILE;
+ }
sz = XFTELL(file);
XREWIND(file);
+ if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
+ WOLFSSL_MSG("ProcessFile file size error");
+ XFCLOSE(file);
+ return WOLFSSL_BAD_FILE;
+ }
+
if (sz > (long)sizeof(staticBuffer)) {
WOLFSSL_MSG("Getting dynamic buffer");
myBuffer = (byte*)XMALLOC(sz, heapHint, DYNAMIC_TYPE_FILE);
if (myBuffer == NULL) {
XFCLOSE(file);
- return SSL_BAD_FILE;
+ return WOLFSSL_BAD_FILE;
}
dynamic = 1;
}
- else if (sz < 0) {
- XFCLOSE(file);
- return SSL_BAD_FILE;
- }
- if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0)
- ret = SSL_BAD_FILE;
+ if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz)
+ ret = WOLFSSL_BAD_FILE;
else {
- if (type == CA_TYPE && format == SSL_FILETYPE_PEM)
- ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl);
+ /* Try to detect type by parsing cert header and footer */
+ if (type == DETECT_CERT_TYPE) {
+ if (wc_PemGetHeaderFooter(CA_TYPE, &header, &footer) == 0 &&
+ (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) {
+ type = CA_TYPE;
+ }
+#ifdef HAVE_CRL
+ else if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 &&
+ (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) {
+ type = CRL_TYPE;
+ }
+#endif
+ else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 &&
+ (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) {
+ type = CERT_TYPE;
+ }
+ else {
+ WOLFSSL_MSG("Failed to detect certificate type");
+ if (dynamic)
+ XFREE(myBuffer, heapHint, DYNAMIC_TYPE_FILE);
+ XFCLOSE(file);
+ return WOLFSSL_BAD_CERTTYPE;
+ }
+ }
+ if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE)
+ && format == WOLFSSL_FILETYPE_PEM) {
+ ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl,
+ verify);
+ }
#ifdef HAVE_CRL
else if (type == CRL_TYPE)
- ret = BufferLoadCRL(crl, myBuffer, sz, format);
+ ret = BufferLoadCRL(crl, myBuffer, sz, format, verify);
#endif
else
ret = ProcessBuffer(ctx, myBuffer, sz, format, type, ssl, NULL,
- userChain);
+ userChain, verify);
}
XFCLOSE(file);
@@ -3178,121 +6564,139 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type,
return ret;
}
-
/* loads file then loads each file in path, no c_rehash */
-int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
- const char* path)
-{
- int ret = SSL_SUCCESS;
+int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file,
+ const char* path, word32 flags)
+{
+ int ret = WOLFSSL_SUCCESS;
+#ifndef NO_WOLFSSL_DIR
+ int fileRet;
+ int successCount = 0;
+ int failCount = 0;
+#endif
+ int verify;
- WOLFSSL_ENTER("wolfSSL_CTX_load_verify_locations");
- (void)path;
+ WOLFSSL_MSG("wolfSSL_CTX_load_verify_locations_ex");
- if (ctx == NULL || (file == NULL && path == NULL) )
- return SSL_FAILURE;
+ if (ctx == NULL || (file == NULL && path == NULL)) {
+ return WOLFSSL_FAILURE;
+ }
- if (file)
- ret = ProcessFile(ctx, file, SSL_FILETYPE_PEM, CA_TYPE, NULL, 0, NULL);
+ verify = GET_VERIFY_SETTING_CTX(ctx);
+ if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY)
+ verify = VERIFY_SKIP_DATE;
- if (ret == SSL_SUCCESS && path) {
- /* try to load each regular file in path */
- #ifdef USE_WINDOWS_API
- WIN32_FIND_DATAA FindFileData;
- HANDLE hFind;
- #ifdef WOLFSSL_SMALL_STACK
- char* name = NULL;
- #else
- char name[MAX_FILENAME_SZ];
- #endif
+ if (file) {
+ ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0,
+ NULL, verify);
+#ifndef NO_WOLFSSL_DIR
+ if (ret == WOLFSSL_SUCCESS)
+ successCount++;
+#endif
+ }
+ if (ret == WOLFSSL_SUCCESS && path) {
+#ifndef NO_WOLFSSL_DIR
+ char* name = NULL;
#ifdef WOLFSSL_SMALL_STACK
- name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (name == NULL)
+ ReadDirCtx* readCtx;
+ readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap,
+ DYNAMIC_TYPE_DIRCTX);
+ if (readCtx == NULL)
return MEMORY_E;
+ #else
+ ReadDirCtx readCtx[1];
#endif
- XMEMSET(name, 0, MAX_FILENAME_SZ);
- XSTRNCPY(name, path, MAX_FILENAME_SZ - 4);
- XSTRNCAT(name, "\\*", 3);
-
- hFind = FindFirstFileA(name, &FindFileData);
- if (hFind == INVALID_HANDLE_VALUE) {
- WOLFSSL_MSG("FindFirstFile for path verify locations failed");
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return BAD_PATH_ERROR;
- }
-
- do {
- if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) {
- XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 3);
- XSTRNCAT(name, "\\", 2);
- XSTRNCAT(name, FindFileData.cFileName, MAX_FILENAME_SZ/2);
-
- ret = ProcessFile(ctx, name, SSL_FILETYPE_PEM, CA_TYPE, NULL,0,
- NULL);
+ /* try to load each regular file in path */
+ fileRet = wc_ReadDirFirst(readCtx, path, &name);
+ while (fileRet == 0 && name) {
+ WOLFSSL_MSG(name); /* log file name */
+ ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, CA_TYPE,
+ NULL, 0, NULL, verify);
+ if (ret != WOLFSSL_SUCCESS) {
+ /* handle flags for ignoring errors, skipping expired certs or
+ by PEM certificate header error */
+ if ( (flags & WOLFSSL_LOAD_FLAG_IGNORE_ERR) ||
+ ((flags & WOLFSSL_LOAD_FLAG_PEM_CA_ONLY) &&
+ (ret == ASN_NO_PEM_HEADER))) {
+ /* Do not fail here if a certificate fails to load,
+ continue to next file */
+ ret = WOLFSSL_SUCCESS;
+ }
+ else {
+ WOLFSSL_ERROR(ret);
+ WOLFSSL_MSG("Load CA file failed, continuing");
+ failCount++;
+ }
}
- } while (ret == SSL_SUCCESS && FindNextFileA(hFind, &FindFileData));
-
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
-
- FindClose(hFind);
- #elif !defined(NO_WOLFSSL_DIR)
- struct dirent* entry;
- DIR* dir = opendir(path);
- #ifdef WOLFSSL_SMALL_STACK
- char* name = NULL;
- #else
- char name[MAX_FILENAME_SZ];
- #endif
+ else {
+ successCount++;
+ }
+ fileRet = wc_ReadDirNext(readCtx, path, &name);
+ }
+ wc_ReadDirClose(readCtx);
- if (dir == NULL) {
- WOLFSSL_MSG("opendir path verify locations failed");
- return BAD_PATH_ERROR;
+ /* pass directory read failure to response code */
+ if (fileRet != WC_READDIR_NOFILE) {
+ ret = fileRet;
+ }
+ /* report failure if no files were loaded or there were failures */
+ else if (successCount == 0 || failCount > 0) {
+ /* use existing error code if exists */
+ if (ret == WOLFSSL_SUCCESS)
+ ret = WOLFSSL_FAILURE;
+ }
+ else {
+ ret = WOLFSSL_SUCCESS;
}
#ifdef WOLFSSL_SMALL_STACK
- name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (name == NULL)
- return MEMORY_E;
+ XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX);
#endif
+#else
+ ret = NOT_COMPILED_IN;
+ (void)flags;
+#endif
+ }
- while ( ret == SSL_SUCCESS && (entry = readdir(dir)) != NULL) {
- struct stat s;
+ return ret;
+}
- XMEMSET(name, 0, MAX_FILENAME_SZ);
- XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2);
- XSTRNCAT(name, "/", 1);
- XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2);
+WOLFSSL_ABI
+int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
+ const char* path)
+{
+ return wolfSSL_CTX_load_verify_locations_ex(ctx, file, path,
+ WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
+}
- if (stat(name, &s) != 0) {
- WOLFSSL_MSG("stat on name failed");
- ret = BAD_PATH_ERROR;
- } else if (s.st_mode & S_IFREG)
- ret = ProcessFile(ctx, name, SSL_FILETYPE_PEM, CA_TYPE, NULL,0,
- NULL);
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* Used to specify a peer cert to match when connecting
+ ctx : the ctx structure to load in peer cert
+ file: the string name of cert file
+ type: type of format such as PEM/DER
+ */
+int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int type)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_cert");
- closedir(dir);
- #endif
+ if (ctx == NULL || file == NULL) {
+ return WOLFSSL_FAILURE;
}
- return ret;
+ return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL,
+ GET_VERIFY_SETTING_CTX(ctx));
}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
-/* Verify the ceritficate, SSL_SUCCESS for ok, < 0 for error */
+/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname,
int format)
{
- int ret = SSL_FATAL_ERROR;
+ int ret = WOLFSSL_FATAL_ERROR;
#ifdef WOLFSSL_SMALL_STACK
byte staticBuffer[1]; /* force heap usage */
#else
@@ -3305,15 +6709,18 @@ int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname,
WOLFSSL_ENTER("wolfSSL_CertManagerVerify");
- if (file == XBADFILE) return SSL_BAD_FILE;
- XFSEEK(file, 0, XSEEK_END);
+ if (file == XBADFILE) return WOLFSSL_BAD_FILE;
+ if(XFSEEK(file, 0, XSEEK_END) != 0) {
+ XFCLOSE(file);
+ return WOLFSSL_BAD_FILE;
+ }
sz = XFTELL(file);
XREWIND(file);
- if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) {
- WOLFSSL_MSG("CertManagerVerify file bad size");
+ if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
+ WOLFSSL_MSG("CertManagerVerify file size error");
XFCLOSE(file);
- return SSL_BAD_FILE;
+ return WOLFSSL_BAD_FILE;
}
if (sz > (long)sizeof(staticBuffer)) {
@@ -3321,13 +6728,13 @@ int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname,
myBuffer = (byte*) XMALLOC(sz, cm->heap, DYNAMIC_TYPE_FILE);
if (myBuffer == NULL) {
XFCLOSE(file);
- return SSL_BAD_FILE;
+ return WOLFSSL_BAD_FILE;
}
dynamic = 1;
}
- if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0)
- ret = SSL_BAD_FILE;
+ if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz)
+ ret = WOLFSSL_BAD_FILE;
else
ret = wolfSSL_CertManagerVerifyBuffer(cm, myBuffer, sz, format);
@@ -3339,31 +6746,11 @@ int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname,
}
-static INLINE WOLFSSL_METHOD* cm_pick_method(void)
-{
- #ifndef NO_WOLFSSL_CLIENT
- #ifdef NO_OLD_TLS
- return wolfTLSv1_2_client_method();
- #else
- return wolfSSLv3_client_method();
- #endif
- #elif !defined(NO_WOLFSSL_SERVER)
- #ifdef NO_OLD_TLS
- return wolfTLSv1_2_server_method();
- #else
- return wolfSSLv3_server_method();
- #endif
- #else
- return NULL;
- #endif
-}
-
-
/* like load verify locations, 1 for success, < 0 for error */
int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* file,
const char* path)
{
- int ret = SSL_FATAL_ERROR;
+ int ret = WOLFSSL_FATAL_ERROR;
WOLFSSL_CTX* tmp;
WOLFSSL_ENTER("wolfSSL_CertManagerLoadCA");
@@ -3385,76 +6772,79 @@ int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* file,
ret = wolfSSL_CTX_load_verify_locations(tmp, file, path);
- /* don't loose our good one */
+ /* don't lose our good one */
tmp->cm = NULL;
wolfSSL_CTX_free(tmp);
return ret;
}
-
-
-/* turn on CRL if off and compiled in, set options */
-int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options)
+#ifndef NO_CHECK_PRIVATE_KEY
+/* Check private against public in certificate for match
+ *
+ * ctx WOLFSSL_CTX structure to check private key in
+ *
+ * Returns SSL_SUCCESS on good private key and SSL_FAILURE if miss matched. */
+int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx)
{
- int ret = SSL_SUCCESS;
+#ifdef WOLFSSL_SMALL_STACK
+ DecodedCert* der = NULL;
+#else
+ DecodedCert der[1];
+#endif
+ word32 size;
+ byte* buff;
+ int ret;
- (void)options;
+ WOLFSSL_ENTER("wolfSSL_CTX_check_private_key");
- WOLFSSL_ENTER("wolfSSL_CertManagerEnableCRL");
- if (cm == NULL)
- return BAD_FUNC_ARG;
+ if (ctx == NULL) {
+ return WOLFSSL_FAILURE;
+ }
- #ifdef HAVE_CRL
- if (cm->crl == NULL) {
- cm->crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap,
- DYNAMIC_TYPE_CRL);
- if (cm->crl == NULL)
- return MEMORY_E;
+#ifndef NO_CERTS
+#ifdef WOLFSSL_SMALL_STACK
+ der = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
+ if (der == NULL)
+ return MEMORY_E;
+#endif
- if (InitCRL(cm->crl, cm) != 0) {
- WOLFSSL_MSG("Init CRL failed");
- FreeCRL(cm->crl, 1);
- cm->crl = NULL;
- return SSL_FAILURE;
- }
- }
- cm->crlEnabled = 1;
- if (options & WOLFSSL_CRL_CHECKALL)
- cm->crlCheckAll = 1;
- #else
- ret = NOT_COMPILED_IN;
+ size = ctx->certificate->length;
+ buff = ctx->certificate->buffer;
+ InitDecodedCert(der, buff, size, ctx->heap);
+ if (ParseCertRelative(der, CERT_TYPE, NO_VERIFY, NULL) != 0) {
+ FreeDecodedCert(der);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(der, NULL, DYNAMIC_TYPE_DCERT);
#endif
+ return WOLFSSL_FAILURE;
+ }
- return ret;
-}
-
-
-int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm)
-{
- WOLFSSL_ENTER("wolfSSL_CertManagerDisableCRL");
- if (cm == NULL)
- return BAD_FUNC_ARG;
-
- cm->crlEnabled = 0;
-
- return SSL_SUCCESS;
-}
-
+ size = ctx->privateKey->length;
+ buff = ctx->privateKey->buffer;
+ ret = wc_CheckPrivateKey(buff, size, der);
+ FreeDecodedCert(der);
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(der, NULL, DYNAMIC_TYPE_DCERT);
+#endif
-int wolfSSL_CTX_check_private_key(WOLFSSL_CTX* ctx)
-{
- /* TODO: check private against public for RSA match */
- (void)ctx;
- WOLFSSL_ENTER("SSL_CTX_check_private_key");
- return SSL_SUCCESS;
+ if (ret == 1) {
+ return WOLFSSL_SUCCESS;
+ }
+ else {
+ return WOLFSSL_FAILURE;
+ }
+#else
+ WOLFSSL_MSG("NO_CERTS is defined, can not check private key");
+ return WOLFSSL_FAILURE;
+#endif
}
+#endif /* !NO_CHECK_PRIVATE_KEY */
#ifdef HAVE_CRL
-
-/* check CRL if enabled, SSL_SUCCESS */
+/* check CRL if enabled, WOLFSSL_SUCCESS */
int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz)
{
int ret = 0;
@@ -3470,18 +6860,17 @@ int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz)
return BAD_FUNC_ARG;
if (cm->crlEnabled == 0)
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
#ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
if (cert == NULL)
return MEMORY_E;
#endif
InitDecodedCert(cert, der, sz, NULL);
- if ((ret = ParseCertRelative(cert, CERT_TYPE, NO_VERIFY, cm)) != 0) {
+ if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_CRL, cm)) != 0) {
WOLFSSL_MSG("ParseCert failed");
}
else if ((ret = CheckCertCRL(cm->crl, cert)) != 0) {
@@ -3490,10 +6879,10 @@ int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz)
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
#endif
- return ret == 0 ? SSL_SUCCESS : ret;
+ return ret == 0 ? WOLFSSL_SUCCESS : ret;
}
@@ -3505,9 +6894,20 @@ int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, CbMissingCRL cb)
cm->cbMissingCRL = cb;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
+#ifdef HAVE_CRL_IO
+int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm, CbCrlIO cb)
+{
+ if (cm == NULL)
+ return BAD_FUNC_ARG;
+
+ cm->crl->crlIOCb = cb;
+
+ return WOLFSSL_SUCCESS;
+}
+#endif
int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path,
int type, int monitor)
@@ -3517,16 +6917,15 @@ int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path,
return BAD_FUNC_ARG;
if (cm->crl == NULL) {
- if (wolfSSL_CertManagerEnableCRL(cm, 0) != SSL_SUCCESS) {
+ if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("Enable CRL failed");
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
}
return LoadCRL(cm->crl, path, type, monitor);
}
-
int wolfSSL_EnableCRL(WOLFSSL* ssl, int options)
{
WOLFSSL_ENTER("wolfSSL_EnableCRL");
@@ -3546,7 +6945,6 @@ int wolfSSL_DisableCRL(WOLFSSL* ssl)
return BAD_FUNC_ARG;
}
-
int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor)
{
WOLFSSL_ENTER("wolfSSL_LoadCRL");
@@ -3566,6 +6964,16 @@ int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb)
return BAD_FUNC_ARG;
}
+#ifdef HAVE_CRL_IO
+int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb)
+{
+ WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
+ if (ssl)
+ return wolfSSL_CertManagerSetCRL_IOCb(ssl->ctx->cm, cb);
+ else
+ return BAD_FUNC_ARG;
+}
+#endif
int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options)
{
@@ -3587,7 +6995,8 @@ int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx)
}
-int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path, int type, int monitor)
+int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path,
+ int type, int monitor)
{
WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL");
if (ctx)
@@ -3606,6 +7015,17 @@ int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb)
return BAD_FUNC_ARG;
}
+#ifdef HAVE_CRL_IO
+int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX* ctx, CbCrlIO cb)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_IOCb");
+ if (ctx)
+ return wolfSSL_CertManagerSetCRL_IOCb(ctx->cm, cb);
+ else
+ return BAD_FUNC_ARG;
+}
+#endif
+
#endif /* HAVE_CRL */
@@ -3614,125 +7034,69 @@ int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb)
/* Add format parameter to allow DER load of CA files */
int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
- int format)
+ int format)
{
WOLFSSL_ENTER("wolfSSL_CTX_der_load_verify_locations");
if (ctx == NULL || file == NULL)
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
- if (ProcessFile(ctx, file, format, CA_TYPE, NULL, 0, NULL) == SSL_SUCCESS)
- return SSL_SUCCESS;
+ if (ProcessFile(ctx, file, format, CA_TYPE, NULL, 0, NULL,
+ GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
+ return WOLFSSL_SUCCESS;
+ }
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
}
#endif /* WOLFSSL_DER_LOAD */
-#ifdef WOLFSSL_CERT_GEN
-/* load pem cert from file into der buffer, return der size or error */
-int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz)
+WOLFSSL_ABI
+int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
+ int format)
{
-#ifdef WOLFSSL_SMALL_STACK
- EncryptedInfo* info = NULL;
- byte staticBuffer[1]; /* force XMALLOC */
-#else
- EncryptedInfo info[1];
- byte staticBuffer[FILE_BUFFER_SIZE];
-#endif
- byte* fileBuf = staticBuffer;
- int dynamic = 0;
- int ret = 0;
- int ecc = 0;
- long sz = 0;
- XFILE file = XFOPEN(fileName, "rb");
- buffer converted;
-
- WOLFSSL_ENTER("wolfSSL_PemCertToDer");
-
- if (file == XBADFILE)
- ret = SSL_BAD_FILE;
- else {
- XFSEEK(file, 0, XSEEK_END);
- sz = XFTELL(file);
- XREWIND(file);
-
- if (sz < 0) {
- ret = SSL_BAD_FILE;
- }
- else if (sz > (long)sizeof(staticBuffer)) {
- fileBuf = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_FILE);
- if (fileBuf == NULL)
- ret = MEMORY_E;
- else
- dynamic = 1;
- }
-
- converted.buffer = 0;
-
- if (ret == 0) {
- if ( (ret = (int)XFREAD(fileBuf, sz, 1, file)) < 0)
- ret = SSL_BAD_FILE;
- else {
- #ifdef WOLFSSL_SMALL_STACK
- info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (info == NULL)
- ret = MEMORY_E;
- else
- #endif
- {
- ret = PemToDer(fileBuf, sz, CA_TYPE, &converted, 0, info,
- &ecc);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- }
- }
-
- if (ret == 0) {
- if (converted.length < (word32)derSz) {
- XMEMCPY(derBuf, converted.buffer, converted.length);
- ret = converted.length;
- }
- else
- ret = BUFFER_E;
- }
-
- XFREE(converted.buffer, 0, DYNAMIC_TYPE_CA);
- }
+ WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file");
- XFCLOSE(file);
- if (dynamic)
- XFREE(fileBuf, 0, DYNAMIC_TYPE_FILE);
+ if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL,
+ GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
+ return WOLFSSL_SUCCESS;
}
- return ret;
+ return WOLFSSL_FAILURE;
}
-#endif /* WOLFSSL_CERT_GEN */
-
-int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
+WOLFSSL_ABI
+int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
int format)
{
- WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file");
- if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL) == SSL_SUCCESS)
- return SSL_SUCCESS;
+ WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file");
- return SSL_FAILURE;
+ if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL,
+ GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
+ return WOLFSSL_SUCCESS;
+ }
+
+ return WOLFSSL_FAILURE;
}
-int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file,int format)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file");
- if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL)
- == SSL_SUCCESS)
- return SSL_SUCCESS;
+/* Sets the max chain depth when verifying a certificate chain. Default depth
+ * is set to MAX_CHAIN_DEPTH.
+ *
+ * ctx WOLFSSL_CTX structure to set depth in
+ * depth max depth
+ */
+void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) {
+ WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth");
- return SSL_FAILURE;
+ if (ctx == NULL || depth < 0 || depth > MAX_CHAIN_DEPTH) {
+ WOLFSSL_MSG("Bad depth argument, too large or less than 0");
+ return;
+ }
+
+ ctx->verifyDepth = (byte)depth;
}
@@ -3742,112 +7106,60 @@ long wolfSSL_get_verify_depth(WOLFSSL* ssl)
if(ssl == NULL) {
return BAD_FUNC_ARG;
}
+#ifndef OPENSSL_EXTRA
return MAX_CHAIN_DEPTH;
+#else
+ return ssl->options.verifyDepth;
+#endif
}
/* get cert chaining depth using ctx struct */
long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx)
{
- if(ctx == NULL) {
+ if (ctx == NULL) {
return BAD_FUNC_ARG;
}
+#ifndef OPENSSL_EXTRA
return MAX_CHAIN_DEPTH;
+#else
+ return ctx->verifyDepth;
+#endif
}
+WOLFSSL_ABI
int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file)
{
- /* procces up to MAX_CHAIN_DEPTH plus subject cert */
- WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file");
- if (ProcessFile(ctx, file, SSL_FILETYPE_PEM,CERT_TYPE,NULL,1, NULL)
- == SSL_SUCCESS)
- return SSL_SUCCESS;
+ /* process up to MAX_CHAIN_DEPTH plus subject cert */
+ WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file");
- return SSL_FAILURE;
-}
-
-
-#ifndef NO_DH
-
-/* server wrapper for ctx or ssl Diffie-Hellman parameters */
-static int wolfSSL_SetTmpDH_buffer_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
- const unsigned char* buf, long sz, int format)
-{
- buffer der;
- int ret = 0;
- int weOwnDer = 0;
- word32 pSz = MAX_DH_SIZE;
- word32 gSz = MAX_DH_SIZE;
-#ifdef WOLFSSL_SMALL_STACK
- byte* p = NULL;
- byte* g = NULL;
-#else
- byte p[MAX_DH_SIZE];
- byte g[MAX_DH_SIZE];
-#endif
-
- der.buffer = (byte*)buf;
- der.length = (word32)sz;
-
-#ifdef WOLFSSL_SMALL_STACK
- p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
- if (p == NULL || g == NULL) {
- XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
+ if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, NULL, 1, NULL,
+ GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
+ return WOLFSSL_SUCCESS;
}
-#endif
- if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM)
- ret = SSL_BAD_FILETYPE;
- else {
- if (format == SSL_FILETYPE_PEM) {
- der.buffer = NULL;
- ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, ctx->heap, NULL,NULL);
- weOwnDer = 1;
- }
-
- if (ret == 0) {
- if (wc_DhParamsLoad(der.buffer, der.length, p, &pSz, g, &gSz) < 0)
- ret = SSL_BAD_FILETYPE;
- else if (ssl)
- ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz);
- else
- ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz);
- }
- }
-
- if (weOwnDer)
- XFREE(der.buffer, ctx->heap, DYNAMIC_TYPE_KEY);
-
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
- return ret;
+ return WOLFSSL_FAILURE;
}
-/* server Diffie-Hellman parameters, SSL_SUCCESS on ok */
-int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz,
- int format)
+int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX* ctx,
+ const char* file, int format)
{
- return wolfSSL_SetTmpDH_buffer_wrapper(ssl->ctx, ssl, buf, sz, format);
-}
+ /* process up to MAX_CHAIN_DEPTH plus subject cert */
+ WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file_format");
+ if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 1, NULL,
+ GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
+ return WOLFSSL_SUCCESS;
+ }
-/* server ctx Diffie-Hellman parameters, SSL_SUCCESS on ok */
-int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX* ctx, const unsigned char* buf,
- long sz, int format)
-{
- return wolfSSL_SetTmpDH_buffer_wrapper(ctx, NULL, buf, sz, format);
+ return WOLFSSL_FAILURE;
}
+#ifndef NO_DH
+
/* server Diffie-Hellman parameters */
static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
const char* fname, int format)
@@ -3861,29 +7173,38 @@ static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
int dynamic = 0;
int ret;
long sz = 0;
- XFILE file = XFOPEN(fname, "rb");
+ XFILE file;
+
+ if (ctx == NULL || fname == NULL)
+ return BAD_FUNC_ARG;
- if (file == XBADFILE) return SSL_BAD_FILE;
- XFSEEK(file, 0, XSEEK_END);
+ file = XFOPEN(fname, "rb");
+ if (file == XBADFILE) return WOLFSSL_BAD_FILE;
+ if(XFSEEK(file, 0, XSEEK_END) != 0) {
+ XFCLOSE(file);
+ return WOLFSSL_BAD_FILE;
+ }
sz = XFTELL(file);
XREWIND(file);
+ if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
+ WOLFSSL_MSG("SetTmpDH file size error");
+ XFCLOSE(file);
+ return WOLFSSL_BAD_FILE;
+ }
+
if (sz > (long)sizeof(staticBuffer)) {
WOLFSSL_MSG("Getting dynamic buffer");
myBuffer = (byte*) XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE);
if (myBuffer == NULL) {
XFCLOSE(file);
- return SSL_BAD_FILE;
+ return WOLFSSL_BAD_FILE;
}
dynamic = 1;
}
- else if (sz < 0) {
- XFCLOSE(file);
- return SSL_BAD_FILE;
- }
- if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0)
- ret = SSL_BAD_FILE;
+ if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz)
+ ret = WOLFSSL_BAD_FILE;
else {
if (ssl)
ret = wolfSSL_SetTmpDH_buffer(ssl, myBuffer, sz, format);
@@ -3901,6 +7222,9 @@ static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
/* server Diffie-Hellman parameters */
int wolfSSL_SetTmpDH_file(WOLFSSL* ssl, const char* fname, int format)
{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
return wolfSSL_SetTmpDH_file_wrapper(ssl->ctx, ssl, fname, format);
}
@@ -3911,88 +7235,2545 @@ int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format)
return wolfSSL_SetTmpDH_file_wrapper(ctx, NULL, fname, format);
}
+#endif /* NO_DH */
-int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz)
+#endif /* NO_FILESYSTEM */
+
+#ifdef OPENSSL_EXTRA
+/* put SSL type in extra for now, not very common */
+
+/* Converts a DER format key read from "bio" to a PKCS8 structure.
+ *
+ * bio input bio to read DER from
+ * pkey If not NULL then this pointer will be overwritten with a new PKCS8
+ * structure.
+ *
+ * returns a WOLFSSL_PKCS8_PRIV_KEY_INFO pointer on success and NULL in fail
+ * case.
+ */
+WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio,
+ WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey)
{
- if (ctx == NULL || keySz > 16000 || keySz % 8 != 0)
- return BAD_FUNC_ARG;
+ WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL;
+#ifdef WOLFSSL_PEM_TO_DER
+ unsigned char* mem = NULL;
+ int memSz;
+ int keySz;
+ word32 algId;
- ctx->minDhKeySz = keySz / 8;
- return SSL_SUCCESS;
+ WOLFSSL_MSG("wolfSSL_d2i_PKCS8_PKEY_bio()");
+
+ if (bio == NULL) {
+ return NULL;
+ }
+
+ if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) {
+ return NULL;
+ }
+
+ if ((keySz = wc_KeyPemToDer(mem, memSz, mem, memSz, NULL)) < 0) {
+ WOLFSSL_MSG("Not PEM format");
+ keySz = memSz;
+ if ((keySz = ToTraditional_ex((byte*)mem, (word32)keySz, &algId)) < 0) {
+ return NULL;
+ }
+ }
+
+ pkcs8 = wolfSSL_EVP_PKEY_new();
+ if (pkcs8 == NULL) {
+ return NULL;
+ }
+
+ pkcs8->pkey.ptr = (char*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ if (pkcs8->pkey.ptr == NULL) {
+ wolfSSL_EVP_PKEY_free(pkcs8);
+ return NULL;
+ }
+ XMEMCPY(pkcs8->pkey.ptr, mem, keySz);
+ pkcs8->pkey_sz = keySz;
+
+ if (pkey != NULL) {
+ *pkey = pkcs8;
+ }
+#else
+ (void)bio;
+ (void)pkey;
+#endif /* WOLFSSL_PEM_TO_DER */
+
+ return pkcs8;
}
-int wolfSSL_SetMinDhKey_Sz(WOLFSSL* ssl, word16 keySz)
+/* expecting DER format public key
+ *
+ * bio input bio to read DER from
+ * out If not NULL then this pointer will be overwritten with a new
+ * WOLFSSL_EVP_PKEY pointer
+ *
+ * returns a WOLFSSL_EVP_PKEY pointer on success and NULL in fail case.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio,
+ WOLFSSL_EVP_PKEY** out)
{
- if (ssl == NULL || keySz > 16000 || keySz % 8 != 0)
- return BAD_FUNC_ARG;
+ unsigned char* mem;
+ long memSz;
+ WOLFSSL_EVP_PKEY* pkey = NULL;
- ssl->options.minDhKeySz = keySz / 8;
- return SSL_SUCCESS;
+ WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio()");
+
+ if (bio == NULL) {
+ return NULL;
+ }
+ (void)out;
+
+ memSz = wolfSSL_BIO_pending(bio);
+ if (memSz <= 0) {
+ return NULL;
+ }
+
+ mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (mem == NULL) {
+ return NULL;
+ }
+
+ if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) {
+ pkey = wolfSSL_d2i_PUBKEY(NULL, (const unsigned char**)&mem, memSz);
+ if (out != NULL && pkey != NULL) {
+ *out = pkey;
+ }
+ }
+
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return pkey;
}
-int wolfSSL_GetDhKey_Sz(WOLFSSL* ssl)
+
+/* Converts a DER encoded public key to a WOLFSSL_EVP_PKEY structure.
+ *
+ * out pointer to new WOLFSSL_EVP_PKEY structure. Can be NULL
+ * in DER buffer to convert
+ * inSz size of in buffer
+ *
+ * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL
+ * on fail
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out,
+ const unsigned char** in, long inSz)
{
- if (ssl == NULL)
+ WOLFSSL_EVP_PKEY* pkey = NULL;
+ const unsigned char* mem;
+ long memSz = inSz;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY");
+
+ if (in == NULL || inSz < 0) {
+ WOLFSSL_MSG("Bad argument");
+ return NULL;
+ }
+ mem = *in;
+
+ #if !defined(NO_RSA)
+ {
+ RsaKey rsa;
+ word32 keyIdx = 0;
+
+ /* test if RSA key */
+ if (wc_InitRsaKey(&rsa, NULL) == 0 &&
+ wc_RsaPublicKeyDecode(mem, &keyIdx, &rsa, (word32)memSz) == 0) {
+ wc_FreeRsaKey(&rsa);
+ pkey = wolfSSL_EVP_PKEY_new();
+ if (pkey != NULL) {
+ pkey->pkey_sz = keyIdx;
+ pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (pkey->pkey.ptr == NULL) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+ XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+ pkey->type = EVP_PKEY_RSA;
+ if (out != NULL) {
+ *out = pkey;
+ }
+
+ pkey->ownRsa = 1;
+ pkey->rsa = wolfSSL_RSA_new();
+ if (pkey->rsa == NULL) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+
+ if (wolfSSL_RSA_LoadDer_ex(pkey->rsa,
+ (const unsigned char*)pkey->pkey.ptr,
+ pkey->pkey_sz, WOLFSSL_RSA_LOAD_PUBLIC) != 1) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+
+ return pkey;
+ }
+ }
+ wc_FreeRsaKey(&rsa);
+ }
+ #endif /* NO_RSA */
+
+ #ifdef HAVE_ECC
+ {
+ word32 keyIdx = 0;
+ ecc_key ecc;
+
+ if (wc_ecc_init(&ecc) == 0 &&
+ wc_EccPublicKeyDecode(mem, &keyIdx, &ecc, (word32)memSz) == 0) {
+ wc_ecc_free(&ecc);
+ pkey = wolfSSL_EVP_PKEY_new();
+ if (pkey != NULL) {
+ pkey->pkey_sz = keyIdx;
+ pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (pkey->pkey.ptr == NULL) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+ XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+ pkey->type = EVP_PKEY_EC;
+ if (out != NULL) {
+ *out = pkey;
+ }
+
+ pkey->ownEcc = 1;
+ pkey->ecc = wolfSSL_EC_KEY_new();
+ if (pkey->ecc == NULL) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+
+ if (wolfSSL_EC_KEY_LoadDer_ex(pkey->ecc,
+ (const unsigned char*)pkey->pkey.ptr,
+ pkey->pkey_sz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != 1) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+
+ return pkey;
+ }
+ }
+ wc_ecc_free(&ecc);
+ }
+ #endif /* HAVE_ECC */
+
+ #if !defined(NO_DSA)
+ {
+ DsaKey dsa;
+ word32 keyIdx = 0;
+
+ /* test if DSA key */
+ if (wc_InitDsaKey(&dsa) == 0 &&
+ wc_DsaPublicKeyDecode(mem, &keyIdx, &dsa, (word32)memSz) == 0) {
+ wc_FreeDsaKey(&dsa);
+ pkey = wolfSSL_EVP_PKEY_new();
+
+ if (pkey != NULL) {
+ pkey->pkey_sz = keyIdx;
+ pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (pkey->pkey.ptr == NULL) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+ XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+ pkey->type = EVP_PKEY_DSA;
+ if (out != NULL) {
+ *out = pkey;
+ }
+
+ pkey->ownDsa = 1;
+ pkey->dsa = wolfSSL_DSA_new();
+ if (pkey->dsa == NULL) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+
+
+ if (wolfSSL_DSA_LoadDer_ex(pkey->dsa,
+ (const unsigned char*)pkey->pkey.ptr,
+ pkey->pkey_sz, WOLFSSL_DSA_LOAD_PUBLIC) != 1) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+
+ return pkey;
+ }
+ }
+ wc_FreeDsaKey(&dsa);
+ }
+ #endif /* NO_DSA */
+
+ #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+ {
+ DhKey dh;
+ word32 keyIdx = 0;
+
+ /* test if DH key */
+ if (wc_InitDhKey(&dh) == 0 &&
+ wc_DhKeyDecode(mem, &keyIdx, &dh, (word32)memSz) == 0) {
+ wc_FreeDhKey(&dh);
+ pkey = wolfSSL_EVP_PKEY_new();
+
+ if (pkey != NULL) {
+ pkey->pkey_sz = (int)memSz;
+ pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (pkey->pkey.ptr == NULL) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+ XMEMCPY(pkey->pkey.ptr, mem, memSz);
+ pkey->type = EVP_PKEY_DH;
+ if (out != NULL) {
+ *out = pkey;
+ }
+
+ pkey->ownDh = 1;
+ pkey->dh = wolfSSL_DH_new();
+ if (pkey->dh == NULL) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+
+ if (wolfSSL_DH_LoadDer(pkey->dh,
+ (const unsigned char*)pkey->pkey.ptr,
+ pkey->pkey_sz) != WOLFSSL_SUCCESS) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+
+ return pkey;
+ }
+ }
+ wc_FreeDhKey(&dh);
+ }
+ #endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
+
+ return pkey;
+}
+
+
+/* Reads in a DER format key. If PKCS8 headers are found they are stripped off.
+ *
+ * type type of key
+ * out newly created WOLFSSL_EVP_PKEY structure
+ * in pointer to input key DER
+ * inSz size of in buffer
+ *
+ * On success a non null pointer is returned and the pointer in is advanced the
+ * same number of bytes read.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out,
+ const unsigned char **in, long inSz)
+{
+ WOLFSSL_EVP_PKEY* local;
+ word32 idx = 0;
+ int ret;
+ word32 algId;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey");
+
+ if (in == NULL || inSz < 0) {
+ WOLFSSL_MSG("Bad argument");
+ return NULL;
+ }
+
+ /* Check if input buffer has PKCS8 header. In the case that it does not
+ * have a PKCS8 header then do not error out. */
+ if ((ret = ToTraditionalInline_ex((const byte*)(*in), &idx, (word32)inSz,
+ &algId)) > 0) {
+ WOLFSSL_MSG("Found and removed PKCS8 header");
+ }
+ else {
+ if (ret != ASN_PARSE_E) {
+ WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header");
+ return NULL;
+ }
+ }
+
+ if (out != NULL && *out != NULL) {
+ wolfSSL_EVP_PKEY_free(*out);
+ *out = NULL;
+ }
+ local = wolfSSL_EVP_PKEY_new();
+ if (local == NULL) {
+ return NULL;
+ }
+
+ /* sanity check on idx before use */
+ if ((int)idx > inSz) {
+ WOLFSSL_MSG("Issue with index pointer");
+ wolfSSL_EVP_PKEY_free(local);
+ local = NULL;
+ return NULL;
+ }
+
+ local->type = type;
+ local->pkey_sz = (int)inSz - idx;
+ local->pkey.ptr = (char*)XMALLOC(inSz - idx, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ if (local->pkey.ptr == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ local = NULL;
+ return NULL;
+ }
+ else {
+ XMEMCPY(local->pkey.ptr, *in + idx, inSz - idx);
+ }
+
+ switch (type) {
+#ifndef NO_RSA
+ case EVP_PKEY_RSA:
+ local->ownRsa = 1;
+ local->rsa = wolfSSL_RSA_new();
+ if (local->rsa == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ if (wolfSSL_RSA_LoadDer_ex(local->rsa,
+ (const unsigned char*)local->pkey.ptr, local->pkey_sz,
+ WOLFSSL_RSA_LOAD_PRIVATE) != SSL_SUCCESS) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ break;
+#endif /* NO_RSA */
+#ifdef HAVE_ECC
+ case EVP_PKEY_EC:
+ local->ownEcc = 1;
+ local->ecc = wolfSSL_EC_KEY_new();
+ if (local->ecc == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ if (wolfSSL_EC_KEY_LoadDer(local->ecc,
+ (const unsigned char*)local->pkey.ptr, local->pkey_sz)
+ != SSL_SUCCESS) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ break;
+#endif /* HAVE_ECC */
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+#ifndef NO_DSA
+ case EVP_PKEY_DSA:
+ local->ownDsa = 1;
+ local->dsa = wolfSSL_DSA_new();
+ if (local->dsa == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ if (wolfSSL_DSA_LoadDer(local->dsa,
+ (const unsigned char*)local->pkey.ptr, local->pkey_sz)
+ != SSL_SUCCESS) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ break;
+#endif /* NO_DSA */
+#ifndef NO_DH
+ case EVP_PKEY_DH:
+ local->ownDh = 1;
+ local->dh = wolfSSL_DH_new();
+ if (local->dh == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ if (wolfSSL_DH_LoadDer(local->dh,
+ (const unsigned char*)local->pkey.ptr, local->pkey_sz)
+ != SSL_SUCCESS) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ break;
+#endif /* HAVE_DH */
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
+ default:
+ WOLFSSL_MSG("Unsupported key type");
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+
+ /* advance pointer with success */
+ if (local != NULL) {
+ if ((idx + local->pkey_sz) <= (word32)inSz) {
+ *in = *in + idx + local->pkey_sz;
+ }
+
+ if (out != NULL) {
+ *out = local;
+ }
+ }
+
+ return local;
+}
+
+#ifndef NO_CERTS
+
+int wolfSSL_check_private_key(const WOLFSSL* ssl)
+{
+ DecodedCert der;
+ word32 size;
+ byte* buff;
+ int ret;
+
+ if (ssl == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ size = ssl->buffers.certificate->length;
+ buff = ssl->buffers.certificate->buffer;
+ InitDecodedCert(&der, buff, size, ssl->heap);
+#ifdef HAVE_PK_CALLBACKS
+ ret = InitSigPkCb((WOLFSSL*)ssl, &der.sigCtx);
+ if (ret != 0) {
+ FreeDecodedCert(&der);
+ return ret;
+ }
+#endif
+
+ if (ParseCertRelative(&der, CERT_TYPE, NO_VERIFY, NULL) != 0) {
+ FreeDecodedCert(&der);
+ return WOLFSSL_FAILURE;
+ }
+
+ size = ssl->buffers.key->length;
+ buff = ssl->buffers.key->buffer;
+ ret = wc_CheckPrivateKey(buff, size, &der);
+ FreeDecodedCert(&der);
+ return ret;
+}
+
+#if defined(OPENSSL_ALL)
+/* Returns the number of X509V3 extensions in X509 object, or 0 on failure */
+int wolfSSL_X509_get_ext_count(const WOLFSSL_X509* passedCert)
+{
+ int extCount = 0;
+ int length = 0;
+ int outSz = 0;
+ const byte* rawCert;
+ int sz = 0;
+ word32 idx = 0;
+ DecodedCert cert;
+ const byte* input;
+
+ WOLFSSL_ENTER("wolfSSL_X509_get_ext_count()");
+ if (passedCert == NULL) {
+ WOLFSSL_MSG("\tNot passed a certificate");
+ return WOLFSSL_FAILURE;
+ }
+
+ rawCert = wolfSSL_X509_get_der((WOLFSSL_X509*)passedCert, &outSz);
+ if (rawCert == NULL) {
+ WOLFSSL_MSG("\tpassedCert has no internal DerBuffer set.");
+ return WOLFSSL_FAILURE;
+ }
+ InitDecodedCert(&cert, rawCert, (word32)outSz, 0);
+
+ if (ParseCert(&cert, CA_TYPE, NO_VERIFY, NULL) < 0) {
+ WOLFSSL_MSG("\tCertificate parsing failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ input = cert.extensions;
+ sz = cert.extensionsSz;
+
+ if (input == NULL || sz == 0) {
+ WOLFSSL_MSG("\tsz or input NULL error");
+ FreeDecodedCert(&cert);
+ return WOLFSSL_FAILURE;
+ }
+
+ if (input[idx++] != ASN_EXTENSIONS) {
+ WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
+ FreeDecodedCert(&cert);
+ return WOLFSSL_FAILURE;
+ }
+
+ if (GetLength(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: invalid length");
+ FreeDecodedCert(&cert);
+ return WOLFSSL_FAILURE;
+ }
+
+ if (GetSequence(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)");
+ FreeDecodedCert(&cert);
+ return WOLFSSL_FAILURE;
+ }
+
+ while (idx < (word32)sz) {
+ if (GetSequence(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: should be a SEQUENCE");
+ FreeDecodedCert(&cert);
+ return WOLFSSL_FAILURE;
+ }
+ idx += length;
+ extCount++;
+ }
+ FreeDecodedCert(&cert);
+ return extCount;
+}
+
+/* Creates and returns pointer to a new X509_EXTENSION object in memory */
+WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_new(void)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_new");
+
+ WOLFSSL_X509_EXTENSION* newExt;
+ newExt = (WOLFSSL_X509_EXTENSION*)XMALLOC(sizeof(WOLFSSL_X509_EXTENSION),
+ NULL, DYNAMIC_TYPE_X509_EXT);
+ if (newExt == NULL)
+ return NULL;
+ XMEMSET(newExt, 0, sizeof(WOLFSSL_X509_EXTENSION));
+
+ return newExt;
+}
+
+void wolfSSL_X509_EXTENSION_free(WOLFSSL_X509_EXTENSION* x)
+{
+ WOLFSSL_ASN1_STRING asn1;
+ WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_free");
+ if (x == NULL)
+ return;
+
+ if (x->obj != NULL)
+ wolfSSL_ASN1_OBJECT_free(x->obj);
+
+ asn1 = x->value;
+ if (asn1.length > 0 && asn1.data != NULL && asn1.isDynamic)
+ XFREE(asn1.data, NULL, DYNAMIC_TYPE_OPENSSL);
+
+ wolfSSL_sk_free(x->ext_sk);
+
+ XFREE(x, NULL, DYNAMIC_TYPE_X509_EXT);
+}
+
+/* Creates and returns a new WOLFSSL_X509_EXTENSION stack. */
+WOLFSSL_STACK* wolfSSL_sk_new_x509_ext(void)
+{
+ WOLFSSL_STACK* sk;
+ WOLFSSL_ENTER("wolfSSL_sk_new_x509_ext");
+
+ sk = wolfSSL_sk_new_null();
+ if (sk) {
+ sk->type = STACK_TYPE_X509_EXT;
+ }
+ return sk;
+}
+
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_X509_EXTENSION_push(WOLFSSL_STACK* sk,WOLFSSL_X509_EXTENSION* ext)
+{
+ WOLFSSL_STACK* node;
+
+ WOLFSSL_ENTER("wolfSSL_sk_X509_EXTENSION_push");
+
+ if (sk == NULL || ext == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* no previous values in stack */
+ if (sk->data.ext == NULL) {
+ sk->data.ext = ext;
+ sk->num += 1;
+ return WOLFSSL_SUCCESS;
+ }
+
+ /* stack already has value(s) create a new node and add more */
+ node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+ DYNAMIC_TYPE_X509);
+ if (node == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return WOLFSSL_FAILURE;
+ }
+ XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+ /* push new obj onto head of stack */
+ node->data.ext = sk->data.ext;
+ node->next = sk->next;
+ node->type = sk->type;
+ sk->next = node;
+ sk->data.ext = ext;
+ sk->num += 1;
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* Free the structure for X509_EXTENSION stack
+ *
+ * sk stack to free nodes in
+ */
+void wolfSSL_sk_X509_EXTENSION_free(WOLFSSL_STACK* sk)
+{
+ WOLFSSL_STACK* node;
+
+ WOLFSSL_ENTER("wolfSSL_sk_X509_EXTENSION_free");
+
+ if (sk == NULL) {
+ return;
+ }
+
+ /* parse through stack freeing each node */
+ node = sk->next;
+ while ((node != NULL) && (sk->num > 1)) {
+ WOLFSSL_STACK* tmp = node;
+ node = node->next;
+
+ wolfSSL_X509_EXTENSION_free(tmp->data.ext);
+ XFREE(tmp, NULL, DYNAMIC_TYPE_X509);
+ sk->num -= 1;
+ }
+
+ /* free head of stack */
+ if (sk->num == 1) {
+ wolfSSL_X509_EXTENSION_free(sk->data.ext);
+ }
+ XFREE(sk, NULL, DYNAMIC_TYPE_X509);
+}
+
+int wolfSSL_ASN1_BIT_STRING_set_bit(WOLFSSL_ASN1_BIT_STRING* str, int pos,
+ int val)
+{
+ int bytes_cnt, bit;
+ byte* temp;
+
+ if (!str || (val != 0 && val != 1) || pos < 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ bytes_cnt = pos/8;
+ bit = 1<<(7-(pos%8));
+
+ if (bytes_cnt+1 > str->length) {
+ if (!(temp = (byte*)XREALLOC(str->data, bytes_cnt+1, NULL,
+ DYNAMIC_TYPE_OPENSSL))) {
+ return WOLFSSL_FAILURE;
+ }
+ XMEMSET(temp+str->length, 0, bytes_cnt+1 - str->length);
+ str->data = temp;
+ str->length = bytes_cnt+1;
+ }
+
+ str->data[bytes_cnt] &= ~bit;
+ str->data[bytes_cnt] |= val ? bit : 0;
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* Gets the X509_EXTENSION* ext based on it's location in WOLFSSL_X509* x509.
+ *
+ * x509 : The X509 structure to look for the extension.
+ * loc : Location of the extension. If the extension is found at the given
+ * location, a new X509_EXTENSION structure is populated with extension-specific
+ * data based on the extension type.
+
+ * Returns NULL on error or pointer to X509_EXTENSION structure containing the
+ * extension. The returned X509_EXTENSION should not be free'd by caller.
+ * The returned X509_EXTENSION is pushed onto a stack inside the x509 argument.
+ * This is later free'd when x509 is free'd.
+ *
+ * NOTE: for unknown extension NIDs, a X509_EXTENSION is populated with the
+ * extension oid as the ASN1_OBJECT (QT compatibility)
+ */
+WOLFSSL_X509_EXTENSION* wolfSSL_X509_get_ext(const WOLFSSL_X509* x509, int loc)
+{
+ WOLFSSL_X509_EXTENSION* ext = NULL;
+ WOLFSSL_ENTER("wolfSSL_X509_get_ext");
+ if (x509 == NULL)
+ return NULL;
+
+ ext = wolfSSL_X509_set_ext((WOLFSSL_X509*) x509, loc);
+ return ext;
+}
+
+/* Pushes a new X509_EXTENSION* ext onto the stack inside WOLFSSL_X509* x509.
+ * This is currently a helper function for wolfSSL_X509_get_ext
+ * Caller does not free the returned WOLFSSL_X509_EXTENSION*
+ */
+WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc)
+{
+ int extCount = 0, length = 0, outSz = 0, sz = 0, ret = 0;
+ int objSz = 0, isSet = 0;
+ const byte* rawCert;
+ const byte* input;
+ byte* oidBuf;
+ word32 oid, idx = 0, tmpIdx = 0;
+ WOLFSSL_X509_EXTENSION* ext = NULL;
+ WOLFSSL_ASN1_INTEGER* a;
+ WOLFSSL_STACK* sk;
+ DecodedCert cert;
+
+ WOLFSSL_ENTER("wolfSSL_X509_set_ext");
+
+ if(x509 == NULL){
+ WOLFSSL_MSG("\tNot passed a certificate");
+ return NULL;
+ }
+
+ if(loc <0 || (loc > wolfSSL_X509_get_ext_count(x509))){
+ WOLFSSL_MSG("\tBad location argument");
+ return NULL;
+ }
+
+ ext = wolfSSL_X509_EXTENSION_new();
+ if (ext == NULL) {
+ WOLFSSL_MSG("\tX509_EXTENSION_new() failed");
+ return NULL;
+ }
+
+ rawCert = wolfSSL_X509_get_der((WOLFSSL_X509*)x509, &outSz);
+ if (rawCert == NULL) {
+ WOLFSSL_MSG("\tX509_get_der() failed");
+ wolfSSL_X509_EXTENSION_free(ext);
+ return NULL;
+ }
+
+ InitDecodedCert( &cert, rawCert, (word32)outSz, 0);
+
+ if (ParseCert(&cert, CA_TYPE, NO_VERIFY, NULL) < 0) {
+ WOLFSSL_MSG("\tCertificate parsing failed");
+ wolfSSL_X509_EXTENSION_free(ext);
+ return NULL;
+ }
+
+ input = cert.extensions;
+ sz = cert.extensionsSz;
+
+ if (input == NULL || sz == 0) {
+ WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+
+ if (input[idx++] != ASN_EXTENSIONS) {
+ WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+
+ if (GetLength(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: invalid length");
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+
+ if (GetSequence(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)");
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+
+ while (idx < (word32)sz) {
+ oid = 0;
+
+ if (GetSequence(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: should be a SEQUENCE");
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+
+ tmpIdx = idx;
+ ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz);
+ if (ret < 0) {
+ WOLFSSL_MSG("\tfail: OBJECT ID");
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ idx = tmpIdx;
+
+ /* Continue while loop until extCount == loc or idx > sz */
+ if (extCount != loc) {
+ idx += length;
+ extCount++;
+ continue;
+ }
+ /* extCount == loc. Now get the extension. */
+ /* Check if extension has been set */
+ isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, oid);
+ ext->obj = wolfSSL_OBJ_nid2obj(oid);
+ if (ext->obj == NULL) {
+ WOLFSSL_MSG("\tfail: Invalid OBJECT");
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ ext->obj->nid = oid;
+
+ switch (oid) {
+ case BASIC_CA_OID:
+ if (!isSet)
+ break;
+ /* Set pathlength */
+ a = wolfSSL_ASN1_INTEGER_new();
+ if (a == NULL) {
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ a->length = x509->pathLength;
+
+ /* Save ASN1_INTEGER in x509 extension */
+ ext->obj->pathlen = a;
+
+ ext->obj->ca = x509->isCa;
+ ext->crit = x509->basicConstCrit;
+ break;
+
+ case AUTH_INFO_OID:
+ if (!isSet)
+ break;
+
+ /* Create a stack to hold both the caIssuer and ocsp objects
+ in X509_EXTENSION structure */
+ sk = (WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*)XMALLOC(
+ sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)),
+ NULL, DYNAMIC_TYPE_ASN1);
+ if (sk == NULL) {
+ WOLFSSL_MSG("Failed to malloc stack");
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)));
+ sk->type = STACK_TYPE_OBJ;
+
+ /* Add CaIssuers object to stack */
+ if (x509->authInfoCaIssuer != NULL &&
+ x509->authInfoCaIssuerSz > 0)
+ {
+ WOLFSSL_ASN1_OBJECT* obj;
+ obj = wolfSSL_ASN1_OBJECT_new();
+ if (obj == NULL) {
+ WOLFSSL_MSG("Error creating ASN1 object");
+ wolfSSL_sk_ASN1_OBJECT_free(sk);
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ obj->obj = (byte*)x509->authInfoCaIssuer;
+ obj->objSz = x509->authInfoCaIssuerSz;
+ obj->grp = oidCertAuthInfoType;
+ obj->nid = AIA_CA_ISSUER_OID;
+
+ ret = wolfSSL_sk_ASN1_OBJECT_push(sk, obj);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error pushing ASN1 object onto stack");
+ wolfSSL_ASN1_OBJECT_free(obj);
+ wolfSSL_sk_ASN1_OBJECT_free(sk);
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ }
+
+ /* Add OCSP object to stack */
+ if (x509->authInfo != NULL &&
+ x509->authInfoSz > 0)
+ {
+ WOLFSSL_ASN1_OBJECT* obj;
+ obj = wolfSSL_ASN1_OBJECT_new();
+ if (obj == NULL) {
+ WOLFSSL_MSG("Error creating ASN1 object");
+ wolfSSL_sk_ASN1_OBJECT_free(sk);
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ obj->obj = x509->authInfo;
+ obj->objSz = x509->authInfoSz;
+ obj->grp = oidCertAuthInfoType;
+ obj->nid = AIA_OCSP_OID;
+
+ ret = wolfSSL_sk_ASN1_OBJECT_push(sk, obj);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error pushing ASN1 object onto stack");
+ wolfSSL_ASN1_OBJECT_free(obj);
+ wolfSSL_sk_ASN1_OBJECT_free(sk);
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ }
+ ext->ext_sk = sk;
+ ext->crit = x509->authInfoCrit;
+ break;
+
+ case AUTH_KEY_OID:
+ if (!isSet)
+ break;
+
+ ret = wolfSSL_ASN1_STRING_set(&ext->value, x509->authKeyId,
+ x509->authKeyIdSz);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ASN1_STRING_set() failed");
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ ext->crit = x509->authKeyIdCrit;
+ break;
+
+ case SUBJ_KEY_OID:
+ if (!isSet)
+ break;
+
+ ret = wolfSSL_ASN1_STRING_set(&ext->value, x509->subjKeyId,
+ x509->subjKeyIdSz);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ASN1_STRING_set() failed");
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ ext->crit = x509->subjKeyIdCrit;
+ break;
+
+ case CERT_POLICY_OID:
+ if (!isSet)
+ break;
+ ext->crit = x509->certPolicyCrit;
+ break;
+
+ case KEY_USAGE_OID:
+ if (!isSet)
+ break;
+
+ ret = wolfSSL_ASN1_STRING_set(&ext->value,
+ (byte*)&(x509->keyUsage), sizeof(word16));
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ASN1_STRING_set() failed");
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ ext->crit = x509->keyUsageCrit;
+ break;
+
+ case EXT_KEY_USAGE_OID:
+ if (!isSet)
+ break;
+ ext->crit = x509->keyUsageCrit;
+ break;
+
+ case CRL_DIST_OID:
+ if (!isSet)
+ break;
+ ext->crit = x509->CRLdistCrit;
+ break;
+
+ case ALT_NAMES_OID:
+ {
+ WOLFSSL_GENERAL_NAME* gn = NULL;
+ DNS_entry* dns = NULL;
+ if (!isSet)
+ break;
+
+ sk = (WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)*)XMALLOC(
+ sizeof(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)), NULL,
+ DYNAMIC_TYPE_ASN1);
+ if (sk == NULL) {
+ return NULL;
+ }
+ XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)));
+ sk->type = STACK_TYPE_GEN_NAME;
+
+ if (x509->subjAltNameSet && x509->altNames != NULL) {
+ /* alt names are DNS_entry structs */
+ dns = x509->altNames;
+ /* Currently only support GEN_DNS type */
+ while (dns != NULL) {
+ gn = wolfSSL_GENERAL_NAME_new();
+ if (gn == NULL) {
+ WOLFSSL_MSG("Error creating GENERAL_NAME");
+ wolfSSL_sk_free(sk);
+ return NULL;
+ }
+
+ gn->type = dns->type;
+ gn->d.ia5->length = dns->len;
+ if (wolfSSL_ASN1_STRING_set(gn->d.ia5, dns->name,
+ gn->d.ia5->length) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ASN1_STRING_set failed");
+ wolfSSL_GENERAL_NAME_free(gn);
+ wolfSSL_sk_free(sk);
+ return NULL;
+ }
+
+ dns = dns->next;
+ /* last dns in list add at end of function */
+ if (dns != NULL) {
+ if (wolfSSL_sk_GENERAL_NAME_push(sk, gn) !=
+ WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error pushing onto stack");
+ wolfSSL_GENERAL_NAME_free(gn);
+ wolfSSL_sk_free(sk);
+ sk = NULL;
+ }
+ }
+ }
+ if (wolfSSL_sk_GENERAL_NAME_push(sk,gn) !=
+ WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error pushing onto stack");
+ wolfSSL_GENERAL_NAME_free(gn);
+ wolfSSL_sk_free(sk);
+ sk = NULL;
+ }
+ }
+ ext->ext_sk = sk;
+ ext->crit = x509->subjAltNameCrit;
+ break;
+ }
+
+ default:
+ WOLFSSL_MSG("Unknown extension type found, parsing OID");
+ /* If the extension type is not recognized/supported,
+ set the ASN1_OBJECT in the extension with the
+ parsed oid for access in later function calls */
+
+ /* Get OID from input */
+ if (GetASNObjectId(input, &idx, &length, sz) != 0) {
+ WOLFSSL_MSG("Failed to Get ASN Object Id");
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ oidBuf = (byte*)XMALLOC(length+1+MAX_LENGTH_SZ, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (oidBuf == NULL) {
+ WOLFSSL_MSG("Failed to malloc tmp buffer");
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ oidBuf[0] = ASN_OBJECT_ID;
+ objSz++;
+ objSz += SetLength(length, oidBuf + 1);
+ objSz += length;
+
+ /* Set object size and reallocate space in object buffer */
+ ext->obj->objSz = objSz;
+ if(((ext->obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) ||
+ (ext->obj->obj == NULL)) {
+ ext->obj->obj =(byte*)XREALLOC((byte*)ext->obj->obj,
+ ext->obj->objSz,
+ NULL,DYNAMIC_TYPE_ASN1);
+ if (ext->obj->obj == NULL) {
+ wolfSSL_ASN1_OBJECT_free(ext->obj);
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ ext->obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA;
+ } else {
+ ext->obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
+ }
+ /* Get OID from input and copy to ASN1_OBJECT buffer */
+ XMEMCPY(oidBuf+2, input+idx, length);
+ XMEMCPY((byte*)ext->obj->obj, oidBuf, ext->obj->objSz);
+ XFREE(oidBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ oidBuf = NULL;
+ ext->obj->grp = oidCertExtType;
+ ext->crit = 0;
+
+ /* Get extension data and copy as ASN1_STRING */
+ tmpIdx = idx + length;
+ if ((tmpIdx >= (word32)sz) || (input[tmpIdx++] != ASN_OCTET_STRING)) {
+ WOLFSSL_MSG("Error decoding unknown extension data");
+ wolfSSL_ASN1_OBJECT_free(ext->obj);
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+
+ if (GetLength(input, &tmpIdx, &length, sz) <= 0) {
+ WOLFSSL_MSG("Error: Invalid Input Length.");
+ wolfSSL_ASN1_OBJECT_free(ext->obj);
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ ext->value.data = (char*)XMALLOC(length, NULL, DYNAMIC_TYPE_ASN1);
+ ext->value.isDynamic = 1;
+ if (ext->value.data == NULL) {
+ WOLFSSL_MSG("Failed to malloc ASN1_STRING data");
+ wolfSSL_X509_EXTENSION_free(ext);
+ FreeDecodedCert(&cert);
+ return NULL;
+ }
+ XMEMCPY(ext->value.data,input+tmpIdx,length);
+ ext->value.length = length;
+ } /* switch(oid) */
+
+ break; /* Got the Extension. Now exit while loop. */
+
+ } /* while(idx < sz) */
+
+ /* Store the new extension in a stack inside x509
+ * The extensions on the stack are free'd internally when FreeX509 is called
+ */
+ if (x509->ext_sk == NULL)
+ x509->ext_sk = wolfSSL_sk_new_x509_ext();
+ if (x509->ext_sk != NULL)
+ wolfSSL_sk_X509_EXTENSION_push(x509->ext_sk, ext);
+
+ FreeDecodedCert(&cert);
+ return ext;
+}
+
+/* Return 0 on success and 1 on failure. Copies ext data to bio, using indent
+ * to pad the output. flag is ignored. */
+int wolfSSL_X509V3_EXT_print(WOLFSSL_BIO *out, WOLFSSL_X509_EXTENSION *ext,
+ unsigned long flag, int indent)
+{
+ ASN1_OBJECT* obj;
+ ASN1_STRING* str;
+ int nid;
+ const int sz = CTC_NAME_SIZE*2;
+ int rc = WOLFSSL_FAILURE;
+ char tmp[CTC_NAME_SIZE*2];
+ WOLFSSL_ENTER("wolfSSL_X509V3_EXT_print");
+
+ if ((out == NULL) || (ext == NULL)) {
+ WOLFSSL_MSG("NULL parameter error");
+ return rc;
+ }
+
+ obj = wolfSSL_X509_EXTENSION_get_object(ext);
+ if (obj == NULL) {
+ WOLFSSL_MSG("Error getting ASN1_OBJECT from X509_EXTENSION");
+ return rc;
+ }
+
+ str = wolfSSL_X509_EXTENSION_get_data(ext);
+ if (obj == NULL) {
+ WOLFSSL_MSG("Error getting ASN1_STRING from X509_EXTENSION");
+ return rc;
+ }
+
+ /* Print extension based on the type */
+ nid = wolfSSL_OBJ_obj2nid(obj);
+ switch (nid) {
+ case BASIC_CA_OID:
+ {
+ char isCa[] = "TRUE";
+ char notCa[] = "FALSE";
+ XSNPRINTF(tmp, sz, "%*sCA:%s", indent, "",
+ obj->ca ? isCa : notCa);
+ break;
+ }
+ case ALT_NAMES_OID:
+ {
+ WOLFSSL_STACK* sk;
+ char* val;
+ int len;
+ tmp[0] = '\0'; /* Make sure tmp is null-terminated */
+
+ sk = ext->ext_sk;
+ while (sk != NULL) {
+ if (sk->type == STACK_TYPE_GEN_NAME && sk->data.gn) {
+ /* str is GENERAL_NAME for subject alternative name ext */
+ str = sk->data.gn->d.ia5;
+ len = str->length + 2; /* + 2 for NULL char and "," */
+ if (len > sz) {
+ WOLFSSL_MSG("len greater than buffer size");
+ return rc;
+ }
+
+ val = (char*)XMALLOC(len + indent, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (val == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return rc;
+ }
+ if (sk->next)
+ XSNPRINTF(val, len, "%*s%s, ", indent, "", str->strData);
+ else
+ XSNPRINTF(val, len, "%*s%s", indent, "", str->strData);
+
+ XSTRNCAT(tmp, val, len);
+ XFREE(val, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ sk = sk->next;
+ }
+ break;
+ }
+ case AUTH_KEY_OID:
+ case SUBJ_KEY_OID:
+ {
+ char* asn1str;
+ asn1str = wolfSSL_i2s_ASN1_STRING(NULL, str);
+ XSNPRINTF(tmp, sz, "%*s%s", indent, "", asn1str);
+ XFREE(asn1str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ break;
+ }
+ case AUTH_INFO_OID:
+ case CERT_POLICY_OID:
+ case CRL_DIST_OID:
+ case KEY_USAGE_OID:
+ WOLFSSL_MSG("X509V3_EXT_print not yet implemented for ext type");
+ break;
+
+ default:
+ XSNPRINTF(tmp, sz, "%*s%s", indent, "", str->strData);
+ }
+
+ if (wolfSSL_BIO_write(out, tmp, (int)XSTRLEN(tmp)) == (int)XSTRLEN(tmp)) {
+ rc = WOLFSSL_SUCCESS;
+ }
+ (void) flag;
+
+ return rc;
+}
+
+/* Returns crit flag in X509_EXTENSION object */
+int wolfSSL_X509_EXTENSION_get_critical(const WOLFSSL_X509_EXTENSION* ex)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_critical");
+ if (ex == NULL)
return BAD_FUNC_ARG;
+ return ex->crit;
+}
- return (ssl->options.dhKeySz * 8);
+/* Creates v3_ext_method for a given X509v3 extension
+ *
+ * ex : The X509_EXTENSION used to create v3_ext_method. If the extension is
+ * not NULL, get the NID of the extension object and populate the
+ * extension type-specific X509V3_EXT_* function(s) in v3_ext_method.
+ *
+ * Returns NULL on error or pointer to the v3_ext_method populated with extension
+ * type-specific X509V3_EXT_* function(s).
+ *
+ * NOTE: NID_subject_key_identifier is currently the only extension implementing
+ * the X509V3_EXT_* functions, as it is the only type called directly by QT. The
+ * other extension types return a pointer to a v3_ext_method struct that contains
+ * only the NID.
+ */
+const WOLFSSL_v3_ext_method* wolfSSL_X509V3_EXT_get(WOLFSSL_X509_EXTENSION* ex)
+{
+ int nid;
+ WOLFSSL_v3_ext_method method;
+
+ WOLFSSL_ENTER("wolfSSL_X509V3_EXT_get");
+ if ((ex == NULL) || (ex->obj == NULL)) {
+ WOLFSSL_MSG("Passed an invalid X509_EXTENSION*");
+ return NULL;
+ }
+ /* Initialize all methods to NULL */
+ method.d2i = NULL;
+ method.i2v = NULL;
+ method.i2s = NULL;
+ method.i2r = NULL;
+
+ nid = ex->obj->nid;
+ if (nid <= 0) {
+ WOLFSSL_MSG("Failed to get nid from passed extension object");
+ return NULL;
+ }
+
+ switch (nid) {
+ case NID_basic_constraints:
+ break;
+ case NID_subject_key_identifier:
+ method.i2s = (X509V3_EXT_I2S)wolfSSL_i2s_ASN1_STRING;
+ break;
+ case NID_key_usage:
+ WOLFSSL_MSG("i2v function not yet implemented for Key Usage");
+ break;
+ case NID_authority_key_identifier:
+ WOLFSSL_MSG("i2v function not yet implemented for Auth Key Id");
+ break;
+ case NID_info_access:
+ WOLFSSL_MSG("i2v function not yet implemented for Info Access");
+ break;
+ case NID_ext_key_usage:
+ WOLFSSL_MSG("i2v function not yet implemented for Ext Key Usage");
+ break;
+ case NID_certificate_policies:
+ WOLFSSL_MSG("r2i function not yet implemented for Cert Policies");
+ break;
+ case NID_crl_distribution_points:
+ WOLFSSL_MSG("r2i function not yet implemented for CRL Dist Points");
+ break;
+ default:
+ /* If extension type is unknown, return NULL -- QT makes call to
+ X509_EXTENSION_get_data() if there is no v3_ext_method */
+ WOLFSSL_MSG("X509V3_EXT_get(): Unknown extension type found");
+ return NULL;
+ }
+
+ method.ext_nid = nid;
+ ex->ext_method = method;
+
+ return (const WOLFSSL_v3_ext_method*)&ex->ext_method;
}
+/* Parses and returns an x509v3 extension internal structure.
+ *
+ * ext : The X509_EXTENSION for parsing internal structure. If extension is
+ * not NULL, get the NID of the extension object and create a new
+ * extension-specific internal structure based on the extension type.
+ *
+ * Returns NULL on error or if NID is not found, otherwise returns a pointer to
+ * the extension type-specific X509_EXTENSION internal structure.
+ * Return is expected to be free'd by caller.
+ */
+void* wolfSSL_X509V3_EXT_d2i(WOLFSSL_X509_EXTENSION* ext)
+{
+ const WOLFSSL_v3_ext_method* method;
+ int ret;
+ WOLFSSL_ASN1_OBJECT* object;
+ WOLFSSL_BASIC_CONSTRAINTS* bc;
+ WOLFSSL_AUTHORITY_KEYID* akey;
+ WOLFSSL_ASN1_STRING* asn1String, *newString;
+ WOLFSSL_AUTHORITY_INFO_ACCESS* aia;
+ WOLFSSL_STACK* sk;
-#endif /* NO_DH */
+ WOLFSSL_ENTER("wolfSSL_X509V3_EXT_d2i");
+
+ if(ext == NULL) {
+ WOLFSSL_MSG("Bad function Argument");
+ return NULL;
+ }
+ /* extract extension info */
+ method = wolfSSL_X509V3_EXT_get(ext);
+ if (method == NULL) {
+ WOLFSSL_MSG("wolfSSL_X509V3_EXT_get error");
+ return NULL;
+ }
+ object = wolfSSL_X509_EXTENSION_get_object(ext);
+ if (object == NULL) {
+ WOLFSSL_MSG("X509_EXTENSION_get_object failed");
+ return NULL;
+ }
-#ifdef OPENSSL_EXTRA
-/* put SSL type in extra for now, not very common */
+ /* Return pointer to proper internal structure based on NID */
+ switch (object->type) {
+ /* basicConstraints */
+ case (NID_basic_constraints):
+ WOLFSSL_MSG("basicConstraints");
+ /* Allocate new BASIC_CONSTRAINTS structure */
+ bc = (WOLFSSL_BASIC_CONSTRAINTS*)
+ XMALLOC(sizeof(WOLFSSL_BASIC_CONSTRAINTS), NULL,
+ DYNAMIC_TYPE_X509_EXT);
+ if (bc == NULL) {
+ WOLFSSL_MSG("Failed to malloc basic constraints");
+ return NULL;
+ }
+ /* Copy pathlen and CA into BASIC_CONSTRAINTS from object */
+ bc->ca = object->ca;
+ if (object->pathlen->length > 0) {
+ bc->pathlen = wolfSSL_ASN1_INTEGER_dup(object->pathlen);
+ if (bc->pathlen == NULL) {
+ WOLFSSL_MSG("Failed to duplicate ASN1_INTEGER");
+ XFREE(bc, NULL, DYNAMIC_TYPE_X509_EXT);
+ return NULL;
+ }
+ }
+ else
+ bc->pathlen = NULL;
+ return bc;
+
+ /* subjectKeyIdentifier */
+ case (NID_subject_key_identifier):
+ WOLFSSL_MSG("subjectKeyIdentifier");
+ asn1String = wolfSSL_X509_EXTENSION_get_data(ext);
+ if (asn1String == NULL) {
+ WOLFSSL_MSG("X509_EXTENSION_get_data() failed");
+ return NULL;
+ }
+ newString = wolfSSL_ASN1_STRING_new();
+ if (newString == NULL) {
+ WOLFSSL_MSG("Failed to malloc ASN1_STRING");
+ return NULL;
+ }
+ ret = wolfSSL_ASN1_STRING_set(newString, asn1String->data,
+ asn1String->length);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ASN1_STRING_set() failed");
+ wolfSSL_ASN1_STRING_free(newString);
+ return NULL;
+ };
+ newString->type = asn1String->type;
+ return newString;
+
+ /* authorityKeyIdentifier */
+ case (NID_authority_key_identifier):
+ WOLFSSL_MSG("AuthorityKeyIdentifier");
+
+ akey = (WOLFSSL_AUTHORITY_KEYID*)
+ XMALLOC(sizeof(WOLFSSL_AUTHORITY_KEYID), NULL,
+ DYNAMIC_TYPE_X509_EXT);
+ if (akey == NULL) {
+ WOLFSSL_MSG("Failed to malloc authority key id");
+ return NULL;
+ }
+
+ akey->keyid = wolfSSL_ASN1_STRING_new();
+ if (akey->keyid == NULL) {
+ WOLFSSL_MSG("ASN1_STRING_new() failed");
+ wolfSSL_AUTHORITY_KEYID_free(akey);
+ return NULL;
+ }
+ asn1String = wolfSSL_X509_EXTENSION_get_data(ext);
+ if (asn1String == NULL) {
+ WOLFSSL_MSG("X509_EXTENSION_get_data() failed");
+ wolfSSL_AUTHORITY_KEYID_free(akey);
+ return NULL;
+ }
+
+ ret = wolfSSL_ASN1_STRING_set(akey->keyid, asn1String->data,
+ asn1String->length);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ASN1_STRING_set() failed");
+ wolfSSL_AUTHORITY_KEYID_free(akey);
+ return NULL;
+ };
+ akey->keyid->type = asn1String->type;
+
+ /* For now, set issuer and serial to NULL. This may need to be
+ updated for future use */
+ akey->issuer = NULL;
+ akey->serial = NULL;
+ return akey;
+
+ /* keyUsage */
+ case (NID_key_usage):
+ WOLFSSL_MSG("keyUsage");
+ /* This may need to be updated for future use. The i2v method for
+ keyUsage is not currently set. For now, return the ASN1_STRING
+ representation of KeyUsage bit string */
+ asn1String = wolfSSL_X509_EXTENSION_get_data(ext);
+ if (asn1String == NULL) {
+ WOLFSSL_MSG("X509_EXTENSION_get_data() failed");
+ return NULL;
+ }
+ newString = wolfSSL_ASN1_STRING_new();
+ if (newString == NULL) {
+ WOLFSSL_MSG("Failed to malloc ASN1_STRING");
+ return NULL;
+ }
+ ret = wolfSSL_ASN1_STRING_set(newString, asn1String->data,
+ asn1String->length);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ASN1_STRING_set() failed");
+ wolfSSL_ASN1_STRING_free(newString);
+ return NULL;
+ };
+ newString->type = asn1String->type;
+ return newString;
+
+ /* extKeyUsage */
+ case (NID_ext_key_usage):
+ WOLFSSL_MSG("extKeyUsage not supported yet");
+ return NULL;
+
+ /* certificatePolicies */
+ case (NID_certificate_policies):
+ WOLFSSL_MSG("certificatePolicies not supported yet");
+ return NULL;
+
+ /* cRLDistributionPoints */
+ case (NID_crl_distribution_points):
+ WOLFSSL_MSG("cRLDistributionPoints not supported yet");
+ return NULL;
+
+ /* authorityInfoAccess */
+ case (NID_info_access):
+ WOLFSSL_MSG("AuthorityInfoAccess");
+
+ sk = ext->ext_sk;
+ if (sk == NULL) {
+ WOLFSSL_MSG("ACCESS_DESCRIPTION stack NULL");
+ return NULL;
+ }
+
+ /* AUTHORITY_INFO_ACCESS is a stack of ACCESS_DESCRIPTION entries */
+ aia = wolfSSL_sk_new_null();
+ if (aia == NULL) {
+ WOLFSSL_MSG("Failed to malloc AUTHORITY_INFO_ACCESS");
+ return NULL;
+ }
+ aia->type = STACK_TYPE_ACCESS_DESCRIPTION;
+
+ while (sk) {
+ WOLFSSL_ACCESS_DESCRIPTION* ad;
+ WOLFSSL_ASN1_OBJECT* aiaEntry;
+
+ if (sk->type != STACK_TYPE_OBJ) {
+ sk = sk->next;
+ continue;
+ }
+
+ aiaEntry = sk->data.obj;
+
+ /* ACCESS_DESCRIPTION has two members, method and location.
+ Method: ASN1_OBJECT as either AIA_OCSP_OID or AIA_CA_ISSUER_OID
+ Location: GENERAL_NAME structure containing the URI. */
+
+ ad = (WOLFSSL_ACCESS_DESCRIPTION*)
+ XMALLOC(sizeof(WOLFSSL_ACCESS_DESCRIPTION), NULL,
+ DYNAMIC_TYPE_X509_EXT);
+ if (ad == NULL) {
+ WOLFSSL_MSG("Failed to malloc ACCESS_DESCRIPTION");
+ XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT);
+ return NULL;
+ }
+ XMEMSET(ad, 0, sizeof(WOLFSSL_ACCESS_DESCRIPTION));
+
+ /* Create new ASN1_OBJECT from oid */
+ ad->method = wolfSSL_OBJ_nid2obj(aiaEntry->nid);
+ if (ad->method == NULL) {
+ WOLFSSL_MSG("OBJ_nid2obj() failed");
+ XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT);
+ XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT);
+ return NULL;
+ }
+
+ /* Allocate memory for GENERAL NAME */
+ ad->location = (WOLFSSL_GENERAL_NAME*)
+ XMALLOC(sizeof(WOLFSSL_GENERAL_NAME), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (ad->location == NULL) {
+ WOLFSSL_MSG("Failed to malloc GENERAL_NAME");
+ wolfSSL_ASN1_OBJECT_free(ad->method);
+ XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT);
+ XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT);
+ return NULL;
+ }
+ XMEMSET(ad->location, 0, sizeof(WOLFSSL_GENERAL_NAME));
+ ad->location->type = GEN_URI;
+ ad->location->d.uniformResourceIdentifier =
+ wolfSSL_ASN1_STRING_new();
+ /* Set the URI in GENERAL_NAME */
+ ret = wolfSSL_ASN1_STRING_set(
+ ad->location->d.uniformResourceIdentifier,
+ aiaEntry->obj, aiaEntry->objSz);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ASN1_STRING_set() failed");
+ wolfSSL_ASN1_OBJECT_free(ad->method);
+ XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT);
+ XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT);
+ return NULL;
+ }
+ /* Push to AUTHORITY_INFO_ACCESS stack */
+ ret = wolfSSL_sk_ACCESS_DESCRIPTION_push(aia, ad);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error pushing ASN1 AD onto stack");
+ wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(aia, NULL);
+ wolfSSL_ASN1_OBJECT_free(ad->method);
+ XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT);
+ XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT);
+ return NULL;
+ }
+
+ sk = sk->next;
+ }
+ return aia;
+
+ default:
+ WOLFSSL_MSG("Extension NID not in table, returning NULL");
+ break;
+ }
+ return NULL;
+}
+
+/* Looks for the extension matching the passed in nid
+ *
+ * x509 : certificate to get parse through for extension.
+ * nid : Extension OID to be found.
+ * lastPos : Start search from extension after lastPos.
+ * Set to -1 to search from index 0.
+ * return >= 0 If successful the extension index is returned.
+ * return -1 If extension is not found or error is encountered.
+ */
+int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509* x509, int nid, int lastPos)
+{
+ int extCount = 0, length = 0, outSz = 0, sz = 0, ret = 0;
+ int isSet = 0, found = 0, loc;
+ const byte* rawCert;
+ const byte* input;
+ word32 oid, idx = 0, tmpIdx = 0;
+ DecodedCert cert;
+
+ WOLFSSL_ENTER("wolfSSL_X509_get_ext_by_NID");
+
+ if(x509 == NULL){
+ WOLFSSL_MSG("\tNot passed a certificate");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if(lastPos < -1 || (lastPos > (wolfSSL_X509_get_ext_count(x509) - 1))){
+ WOLFSSL_MSG("\tBad location argument");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ loc = lastPos + 1;
+
+ rawCert = wolfSSL_X509_get_der((WOLFSSL_X509*)x509, &outSz);
+ if (rawCert == NULL) {
+ WOLFSSL_MSG("\tX509_get_der() failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ InitDecodedCert( &cert, rawCert, (word32)outSz, 0);
+
+ if (ParseCert(&cert, CA_TYPE, NO_VERIFY, NULL) < 0) {
+ WOLFSSL_MSG("\tCertificate parsing failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ input = cert.extensions;
+ sz = cert.extensionsSz;
+
+ if (input == NULL || sz == 0) {
+ WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
+ FreeDecodedCert(&cert);
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (input[idx++] != ASN_EXTENSIONS) {
+ WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
+ FreeDecodedCert(&cert);
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (GetLength(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: invalid length");
+ FreeDecodedCert(&cert);
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (GetSequence(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)");
+ FreeDecodedCert(&cert);
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ while (idx < (word32)sz) {
+ oid = 0;
+
+ if (GetSequence(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: should be a SEQUENCE");
+ FreeDecodedCert(&cert);
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ tmpIdx = idx;
+ ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz);
+ if (ret < 0) {
+ WOLFSSL_MSG("\tfail: OBJECT ID");
+ FreeDecodedCert(&cert);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ idx = tmpIdx;
+
+ if (extCount >= loc) {
+ /* extCount >= loc. Now check if extension has been set */
+ isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, oid);
+
+ if (isSet && ((word32)nid == oid)) {
+ found = 1;
+ break;
+ }
+ }
+
+ idx += length;
+ extCount++;
+ } /* while(idx < sz) */
+
+ FreeDecodedCert(&cert);
+
+ return found ? extCount : WOLFSSL_FATAL_ERROR;
+}
+
+
+#endif /* OPENSSL_ALL */
+
+WOLFSSL_ASN1_BIT_STRING* wolfSSL_ASN1_BIT_STRING_new(void)
+{
+ WOLFSSL_ASN1_BIT_STRING* str;
+
+ str = (WOLFSSL_ASN1_BIT_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_BIT_STRING),
+ NULL, DYNAMIC_TYPE_OPENSSL);
+ if (str) {
+ XMEMSET(str, 0, sizeof(WOLFSSL_ASN1_BIT_STRING));
+ }
+ return str;
+}
+
+void wolfSSL_ASN1_BIT_STRING_free(WOLFSSL_ASN1_BIT_STRING* str)
+{
+ if (str) {
+ if (str->data) {
+ XFREE(str->data, NULL, DYNAMIC_TYPE_OPENSSL);
+ str->data = NULL;
+ }
+ XFREE(str, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+
+int wolfSSL_ASN1_BIT_STRING_get_bit(const WOLFSSL_ASN1_BIT_STRING* str, int i)
+{
+ if (!str || !str->data || str->length <= (i/8) || i < 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ return (str->data[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
+}
+
+/* Looks for the extension matching the passed in nid
+ *
+ * c : if not null then is set to status value -2 if multiple occurrences
+ * of the extension are found, -1 if not found, 0 if found and not
+ * critical, and 1 if found and critical.
+ * nid : Extension OID to be found.
+ * idx : if NULL return first extension found match, otherwise start search at
+ * idx location and set idx to the location of extension returned.
+ * returns NULL or a pointer to an WOLFSSL_ASN1_BIT_STRING (for KEY_USAGE_OID)
+ * or WOLFSSL_STACK (for other)
+ * holding extension structure
+ *
+ * NOTE code for decoding extensions is in asn.c DecodeCertExtensions --
+ * use already decoded extension in this function to avoid decoding twice.
+ * Currently we do not make use of idx since getting pre decoded extensions.
+ */
+void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c,
+ int* idx)
+{
+ void* ret = NULL;
+ WOLFSSL_STACK* sk = NULL;
+ WOLFSSL_ASN1_OBJECT* obj = NULL;
+ WOLFSSL_GENERAL_NAME* gn = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_X509_get_ext_d2i");
+
+ if (x509 == NULL) {
+ return NULL;
+ }
+
+ if (c != NULL) {
+ *c = -1; /* default to not found */
+ }
+
+ switch (nid) {
+ case BASIC_CA_OID:
+ if (x509->basicConstSet) {
+ obj = wolfSSL_ASN1_OBJECT_new();
+ if (obj == NULL) {
+ WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+ return NULL;
+ }
+ if (c != NULL) {
+ *c = x509->basicConstCrit;
+ }
+ obj->type = BASIC_CA_OID;
+ obj->grp = oidCertExtType;
+ obj->nid = nid;
+ obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || \
+ defined(WOLFSSL_APACHE_HTTPD)
+ obj->ca = x509->isCa;
+ #endif
+ }
+ else {
+ WOLFSSL_MSG("No Basic Constraint set");
+ }
+ return obj;
+
+ case ALT_NAMES_OID:
+ {
+ DNS_entry* dns = NULL;
+ /* Malloc GENERAL_NAME stack */
+ sk = (WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)*)XMALLOC(
+ sizeof(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)), NULL,
+ DYNAMIC_TYPE_ASN1);
+ if (sk == NULL) {
+ return NULL;
+ }
+ XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)));
+ sk->type = STACK_TYPE_GEN_NAME;
+
+ if (x509->subjAltNameSet && x509->altNames != NULL) {
+ /* alt names are DNS_entry structs */
+ if (c != NULL) {
+ if (x509->altNames->next != NULL) {
+ *c = -2; /* more then one found */
+ }
+ else {
+ *c = x509->subjAltNameCrit;
+ }
+ }
+
+ dns = x509->altNames;
+ /* Currently only support GEN_DNS type */
+ while (dns != NULL) {
+ gn = wolfSSL_GENERAL_NAME_new();
+ if (gn == NULL) {
+ WOLFSSL_MSG("Error creating GENERAL_NAME");
+ wolfSSL_sk_free(sk);
+ return NULL;
+ }
+
+ gn->type = dns->type;
+ gn->d.ia5->length = dns->len;
+ if (wolfSSL_ASN1_STRING_set(gn->d.ia5, dns->name,
+ gn->d.ia5->length) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ASN1_STRING_set failed");
+ wolfSSL_GENERAL_NAME_free(gn);
+ wolfSSL_sk_free(sk);
+ return NULL;
+ }
+
+ dns = dns->next;
+ /* last dns in list add at end of function */
+ if (dns != NULL) {
+ if (wolfSSL_sk_GENERAL_NAME_push(sk, gn) !=
+ WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error pushing ASN1 object onto stack");
+ wolfSSL_GENERAL_NAME_free(gn);
+ wolfSSL_sk_free(sk);
+ sk = NULL;
+ }
+ }
+ }
+ }
+ else {
+ WOLFSSL_MSG("No Alt Names set");
+ }
+
+ break;
+ }
+
+ case CRL_DIST_OID:
+ if (x509->CRLdistSet && x509->CRLInfo != NULL) {
+ if (c != NULL) {
+ *c = x509->CRLdistCrit;
+ }
+ obj = wolfSSL_ASN1_OBJECT_new();
+ if (obj == NULL) {
+ WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+ return NULL;
+ }
+ obj->type = CRL_DIST_OID;
+ obj->grp = oidCertExtType;
+ obj->obj = x509->CRLInfo;
+ obj->objSz = x509->CRLInfoSz;
+ obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+ obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA ;
+ }
+ else {
+ WOLFSSL_MSG("No CRL dist set");
+ }
+ break;
+
+ case AUTH_INFO_OID:
+ if (x509->authInfoSet && x509->authInfo != NULL) {
+ if (c != NULL) {
+ *c = x509->authInfoCrit;
+ }
+ obj = wolfSSL_ASN1_OBJECT_new();
+ if (obj == NULL) {
+ WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+ return NULL;
+ }
+ obj->type = AUTH_INFO_OID;
+ obj->grp = oidCertExtType;
+ obj->obj = x509->authInfo;
+ obj->objSz = x509->authInfoSz;
+ obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+ obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
+ }
+ else {
+ WOLFSSL_MSG("No Auth Info set");
+ }
+ break;
+
+ case AUTH_KEY_OID:
+ if (x509->authKeyIdSet) {
+ if (c != NULL) {
+ *c = x509->authKeyIdCrit;
+ }
+ obj = wolfSSL_ASN1_OBJECT_new();
+ if (obj == NULL) {
+ WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+ return NULL;
+ }
+ obj->type = AUTH_KEY_OID;
+ obj->grp = oidCertExtType;
+ obj->obj = x509->authKeyId;
+ obj->objSz = x509->authKeyIdSz;
+ obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+ obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
+ }
+ else {
+ WOLFSSL_MSG("No Auth Key set");
+ }
+ break;
+
+ case SUBJ_KEY_OID:
+ if (x509->subjKeyIdSet) {
+ if (c != NULL) {
+ *c = x509->subjKeyIdCrit;
+ }
+ obj = wolfSSL_ASN1_OBJECT_new();
+ if (obj == NULL) {
+ WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+ return NULL;
+ }
+ obj->type = SUBJ_KEY_OID;
+ obj->grp = oidCertExtType;
+ obj->obj = x509->subjKeyId;
+ obj->objSz = x509->subjKeyIdSz;
+ obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+ obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
+ }
+ else {
+ WOLFSSL_MSG("No Subject Key set");
+ }
+ break;
+
+ case CERT_POLICY_OID:
+ {
+ #ifdef WOLFSSL_CERT_EXT
+ int i;
+
+ if (x509->certPoliciesNb > 0) {
+ if (c != NULL) {
+ if (x509->certPoliciesNb > 1) {
+ *c = -2;
+ }
+ else {
+ *c = 0;
+ }
+ }
+
+ sk = wolfSSL_sk_new_asn1_obj();
+ if (sk == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < x509->certPoliciesNb - 1; i++) {
+ obj = wolfSSL_ASN1_OBJECT_new();
+ if (obj == NULL) {
+ WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+ wolfSSL_sk_ASN1_OBJECT_free(sk);
+ return NULL;
+ }
+ obj->type = CERT_POLICY_OID;
+ obj->grp = oidCertExtType;
+ obj->obj = (byte*)(x509->certPolicies[i]);
+ obj->objSz = MAX_CERTPOL_SZ;
+ obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+ obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
+ if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj)
+ != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error pushing ASN1 object onto stack");
+ wolfSSL_ASN1_OBJECT_free(obj);
+ wolfSSL_sk_ASN1_OBJECT_free(sk);
+ sk = NULL;
+ }
+ }
+ obj = wolfSSL_ASN1_OBJECT_new();
+ if (obj == NULL) {
+ WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+ wolfSSL_sk_ASN1_OBJECT_free(sk);
+ return NULL;
+ }
+ obj->type = CERT_POLICY_OID;
+ obj->grp = oidCertExtType;
+ obj->obj = (byte*)(x509->certPolicies[i]);
+ obj->objSz = MAX_CERTPOL_SZ;
+ obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+ obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
+ }
+ else {
+ WOLFSSL_MSG("No Cert Policy set");
+ }
+ #elif defined(WOLFSSL_SEP)
+ if (x509->certPolicySet) {
+ if (c != NULL) {
+ *c = x509->certPolicyCrit;
+ }
+ obj = wolfSSL_ASN1_OBJECT_new();
+ if (obj == NULL) {
+ WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+ return NULL;
+ }
+ obj->type = CERT_POLICY_OID;
+ obj->grp = oidCertExtType;
+ obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+ }
+ else {
+ WOLFSSL_MSG("No Cert Policy set");
+ }
+ #else
+ WOLFSSL_MSG("wolfSSL not built with WOLFSSL_SEP or WOLFSSL_CERT_EXT");
+ #endif
+ break;
+ }
+ case KEY_USAGE_OID:
+ {
+ WOLFSSL_ASN1_BIT_STRING* bit_str = NULL;
+ if (x509->keyUsageSet) {
+ if (c != NULL) {
+ *c = x509->keyUsageCrit;
+ }
+
+ bit_str = wolfSSL_ASN1_BIT_STRING_new();
+ if (bit_str == NULL) {
+ WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_BIT_STRING struct");
+ return NULL;
+ }
+
+ bit_str->type = KEY_USAGE_OID;
+ bit_str->flags = 0;
+ bit_str->length = sizeof(word16);
+ bit_str->data = (byte*)XMALLOC(bit_str->length, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (bit_str->data == NULL) {
+ wolfSSL_ASN1_BIT_STRING_free(bit_str);
+ return NULL;
+ }
+ XMEMCPY(bit_str->data, &x509->keyUsage, bit_str->length);
+ }
+ else {
+ WOLFSSL_MSG("No Key Usage set");
+ }
+ /* don't add stack of and return bit string directly */
+ return bit_str;
+ }
+ case INHIBIT_ANY_OID:
+ WOLFSSL_MSG("INHIBIT ANY extension not supported");
+ break;
+
+ case EXT_KEY_USAGE_OID:
+ if (x509->extKeyUsageSrc != NULL) {
+ if (c != NULL) {
+ if (x509->extKeyUsageCount > 1) {
+ *c = -2;
+ }
+ else {
+ *c = x509->extKeyUsageCrit;
+ }
+ }
+ obj = wolfSSL_ASN1_OBJECT_new();
+ if (obj == NULL) {
+ WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+ return NULL;
+ }
+ obj->type = EXT_KEY_USAGE_OID;
+ obj->grp = oidCertExtType;
+ obj->obj = x509->extKeyUsageSrc;
+ obj->objSz = x509->extKeyUsageSz;
+ obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+ obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
+ }
+ else {
+ WOLFSSL_MSG("No Extended Key Usage set");
+ }
+ break;
+
+ case NAME_CONS_OID:
+ WOLFSSL_MSG("Name Constraint OID extension not supported");
+ break;
+
+ case PRIV_KEY_USAGE_PERIOD_OID:
+ WOLFSSL_MSG("Private Key Usage Period extension not supported");
+ break;
+
+ case SUBJECT_INFO_ACCESS:
+ WOLFSSL_MSG("Subject Info Access extension not supported");
+ break;
+
+ case POLICY_MAP_OID:
+ WOLFSSL_MSG("Policy Map extension not supported");
+ break;
+
+ case POLICY_CONST_OID:
+ WOLFSSL_MSG("Policy Constraint extension not supported");
+ break;
+
+ case ISSUE_ALT_NAMES_OID:
+ WOLFSSL_MSG("Issue Alt Names extension not supported");
+ break;
+
+ case TLS_FEATURE_OID:
+ WOLFSSL_MSG("TLS Feature extension not supported");
+ break;
+
+ default:
+ WOLFSSL_MSG("Unsupported/Unknown extension OID");
+ }
+
+ /* make sure stack of is allocated */
+ if ((obj || gn) && sk == NULL) {
+ sk = wolfSSL_sk_new_asn1_obj();
+ if (sk == NULL) {
+ goto err;
+ }
+ }
+ if (obj && wolfSSL_sk_ASN1_OBJECT_push(sk, obj) == WOLFSSL_SUCCESS) {
+ /* obj pushed successfully on stack */
+ }
+ else if (gn && wolfSSL_sk_GENERAL_NAME_push(sk, gn) == WOLFSSL_SUCCESS) {
+ /* gn pushed successfully on stack */
+ }
+ else {
+ /* Nothing to push or push failed */
+ WOLFSSL_MSG("Error pushing ASN1_OBJECT or GENERAL_NAME object onto stack "
+ "or nothing to push.");
+ goto err;
+ }
+ ret = sk;
+
+ (void)idx;
+
+ return ret;
+
+err:
+ if (obj) {
+ wolfSSL_ASN1_OBJECT_free(obj);
+ }
+ if (gn) {
+ wolfSSL_GENERAL_NAME_free(gn);
+ }
+ if (sk) {
+ wolfSSL_sk_ASN1_OBJECT_free(sk);
+ }
+ return NULL;
+}
+
+
+int wolfSSL_X509_add_altname(WOLFSSL_X509* x509, const char* name, int type)
+{
+ DNS_entry* newAltName = NULL;
+ char* nameCopy = NULL;
+ word32 nameSz;
+
+ if (x509 == NULL)
+ return WOLFSSL_FAILURE;
+
+ if (name == NULL)
+ return WOLFSSL_SUCCESS;
+
+ nameSz = (word32)XSTRLEN(name);
+ if (nameSz == 0)
+ return WOLFSSL_SUCCESS;
+
+ newAltName = (DNS_entry*)XMALLOC(sizeof(DNS_entry),
+ x509->heap, DYNAMIC_TYPE_ALTNAME);
+ if (newAltName == NULL)
+ return WOLFSSL_FAILURE;
+
+ nameCopy = (char*)XMALLOC(nameSz + 1, x509->heap, DYNAMIC_TYPE_ALTNAME);
+ if (nameCopy == NULL) {
+ XFREE(newAltName, x509->heap, DYNAMIC_TYPE_ALTNAME);
+ return WOLFSSL_FAILURE;
+ }
+
+ XMEMCPY(nameCopy, name, nameSz + 1);
+
+ newAltName->next = x509->altNames;
+ newAltName->type = type;
+ newAltName->len = nameSz;
+ newAltName->name = nameCopy;
+ x509->altNames = newAltName;
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_X509_add_ext(WOLFSSL_X509 *x509, WOLFSSL_X509_EXTENSION *ext, int loc)
+{
+ WOLFSSL_STUB("wolfSSL_X509_add_ext");
+ (void)x509;
+ (void)ext;
+ (void)loc;
+ return WOLFSSL_FAILURE;
+}
+
+/* currently LHASH is not implemented (and not needed for Apache port) */
+WOLFSSL_X509_EXTENSION* wolfSSL_X509V3_EXT_conf_nid(
+ WOLF_LHASH_OF(CONF_VALUE)* conf, WOLFSSL_X509V3_CTX* ctx, int nid,
+ char* value)
+{
+ WOLFSSL_STUB("wolfSSL_X509V3_EXT_conf_nid");
+
+ if (conf != NULL) {
+ WOLFSSL_MSG("Handling LHASH not implemented yet");
+ return NULL;
+ }
+
+ (void)conf;
+ (void)ctx;
+ (void)nid;
+ (void)value;
+ return NULL;
+}
+
+void wolfSSL_X509V3_set_ctx_nodb(WOLFSSL_X509V3_CTX* ctx)
+{
+ WOLFSSL_STUB("wolfSSL_X509V3_set_ctx_nodb");
+ (void)ctx;
+}
+#endif /* !NO_WOLFSSL_STUB */
+
+/* Returns pointer to ASN1_OBJECT from an X509_EXTENSION object */
+WOLFSSL_ASN1_OBJECT* wolfSSL_X509_EXTENSION_get_object \
+ (WOLFSSL_X509_EXTENSION* ext)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_object");
+ if(ext == NULL)
+ return NULL;
+ return ext->obj;
+}
+
+/* Returns pointer to ASN1_STRING in X509_EXTENSION object */
+WOLFSSL_ASN1_STRING* wolfSSL_X509_EXTENSION_get_data(WOLFSSL_X509_EXTENSION* ext)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_data");
+ if (ext == NULL)
+ return NULL;
+ return &ext->value;
+}
+
+#if !defined(NO_PWDBASED)
+int wolfSSL_X509_digest(const WOLFSSL_X509* x509, const WOLFSSL_EVP_MD* digest,
+ unsigned char* buf, unsigned int* len)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_X509_digest");
+
+ if (x509 == NULL || digest == NULL) {
+ WOLFSSL_MSG("Null argument found");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (x509->derCert == NULL) {
+ WOLFSSL_MSG("No DER certificate stored in X509");
+ return WOLFSSL_FAILURE;
+ }
+
+ ret = wolfSSL_EVP_Digest(x509->derCert->buffer, x509->derCert->length, buf,
+ len, digest, NULL);
+ WOLFSSL_LEAVE("wolfSSL_X509_digest", ret);
+ return ret;
+}
+#endif
+
+int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey)
+{
+ WOLFSSL_ENTER("wolfSSL_use_PrivateKey");
+ if (ssl == NULL || pkey == NULL ) {
+ return WOLFSSL_FAILURE;
+ }
+
+ return wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr,
+ pkey->pkey_sz, WOLFSSL_FILETYPE_ASN1);
+}
+
+
+int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, const unsigned char* der,
+ long derSz)
+{
+ WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1");
+ if (ssl == NULL || der == NULL ) {
+ return WOLFSSL_FAILURE;
+ }
+
+ (void)pri; /* type of private key */
+ return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1);
+}
+/******************************************************************************
+* wolfSSL_CTX_use_PrivateKey_ASN1 - loads a private key buffer into the SSL ctx
+*
+* RETURNS:
+* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE
+*/
+
+int wolfSSL_CTX_use_PrivateKey_ASN1(int pri, WOLFSSL_CTX* ctx,
+ unsigned char* der, long derSz)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_ASN1");
+ if (ctx == NULL || der == NULL ) {
+ return WOLFSSL_FAILURE;
+ }
+
+ (void)pri; /* type of private key */
+ return wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1);
+}
+
+
+#ifndef NO_RSA
+int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz)
+{
+ WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1");
+ if (ssl == NULL || der == NULL ) {
+ return WOLFSSL_FAILURE;
+ }
+
+ return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1);
+}
+#endif
+
+int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509)
+{
+ long idx;
+
+ WOLFSSL_ENTER("wolfSSL_use_certificate");
+ if (x509 != NULL && ssl != NULL && x509->derCert != NULL) {
+ if (ProcessBuffer(NULL, x509->derCert->buffer, x509->derCert->length,
+ WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0,
+ GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
+ return WOLFSSL_SUCCESS;
+ }
+ }
+
+ (void)idx;
+ return WOLFSSL_FAILURE;
+}
+
+#endif /* NO_CERTS */
+
+#endif /* OPENSSL_EXTRA */
+
+#ifndef NO_CERTS
+int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, const unsigned char* der,
+ int derSz)
+{
+ long idx;
+
+ WOLFSSL_ENTER("wolfSSL_use_certificate_ASN1");
+ if (der != NULL && ssl != NULL) {
+ if (ProcessBuffer(NULL, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE,
+ ssl, &idx, 0, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
+ return WOLFSSL_SUCCESS;
+ }
+ }
+
+ (void)idx;
+ return WOLFSSL_FAILURE;
+}
+
+#ifndef NO_FILESYSTEM
+
+WOLFSSL_ABI
int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format)
{
WOLFSSL_ENTER("wolfSSL_use_certificate_file");
- if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 0, NULL)
- == SSL_SUCCESS)
- return SSL_SUCCESS;
- return SSL_FAILURE;
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (ProcessFile(ssl->ctx, file, format, CERT_TYPE,
+ ssl, 0, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
+ return WOLFSSL_SUCCESS;
+ }
+
+ return WOLFSSL_FAILURE;
}
+WOLFSSL_ABI
int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format)
{
WOLFSSL_ENTER("wolfSSL_use_PrivateKey_file");
- if (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE, ssl, 0, NULL)
- == SSL_SUCCESS)
- return SSL_SUCCESS;
- return SSL_FAILURE;
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE,
+ ssl, 0, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
+ return WOLFSSL_SUCCESS;
+ }
+
+ return WOLFSSL_FAILURE;
}
+WOLFSSL_ABI
int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file)
{
- /* procces up to MAX_CHAIN_DEPTH plus subject cert */
- WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file");
- if (ProcessFile(ssl->ctx, file, SSL_FILETYPE_PEM, CERT_TYPE, ssl, 1, NULL)
- == SSL_SUCCESS)
- return SSL_SUCCESS;
+ /* process up to MAX_CHAIN_DEPTH plus subject cert */
+ WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file");
+
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE,
+ ssl, 1, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
+ return WOLFSSL_SUCCESS;
+ }
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
}
+int wolfSSL_use_certificate_chain_file_format(WOLFSSL* ssl, const char* file,
+ int format)
+{
+ /* process up to MAX_CHAIN_DEPTH plus subject cert */
+ WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file_format");
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 1,
+ NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
+ return WOLFSSL_SUCCESS;
+ }
+ return WOLFSSL_FAILURE;
+}
+
+#endif /* !NO_FILESYSTEM */
+#endif /* !NO_CERTS */
#ifdef HAVE_ECC
/* Set Temp CTX EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */
int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz)
{
- if (ctx == NULL || sz < ECC_MINSIZE || sz > ECC_MAXSIZE)
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ if (sz == 0) {
+ /* applies only to ECDSA */
+ if (ctx->privateKeyType != ecc_dsa_sa_algo)
+ return WOLFSSL_SUCCESS;
+
+ if (ctx->privateKeySz == 0) {
+ WOLFSSL_MSG("Must set private key/cert first");
+ return BAD_FUNC_ARG;
+ }
+
+ sz = (word16)ctx->privateKeySz;
+ }
+
+ /* check size */
+ if (sz < ECC_MINSIZE || sz > ECC_MAXSIZE)
return BAD_FUNC_ARG;
ctx->eccTempKeySz = sz;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
@@ -4004,14 +9785,15 @@ int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz)
ssl->eccTempKeySz = sz;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
#endif /* HAVE_ECC */
+#ifdef OPENSSL_EXTRA
-
+#ifndef NO_FILESYSTEM
int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX* ctx,const char* file,
int format)
{
@@ -4027,24 +9809,68 @@ int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format)
return wolfSSL_use_PrivateKey_file(ssl, file, format);
}
+#endif /* NO_FILESYSTEM */
+
+
+/* Copies the master secret over to out buffer. If outSz is 0 returns the size
+ * of master secret.
+ *
+ * ses : a session from completed TLS/SSL handshake
+ * out : buffer to hold copy of master secret
+ * outSz : size of out buffer
+ * returns : number of bytes copied into out buffer on success
+ * less then or equal to 0 is considered a failure case
+ */
+int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses,
+ unsigned char* out, int outSz)
+{
+ int size;
+
+ if (outSz == 0) {
+ return SECRET_LEN;
+ }
+
+ if (ses == NULL || out == NULL || outSz < 0) {
+ return 0;
+ }
+
+ if (outSz > SECRET_LEN) {
+ size = SECRET_LEN;
+ }
+ else {
+ size = outSz;
+ }
+
+ XMEMCPY(out, ses->masterSecret, size);
+ return size;
+}
+
+
+int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses)
+{
+ (void)ses;
+ return SECRET_LEN;
+}
#endif /* OPENSSL_EXTRA */
+#ifndef NO_FILESYSTEM
#ifdef HAVE_NTRU
int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX* ctx, const char* file)
{
WOLFSSL_ENTER("wolfSSL_CTX_use_NTRUPrivateKey_file");
+
if (ctx == NULL)
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
- if (ProcessFile(ctx, file, SSL_FILETYPE_RAW, PRIVATEKEY_TYPE, NULL, 0, NULL)
- == SSL_SUCCESS) {
+ if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_RAW, PRIVATEKEY_TYPE, NULL, 0,
+ NULL, GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
ctx->haveNTRU = 1;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
}
#endif /* HAVE_NTRU */
@@ -4056,42 +9882,86 @@ int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX* ctx, const char* file)
void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc)
{
WOLFSSL_ENTER("wolfSSL_CTX_set_verify");
- if (mode & SSL_VERIFY_PEER) {
+ if (ctx == NULL)
+ return;
+
+ if (mode & WOLFSSL_VERIFY_PEER) {
ctx->verifyPeer = 1;
- ctx->verifyNone = 0; /* in case perviously set */
+ ctx->verifyNone = 0; /* in case previously set */
}
- if (mode == SSL_VERIFY_NONE) {
+ if (mode == WOLFSSL_VERIFY_NONE) {
ctx->verifyNone = 1;
ctx->verifyPeer = 0; /* in case previously set */
}
- if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
+ if (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
ctx->failNoCert = 1;
+ }
+
+ if (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) {
+ ctx->failNoCert = 0; /* fail on all is set to fail on PSK */
+ ctx->failNoCertxPSK = 1;
+ }
ctx->verifyCallback = vc;
}
+#ifdef OPENSSL_ALL
+void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx,
+ CertVerifyCallback cb, void* arg)
+{
+ WOLFSSL_ENTER("SSL_CTX_set_cert_verify_callback");
+ if (ctx == NULL)
+ return;
+
+ ctx->verifyCertCb = cb;
+ ctx->verifyCertCbArg = arg;
+}
+#endif
+
void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc)
{
WOLFSSL_ENTER("wolfSSL_set_verify");
- if (mode & SSL_VERIFY_PEER) {
+ if (ssl == NULL)
+ return;
+
+ if (mode & WOLFSSL_VERIFY_PEER) {
ssl->options.verifyPeer = 1;
- ssl->options.verifyNone = 0; /* in case perviously set */
+ ssl->options.verifyNone = 0; /* in case previously set */
}
- if (mode == SSL_VERIFY_NONE) {
+ if (mode == WOLFSSL_VERIFY_NONE) {
ssl->options.verifyNone = 1;
ssl->options.verifyPeer = 0; /* in case previously set */
}
- if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
+ if (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT)
ssl->options.failNoCert = 1;
+ if (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) {
+ ssl->options.failNoCert = 0; /* fail on all is set to fail on PSK */
+ ssl->options.failNoCertxPSK = 1;
+ }
+
ssl->verifyCallback = vc;
}
+void wolfSSL_set_verify_result(WOLFSSL *ssl, long v)
+{
+ WOLFSSL_ENTER("wolfSSL_set_verify_result");
+
+ if (ssl == NULL)
+ return;
+
+#ifdef OPENSSL_ALL
+ ssl->verifyCallbackResult = v;
+#else
+ (void)v;
+ WOLFSSL_STUB("wolfSSL_set_verify_result");
+#endif
+}
/* store user ctx for verify callback */
void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx)
@@ -4140,7 +10010,8 @@ int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
#endif /* NO_FILESYSTEM */
/* Persist cert cache to memory */
-int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem, int sz, int* used)
+int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem,
+ int sz, int* used)
{
WOLFSSL_ENTER("wolfSSL_CTX_memsave_cert_cache");
@@ -4174,29 +10045,31 @@ int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx)
return CM_GetCertCacheMemSize(ctx->cm);
}
-#endif /* PERSISTE_CERT_CACHE */
+#endif /* PERSIST_CERT_CACHE */
#endif /* !NO_CERTS */
#ifndef NO_SESSION_CACHE
+WOLFSSL_ABI
WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl)
{
WOLFSSL_ENTER("SSL_get_session");
if (ssl)
- return GetSession(ssl, 0);
+ return GetSession(ssl, 0, 1);
return NULL;
}
+WOLFSSL_ABI
int wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session)
{
WOLFSSL_ENTER("SSL_set_session");
if (session)
return SetSession(ssl, session);
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
}
@@ -4204,7 +10077,7 @@ int wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session)
/* Associate client session with serverID, find existing or store for saving
if newSession flag on, don't reuse existing session
- SSL_SUCCESS on ok */
+ WOLFSSL_SUCCESS on ok */
int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession)
{
WOLFSSL_SESSION* session = NULL;
@@ -4217,7 +10090,10 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession)
if (newSession == 0) {
session = GetSessionClient(ssl, id, len);
if (session) {
- if (SetSession(ssl, session) != SSL_SUCCESS) {
+ if (SetSession(ssl, session) != WOLFSSL_SUCCESS) {
+ #ifdef HAVE_EXT_CACHE
+ wolfSSL_SESSION_free(session);
+ #endif
WOLFSSL_MSG("SetSession failed");
session = NULL;
}
@@ -4230,15 +10106,19 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession)
ssl->session.idLen = (word16)min(SERVER_ID_LEN, (word32)len);
XMEMCPY(ssl->session.serverID, id, ssl->session.idLen);
}
+ #ifdef HAVE_EXT_CACHE
+ else
+ wolfSSL_SESSION_free(session);
+ #endif
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
#endif /* NO_CLIENT_CACHE */
#if defined(PERSIST_SESSION_CACHE)
-/* for persistance, if changes to layout need to increment and modify
+/* for persistence, if changes to layout need to increment and modify
save_session_cache() and restore_session_cache and memory versions too */
#define WOLFSSL_CACHE_VERSION 2
@@ -4297,7 +10177,7 @@ int wolfSSL_memsave_session_cache(void* mem, int sz)
cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION);
XMEMCPY(mem, &cache_header, sizeof(cache_header));
- if (LockMutex(&session_mutex) != 0) {
+ if (wc_LockMutex(&session_mutex) != 0) {
WOLFSSL_MSG("Session cache mutex lock failed");
return BAD_MUTEX_E;
}
@@ -4311,15 +10191,15 @@ int wolfSSL_memsave_session_cache(void* mem, int sz)
XMEMCPY(clRow++, ClientCache + i, sizeof(ClientRow));
#endif
- UnLockMutex(&session_mutex);
+ wc_UnLockMutex(&session_mutex);
- WOLFSSL_LEAVE("wolfSSL_memsave_session_cache", SSL_SUCCESS);
+ WOLFSSL_LEAVE("wolfSSL_memsave_session_cache", WOLFSSL_SUCCESS);
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
-/* Restore the persistant session cache from memory */
+/* Restore the persistent session cache from memory */
int wolfSSL_memrestore_session_cache(const void* mem, int sz)
{
int i;
@@ -4346,7 +10226,7 @@ int wolfSSL_memrestore_session_cache(const void* mem, int sz)
return CACHE_MATCH_ERROR;
}
- if (LockMutex(&session_mutex) != 0) {
+ if (wc_LockMutex(&session_mutex) != 0) {
WOLFSSL_MSG("Session cache mutex lock failed");
return BAD_MUTEX_E;
}
@@ -4360,11 +10240,11 @@ int wolfSSL_memrestore_session_cache(const void* mem, int sz)
XMEMCPY(ClientCache + i, clRow++, sizeof(ClientRow));
#endif
- UnLockMutex(&session_mutex);
+ wc_UnLockMutex(&session_mutex);
- WOLFSSL_LEAVE("wolfSSL_memrestore_session_cache", SSL_SUCCESS);
+ WOLFSSL_LEAVE("wolfSSL_memrestore_session_cache", WOLFSSL_SUCCESS);
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
#if !defined(NO_FILESYSTEM)
@@ -4375,7 +10255,7 @@ int wolfSSL_save_session_cache(const char *fname)
{
XFILE file;
int ret;
- int rc = SSL_SUCCESS;
+ int rc = WOLFSSL_SUCCESS;
int i;
cache_header_t cache_header;
@@ -4384,7 +10264,7 @@ int wolfSSL_save_session_cache(const char *fname)
file = XFOPEN(fname, "w+b");
if (file == XBADFILE) {
WOLFSSL_MSG("Couldn't open session cache save file");
- return SSL_BAD_FILE;
+ return WOLFSSL_BAD_FILE;
}
cache_header.version = WOLFSSL_CACHE_VERSION;
cache_header.rows = SESSION_ROWS;
@@ -4399,7 +10279,7 @@ int wolfSSL_save_session_cache(const char *fname)
return FWRITE_ERROR;
}
- if (LockMutex(&session_mutex) != 0) {
+ if (wc_LockMutex(&session_mutex) != 0) {
WOLFSSL_MSG("Session cache mutex lock failed");
XFCLOSE(file);
return BAD_MUTEX_E;
@@ -4427,7 +10307,7 @@ int wolfSSL_save_session_cache(const char *fname)
}
#endif /* NO_CLIENT_CACHE */
- UnLockMutex(&session_mutex);
+ wc_UnLockMutex(&session_mutex);
XFCLOSE(file);
WOLFSSL_LEAVE("wolfSSL_save_session_cache", rc);
@@ -4436,12 +10316,12 @@ int wolfSSL_save_session_cache(const char *fname)
}
-/* Restore the persistant session cache from file */
+/* Restore the persistent session cache from file */
/* doesn't use memstore because of additional memory use */
int wolfSSL_restore_session_cache(const char *fname)
{
XFILE file;
- int rc = SSL_SUCCESS;
+ int rc = WOLFSSL_SUCCESS;
int ret;
int i;
cache_header_t cache_header;
@@ -4451,7 +10331,7 @@ int wolfSSL_restore_session_cache(const char *fname)
file = XFOPEN(fname, "rb");
if (file == XBADFILE) {
WOLFSSL_MSG("Couldn't open session cache save file");
- return SSL_BAD_FILE;
+ return WOLFSSL_BAD_FILE;
}
/* cache header */
ret = (int)XFREAD(&cache_header, sizeof cache_header, 1, file);
@@ -4470,7 +10350,7 @@ int wolfSSL_restore_session_cache(const char *fname)
return CACHE_MATCH_ERROR;
}
- if (LockMutex(&session_mutex) != 0) {
+ if (wc_LockMutex(&session_mutex) != 0) {
WOLFSSL_MSG("Session cache mutex lock failed");
XFCLOSE(file);
return BAD_MUTEX_E;
@@ -4501,7 +10381,7 @@ int wolfSSL_restore_session_cache(const char *fname)
#endif /* NO_CLIENT_CACHE */
- UnLockMutex(&session_mutex);
+ wc_UnLockMutex(&session_mutex);
XFCLOSE(file);
WOLFSSL_LEAVE("wolfSSL_restore_session_cache", rc);
@@ -4521,10 +10401,10 @@ void wolfSSL_load_error_strings(void) /* compatibility only */
int wolfSSL_library_init(void)
{
WOLFSSL_ENTER("SSL_library_init");
- if (wolfSSL_Init() == SSL_SUCCESS)
- return SSL_SUCCESS;
+ if (wolfSSL_Init() == WOLFSSL_SUCCESS)
+ return WOLFSSL_SUCCESS;
else
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
@@ -4534,7 +10414,7 @@ int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx)
{
WOLFSSL_ENTER("wolfSSL_set_session_secret_cb");
if (ssl == NULL)
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
ssl->sessionSecretCb = cb;
ssl->sessionSecretCtx = ctx;
@@ -4542,7 +10422,7 @@ int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx)
ssl->session.sessionIDSz = 0;
ssl->options.resuming = 1;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
#endif
@@ -4551,16 +10431,22 @@ int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx)
#ifndef NO_SESSION_CACHE
/* on by default if built in but allow user to turn off */
+WOLFSSL_ABI
long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode)
{
WOLFSSL_ENTER("SSL_CTX_set_session_cache_mode");
- if (mode == SSL_SESS_CACHE_OFF)
+ if (mode == WOLFSSL_SESS_CACHE_OFF)
ctx->sessionCacheOff = 1;
- if (mode == SSL_SESS_CACHE_NO_AUTO_CLEAR)
+ if ((mode & WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR) != 0)
ctx->sessionCacheFlushOff = 1;
- return SSL_SUCCESS;
+#ifdef HAVE_EXT_CACHE
+ if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE) != 0)
+ ctx->internalCacheOff = 1;
+#endif
+
+ return WOLFSSL_SUCCESS;
}
#endif /* NO_SESSION_CACHE */
@@ -4579,7 +10465,7 @@ typedef struct {
int signerSz; /* sizeof Signer object */
} CertCacheHeader;
-/* current cert persistance layout is:
+/* current cert persistence layout is:
1) CertCacheHeader
2) caTable
@@ -4590,7 +10476,7 @@ typedef struct {
/* Return memory needed to persist this signer, have lock */
-static INLINE int GetSignerMemory(Signer* signer)
+static WC_INLINE int GetSignerMemory(Signer* signer)
{
int sz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID)
+ sizeof(signer->nameLen) + sizeof(signer->subjectNameHash);
@@ -4608,7 +10494,7 @@ static INLINE int GetSignerMemory(Signer* signer)
/* Return memory needed to persist this row, have lock */
-static INLINE int GetCertCacheRowMemory(Signer* row)
+static WC_INLINE int GetCertCacheRowMemory(Signer* row)
{
int sz = 0;
@@ -4622,7 +10508,7 @@ static INLINE int GetCertCacheRowMemory(Signer* row)
/* get the size of persist cert cache, have lock */
-static INLINE int GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
+static WC_INLINE int GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
{
int sz;
int i;
@@ -4637,7 +10523,7 @@ static INLINE int GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
/* Store cert cache header columns with number of items per list, have lock */
-static INLINE void SetCertHeaderColumns(WOLFSSL_CERT_MANAGER* cm, int* columns)
+static WC_INLINE void SetCertHeaderColumns(WOLFSSL_CERT_MANAGER* cm, int* columns)
{
int i;
Signer* row;
@@ -4657,7 +10543,7 @@ static INLINE void SetCertHeaderColumns(WOLFSSL_CERT_MANAGER* cm, int* columns)
/* Restore whole cert row from memory, have lock, return bytes consumed,
< 0 on error, have lock */
-static INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current,
+static WC_INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current,
int row, int listSz, const byte* end)
{
int idx = 0;
@@ -4669,6 +10555,7 @@ static INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current,
while (listSz) {
Signer* signer;
+ byte* publicKey;
byte* start = current + idx; /* for end checks on this signer */
int minSz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID) +
sizeof(signer->nameLen) + sizeof(signer->subjectNameHash);
@@ -4698,14 +10585,15 @@ static INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current,
FreeSigner(signer, cm->heap);
return BUFFER_E;
}
- signer->publicKey = (byte*)XMALLOC(signer->pubKeySize, cm->heap,
- DYNAMIC_TYPE_KEY);
- if (signer->publicKey == NULL) {
+ publicKey = (byte*)XMALLOC(signer->pubKeySize, cm->heap,
+ DYNAMIC_TYPE_KEY);
+ if (publicKey == NULL) {
FreeSigner(signer, cm->heap);
return MEMORY_E;
}
- XMEMCPY(signer->publicKey, current + idx, signer->pubKeySize);
+ XMEMCPY(publicKey, current + idx, signer->pubKeySize);
+ signer->publicKey = publicKey;
idx += signer->pubKeySize;
/* nameLen */
@@ -4749,7 +10637,7 @@ static INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current,
/* Store whole cert row into memory, have lock, return bytes added */
-static INLINE int StoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, int row)
+static WC_INLINE int StoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, int row)
{
int added = 0;
Signer* list = cm->caTable[row];
@@ -4786,10 +10674,11 @@ static INLINE int StoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, int row)
/* Persist cert cache to memory, have lock */
-static INLINE int DoMemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz)
+static WC_INLINE int DoMemSaveCertCache(WOLFSSL_CERT_MANAGER* cm,
+ void* mem, int sz)
{
int realSz;
- int ret = SSL_SUCCESS;
+ int ret = WOLFSSL_SUCCESS;
int i;
WOLFSSL_ENTER("DoMemSaveCertCache");
@@ -4825,7 +10714,7 @@ static INLINE int DoMemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz
int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
{
XFILE file;
- int rc = SSL_SUCCESS;
+ int rc = WOLFSSL_SUCCESS;
int memSz;
byte* mem;
@@ -4834,11 +10723,11 @@ int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
file = XFOPEN(fname, "w+b");
if (file == XBADFILE) {
WOLFSSL_MSG("Couldn't open cert cache save file");
- return SSL_BAD_FILE;
+ return WOLFSSL_BAD_FILE;
}
- if (LockMutex(&cm->caLock) != 0) {
- WOLFSSL_MSG("LockMutex on caLock failed");
+ if (wc_LockMutex(&cm->caLock) != 0) {
+ WOLFSSL_MSG("wc_LockMutex on caLock failed");
XFCLOSE(file);
return BAD_MUTEX_E;
}
@@ -4850,7 +10739,7 @@ int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
rc = MEMORY_E;
} else {
rc = DoMemSaveCertCache(cm, mem, memSz);
- if (rc == SSL_SUCCESS) {
+ if (rc == WOLFSSL_SUCCESS) {
int ret = (int)XFWRITE(mem, memSz, 1, file);
if (ret != 1) {
WOLFSSL_MSG("Cert cache file write failed");
@@ -4860,7 +10749,7 @@ int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
- UnLockMutex(&cm->caLock);
+ wc_UnLockMutex(&cm->caLock);
XFCLOSE(file);
return rc;
@@ -4871,7 +10760,7 @@ int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
{
XFILE file;
- int rc = SSL_SUCCESS;
+ int rc = WOLFSSL_SUCCESS;
int ret;
int memSz;
byte* mem;
@@ -4881,17 +10770,20 @@ int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
file = XFOPEN(fname, "rb");
if (file == XBADFILE) {
WOLFSSL_MSG("Couldn't open cert cache save file");
- return SSL_BAD_FILE;
+ return WOLFSSL_BAD_FILE;
}
- XFSEEK(file, 0, XSEEK_END);
+ if(XFSEEK(file, 0, XSEEK_END) != 0) {
+ XFCLOSE(file);
+ return WOLFSSL_BAD_FILE;
+ }
memSz = (int)XFTELL(file);
XREWIND(file);
- if (memSz <= 0) {
- WOLFSSL_MSG("Bad file size");
+ if (memSz > MAX_WOLFSSL_FILE_SIZE || memSz <= 0) {
+ WOLFSSL_MSG("CM_RestoreCertCache file size error");
XFCLOSE(file);
- return SSL_BAD_FILE;
+ return WOLFSSL_BAD_FILE;
}
mem = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -4907,7 +10799,7 @@ int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
rc = FREAD_ERROR;
} else {
rc = CM_MemRestoreCertCache(cm, mem, memSz);
- if (rc != SSL_SUCCESS) {
+ if (rc != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("Mem restore cert cache failed");
}
}
@@ -4924,20 +10816,20 @@ int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
/* Persist cert cache to memory */
int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used)
{
- int ret = SSL_SUCCESS;
+ int ret = WOLFSSL_SUCCESS;
WOLFSSL_ENTER("CM_MemSaveCertCache");
- if (LockMutex(&cm->caLock) != 0) {
- WOLFSSL_MSG("LockMutex on caLock failed");
+ if (wc_LockMutex(&cm->caLock) != 0) {
+ WOLFSSL_MSG("wc_LockMutex on caLock failed");
return BAD_MUTEX_E;
}
ret = DoMemSaveCertCache(cm, mem, sz);
- if (ret == SSL_SUCCESS)
+ if (ret == WOLFSSL_SUCCESS)
*used = GetCertCacheMemSize(cm);
- UnLockMutex(&cm->caLock);
+ wc_UnLockMutex(&cm->caLock);
return ret;
}
@@ -4946,7 +10838,7 @@ int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used)
/* Restore cert cache from memory */
int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz)
{
- int ret = SSL_SUCCESS;
+ int ret = WOLFSSL_SUCCESS;
int i;
CertCacheHeader* hdr = (CertCacheHeader*)mem;
byte* current = (byte*)mem + sizeof(CertCacheHeader);
@@ -4967,8 +10859,8 @@ int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz)
return CACHE_MATCH_ERROR;
}
- if (LockMutex(&cm->caLock) != 0) {
- WOLFSSL_MSG("LockMutex on caLock failed");
+ if (wc_LockMutex(&cm->caLock) != 0) {
+ WOLFSSL_MSG("wc_LockMutex on caLock failed");
return BAD_MUTEX_E;
}
@@ -4984,7 +10876,7 @@ int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz)
current += added;
}
- UnLockMutex(&cm->caLock);
+ wc_UnLockMutex(&cm->caLock);
return ret;
}
@@ -4997,14 +10889,14 @@ int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
WOLFSSL_ENTER("CM_GetCertCacheMemSize");
- if (LockMutex(&cm->caLock) != 0) {
- WOLFSSL_MSG("LockMutex on caLock failed");
+ if (wc_LockMutex(&cm->caLock) != 0) {
+ WOLFSSL_MSG("wc_LockMutex on caLock failed");
return BAD_MUTEX_E;
}
sz = GetCertCacheMemSize(cm);
- UnLockMutex(&cm->caLock);
+ wc_UnLockMutex(&cm->caLock);
return sz;
}
@@ -5012,45 +10904,251 @@ int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
#endif /* PERSIST_CERT_CACHE */
#endif /* NO_CERTS */
+#ifdef OPENSSL_EXTRA
+
+
+/* removes all cipher suites from the list that contain "toRemove"
+ * returns the new list size on success
+ */
+static int wolfSSL_remove_ciphers(char* list, int sz, const char* toRemove)
+{
+ int idx = 0;
+ char* next = (char*)list;
+ int totalSz = sz;
+
+ if (list == NULL) {
+ return 0;
+ }
+
+ do {
+ char* current = next;
+ char name[MAX_SUITE_NAME + 1];
+ word32 length;
+
+ next = XSTRSTR(next, ":");
+ length = min(sizeof(name), !next ? (word32)XSTRLEN(current) /* last */
+ : (word32)(next - current));
+
+ XSTRNCPY(name, current, length);
+ name[(length == sizeof(name)) ? length - 1 : length] = 0;
+
+ if (XSTRSTR(name, toRemove)) {
+ XMEMMOVE(list + idx, list + idx + length, totalSz - (idx + length));
+ totalSz -= length;
+ list[totalSz] = '\0';
+ next = current;
+ }
+ else {
+ idx += length;
+ }
+ } while (next++); /* ++ needed to skip ':' */
+
+ return totalSz;
+}
+
+/* parse some bulk lists like !eNULL / !aNULL
+ *
+ * returns WOLFSSL_SUCCESS on success and sets the cipher suite list
+ */
+static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, Suites* suites,
+ const char* list)
+{
+ int ret = 0;
+ const int suiteSz = GetCipherNamesSize();
+ char* next = (char*)list;
+ const CipherSuiteInfo* names = GetCipherNames();
+ char* localList = NULL;
+ int sz = 0;
+
+ if (suites == NULL || list == NULL) {
+ WOLFSSL_MSG("NULL argument");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* does list contain eNULL or aNULL? */
+ if (XSTRSTR(list, "aNULL") || XSTRSTR(list, "eNULL")) {
+ do {
+ char* current = next;
+ char name[MAX_SUITE_NAME + 1];
+ int i;
+ word32 length;
+
+ next = XSTRSTR(next, ":");
+ length = min(sizeof(name), !next ? (word32)XSTRLEN(current) /*last*/
+ : (word32)(next - current));
+
+ XSTRNCPY(name, current, length);
+ name[(length == sizeof(name)) ? length - 1 : length] = 0;
+
+ /* check for "not" case */
+ if (name[0] == '!' && suiteSz > 0) {
+ /* populate list with all suites if not already created */
+ if (localList == NULL) {
+ for (i = 0; i < suiteSz; i++) {
+ sz += (int)XSTRLEN(names[i].name) + 2;
+ }
+ localList = (char*)XMALLOC(sz, ctx->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (localList == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+ wolfSSL_get_ciphers(localList, sz);
+ sz = (int)XSTRLEN(localList);
+ }
+
+ if (XSTRSTR(name, "eNULL")) {
+ wolfSSL_remove_ciphers(localList, sz, "-NULL");
+ }
+ }
+ }
+ while (next++); /* ++ needed to skip ':' */
+
+ ret = SetCipherList(ctx, suites, localList);
+ XFREE(localList, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return (ret)? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+ }
+ else {
+ return (SetCipherList(ctx, suites, list)) ? WOLFSSL_SUCCESS :
+ WOLFSSL_FAILURE;
+ }
+}
+
+#endif
+
int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list)
{
WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list");
+ if (ctx == NULL)
+ return WOLFSSL_FAILURE;
+
/* alloc/init on demand only */
if (ctx->suites == NULL) {
ctx->suites = (Suites*)XMALLOC(sizeof(Suites), ctx->heap,
DYNAMIC_TYPE_SUITES);
if (ctx->suites == NULL) {
WOLFSSL_MSG("Memory alloc for Suites failed");
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
}
XMEMSET(ctx->suites, 0, sizeof(Suites));
}
- return (SetCipherList(ctx->suites, list)) ? SSL_SUCCESS : SSL_FAILURE;
+#ifdef OPENSSL_EXTRA
+ return wolfSSL_parse_cipher_list(ctx, ctx->suites, list);
+#else
+ return (SetCipherList(ctx, ctx->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+#endif
}
int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list)
{
WOLFSSL_ENTER("wolfSSL_set_cipher_list");
- return (SetCipherList(ssl->suites, list)) ? SSL_SUCCESS : SSL_FAILURE;
+#ifdef SINGLE_THREADED
+ if (ssl->ctx->suites == ssl->suites) {
+ ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
+ DYNAMIC_TYPE_SUITES);
+ if (ssl->suites == NULL) {
+ WOLFSSL_MSG("Suites Memory error");
+ return MEMORY_E;
+ }
+ ssl->options.ownSuites = 1;
+ }
+#endif
+
+#ifdef OPENSSL_EXTRA
+ return wolfSSL_parse_cipher_list(ssl->ctx, ssl->suites, list);
+#else
+ return (SetCipherList(ssl->ctx, ssl->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+#endif
+}
+
+
+int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl)
+{
+ int useNb = 0;
+
+ if (ssl == NULL)
+ return WOLFSSL_FAILURE;
+
+ WOLFSSL_ENTER("wolfSSL_dtls_get_using_nonblock");
+ if (ssl->options.dtls) {
+#ifdef WOLFSSL_DTLS
+ useNb = ssl->options.dtlsUseNonblock;
+#endif
+ }
+ else {
+ WOLFSSL_MSG("wolfSSL_dtls_get_using_nonblock() is "
+ "DEPRECATED for non-DTLS use.");
+ }
+ return useNb;
}
#ifndef WOLFSSL_LEANPSK
+
+void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock)
+{
+ (void)nonblock;
+
+ WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock");
+
+ if (ssl == NULL)
+ return;
+
+ if (ssl->options.dtls) {
+#ifdef WOLFSSL_DTLS
+ ssl->options.dtlsUseNonblock = (nonblock != 0);
+#endif
+ }
+ else {
+ WOLFSSL_MSG("wolfSSL_dtls_set_using_nonblock() is "
+ "DEPRECATED for non-DTLS use.");
+ }
+}
+
+
#ifdef WOLFSSL_DTLS
int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl)
{
- (void)ssl;
+ int timeout = 0;
+ if (ssl)
+ timeout = ssl->dtls_timeout;
- return ssl->dtls_timeout;
+ WOLFSSL_LEAVE("wolfSSL_dtls_get_current_timeout()", timeout);
+ return timeout;
+}
+
+int wolfSSL_DTLSv1_get_timeout(WOLFSSL* ssl, WOLFSSL_TIMEVAL* timeleft)
+{
+ if (ssl && timeleft) {
+ XMEMSET(timeleft, 0, sizeof(WOLFSSL_TIMEVAL));
+ timeleft->tv_sec = ssl->dtls_timeout;
+ }
+ return 0;
}
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_DTLSv1_handle_timeout(WOLFSSL* ssl)
+{
+ WOLFSSL_STUB("SSL_DTLSv1_handle_timeout");
+ (void)ssl;
+ return 0;
+}
+#endif
-/* user may need to alter init dtls recv timeout, SSL_SUCCESS on ok */
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_DTLSv1_set_initial_timeout_duration(WOLFSSL* ssl, word32 duration_ms)
+{
+ WOLFSSL_STUB("SSL_DTLSv1_set_initial_timeout_duration");
+ (void)ssl;
+ (void)duration_ms;
+}
+#endif
+
+/* user may need to alter init dtls recv timeout, WOLFSSL_SUCCESS on ok */
int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int timeout)
{
if (ssl == NULL || timeout < 0)
@@ -5064,11 +11162,11 @@ int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int timeout)
ssl->dtls_timeout_init = timeout;
ssl->dtls_timeout = timeout;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
-/* user may need to alter max dtls recv timeout, SSL_SUCCESS on ok */
+/* user may need to alter max dtls recv timeout, WOLFSSL_SUCCESS on ok */
int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int timeout)
{
if (ssl == NULL || timeout < 0)
@@ -5081,74 +11179,248 @@ int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int timeout)
ssl->dtls_timeout_max = timeout;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
{
- int result = SSL_SUCCESS;
+ int result = WOLFSSL_SUCCESS;
+ WOLFSSL_ENTER("wolfSSL_dtls_got_timeout()");
+
+ if (ssl == NULL)
+ return WOLFSSL_FATAL_ERROR;
- DtlsMsgListDelete(ssl->dtls_msg_list, ssl->heap);
- ssl->dtls_msg_list = NULL;
- if (DtlsPoolTimeout(ssl) < 0 || DtlsPoolSend(ssl) < 0) {
- result = SSL_FATAL_ERROR;
+ if (!ssl->options.handShakeDone &&
+ (DtlsMsgPoolTimeout(ssl) < 0 || DtlsMsgPoolSend(ssl, 0) < 0)) {
+
+ result = WOLFSSL_FATAL_ERROR;
}
+
+ WOLFSSL_LEAVE("wolfSSL_dtls_got_timeout()", result);
return result;
}
+
+/* retransmit all the saves messages, WOLFSSL_SUCCESS on ok */
+int wolfSSL_dtls_retransmit(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_dtls_retransmit()");
+
+ if (ssl == NULL)
+ return WOLFSSL_FATAL_ERROR;
+
+ if (!ssl->options.handShakeDone) {
+ int result = DtlsMsgPoolSend(ssl, 0);
+ if (result < 0) {
+ ssl->error = result;
+ WOLFSSL_ERROR(result);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ return 0;
+}
+
#endif /* DTLS */
#endif /* LEANPSK */
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+
+/* Not an SSL function, return 0 for success, error code otherwise */
+/* Prereq: ssl's RNG needs to be initialized. */
+int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
+ const byte* secret, word32 secretSz)
+{
+ int ret = 0;
+
+ WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret");
+
+ if (ssl == NULL) {
+ WOLFSSL_MSG("need a SSL object");
+ return BAD_FUNC_ARG;
+ }
+
+ if (secret != NULL && secretSz == 0) {
+ WOLFSSL_MSG("can't have a new secret without a size");
+ return BAD_FUNC_ARG;
+ }
+
+ /* If secretSz is 0, use the default size. */
+ if (secretSz == 0)
+ secretSz = COOKIE_SECRET_SZ;
+
+ if (secretSz != ssl->buffers.dtlsCookieSecret.length) {
+ byte* newSecret;
+
+ if (ssl->buffers.dtlsCookieSecret.buffer != NULL) {
+ ForceZero(ssl->buffers.dtlsCookieSecret.buffer,
+ ssl->buffers.dtlsCookieSecret.length);
+ XFREE(ssl->buffers.dtlsCookieSecret.buffer,
+ ssl->heap, DYNAMIC_TYPE_NONE);
+ }
+
+ newSecret = (byte*)XMALLOC(secretSz, ssl->heap,DYNAMIC_TYPE_COOKIE_PWD);
+ if (newSecret == NULL) {
+ ssl->buffers.dtlsCookieSecret.buffer = NULL;
+ ssl->buffers.dtlsCookieSecret.length = 0;
+ WOLFSSL_MSG("couldn't allocate new cookie secret");
+ return MEMORY_ERROR;
+ }
+ ssl->buffers.dtlsCookieSecret.buffer = newSecret;
+ ssl->buffers.dtlsCookieSecret.length = secretSz;
+ }
+
+ /* If the supplied secret is NULL, randomly generate a new secret. */
+ if (secret == NULL) {
+ ret = wc_RNG_GenerateBlock(ssl->rng,
+ ssl->buffers.dtlsCookieSecret.buffer, secretSz);
+ }
+ else
+ XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz);
+
+ WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0);
+ return ret;
+}
+
+#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
+
+
+/* EITHER SIDE METHODS */
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+ WOLFSSL_METHOD* wolfSSLv23_method(void)
+ {
+ return wolfSSLv23_method_ex(NULL);
+ }
+ WOLFSSL_METHOD* wolfSSLv23_method_ex(void* heap)
+ {
+ WOLFSSL_METHOD* m = NULL;
+ WOLFSSL_ENTER("SSLv23_method");
+ #if !defined(NO_WOLFSSL_CLIENT)
+ m = wolfSSLv23_client_method_ex(heap);
+ #elif !defined(NO_WOLFSSL_SERVER)
+ m = wolfSSLv23_server_method_ex(heap);
+ #endif
+ if (m != NULL) {
+ m->side = WOLFSSL_NEITHER_END;
+ }
+
+ return m;
+ }
+
+ #ifdef WOLFSSL_ALLOW_SSLV3
+ WOLFSSL_METHOD* wolfSSLv3_method(void)
+ {
+ return wolfSSLv3_method_ex(NULL);
+ }
+ WOLFSSL_METHOD* wolfSSLv3_method_ex(void* heap)
+ {
+ WOLFSSL_METHOD* m = NULL;
+ WOLFSSL_ENTER("SSLv3_method");
+ #if !defined(NO_WOLFSSL_CLIENT)
+ m = wolfSSLv3_client_method_ex(heap);
+ #elif !defined(NO_WOLFSSL_SERVER)
+ m = wolfSSLv3_server_method_ex(heap);
+ #endif
+ if (m != NULL) {
+ m->side = WOLFSSL_NEITHER_END;
+ }
+
+ return m;
+ }
+ #endif
+#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
+
/* client only parts */
#ifndef NO_WOLFSSL_CLIENT
- #ifndef NO_OLD_TLS
+ #ifdef OPENSSL_EXTRA
+ WOLFSSL_METHOD* wolfSSLv2_client_method(void)
+ {
+ WOLFSSL_STUB("wolfSSLv2_client_method");
+ return NULL;
+ }
+ #endif
+
+ #ifdef WOLFSSL_ALLOW_SSLV3
WOLFSSL_METHOD* wolfSSLv3_client_method(void)
{
+ return wolfSSLv3_client_method_ex(NULL);
+ }
+ WOLFSSL_METHOD* wolfSSLv3_client_method_ex(void* heap)
+ {
WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0,
- DYNAMIC_TYPE_METHOD);
- WOLFSSL_ENTER("SSLv3_client_method");
+ (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+ heap, DYNAMIC_TYPE_METHOD);
+ (void)heap;
+ WOLFSSL_ENTER("SSLv3_client_method_ex");
if (method)
InitSSL_Method(method, MakeSSLv3());
return method;
}
- #endif
+ #endif /* WOLFSSL_ALLOW_SSLV3 */
- #ifdef WOLFSSL_DTLS
+ WOLFSSL_METHOD* wolfSSLv23_client_method(void)
+ {
+ return wolfSSLv23_client_method_ex(NULL);
+ }
+ WOLFSSL_METHOD* wolfSSLv23_client_method_ex(void* heap)
+ {
+ WOLFSSL_METHOD* method =
+ (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+ heap, DYNAMIC_TYPE_METHOD);
+ (void)heap;
+ WOLFSSL_ENTER("SSLv23_client_method_ex");
+ if (method) {
+ #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
+ #if defined(WOLFSSL_TLS13)
+ InitSSL_Method(method, MakeTLSv1_3());
+ #elif !defined(WOLFSSL_NO_TLS12)
+ InitSSL_Method(method, MakeTLSv1_2());
+ #elif !defined(NO_OLD_TLS)
+ InitSSL_Method(method, MakeTLSv1_1());
+ #endif
+ #else
#ifndef NO_OLD_TLS
- WOLFSSL_METHOD* wolfDTLSv1_client_method(void)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0,
- DYNAMIC_TYPE_METHOD);
- WOLFSSL_ENTER("DTLSv1_client_method");
- if (method)
- InitSSL_Method(method, MakeDTLSv1());
- return method;
+ InitSSL_Method(method, MakeTLSv1_1());
+ #endif
+ #endif
+ #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13)
+ method->downgrade = 1;
+ #endif
}
- #endif /* NO_OLD_TLS */
+ return method;
+ }
- WOLFSSL_METHOD* wolfDTLSv1_2_client_method(void)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0,
- DYNAMIC_TYPE_METHOD);
- WOLFSSL_ENTER("DTLSv1_2_client_method");
- if (method)
- InitSSL_Method(method, MakeDTLSv1_2());
- return method;
+
+ #if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS) || \
+ defined(WOLFSSL_ALLOW_SSLV3)
+ /* If SCTP is not enabled returns the state of the dtls option.
+ * If SCTP is enabled returns dtls && !sctp. */
+ static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl)
+ {
+ int result = ssl->options.dtls;
+
+ if (result) {
+ #ifdef WOLFSSL_SCTP
+ result = !ssl->options.dtlsSctp;
+ #endif
}
- #endif
+
+ return result;
+ }
+ #endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 || !NO_OLD_TLS */
/* please see note at top of README if you get an error from connect */
+ WOLFSSL_ABI
int wolfSSL_connect(WOLFSSL* ssl)
{
+ #if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13))
int neededState;
+ #endif
WOLFSSL_ENTER("SSL_connect()");
@@ -5156,33 +11428,72 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
errno = 0;
#endif
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+ if (ssl->options.side == WOLFSSL_NEITHER_END) {
+ ssl->error = InitSSL_Side(ssl, WOLFSSL_CLIENT_END);
+ if (ssl->error != WOLFSSL_SUCCESS) {
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ ssl->error = 0; /* expected to be zero here */
+ }
+
+ #ifdef OPENSSL_EXTRA
+ if (ssl->CBIS != NULL) {
+ ssl->CBIS(ssl, SSL_ST_CONNECT, SSL_SUCCESS);
+ ssl->cbmode = SSL_CB_WRITE;
+ }
+ #endif
+ #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
+
+ #if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13)
+ return wolfSSL_connect_TLSv13(ssl);
+ #else
+ #ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3)
+ return wolfSSL_connect_TLSv13(ssl);
+ #endif
+
if (ssl->options.side != WOLFSSL_CLIENT_END) {
WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
#ifdef WOLFSSL_DTLS
- if (ssl->version.major == DTLS_MAJOR) {
- ssl->options.dtls = 1;
- ssl->options.tls = 1;
- ssl->options.tls1_1 = 1;
-
- if (DtlsPoolInit(ssl) != 0) {
- ssl->error = MEMORY_ERROR;
- WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
- }
- }
+ if (ssl->version.major == DTLS_MAJOR) {
+ ssl->options.dtls = 1;
+ ssl->options.tls = 1;
+ ssl->options.tls1_1 = 1;
+ }
#endif
- if (ssl->buffers.outputBuffer.length > 0) {
+ if (ssl->buffers.outputBuffer.length > 0
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* do not send buffered or advance state if last error was an
+ async pending operation */
+ && ssl->error != WC_PENDING_E
+ #endif
+ ) {
if ( (ssl->error = SendBuffered(ssl)) == 0) {
- ssl->options.connectState++;
- WOLFSSL_MSG("connect state: Advanced from buffered send");
+ /* fragOffset is non-zero when sending fragments. On the last
+ * fragment, fragOffset is zero again, and the state can be
+ * advanced. */
+ if (ssl->fragOffset == 0) {
+ ssl->options.connectState++;
+ WOLFSSL_MSG("connect state: "
+ "Advanced from last buffered fragment send");
+ }
+ else {
+ WOLFSSL_MSG("connect state: "
+ "Not advanced, more fragments to send");
+ }
}
else {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
}
@@ -5192,10 +11503,11 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
/* always send client hello first */
if ( (ssl->error = SendClientHello(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
ssl->options.connectState = CLIENT_HELLO_SENT;
WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT");
+ FALL_THROUGH;
case CLIENT_HELLO_SENT :
neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE :
@@ -5204,19 +11516,23 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
/* In DTLS, when resuming, we can go straight to FINISHED,
* or do a cookie exchange and then skip to FINISHED, assume
* we need the cookie exchange first. */
- if (ssl->options.dtls)
+ if (IsDtlsNotSctpMode(ssl))
neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
#endif
/* get response */
while (ssl->options.serverState < neededState) {
+ #ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3)
+ return wolfSSL_connect_TLSv13(ssl);
+ #endif
if ( (ssl->error = ProcessReply(ssl)) < 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
/* if resumption failed, reset needed state */
else if (neededState == SERVER_FINISHED_COMPLETE)
if (!ssl->options.resuming) {
- if (!ssl->options.dtls)
+ if (!IsDtlsNotSctpMode(ssl))
neededState = SERVER_HELLODONE_COMPLETE;
else
neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
@@ -5225,84 +11541,73 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
ssl->options.connectState = HELLO_AGAIN;
WOLFSSL_MSG("connect state: HELLO_AGAIN");
+ FALL_THROUGH;
case HELLO_AGAIN :
if (ssl->options.certOnly)
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
+
+ #ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3)
+ return wolfSSL_connect_TLSv13(ssl);
+ #endif
#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
+ if (ssl->options.serverState ==
+ SERVER_HELLOVERIFYREQUEST_COMPLETE) {
+ if (IsDtlsNotSctpMode(ssl)) {
/* re-init hashes, exclude first hello and verify request */
-#ifndef NO_OLD_TLS
- wc_InitMd5(&ssl->hsHashes->hashMd5);
- if ( (ssl->error = wc_InitSha(&ssl->hsHashes->hashSha))
- != 0) {
+ if ((ssl->error = InitHandshakeHashes(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
- }
-#endif
- if (IsAtLeastTLSv1_2(ssl)) {
- #ifndef NO_SHA256
- if ( (ssl->error = wc_InitSha256(
- &ssl->hsHashes->hashSha256)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
- }
- #endif
- #ifdef WOLFSSL_SHA384
- if ( (ssl->error = wc_InitSha384(
- &ssl->hsHashes->hashSha384)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
- }
- #endif
- #ifdef WOLFSSL_SHA512
- if ( (ssl->error = wc_InitSha512(
- &ssl->hsHashes->hashSha512)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
- }
- #endif
+ return WOLFSSL_FATAL_ERROR;
}
if ( (ssl->error = SendClientHello(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
}
+ }
#endif
ssl->options.connectState = HELLO_AGAIN_REPLY;
WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY");
+ FALL_THROUGH;
case HELLO_AGAIN_REPLY :
#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
+ if (IsDtlsNotSctpMode(ssl)) {
neededState = ssl->options.resuming ?
SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE;
/* get response */
while (ssl->options.serverState < neededState) {
if ( (ssl->error = ProcessReply(ssl)) < 0) {
- WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
}
/* if resumption failed, reset needed state */
- else if (neededState == SERVER_FINISHED_COMPLETE)
+ if (neededState == SERVER_FINISHED_COMPLETE) {
if (!ssl->options.resuming)
neededState = SERVER_HELLODONE_COMPLETE;
+ }
}
}
#endif
ssl->options.connectState = FIRST_REPLY_DONE;
WOLFSSL_MSG("connect state: FIRST_REPLY_DONE");
+ FALL_THROUGH;
case FIRST_REPLY_DONE :
- #ifndef NO_CERTS
+ #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+ #ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3)
+ return wolfSSL_connect_TLSv13(ssl);
+ #endif
if (ssl->options.sendVerify) {
if ( (ssl->error = SendCertificate(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
WOLFSSL_MSG("sent: certificate");
}
@@ -5310,60 +11615,70 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
#endif
ssl->options.connectState = FIRST_REPLY_FIRST;
WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST");
+ FALL_THROUGH;
case FIRST_REPLY_FIRST :
+ #ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3)
+ return wolfSSL_connect_TLSv13(ssl);
+ #endif
if (!ssl->options.resuming) {
if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
WOLFSSL_MSG("sent: client key exchange");
}
ssl->options.connectState = FIRST_REPLY_SECOND;
WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND");
+ FALL_THROUGH;
case FIRST_REPLY_SECOND :
- #ifndef NO_CERTS
+ #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
if (ssl->options.sendVerify) {
if ( (ssl->error = SendCertificateVerify(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
WOLFSSL_MSG("sent: certificate verify");
}
- #endif
+ #endif /* !NO_CERTS && !WOLFSSL_NO_CLIENT_AUTH */
ssl->options.connectState = FIRST_REPLY_THIRD;
WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD");
+ FALL_THROUGH;
case FIRST_REPLY_THIRD :
if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
WOLFSSL_MSG("sent: change cipher spec");
ssl->options.connectState = FIRST_REPLY_FOURTH;
WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH");
+ FALL_THROUGH;
case FIRST_REPLY_FOURTH :
if ( (ssl->error = SendFinished(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
WOLFSSL_MSG("sent: finished");
ssl->options.connectState = FINISHED_DONE;
WOLFSSL_MSG("connect state: FINISHED_DONE");
+ FALL_THROUGH;
case FINISHED_DONE :
/* get response */
while (ssl->options.serverState < SERVER_FINISHED_COMPLETE)
if ( (ssl->error = ProcessReply(ssl)) < 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
ssl->options.connectState = SECOND_REPLY_DONE;
WOLFSSL_MSG("connect state: SECOND_REPLY_DONE");
+ FALL_THROUGH;
case SECOND_REPLY_DONE:
#ifndef NO_HANDSHAKE_DONE_CB
@@ -5372,18 +11687,30 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
if (cbret < 0) {
ssl->error = cbret;
WOLFSSL_MSG("HandShake Done Cb don't continue error");
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
}
#endif /* NO_HANDSHAKE_DONE_CB */
- FreeHandshakeResources(ssl);
- WOLFSSL_LEAVE("SSL_connect()", SSL_SUCCESS);
- return SSL_SUCCESS;
+
+ if (!ssl->options.dtls) {
+ if (!ssl->options.keepResources) {
+ FreeHandshakeResources(ssl);
+ }
+ }
+#ifdef WOLFSSL_DTLS
+ else {
+ ssl->options.dtlsHsRetain = 1;
+ }
+#endif /* WOLFSSL_DTLS */
+
+ WOLFSSL_LEAVE("SSL_connect()", WOLFSSL_SUCCESS);
+ return WOLFSSL_SUCCESS;
default:
WOLFSSL_MSG("Unknown connect state ERROR");
- return SSL_FATAL_ERROR; /* unknown connect state */
+ return WOLFSSL_FATAL_ERROR; /* unknown connect state */
}
+ #endif /* !WOLFSSL_NO_TLS12 */
}
#endif /* NO_WOLFSSL_CLIENT */
@@ -5392,58 +11719,101 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
/* server only parts */
#ifndef NO_WOLFSSL_SERVER
- #ifndef NO_OLD_TLS
+ #ifdef OPENSSL_EXTRA
+ WOLFSSL_METHOD* wolfSSLv2_server_method(void)
+ {
+ WOLFSSL_STUB("wolfSSLv2_server_method");
+ return 0;
+ }
+ #endif
+
+ #ifdef WOLFSSL_ALLOW_SSLV3
WOLFSSL_METHOD* wolfSSLv3_server_method(void)
{
+ return wolfSSLv3_server_method_ex(NULL);
+ }
+ WOLFSSL_METHOD* wolfSSLv3_server_method_ex(void* heap)
+ {
WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0,
- DYNAMIC_TYPE_METHOD);
- WOLFSSL_ENTER("SSLv3_server_method");
+ (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+ heap, DYNAMIC_TYPE_METHOD);
+ (void)heap;
+ WOLFSSL_ENTER("SSLv3_server_method_ex");
if (method) {
InitSSL_Method(method, MakeSSLv3());
method->side = WOLFSSL_SERVER_END;
}
return method;
}
- #endif
+ #endif /* WOLFSSL_ALLOW_SSLV3 */
+ WOLFSSL_METHOD* wolfSSLv23_server_method(void)
+ {
+ return wolfSSLv23_server_method_ex(NULL);
+ }
- #ifdef WOLFSSL_DTLS
-
- #ifndef NO_OLD_TLS
- WOLFSSL_METHOD* wolfDTLSv1_server_method(void)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- 0, DYNAMIC_TYPE_METHOD);
- WOLFSSL_ENTER("DTLSv1_server_method");
- if (method) {
- InitSSL_Method(method, MakeDTLSv1());
- method->side = WOLFSSL_SERVER_END;
- }
- return method;
- }
- #endif /* NO_OLD_TLS */
-
- WOLFSSL_METHOD* wolfDTLSv1_2_server_method(void)
- {
- WOLFSSL_METHOD* method =
+ WOLFSSL_METHOD* wolfSSLv23_server_method_ex(void* heap)
+ {
+ WOLFSSL_METHOD* method =
(WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- 0, DYNAMIC_TYPE_METHOD);
- WOLFSSL_ENTER("DTLSv1_2_server_method");
- if (method) {
- InitSSL_Method(method, MakeDTLSv1_2());
- method->side = WOLFSSL_SERVER_END;
- }
- return method;
- }
+ heap, DYNAMIC_TYPE_METHOD);
+ (void)heap;
+ WOLFSSL_ENTER("SSLv23_server_method_ex");
+ if (method) {
+ #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
+ #ifdef WOLFSSL_TLS13
+ InitSSL_Method(method, MakeTLSv1_3());
+ #elif !defined(WOLFSSL_NO_TLS12)
+ InitSSL_Method(method, MakeTLSv1_2());
+ #elif !defined(NO_OLD_TLS)
+ InitSSL_Method(method, MakeTLSv1_1());
+ #endif
+ #else
+ #ifndef NO_OLD_TLS
+ InitSSL_Method(method, MakeTLSv1_1());
+ #else
+ #error Must have SHA256, SHA384 or SHA512 enabled for TLS 1.2
+ #endif
+ #endif
+ #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13)
+ method->downgrade = 1;
#endif
+ method->side = WOLFSSL_SERVER_END;
+ }
+ return method;
+ }
int wolfSSL_accept(WOLFSSL* ssl)
{
- byte havePSK = 0;
- byte haveAnon = 0;
+#if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13))
+ word16 havePSK = 0;
+ word16 haveAnon = 0;
+ word16 haveMcast = 0;
+#endif
+
+ if (ssl == NULL)
+ return WOLFSSL_FATAL_ERROR;
+
+ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+ if (ssl->options.side == WOLFSSL_NEITHER_END) {
+ WOLFSSL_MSG("Setting WOLFSSL_SSL to be server side");
+ ssl->error = InitSSL_Side(ssl, WOLFSSL_SERVER_END);
+ if (ssl->error != WOLFSSL_SUCCESS) {
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ ssl->error = 0; /* expected to be zero here */
+ }
+ #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
+
+#if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13)
+ return wolfSSL_accept_TLSv13(ssl);
+#else
+ #ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3)
+ return wolfSSL_accept_TLSv13(ssl);
+ #endif
WOLFSSL_ENTER("SSL_accept()");
#ifdef HAVE_ERRNO_H
@@ -5460,219 +11830,236 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
#endif
(void)haveAnon;
+ #ifdef WOLFSSL_MULTICAST
+ haveMcast = ssl->options.haveMcast;
+ #endif
+ (void)haveMcast;
+
if (ssl->options.side != WOLFSSL_SERVER_END) {
WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
- #ifndef NO_CERTS
- /* in case used set_accept_state after init */
- if (!havePSK && !haveAnon &&
- (ssl->buffers.certificate.buffer == NULL ||
- ssl->buffers.key.buffer == NULL)) {
- WOLFSSL_MSG("accept error: don't have server cert and key");
- ssl->error = NO_PRIVATE_KEY;
- WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
- }
- #endif
+ #ifndef NO_CERTS
+ /* in case used set_accept_state after init */
+ /* allow no private key if using PK callbacks and CB is set */
+ if (!havePSK && !haveAnon && !haveMcast) {
+ if (!ssl->buffers.certificate ||
+ !ssl->buffers.certificate->buffer) {
- #ifdef WOLFSSL_DTLS
- if (ssl->version.major == DTLS_MAJOR) {
- ssl->options.dtls = 1;
- ssl->options.tls = 1;
- ssl->options.tls1_1 = 1;
+ WOLFSSL_MSG("accept error: server cert required");
+ WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY);
+ return WOLFSSL_FATAL_ERROR;
+ }
- if (DtlsPoolInit(ssl) != 0) {
- ssl->error = MEMORY_ERROR;
- WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
- }
+ #ifdef HAVE_PK_CALLBACKS
+ if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+ WOLFSSL_MSG("Using PK for server private key");
}
+ else
#endif
+ if (!ssl->buffers.key || !ssl->buffers.key->buffer) {
+ WOLFSSL_MSG("accept error: server key required");
+ WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+ #endif
+
+ #ifdef WOLFSSL_DTLS
+ if (ssl->version.major == DTLS_MAJOR) {
+ ssl->options.dtls = 1;
+ ssl->options.tls = 1;
+ ssl->options.tls1_1 = 1;
+ }
+ #endif
- if (ssl->buffers.outputBuffer.length > 0) {
+ if (ssl->buffers.outputBuffer.length > 0
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ /* do not send buffered or advance state if last error was an
+ async pending operation */
+ && ssl->error != WC_PENDING_E
+ #endif
+ ) {
if ( (ssl->error = SendBuffered(ssl)) == 0) {
- ssl->options.acceptState++;
- WOLFSSL_MSG("accept state: Advanced from buffered send");
+ /* fragOffset is non-zero when sending fragments. On the last
+ * fragment, fragOffset is zero again, and the state can be
+ * advanced. */
+ if (ssl->fragOffset == 0) {
+ ssl->options.acceptState++;
+ WOLFSSL_MSG("accept state: "
+ "Advanced from last buffered fragment send");
+ }
+ else {
+ WOLFSSL_MSG("accept state: "
+ "Not advanced, more fragments to send");
+ }
}
else {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
}
switch (ssl->options.acceptState) {
case ACCEPT_BEGIN :
+#ifdef HAVE_SECURE_RENEGOTIATION
+ case ACCEPT_BEGIN_RENEG:
+#endif
/* get response */
while (ssl->options.clientState < CLIENT_HELLO_COMPLETE)
if ( (ssl->error = ProcessReply(ssl)) < 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
+#ifdef WOLFSSL_TLS13
ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE;
WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE");
+ FALL_THROUGH;
case ACCEPT_CLIENT_HELLO_DONE :
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls)
- if ( (ssl->error = SendHelloVerifyRequest(ssl)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
- }
- #endif
- ssl->options.acceptState = HELLO_VERIFY_SENT;
- WOLFSSL_MSG("accept state HELLO_VERIFY_SENT");
-
- case HELLO_VERIFY_SENT:
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- ssl->options.clientState = NULL_STATE; /* get again */
- /* reset messages received */
- XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
- /* re-init hashes, exclude first hello and verify request */
-#ifndef NO_OLD_TLS
- wc_InitMd5(&ssl->hsHashes->hashMd5);
- if ( (ssl->error = wc_InitSha(&ssl->hsHashes->hashSha))
- != 0) {
- WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
- }
+ if (ssl->options.tls1_3) {
+ return wolfSSL_accept_TLSv13(ssl);
+ }
#endif
- if (IsAtLeastTLSv1_2(ssl)) {
- #ifndef NO_SHA256
- if ( (ssl->error = wc_InitSha256(
- &ssl->hsHashes->hashSha256)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
- }
- #endif
- #ifdef WOLFSSL_SHA384
- if ( (ssl->error = wc_InitSha384(
- &ssl->hsHashes->hashSha384)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
- }
- #endif
- #ifdef WOLFSSL_SHA512
- if ( (ssl->error = wc_InitSha512(
- &ssl->hsHashes->hashSha512)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
- }
- #endif
- }
-
- while (ssl->options.clientState < CLIENT_HELLO_COMPLETE)
- if ( (ssl->error = ProcessReply(ssl)) < 0) {
- WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
- }
- }
- #endif
ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE;
WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
+ FALL_THROUGH;
case ACCEPT_FIRST_REPLY_DONE :
if ( (ssl->error = SendServerHello(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
ssl->options.acceptState = SERVER_HELLO_SENT;
WOLFSSL_MSG("accept state SERVER_HELLO_SENT");
+ FALL_THROUGH;
case SERVER_HELLO_SENT :
+ #ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3) {
+ return wolfSSL_accept_TLSv13(ssl);
+ }
+ #endif
#ifndef NO_CERTS
if (!ssl->options.resuming)
if ( (ssl->error = SendCertificate(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
#endif
ssl->options.acceptState = CERT_SENT;
WOLFSSL_MSG("accept state CERT_SENT");
+ FALL_THROUGH;
case CERT_SENT :
+ #ifndef NO_CERTS
+ if (!ssl->options.resuming)
+ if ( (ssl->error = SendCertificateStatus(ssl)) != 0) {
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ #endif
+ ssl->options.acceptState = CERT_STATUS_SENT;
+ WOLFSSL_MSG("accept state CERT_STATUS_SENT");
+ FALL_THROUGH;
+
+ case CERT_STATUS_SENT :
+ #ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3) {
+ return wolfSSL_accept_TLSv13(ssl);
+ }
+ #endif
if (!ssl->options.resuming)
if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
ssl->options.acceptState = KEY_EXCHANGE_SENT;
WOLFSSL_MSG("accept state KEY_EXCHANGE_SENT");
+ FALL_THROUGH;
case KEY_EXCHANGE_SENT :
#ifndef NO_CERTS
- if (!ssl->options.resuming)
- if (ssl->options.verifyPeer)
+ if (!ssl->options.resuming) {
+ if (ssl->options.verifyPeer) {
if ( (ssl->error = SendCertificateRequest(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
+ }
+ }
#endif
ssl->options.acceptState = CERT_REQ_SENT;
WOLFSSL_MSG("accept state CERT_REQ_SENT");
+ FALL_THROUGH;
case CERT_REQ_SENT :
if (!ssl->options.resuming)
if ( (ssl->error = SendServerHelloDone(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
ssl->options.acceptState = SERVER_HELLO_DONE;
WOLFSSL_MSG("accept state SERVER_HELLO_DONE");
+ FALL_THROUGH;
case SERVER_HELLO_DONE :
if (!ssl->options.resuming) {
while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
if ( (ssl->error = ProcessReply(ssl)) < 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
}
ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE;
WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE");
+ FALL_THROUGH;
case ACCEPT_SECOND_REPLY_DONE :
#ifdef HAVE_SESSION_TICKET
if (ssl->options.createTicket) {
if ( (ssl->error = SendTicket(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
}
#endif /* HAVE_SESSION_TICKET */
ssl->options.acceptState = TICKET_SENT;
WOLFSSL_MSG("accept state TICKET_SENT");
+ FALL_THROUGH;
case TICKET_SENT:
if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
ssl->options.acceptState = CHANGE_CIPHER_SENT;
WOLFSSL_MSG("accept state CHANGE_CIPHER_SENT");
+ FALL_THROUGH;
case CHANGE_CIPHER_SENT :
if ( (ssl->error = SendFinished(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
ssl->options.acceptState = ACCEPT_FINISHED_DONE;
WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE");
+ FALL_THROUGH;
case ACCEPT_FINISHED_DONE :
if (ssl->options.resuming)
while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
if ( (ssl->error = ProcessReply(ssl)) < 0) {
WOLFSSL_ERROR(ssl->error);
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE;
WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE");
+ FALL_THROUGH;
case ACCEPT_THIRD_REPLY_DONE :
#ifndef NO_HANDSHAKE_DONE_CB
@@ -5681,18 +12068,40 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
if (cbret < 0) {
ssl->error = cbret;
WOLFSSL_MSG("HandShake Done Cb don't continue error");
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
}
#endif /* NO_HANDSHAKE_DONE_CB */
- FreeHandshakeResources(ssl);
- WOLFSSL_LEAVE("SSL_accept()", SSL_SUCCESS);
- return SSL_SUCCESS;
+
+ if (!ssl->options.dtls) {
+ if (!ssl->options.keepResources) {
+ FreeHandshakeResources(ssl);
+ }
+ }
+#ifdef WOLFSSL_DTLS
+ else {
+ ssl->options.dtlsHsRetain = 1;
+ }
+#endif /* WOLFSSL_DTLS */
+
+#ifdef WOLFSSL_SESSION_EXPORT
+ if (ssl->dtls_export) {
+ if ((ssl->error = wolfSSL_send_session(ssl)) != 0) {
+ WOLFSSL_MSG("Export DTLS session error");
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+#endif
+
+ WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS);
+ return WOLFSSL_SUCCESS;
default :
WOLFSSL_MSG("Unknown accept state ERROR");
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
+#endif /* !WOLFSSL_NO_TLS12 */
}
#endif /* NO_WOLFSSL_SERVER */
@@ -5711,15 +12120,15 @@ int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx)
ssl->hsDoneCtx = user_ctx;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
#endif /* NO_HANDSHAKE_DONE_CB */
-
+WOLFSSL_ABI
int wolfSSL_Cleanup(void)
{
- int ret = SSL_SUCCESS;
+ int ret = WOLFSSL_SUCCESS;
int release = 0;
WOLFSSL_ENTER("wolfSSL_Cleanup");
@@ -5727,7 +12136,7 @@ int wolfSSL_Cleanup(void)
if (initRefCount == 0)
return ret; /* possibly no init yet, but not failure either way */
- if (LockMutex(&count_mutex) != 0) {
+ if (wc_LockMutex(&count_mutex) != 0) {
WOLFSSL_MSG("Bad Lock Mutex count");
return BAD_MUTEX_E;
}
@@ -5736,22 +12145,34 @@ int wolfSSL_Cleanup(void)
if (initRefCount < 0)
initRefCount = 0;
- UnLockMutex(&count_mutex);
+ wc_UnLockMutex(&count_mutex);
if (!release)
return ret;
+#ifdef OPENSSL_EXTRA
+ if (bn_one) {
+ wolfSSL_BN_free(bn_one);
+ bn_one = NULL;
+ }
+#endif
+
#ifndef NO_SESSION_CACHE
- if (FreeMutex(&session_mutex) != 0)
+ if (wc_FreeMutex(&session_mutex) != 0)
ret = BAD_MUTEX_E;
#endif
- if (FreeMutex(&count_mutex) != 0)
+ if (wc_FreeMutex(&count_mutex) != 0)
ret = BAD_MUTEX_E;
-#if defined(HAVE_ECC) && defined(FP_ECC)
- wc_ecc_fp_free();
+#ifdef OPENSSL_EXTRA
+ wolfSSL_RAND_Cleanup();
#endif
+ if (wolfCrypt_Cleanup() != 0) {
+ WOLFSSL_MSG("Error with wolfCrypt_Cleanup call");
+ ret = WC_CLEANUP_E;
+ }
+
return ret;
}
@@ -5759,10 +12180,10 @@ int wolfSSL_Cleanup(void)
#ifndef NO_SESSION_CACHE
-/* some session IDs aren't random afterall, let's make them random */
-static INLINE word32 HashSession(const byte* sessionID, word32 len, int* error)
+/* some session IDs aren't random after all, let's make them random */
+static WC_INLINE word32 HashSession(const byte* sessionID, word32 len, int* error)
{
- byte digest[MAX_DIGEST_SIZE];
+ byte digest[WC_MAX_DIGEST_SIZE];
#ifndef NO_MD5
*error = wc_Md5Hash(sessionID, len, digest);
@@ -5778,35 +12199,42 @@ static INLINE word32 HashSession(const byte* sessionID, word32 len, int* error)
}
+WOLFSSL_ABI
void wolfSSL_flush_sessions(WOLFSSL_CTX* ctx, long tm)
{
- /* static table now, no flusing needed */
+ /* static table now, no flushing needed */
(void)ctx;
(void)tm;
}
/* set ssl session timeout in seconds */
+WOLFSSL_ABI
int wolfSSL_set_timeout(WOLFSSL* ssl, unsigned int to)
{
if (ssl == NULL)
return BAD_FUNC_ARG;
+ if (to == 0)
+ to = WOLFSSL_SESSION_TIMEOUT;
ssl->timeout = to;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
/* set ctx session timeout in seconds */
+WOLFSSL_ABI
int wolfSSL_CTX_set_timeout(WOLFSSL_CTX* ctx, unsigned int to)
{
if (ctx == NULL)
return BAD_FUNC_ARG;
+ if (to == 0)
+ to = WOLFSSL_SESSION_TIMEOUT;
ctx->timeout = to;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
@@ -5823,17 +12251,33 @@ WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len)
WOLFSSL_ENTER("GetSessionClient");
+ if (ssl->ctx->sessionCacheOff)
+ return NULL;
+
if (ssl->options.side == WOLFSSL_SERVER_END)
return NULL;
len = min(SERVER_ID_LEN, (word32)len);
+
+#ifdef HAVE_EXT_CACHE
+ if (ssl->ctx->get_sess_cb != NULL) {
+ int copy = 0;
+ ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, len, &copy);
+ if (ret != NULL)
+ return ret;
+ }
+
+ if (ssl->ctx->internalCacheOff)
+ return NULL;
+#endif
+
row = HashSession(id, len, &error) % SESSION_ROWS;
if (error != 0) {
WOLFSSL_MSG("Hash session failed");
return NULL;
}
- if (LockMutex(&session_mutex) != 0) {
+ if (wc_LockMutex(&session_mutex) != 0) {
WOLFSSL_MSG("Lock session mutex failed");
return NULL;
}
@@ -5870,15 +12314,49 @@ WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len)
}
}
- UnLockMutex(&session_mutex);
+ wc_UnLockMutex(&session_mutex);
return ret;
}
#endif /* NO_CLIENT_CACHE */
+/* Restore the master secret and session information for certificates.
+ *
+ * ssl The SSL/TLS object.
+ * session The cached session to restore.
+ * masterSecret The master secret from the cached session.
+ * restoreSessionCerts Restoring session certificates is required.
+ */
+static WC_INLINE void RestoreSession(WOLFSSL* ssl, WOLFSSL_SESSION* session,
+ byte* masterSecret, byte restoreSessionCerts)
+{
+ (void)ssl;
+ (void)restoreSessionCerts;
-WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
+ if (masterSecret)
+ XMEMCPY(masterSecret, session->masterSecret, SECRET_LEN);
+#ifdef SESSION_CERTS
+ /* If set, we should copy the session certs into the ssl object
+ * from the session we are returning so we can resume */
+ if (restoreSessionCerts) {
+ ssl->session.chain = session->chain;
+ ssl->session.version = session->version;
+ #ifdef NO_RESUME_SUITE_CHECK
+ ssl->session.cipherSuite0 = session->cipherSuite0;
+ ssl->session.cipherSuite = session->cipherSuite;
+ #endif
+ }
+#endif /* SESSION_CERTS */
+#if !defined(NO_RESUME_SUITE_CHECK) || \
+ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+ ssl->session.cipherSuite0 = session->cipherSuite0;
+ ssl->session.cipherSuite = session->cipherSuite;
+#endif
+}
+
+WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret,
+ byte restoreSessionCerts)
{
WOLFSSL_SESSION* ret = 0;
const byte* id = NULL;
@@ -5887,6 +12365,8 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
int count;
int error = 0;
+ (void) restoreSessionCerts;
+
if (ssl->options.sessionCacheOff)
return NULL;
@@ -5898,18 +12378,33 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
return NULL;
#endif
- if (ssl->arrays)
+ if (!ssl->options.tls1_3 && ssl->arrays != NULL)
id = ssl->arrays->sessionID;
else
id = ssl->session.sessionID;
+#ifdef HAVE_EXT_CACHE
+ if (ssl->ctx->get_sess_cb != NULL) {
+ int copy = 0;
+ /* Attempt to retrieve the session from the external cache. */
+ ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, &copy);
+ if (ret != NULL) {
+ RestoreSession(ssl, ret, masterSecret, restoreSessionCerts);
+ return ret;
+ }
+ }
+
+ if (ssl->ctx->internalCacheOff)
+ return NULL;
+#endif
+
row = HashSession(id, ID_LEN, &error) % SESSION_ROWS;
if (error != 0) {
WOLFSSL_MSG("Hash session failed");
return NULL;
}
- if (LockMutex(&session_mutex) != 0)
+ if (wc_LockMutex(&session_mutex) != 0)
return 0;
/* start from most recently used */
@@ -5932,8 +12427,7 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
if (LowResTimer() < (current->bornOn + current->timeout)) {
WOLFSSL_MSG("Session valid");
ret = current;
- if (masterSecret)
- XMEMCPY(masterSecret, current->masterSecret, SECRET_LEN);
+ RestoreSession(ssl, ret, masterSecret, restoreSessionCerts);
} else {
WOLFSSL_MSG("Session timed out");
}
@@ -5943,8 +12437,135 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
}
}
- UnLockMutex(&session_mutex);
+ wc_UnLockMutex(&session_mutex);
+
+ return ret;
+}
+
+
+static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom)
+{
+ WOLFSSL_SESSION* copyInto = &ssl->session;
+ void* tmpBuff = NULL;
+ int ticketLen = 0;
+ int doDynamicCopy = 0;
+ int ret = WOLFSSL_SUCCESS;
+
+ (void)ticketLen;
+ (void)doDynamicCopy;
+ (void)tmpBuff;
+
+ if (!ssl || !copyFrom)
+ return BAD_FUNC_ARG;
+
+#ifdef HAVE_SESSION_TICKET
+ /* Free old dynamic ticket if we had one to avoid leak */
+ if (copyInto->isDynamic) {
+ XFREE(copyInto->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+ copyInto->ticket = copyInto->staticTicket;
+ copyInto->isDynamic = 0;
+ }
+#endif
+
+ if (wc_LockMutex(&session_mutex) != 0)
+ return BAD_MUTEX_E;
+
+#ifdef HAVE_SESSION_TICKET
+ /* Size of ticket to alloc if needed; Use later for alloc outside lock */
+ doDynamicCopy = copyFrom->isDynamic;
+ ticketLen = copyFrom->ticketLen;
+#endif
+
+ *copyInto = *copyFrom;
+
+ /* Default ticket to non dynamic. This will avoid crash if we fail below */
+#ifdef HAVE_SESSION_TICKET
+ copyInto->ticket = copyInto->staticTicket;
+ copyInto->isDynamic = 0;
+#endif
+
+#ifndef NO_RESUME_SUITE_CHECK
+ copyInto->cipherSuite0 = copyFrom->cipherSuite0;
+ copyInto->cipherSuite = copyFrom->cipherSuite;
+#endif
+
+ if (wc_UnLockMutex(&session_mutex) != 0) {
+ return BAD_MUTEX_E;
+ }
+
+#ifdef HAVE_SESSION_TICKET
+#ifdef WOLFSSL_TLS13
+ if (wc_LockMutex(&session_mutex) != 0) {
+ XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+ return BAD_MUTEX_E;
+ }
+
+#ifdef NO_RESUME_SUITE_CHECK
+ copyInto->cipherSuite0 = copyFrom->cipherSuite0;
+ copyInto->cipherSuite = copyFrom->cipherSuite;
+#endif
+ copyInto->namedGroup = copyFrom->namedGroup;
+ copyInto->ticketSeen = copyFrom->ticketSeen;
+ copyInto->ticketAdd = copyFrom->ticketAdd;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+ XMEMCPY(&copyInto->ticketNonce, &copyFrom->ticketNonce,
+ sizeof(TicketNonce));
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+ copyInto->maxEarlyDataSz = copyFrom->maxEarlyDataSz;
+#endif
+ XMEMCPY(copyInto->masterSecret, copyFrom->masterSecret, SECRET_LEN);
+
+ if (wc_UnLockMutex(&session_mutex) != 0) {
+ if (ret == WOLFSSL_SUCCESS)
+ ret = BAD_MUTEX_E;
+ }
+#endif
+ /* If doing dynamic copy, need to alloc outside lock, then inside a lock
+ * confirm the size still matches and memcpy */
+ if (doDynamicCopy) {
+ tmpBuff = (byte*)XMALLOC(ticketLen, ssl->heap,
+ DYNAMIC_TYPE_SESSION_TICK);
+ if (!tmpBuff)
+ return MEMORY_ERROR;
+
+ if (wc_LockMutex(&session_mutex) != 0) {
+ XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+ return BAD_MUTEX_E;
+ }
+
+ if ((word16)ticketLen != copyFrom->ticketLen) {
+ /* Another thread modified the ssl-> session ticket during alloc.
+ * Treat as error, since ticket different than when copy requested */
+ ret = VAR_STATE_CHANGE_E;
+ }
+
+ if (ret == WOLFSSL_SUCCESS) {
+ copyInto->ticket = (byte*)tmpBuff;
+ copyInto->isDynamic = 1;
+ XMEMCPY(copyInto->ticket, copyFrom->ticket, ticketLen);
+ }
+ } else {
+ /* Need to ensure ticket pointer gets updated to own buffer
+ * and is not pointing to buff of session copied from */
+ copyInto->ticket = copyInto->staticTicket;
+ }
+
+ if (doDynamicCopy) {
+ if (wc_UnLockMutex(&session_mutex) != 0) {
+ if (ret == WOLFSSL_SUCCESS)
+ ret = BAD_MUTEX_E;
+ }
+ }
+ if (ret != WOLFSSL_SUCCESS) {
+ /* cleanup */
+ if (tmpBuff)
+ XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+ copyInto->ticket = copyInto->staticTicket;
+ copyInto->isDynamic = 0;
+ }
+#endif /* HAVE_SESSION_TICKET */
return ret;
}
@@ -5952,21 +12573,38 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session)
{
if (ssl->options.sessionCacheOff)
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
+
+#ifdef OPENSSL_EXTRA
+ /* check for application context id */
+ if (ssl->sessionCtxSz > 0) {
+ if (XMEMCMP(ssl->sessionCtx, session->sessionCtx, ssl->sessionCtxSz)) {
+ /* context id did not match! */
+ WOLFSSL_MSG("Session context did not match");
+ return SSL_FAILURE;
+ }
+ }
+#endif /* OPENSSL_EXTRA */
if (LowResTimer() < (session->bornOn + session->timeout)) {
- ssl->session = *session;
- ssl->options.resuming = 1;
+ int ret = GetDeepCopySession(ssl, session);
+ if (ret == WOLFSSL_SUCCESS) {
+ ssl->options.resuming = 1;
-#ifdef SESSION_CERTS
- ssl->version = session->version;
- ssl->options.cipherSuite0 = session->cipherSuite0;
- ssl->options.cipherSuite = session->cipherSuite;
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+ defined(HAVE_SESSION_TICKET))
+ ssl->version = session->version;
#endif
+#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
+ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+ ssl->options.cipherSuite0 = session->cipherSuite0;
+ ssl->options.cipherSuite = session->cipherSuite;
+#endif
+ }
- return SSL_SUCCESS;
+ return ret;
}
- return SSL_FAILURE; /* session timed out */
+ return WOLFSSL_FAILURE; /* session timed out */
}
@@ -5977,8 +12615,16 @@ static int get_locked_session_stats(word32* active, word32* total,
int AddSession(WOLFSSL* ssl)
{
- word32 row, idx;
+ word32 row = 0;
+ word32 idx = 0;
int error = 0;
+#ifdef HAVE_SESSION_TICKET
+ byte* tmpBuff = NULL;
+ int ticLen = 0;
+#endif
+ WOLFSSL_SESSION* session;
+ int i;
+ int overwrite = 0;
if (ssl->options.sessionCacheOff)
return 0;
@@ -5991,94 +12637,278 @@ int AddSession(WOLFSSL* ssl)
return 0;
#endif
- row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) % SESSION_ROWS;
- if (error != 0) {
- WOLFSSL_MSG("Hash session failed");
- return error;
+#ifdef HAVE_SESSION_TICKET
+ ticLen = ssl->session.ticketLen;
+ /* Alloc Memory here so if Malloc fails can exit outside of lock */
+ if(ticLen > SESSION_TICKET_LEN) {
+ tmpBuff = (byte*)XMALLOC(ticLen, ssl->heap,
+ DYNAMIC_TYPE_SESSION_TICK);
+ if(!tmpBuff)
+ return MEMORY_E;
}
+#endif
- if (LockMutex(&session_mutex) != 0)
- return BAD_MUTEX_E;
+#ifdef HAVE_EXT_CACHE
+ if (ssl->options.internalCacheOff) {
+ /* Create a new session object to be stored. */
+ session = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (session == NULL) {
+#ifdef HAVE_SESSION_TICKET
+ XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+#endif
+ return MEMORY_E;
+ }
+ XMEMSET(session, 0, sizeof(WOLFSSL_SESSION));
+ session->isAlloced = 1;
+ }
+ else
+#endif
+ {
+ /* Use the session object in the cache for external cache if required.
+ */
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
+ if (ssl->options.tls1_3) {
+ row = HashSession(ssl->session.sessionID, ID_LEN, &error) %
+ SESSION_ROWS;
+ }
+ else
+#endif
+ {
+ row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) %
+ SESSION_ROWS;
+ }
+ if (error != 0) {
+ WOLFSSL_MSG("Hash session failed");
+#ifdef HAVE_SESSION_TICKET
+ XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+#endif
+ return error;
+ }
+
+ if (wc_LockMutex(&session_mutex) != 0) {
+#ifdef HAVE_SESSION_TICKET
+ XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+#endif
+ return BAD_MUTEX_E;
+ }
- idx = SessionCache[row].nextIdx++;
+ for (i=0; i<SESSIONS_PER_ROW; i++) {
+ if (ssl->options.tls1_3) {
+ if (XMEMCMP(ssl->session.sessionID, SessionCache[row].Sessions[i].sessionID, ID_LEN) == 0) {
+ WOLFSSL_MSG("Session already exists. Overwriting.");
+ overwrite = 1;
+ idx = i;
+ break;
+ }
+ }
+ else {
+ if (XMEMCMP(ssl->arrays->sessionID, SessionCache[row].Sessions[i].sessionID, ID_LEN) == 0) {
+ WOLFSSL_MSG("Session already exists. Overwriting.");
+ overwrite = 1;
+ idx = i;
+ break;
+ }
+ }
+ }
+
+ if (!overwrite) {
+ idx = SessionCache[row].nextIdx++;
+ }
#ifdef SESSION_INDEX
- ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx;
+ ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx;
#endif
+ session = &SessionCache[row].Sessions[idx];
+ }
- XMEMCPY(SessionCache[row].Sessions[idx].masterSecret,
- ssl->arrays->masterSecret, SECRET_LEN);
- XMEMCPY(SessionCache[row].Sessions[idx].sessionID, ssl->arrays->sessionID,
- ID_LEN);
- SessionCache[row].Sessions[idx].sessionIDSz = ssl->arrays->sessionIDSz;
+ if (!ssl->options.tls1_3)
+ XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN);
+ else
+ XMEMCPY(session->masterSecret, ssl->session.masterSecret, SECRET_LEN);
+ session->haveEMS = ssl->options.haveEMS;
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
+ if (ssl->options.tls1_3) {
+ XMEMCPY(session->sessionID, ssl->session.sessionID, ID_LEN);
+ session->sessionIDSz = ID_LEN;
+ }
+ else
+#endif
+ {
+ XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN);
+ session->sessionIDSz = ssl->arrays->sessionIDSz;
+ }
- SessionCache[row].Sessions[idx].timeout = ssl->timeout;
- SessionCache[row].Sessions[idx].bornOn = LowResTimer();
+#ifdef OPENSSL_EXTRA
+ /* If using compatibility layer then check for and copy over session context
+ * id. */
+ if (ssl->sessionCtxSz > 0 && ssl->sessionCtxSz < ID_LEN) {
+ XMEMCPY(session->sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz);
+ }
+#endif
+
+ session->timeout = ssl->timeout;
+ session->bornOn = LowResTimer();
#ifdef HAVE_SESSION_TICKET
- SessionCache[row].Sessions[idx].ticketLen = ssl->session.ticketLen;
- XMEMCPY(SessionCache[row].Sessions[idx].ticket,
- ssl->session.ticket, ssl->session.ticketLen);
-#endif
+ /* Check if another thread modified ticket since alloc */
+ if ((word16)ticLen != ssl->session.ticketLen) {
+ error = VAR_STATE_CHANGE_E;
+ }
-#ifdef SESSION_CERTS
- SessionCache[row].Sessions[idx].chain.count = ssl->session.chain.count;
- XMEMCPY(SessionCache[row].Sessions[idx].chain.certs,
- ssl->session.chain.certs, sizeof(x509_buffer) * MAX_CHAIN_DEPTH);
+ if (error == 0) {
+ /* Cleanup cache row's old Dynamic buff if exists */
+ if(session->isDynamic) {
+ XFREE(session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+ session->ticket = NULL;
+ }
- SessionCache[row].Sessions[idx].version = ssl->version;
- SessionCache[row].Sessions[idx].cipherSuite0 = ssl->options.cipherSuite0;
- SessionCache[row].Sessions[idx].cipherSuite = ssl->options.cipherSuite;
-#endif /* SESSION_CERTS */
+ /* If too large to store in static buffer, use dyn buffer */
+ if (ticLen > SESSION_TICKET_LEN) {
+ session->ticket = tmpBuff;
+ session->isDynamic = 1;
+ } else {
+ session->ticket = session->staticTicket;
+ session->isDynamic = 0;
+ }
- SessionCache[row].totalCount++;
- if (SessionCache[row].nextIdx == SESSIONS_PER_ROW)
- SessionCache[row].nextIdx = 0;
+ session->ticketLen = (word16)ticLen;
+ XMEMCPY(session->ticket, ssl->session.ticket, ticLen);
+ } else { /* cleanup, reset state */
+ session->ticket = session->staticTicket;
+ session->isDynamic = 0;
+ session->ticketLen = 0;
+ if (tmpBuff) {
+ XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+ tmpBuff = NULL;
+ }
+ }
+#endif
+#ifdef SESSION_CERTS
+ if (error == 0) {
+ if (!overwrite || ssl->session.chain.count > 0) {
+ /*
+ * If we are overwriting and no certs present in ssl->session.chain
+ * then keep the old chain.
+ */
+ session->chain.count = ssl->session.chain.count;
+ XMEMCPY(session->chain.certs, ssl->session.chain.certs,
+ sizeof(x509_buffer) * session->chain.count);
+ }
+ }
+#endif /* SESSION_CERTS */
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+ defined(HAVE_SESSION_TICKET))
+ if (error == 0) {
+ session->version = ssl->version;
+ }
+#endif /* SESSION_CERTS || (WOLFSSL_TLS13 & HAVE_SESSION_TICKET) */
+#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
+ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+ if (error == 0) {
+ session->cipherSuite0 = ssl->options.cipherSuite0;
+ session->cipherSuite = ssl->options.cipherSuite;
+ }
+#endif
+#if defined(WOLFSSL_TLS13)
+ if (error == 0) {
+ session->namedGroup = ssl->session.namedGroup;
+ }
+#endif
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
+ if (error == 0) {
+ session->ticketSeen = ssl->session.ticketSeen;
+ session->ticketAdd = ssl->session.ticketAdd;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+ XMEMCPY(&session->ticketNonce, &ssl->session.ticketNonce,
+ sizeof(TicketNonce));
+#endif
+ #ifdef WOLFSSL_EARLY_DATA
+ session->maxEarlyDataSz = ssl->session.maxEarlyDataSz;
+ #endif
+ }
+#endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET */
+#ifdef HAVE_EXT_CACHE
+ if (!ssl->options.internalCacheOff)
+#endif
+ {
+ if (error == 0) {
+ SessionCache[row].totalCount++;
+ if (SessionCache[row].nextIdx == SESSIONS_PER_ROW)
+ SessionCache[row].nextIdx = 0;
+ }
+ }
#ifndef NO_CLIENT_CACHE
- if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->session.idLen) {
- word32 clientRow, clientIdx;
+ if (error == 0) {
+ if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->session.idLen) {
+ word32 clientRow, clientIdx;
- WOLFSSL_MSG("Adding client cache entry");
+ WOLFSSL_MSG("Adding client cache entry");
- SessionCache[row].Sessions[idx].idLen = ssl->session.idLen;
- XMEMCPY(SessionCache[row].Sessions[idx].serverID, ssl->session.serverID,
- ssl->session.idLen);
+ session->idLen = ssl->session.idLen;
+ XMEMCPY(session->serverID, ssl->session.serverID,
+ ssl->session.idLen);
- clientRow = HashSession(ssl->session.serverID, ssl->session.idLen,
- &error) % SESSION_ROWS;
- if (error != 0) {
- WOLFSSL_MSG("Hash session failed");
- } else {
- clientIdx = ClientCache[clientRow].nextIdx++;
+#ifdef HAVE_EXT_CACHE
+ if (!ssl->options.internalCacheOff)
+#endif
+ {
+ clientRow = HashSession(ssl->session.serverID,
+ ssl->session.idLen, &error) % SESSION_ROWS;
+ if (error != 0) {
+ WOLFSSL_MSG("Hash session failed");
+ } else {
+ clientIdx = ClientCache[clientRow].nextIdx++;
- ClientCache[clientRow].Clients[clientIdx].serverRow = (word16)row;
- ClientCache[clientRow].Clients[clientIdx].serverIdx = (word16)idx;
+ ClientCache[clientRow].Clients[clientIdx].serverRow =
+ (word16)row;
+ ClientCache[clientRow].Clients[clientIdx].serverIdx =
+ (word16)idx;
- ClientCache[clientRow].totalCount++;
- if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW)
- ClientCache[clientRow].nextIdx = 0;
+ ClientCache[clientRow].totalCount++;
+ if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW)
+ ClientCache[clientRow].nextIdx = 0;
+ }
+ }
}
+ else
+ session->idLen = 0;
}
- else
- SessionCache[row].Sessions[idx].idLen = 0;
#endif /* NO_CLIENT_CACHE */
#if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS)
- if (error == 0) {
- word32 active = 0;
+#ifdef HAVE_EXT_CACHE
+ if (!ssl->options.internalCacheOff)
+#endif
+ {
+ if (error == 0) {
+ word32 active = 0;
- error = get_locked_session_stats(&active, NULL, NULL);
- if (error == SSL_SUCCESS) {
- error = 0; /* back to this function ok */
+ error = get_locked_session_stats(&active, NULL, NULL);
+ if (error == WOLFSSL_SUCCESS) {
+ error = 0; /* back to this function ok */
- if (active > PeakSessions)
- PeakSessions = active;
+ if (active > PeakSessions)
+ PeakSessions = active;
+ }
}
}
#endif /* defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) */
- if (UnLockMutex(&session_mutex) != 0)
- return BAD_MUTEX_E;
+#ifdef HAVE_EXT_CACHE
+ if (!ssl->options.internalCacheOff)
+#endif
+ {
+ if (wc_UnLockMutex(&session_mutex) != 0)
+ return BAD_MUTEX_E;
+ }
+
+#ifdef HAVE_EXT_CACHE
+ if (error == 0 && ssl->ctx->new_sess_cb != NULL)
+ ssl->ctx->new_sess_cb(ssl, session);
+ if (ssl->options.internalCacheOff)
+ wolfSSL_SESSION_free(session);
+#endif
return error;
}
@@ -6096,14 +12926,14 @@ int wolfSSL_GetSessionIndex(WOLFSSL* ssl)
int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session)
{
- int row, col, result = SSL_FAILURE;
+ int row, col, result = WOLFSSL_FAILURE;
WOLFSSL_ENTER("wolfSSL_GetSessionAtIndex");
row = idx >> SESSIDX_ROW_SHIFT;
col = idx & SESSIDX_IDX_MASK;
- if (LockMutex(&session_mutex) != 0) {
+ if (wc_LockMutex(&session_mutex) != 0) {
return BAD_MUTEX_E;
}
@@ -6111,10 +12941,10 @@ int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session)
col < (int)min(SessionCache[row].totalCount, SESSIONS_PER_ROW)) {
XMEMCPY(session,
&SessionCache[row].Sessions[col], sizeof(WOLFSSL_SESSION));
- result = SSL_SUCCESS;
+ result = WOLFSSL_SUCCESS;
}
- if (UnLockMutex(&session_mutex) != 0)
+ if (wc_UnLockMutex(&session_mutex) != 0)
result = BAD_MUTEX_E;
WOLFSSL_LEAVE("wolfSSL_GetSessionAtIndex", result);
@@ -6123,7 +12953,7 @@ int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session)
#endif /* SESSION_INDEX */
-#if defined(SESSION_INDEX) && defined(SESSION_CERTS)
+#if defined(SESSION_CERTS)
WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session)
{
@@ -6137,15 +12967,41 @@ WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session)
return chain;
}
+
+#ifdef OPENSSL_EXTRA
+/* gets the peer certificate associated with the session passed in
+ * returns null on failure, the caller should not free the returned pointer */
+WOLFSSL_X509* wolfSSL_SESSION_get0_peer(WOLFSSL_SESSION* session)
+{
+ WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain");
+ if (session) {
+ int count;
+
+ count = wolfSSL_get_chain_count(&session->chain);
+ if (count < 1 || count >= MAX_CHAIN_DEPTH) {
+ WOLFSSL_MSG("bad count found");
+ return NULL;
+ }
+
+ if (session->peer == NULL) {
+ session->peer = wolfSSL_get_chain_X509(&session->chain, 0);
+ }
+ return session->peer;
+ }
+ WOLFSSL_MSG("No session passed in");
+
+ return NULL;
+}
+#endif /* OPENSSL_EXTRA */
#endif /* SESSION_INDEX && SESSION_CERTS */
#ifdef WOLFSSL_SESSION_STATS
-/* requires session_mutex lock held, SSL_SUCCESS on ok */
+/* requires session_mutex lock held, WOLFSSL_SUCCESS on ok */
static int get_locked_session_stats(word32* active, word32* total, word32* peak)
{
- int result = SSL_SUCCESS;
+ int result = WOLFSSL_SUCCESS;
int i;
int count;
int idx;
@@ -6174,7 +13030,7 @@ static int get_locked_session_stats(word32* active, word32* total, word32* peak)
break;
}
- /* if not expried then good */
+ /* if not expired then good */
if (ticks < (SessionCache[i].Sessions[idx].bornOn +
SessionCache[i].Sessions[idx].timeout) ) {
now++;
@@ -6199,11 +13055,11 @@ static int get_locked_session_stats(word32* active, word32* total, word32* peak)
}
-/* return SSL_SUCCESS on ok */
+/* return WOLFSSL_SUCCESS on ok */
int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak,
word32* maxSessions)
{
- int result = SSL_SUCCESS;
+ int result = WOLFSSL_SUCCESS;
WOLFSSL_ENTER("wolfSSL_get_session_stats");
@@ -6218,13 +13074,13 @@ int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak,
if (active == NULL && total == NULL && peak == NULL)
return BAD_FUNC_ARG;
- if (LockMutex(&session_mutex) != 0) {
+ if (wc_LockMutex(&session_mutex) != 0) {
return BAD_MUTEX_E;
}
result = get_locked_session_stats(active, total, peak);
- if (UnLockMutex(&session_mutex) != 0)
+ if (wc_UnLockMutex(&session_mutex) != 0)
result = BAD_MUTEX_E;
WOLFSSL_LEAVE("wolfSSL_get_session_stats", result);
@@ -6237,7 +13093,7 @@ int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak,
#ifdef PRINT_SESSION_STATS
- /* SSL_SUCCESS on ok */
+ /* WOLFSSL_SUCCESS on ok */
int wolfSSL_PrintSessionStats(void)
{
word32 totalSessionsSeen = 0;
@@ -6251,7 +13107,7 @@ int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak,
ret = wolfSSL_get_session_stats(&totalSessionsNow, &totalSessionsSeen,
&peak, &maxSessions);
- if (ret != SSL_SUCCESS)
+ if (ret != WOLFSSL_SUCCESS)
return ret;
printf("Total Sessions Seen = %d\n", totalSessionsSeen);
printf("Total Sessions Now = %d\n", totalSessionsNow);
@@ -6292,10 +13148,12 @@ int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak,
#else /* NO_SESSION_CACHE */
/* No session cache version */
-WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
+WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret,
+ byte restoreSessionCerts)
{
(void)ssl;
(void)masterSecret;
+ (void)restoreSessionCerts;
return NULL;
}
@@ -6305,30 +13163,38 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
/* call before SSL_connect, if verifying will add name check to
date check and signature check */
+WOLFSSL_ABI
int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn)
{
WOLFSSL_ENTER("wolfSSL_check_domain_name");
+
+ if (ssl == NULL || dn == NULL) {
+ WOLFSSL_MSG("Bad function argument: NULL");
+ return WOLFSSL_FAILURE;
+ }
+
if (ssl->buffers.domainName.buffer)
XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
- ssl->buffers.domainName.length = (word32)XSTRLEN(dn) + 1;
- ssl->buffers.domainName.buffer = (byte*) XMALLOC(
- ssl->buffers.domainName.length, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+ ssl->buffers.domainName.length = (word32)XSTRLEN(dn);
+ ssl->buffers.domainName.buffer = (byte*)XMALLOC(
+ ssl->buffers.domainName.length + 1, ssl->heap, DYNAMIC_TYPE_DOMAIN);
if (ssl->buffers.domainName.buffer) {
- XSTRNCPY((char*)ssl->buffers.domainName.buffer, dn,
- ssl->buffers.domainName.length);
- return SSL_SUCCESS;
+ unsigned char* domainName = ssl->buffers.domainName.buffer;
+ XMEMCPY(domainName, dn, ssl->buffers.domainName.length);
+ domainName[ssl->buffers.domainName.length] = '\0';
+ return WOLFSSL_SUCCESS;
}
else {
ssl->error = MEMORY_ERROR;
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
}
}
/* turn on wolfSSL zlib compression
- returns SSL_SUCCESS for success, else error (not built in)
+ returns WOLFSSL_SUCCESS for success, else error (not built in)
*/
int wolfSSL_set_compression(WOLFSSL* ssl)
{
@@ -6336,7 +13202,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
(void)ssl;
#ifdef HAVE_LIBZ
ssl->options.usingCompression = 1;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
#else
return NOT_COMPILED_IN;
#endif
@@ -6396,7 +13262,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
typedef struct itimerval Itimerval;
- /* don't keep calling simple functions while setting up timer and singals
+ /* don't keep calling simple functions while setting up timer and signals
if no inlining these are the next best */
#define AddTimes(a, b, c) \
@@ -6435,13 +13301,13 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
static int wolfSSL_ex_wrapper(WOLFSSL* ssl, HandShakeCallBack hsCb,
- TimeoutCallBack toCb, Timeval timeout)
+ TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout)
{
- int ret = SSL_FATAL_ERROR;
+ int ret = WOLFSSL_FATAL_ERROR;
int oldTimerOn = 0; /* was timer already on */
- Timeval startTime;
- Timeval endTime;
- Timeval totalTime;
+ WOLFSSL_TIMEVAL startTime;
+ WOLFSSL_TIMEVAL endTime;
+ WOLFSSL_TIMEVAL totalTime;
Itimerval myTimeout;
Itimerval oldTimeout; /* if old timer adjust from total time to reset */
struct sigaction act, oact;
@@ -6450,7 +13316,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
if (hsCb) {
ssl->hsInfoOn = 1;
- InitHandShakeInfo(&ssl->handShakeInfo);
+ InitHandShakeInfo(&ssl->handShakeInfo, ssl);
}
if (toCb) {
ssl->toInfoOn = 1;
@@ -6538,7 +13404,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
ssl->toInfoOn = 0;
}
if (hsCb) {
- FinishHandShakeInfo(&ssl->handShakeInfo, ssl);
+ FinishHandShakeInfo(&ssl->handShakeInfo);
(hsCb)(&ssl->handShakeInfo);
ssl->hsInfoOn = 0;
}
@@ -6549,7 +13415,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
#ifndef NO_WOLFSSL_CLIENT
int wolfSSL_connect_ex(WOLFSSL* ssl, HandShakeCallBack hsCb,
- TimeoutCallBack toCb, Timeval timeout)
+ TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout)
{
WOLFSSL_ENTER("wolfSSL_connect_ex");
return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
@@ -6561,7 +13427,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
#ifndef NO_WOLFSSL_SERVER
int wolfSSL_accept_ex(WOLFSSL* ssl, HandShakeCallBack hsCb,
- TimeoutCallBack toCb,Timeval timeout)
+ TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout)
{
WOLFSSL_ENTER("wolfSSL_accept_ex");
return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
@@ -6575,56 +13441,77 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
#ifndef NO_PSK
void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX* ctx,
- psk_client_callback cb)
+ wc_psk_client_callback cb)
{
WOLFSSL_ENTER("SSL_CTX_set_psk_client_callback");
+
+ if (ctx == NULL)
+ return;
+
ctx->havePSK = 1;
ctx->client_psk_cb = cb;
}
- void wolfSSL_set_psk_client_callback(WOLFSSL* ssl, psk_client_callback cb)
+ void wolfSSL_set_psk_client_callback(WOLFSSL* ssl,wc_psk_client_callback cb)
{
byte haveRSA = 1;
+ int keySz = 0;
WOLFSSL_ENTER("SSL_set_psk_client_callback");
+
+ if (ssl == NULL)
+ return;
+
ssl->options.havePSK = 1;
ssl->options.client_psk_cb = cb;
#ifdef NO_RSA
haveRSA = 0;
#endif
- InitSuites(ssl->suites, ssl->version, haveRSA, TRUE,
+ #ifndef NO_CERTS
+ keySz = ssl->buffers.keySz;
+ #endif
+ InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE,
ssl->options.haveDH, ssl->options.haveNTRU,
- ssl->options.haveECDSAsig, ssl->options.haveStaticECC,
- ssl->options.side);
+ ssl->options.haveECDSAsig, ssl->options.haveECC,
+ ssl->options.haveStaticECC, ssl->options.side);
}
void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX* ctx,
- psk_server_callback cb)
+ wc_psk_server_callback cb)
{
WOLFSSL_ENTER("SSL_CTX_set_psk_server_callback");
+ if (ctx == NULL)
+ return;
ctx->havePSK = 1;
ctx->server_psk_cb = cb;
}
- void wolfSSL_set_psk_server_callback(WOLFSSL* ssl, psk_server_callback cb)
+ void wolfSSL_set_psk_server_callback(WOLFSSL* ssl,wc_psk_server_callback cb)
{
byte haveRSA = 1;
+ int keySz = 0;
WOLFSSL_ENTER("SSL_set_psk_server_callback");
+ if (ssl == NULL)
+ return;
+
ssl->options.havePSK = 1;
ssl->options.server_psk_cb = cb;
#ifdef NO_RSA
haveRSA = 0;
#endif
- InitSuites(ssl->suites, ssl->version, haveRSA, TRUE,
+ #ifndef NO_CERTS
+ keySz = ssl->buffers.keySz;
+ #endif
+ InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE,
ssl->options.haveDH, ssl->options.haveNTRU,
- ssl->options.haveECDSAsig, ssl->options.haveStaticECC,
- ssl->options.side);
+ ssl->options.haveECDSAsig, ssl->options.haveECC,
+ ssl->options.haveStaticECC, ssl->options.side);
}
@@ -6654,12 +13541,16 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
{
WOLFSSL_ENTER("SSL_CTX_use_psk_identity_hint");
if (hint == 0)
- ctx->server_hint[0] = 0;
+ ctx->server_hint[0] = '\0';
else {
+ /* Qt does not call CTX_set_*_psk_callbacks where havePSK is set */
+ #ifdef WOLFSSL_QT
+ ctx->havePSK=1;
+ #endif
XSTRNCPY(ctx->server_hint, hint, MAX_PSK_ID_LEN);
- ctx->server_hint[MAX_PSK_ID_LEN - 1] = '\0';
+ ctx->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */
}
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
@@ -6668,15 +13559,16 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
WOLFSSL_ENTER("SSL_use_psk_identity_hint");
if (ssl == NULL || ssl->arrays == NULL)
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
if (hint == 0)
ssl->arrays->server_hint[0] = 0;
else {
- XSTRNCPY(ssl->arrays->server_hint, hint, MAX_PSK_ID_LEN);
- ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0';
+ XSTRNCPY(ssl->arrays->server_hint, hint,
+ sizeof(ssl->arrays->server_hint)-1);
+ ssl->arrays->server_hint[sizeof(ssl->arrays->server_hint)-1] = '\0';
}
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
#endif /* NO_PSK */
@@ -6689,11 +13581,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
WOLFSSL_ENTER("wolfSSL_CTX_allow_anon_cipher");
if (ctx == NULL)
- return SSL_FAILURE;
+ return WOLFSSL_FAILURE;
ctx->haveAnon = 1;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
#endif /* HAVE_ANON */
@@ -6702,23 +13594,73 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
#ifndef NO_CERTS
/* used to be defined on NO_FILESYSTEM only, but are generally useful */
+ int wolfSSL_CTX_load_verify_buffer_ex(WOLFSSL_CTX* ctx,
+ const unsigned char* in,
+ long sz, int format, int userChain,
+ word32 flags)
+ {
+ int verify;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer_ex");
+
+ verify = GET_VERIFY_SETTING_CTX(ctx);
+ if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY)
+ verify = VERIFY_SKIP_DATE;
+
+ if (format == WOLFSSL_FILETYPE_PEM)
+ return ProcessChainBuffer(ctx, in, sz, format, CA_TYPE, NULL,
+ verify);
+ else
+ return ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL, NULL,
+ userChain, verify);
+ }
+
/* wolfSSL extension allows DER files to be loaded from buffers as well */
- int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX* ctx, const unsigned char* in,
- long sz, int format)
+ int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX* ctx,
+ const unsigned char* in,
+ long sz, int format)
+ {
+ return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 0,
+ WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
+ }
+
+ int wolfSSL_CTX_load_verify_chain_buffer_format(WOLFSSL_CTX* ctx,
+ const unsigned char* in,
+ long sz, int format)
+ {
+ return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 1,
+ WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
+ }
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+ int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX* ctx,
+ const unsigned char* in,
+ long sz, int format)
{
- WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer");
- if (format == SSL_FILETYPE_PEM)
- return ProcessChainBuffer(ctx, in, sz, format, CA_TYPE, NULL);
+ WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_buffer");
+
+ /* sanity check on arguments */
+ if (sz < 0 || in == NULL || ctx == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (format == WOLFSSL_FILETYPE_PEM)
+ return ProcessChainBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE,
+ NULL, GET_VERIFY_SETTING_CTX(ctx));
else
- return ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL,NULL,0);
+ return ProcessBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE, NULL,
+ NULL, 0, GET_VERIFY_SETTING_CTX(ctx));
}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX* ctx,
const unsigned char* in, long sz, int format)
{
WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_buffer");
- return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 0);
+ return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 0,
+ GET_VERIFY_SETTING_CTX(ctx));
}
@@ -6726,23 +13668,162 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
const unsigned char* in, long sz, int format)
{
WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_buffer");
- return ProcessBuffer(ctx, in, sz, format, PRIVATEKEY_TYPE, NULL,NULL,0);
+ return ProcessBuffer(ctx, in, sz, format, PRIVATEKEY_TYPE, NULL, NULL,
+ 0, GET_VERIFY_SETTING_CTX(ctx));
}
+#ifdef HAVE_PKCS11
+ int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id,
+ long sz, int devId, long keySz)
+ {
+ int ret = WOLFSSL_FAILURE;
+
+ FreeDer(&ctx->privateKey);
+ if (AllocDer(&ctx->privateKey, (word32)sz, PRIVATEKEY_TYPE,
+ ctx->heap) == 0) {
+ XMEMCPY(ctx->privateKey->buffer, id, sz);
+ ctx->privateKeyId = 1;
+ ctx->privateKeySz = (word32)keySz;
+ if (devId != INVALID_DEVID)
+ ctx->privateKeyDevId = devId;
+ else
+ ctx->privateKeyDevId = ctx->devId;
+
+ ret = WOLFSSL_SUCCESS;
+ }
+
+ return ret;
+ }
+#endif
+
+ int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX* ctx,
+ const unsigned char* in, long sz, int format)
+ {
+ WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer_format");
+ return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 1,
+ GET_VERIFY_SETTING_CTX(ctx));
+ }
int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx,
const unsigned char* in, long sz)
{
- WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer");
- return ProcessBuffer(ctx, in, sz, SSL_FILETYPE_PEM, CERT_TYPE, NULL,
- NULL, 1);
+ return wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, in, sz,
+ WOLFSSL_FILETYPE_PEM);
}
+
+#ifndef NO_DH
+
+ /* server wrapper for ctx or ssl Diffie-Hellman parameters */
+ static int wolfSSL_SetTmpDH_buffer_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
+ const unsigned char* buf,
+ long sz, int format)
+ {
+ DerBuffer* der = NULL;
+ int ret = 0;
+ word32 pSz = MAX_DH_SIZE;
+ word32 gSz = MAX_DH_SIZE;
+ #ifdef WOLFSSL_SMALL_STACK
+ byte* p = NULL;
+ byte* g = NULL;
+ #else
+ byte p[MAX_DH_SIZE];
+ byte g[MAX_DH_SIZE];
+ #endif
+
+ if (ctx == NULL || buf == NULL)
+ return BAD_FUNC_ARG;
+
+ ret = AllocDer(&der, 0, DH_PARAM_TYPE, ctx->heap);
+ if (ret != 0) {
+ return ret;
+ }
+ der->buffer = (byte*)buf;
+ der->length = (word32)sz;
+
+ #ifdef WOLFSSL_SMALL_STACK
+ p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+
+ if (p == NULL || g == NULL) {
+ XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ return MEMORY_E;
+ }
+ #endif
+
+ if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM)
+ ret = WOLFSSL_BAD_FILETYPE;
+ else {
+ if (format == WOLFSSL_FILETYPE_PEM) {
+#ifdef WOLFSSL_PEM_TO_DER
+ FreeDer(&der);
+ ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, ctx->heap,
+ NULL, NULL);
+ #ifdef WOLFSSL_WPAS
+ #ifndef NO_DSA
+ if (ret < 0) {
+ ret = PemToDer(buf, sz, DSA_PARAM_TYPE, &der, ctx->heap,
+ NULL, NULL);
+ }
+ #endif
+ #endif /* WOLFSSL_WPAS */
+#else
+ ret = NOT_COMPILED_IN;
+#endif /* WOLFSSL_PEM_TO_DER */
+ }
+
+ if (ret == 0) {
+ if (wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz) < 0)
+ ret = WOLFSSL_BAD_FILETYPE;
+ else if (ssl)
+ ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz);
+ else
+ ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz);
+ }
+ }
+
+ FreeDer(&der);
+
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ #endif
+
+ return ret;
+ }
+
+
+ /* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
+ int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz,
+ int format)
+ {
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ return wolfSSL_SetTmpDH_buffer_wrapper(ssl->ctx, ssl, buf, sz, format);
+ }
+
+
+ /* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
+ int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX* ctx, const unsigned char* buf,
+ long sz, int format)
+ {
+ return wolfSSL_SetTmpDH_buffer_wrapper(ctx, NULL, buf, sz, format);
+ }
+
+#endif /* NO_DH */
+
+
int wolfSSL_use_certificate_buffer(WOLFSSL* ssl,
const unsigned char* in, long sz, int format)
{
WOLFSSL_ENTER("wolfSSL_use_certificate_buffer");
- return ProcessBuffer(ssl->ctx, in, sz, format,CERT_TYPE,ssl,NULL,0);
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, ssl, NULL, 0,
+ GET_VERIFY_SETTING_SSL(ssl));
}
@@ -6750,22 +13831,60 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
const unsigned char* in, long sz, int format)
{
WOLFSSL_ENTER("wolfSSL_use_PrivateKey_buffer");
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
return ProcessBuffer(ssl->ctx, in, sz, format, PRIVATEKEY_TYPE,
- ssl, NULL, 0);
+ ssl, NULL, 0, GET_VERIFY_SETTING_SSL(ssl));
+ }
+
+#ifdef HAVE_PKCS11
+ int wolfSSL_use_PrivateKey_id(WOLFSSL* ssl, const unsigned char* id,
+ long sz, int devId, long keySz)
+ {
+ int ret = WOLFSSL_FAILURE;
+
+ if (ssl->buffers.weOwnKey)
+ FreeDer(&ssl->buffers.key);
+ if (AllocDer(&ssl->buffers.key, (word32)sz, PRIVATEKEY_TYPE,
+ ssl->heap) == 0) {
+ XMEMCPY(ssl->buffers.key->buffer, id, sz);
+ ssl->buffers.weOwnKey = 1;
+ ssl->buffers.keyId = 1;
+ ssl->buffers.keySz = (word32)keySz;
+ if (devId != INVALID_DEVID)
+ ssl->buffers.keyDevId = devId;
+ else
+ ssl->buffers.keyDevId = ssl->devId;
+
+ ret = WOLFSSL_SUCCESS;
+ }
+
+ return ret;
}
+#endif
+
+ int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL* ssl,
+ const unsigned char* in, long sz, int format)
+ {
+ WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format");
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+ return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE,
+ ssl, NULL, 1, GET_VERIFY_SETTING_SSL(ssl));
+ }
int wolfSSL_use_certificate_chain_buffer(WOLFSSL* ssl,
const unsigned char* in, long sz)
{
- WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer");
- return ProcessBuffer(ssl->ctx, in, sz, SSL_FILETYPE_PEM, CERT_TYPE,
- ssl, NULL, 1);
+ return wolfSSL_use_certificate_chain_buffer_format(ssl, in, sz,
+ WOLFSSL_FILETYPE_PEM);
}
/* unload any certs or keys that SSL owns, leave CTX as is
- SSL_SUCCESS on ok */
+ WOLFSSL_SUCCESS on ok */
int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl)
{
if (ssl == NULL) {
@@ -6773,31 +13892,32 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
return BAD_FUNC_ARG;
}
- if (ssl->buffers.weOwnCert) {
+ if (ssl->buffers.weOwnCert && !ssl->keepCert) {
WOLFSSL_MSG("Unloading cert");
- XFREE(ssl->buffers.certificate.buffer, ssl->heap,DYNAMIC_TYPE_CERT);
+ FreeDer(&ssl->buffers.certificate);
+ #ifdef KEEP_OUR_CERT
+ FreeX509(ssl->ourCert);
+ if (ssl->ourCert) {
+ XFREE(ssl->ourCert, ssl->heap, DYNAMIC_TYPE_X509);
+ ssl->ourCert = NULL;
+ }
+ #endif
ssl->buffers.weOwnCert = 0;
- ssl->buffers.certificate.length = 0;
- ssl->buffers.certificate.buffer = NULL;
}
if (ssl->buffers.weOwnCertChain) {
WOLFSSL_MSG("Unloading cert chain");
- XFREE(ssl->buffers.certChain.buffer, ssl->heap,DYNAMIC_TYPE_CERT);
+ FreeDer(&ssl->buffers.certChain);
ssl->buffers.weOwnCertChain = 0;
- ssl->buffers.certChain.length = 0;
- ssl->buffers.certChain.buffer = NULL;
}
if (ssl->buffers.weOwnKey) {
WOLFSSL_MSG("Unloading key");
- XFREE(ssl->buffers.key.buffer, ssl->heap, DYNAMIC_TYPE_KEY);
+ FreeDer(&ssl->buffers.key);
ssl->buffers.weOwnKey = 0;
- ssl->buffers.key.length = 0;
- ssl->buffers.key.buffer = NULL;
}
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
@@ -6811,30 +13931,74 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
return wolfSSL_CertManagerUnloadCAs(ctx->cm);
}
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+ int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx)
+ {
+ WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
+
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ return wolfSSL_CertManagerUnload_trust_peers(ctx->cm);
+ }
+#endif /* WOLFSSL_TRUST_PEER_CERT */
/* old NO_FILESYSTEM end */
#endif /* !NO_CERTS */
-#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
-
+#ifdef OPENSSL_EXTRA
int wolfSSL_add_all_algorithms(void)
{
WOLFSSL_ENTER("wolfSSL_add_all_algorithms");
- wolfSSL_Init();
- return SSL_SUCCESS;
+ if (wolfSSL_Init() == WOLFSSL_SUCCESS)
+ return WOLFSSL_SUCCESS;
+ else
+ return WOLFSSL_FATAL_ERROR;
}
+ int wolfSSL_OpenSSL_add_all_algorithms_noconf(void)
+ {
+ WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_noconf");
+
+ if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR)
+ return WOLFSSL_FATAL_ERROR;
+ return WOLFSSL_SUCCESS;
+ }
+
+ int wolfSSL_OpenSSL_add_all_algorithms_conf(void)
+ {
+ WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_conf");
+ /* This function is currently the same as
+ wolfSSL_OpenSSL_add_all_algorithms_noconf since we do not employ
+ the use of a wolfssl.cnf type configuration file and is only used for
+ OpenSSL compatability. */
+
+ if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+ return WOLFSSL_SUCCESS;
+ }
+
+ /* returns previous set cache size which stays constant */
long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX* ctx, long sz)
{
/* cache size fixed at compile time in wolfSSL */
(void)ctx;
(void)sz;
- return 0;
+ WOLFSSL_MSG("session cache is set at compile time");
+ #ifndef NO_SESSION_CACHE
+ return (long)(SESSIONS_PER_ROW * SESSION_ROWS);
+ #else
+ return 0;
+ #endif
}
+#endif
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX* ctx, int mode)
{
WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown");
@@ -6849,60 +14013,457 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
if (mode)
ssl->options.quietShutdown = 1;
}
+#endif
-
+#ifdef OPENSSL_EXTRA
void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr)
{
- WOLFSSL_ENTER("SSL_set_bio");
- wolfSSL_set_rfd(ssl, rd->fd);
- wolfSSL_set_wfd(ssl, wr->fd);
+ WOLFSSL_ENTER("wolfSSL_set_bio");
+
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Bad argument, ssl was NULL");
+ return;
+ }
+
+ /* if WOLFSSL_BIO is socket type then set WOLFSSL socket to use */
+ if (rd != NULL && rd->type == WOLFSSL_BIO_SOCKET) {
+ wolfSSL_set_rfd(ssl, rd->num);
+ }
+ if (wr != NULL && wr->type == WOLFSSL_BIO_SOCKET) {
+ wolfSSL_set_wfd(ssl, wr->num);
+ }
+
+ /* free any existing WOLFSSL_BIOs in use */
+ if (ssl->biord != NULL) {
+ if (ssl->biord != ssl->biowr) {
+ if (ssl->biowr != NULL) {
+ wolfSSL_BIO_free(ssl->biowr);
+ ssl->biowr = NULL;
+ }
+ }
+ wolfSSL_BIO_free(ssl->biord);
+ ssl->biord = NULL;
+ }
+
ssl->biord = rd;
ssl->biowr = wr;
- }
+ /* set SSL to use BIO callbacks instead */
+ if (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0) &&
+ (rd != NULL && rd->type != WOLFSSL_BIO_SOCKET)) {
+ ssl->CBIORecv = BioReceive;
+ }
+ if (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0) &&
+ (wr != NULL && wr->type != WOLFSSL_BIO_SOCKET)) {
+ ssl->CBIOSend = BioSend;
+ }
+ /* User programs should always retry reading from these BIOs */
+ if (rd) {
+ /* User writes to rd */
+ BIO_set_retry_write(rd);
+ }
+ if (wr) {
+ /* User reads from wr */
+ BIO_set_retry_read(wr);
+ }
+ }
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_WEBSERVER)
void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx,
- STACK_OF(WOLFSSL_X509_NAME)* names)
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_client_CA_list");
+ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
+ if (ctx != NULL)
+ ctx->ca_names = names;
+ #else
(void)ctx;
(void)names;
+ #endif
+ }
+
+
+ /* returns the CA's set on server side or the CA's sent from server when
+ * on client side */
+#if defined(SESSION_CERTS) && defined(OPENSSL_ALL)
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list(
+ const WOLFSSL* ssl)
+ {
+ WOLFSSL_ENTER("wolfSSL_get_client_CA_list");
+
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list");
+ return NULL;
+ }
+
+ /* return list of CAs sent from the server */
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ WOLF_STACK_OF(WOLFSSL_X509)* sk;
+
+ sk = wolfSSL_get_peer_cert_chain(ssl);
+ if (sk != NULL) {
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret;
+ WOLFSSL_X509* x509;
+
+ ret = wolfSSL_sk_X509_NAME_new(NULL);
+ do {
+ x509 = wolfSSL_sk_X509_pop(sk);
+ if (x509 != NULL) {
+ if (wolfSSL_X509_get_isCA(x509)) {
+ if (wolfSSL_sk_X509_NAME_push(ret,
+ wolfSSL_X509_get_subject_name(x509)) != 0) {
+ WOLFSSL_MSG("Error pushing X509 name to stack");
+ /* continue on to try other certificates and
+ * do not fail out here */
+ }
+ }
+ wolfSSL_X509_free(x509);
+ }
+ } while (x509 != NULL);
+ wolfSSL_sk_X509_free(sk);
+ return ret;
+ }
+ return NULL;
+ }
+ else {
+ /* currently only can be set in the CTX */
+ return ssl->ctx->ca_names;
+ }
+ }
+#endif /* SESSION_CERTS */
+
+
+ #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \
+ defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY)
+ /* registers client cert callback, called during handshake if server
+ requests client auth but user has not loaded client cert/key */
+ void wolfSSL_CTX_set_client_cert_cb(WOLFSSL_CTX *ctx, client_cert_cb cb)
+ {
+ WOLFSSL_ENTER("wolfSSL_CTX_set_client_cert_cb");
+
+ if (ctx != NULL) {
+ ctx->CBClientCert = cb;
+ }
}
+ #endif /* OPENSSL_ALL || OPENSSL_EXTRA || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || HAVE_WEBSERVER */
- STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname)
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list(
+ const WOLFSSL_CTX *s)
{
+ WOLFSSL_ENTER("wolfSSL_CTX_get_client_CA_list");
+
+ if (s == NULL)
+ return NULL;
+
+ return s->ca_names;
+ }
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+ #if !defined(NO_RSA) && !defined(NO_CERTS)
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname)
+ {
+ /* The webserver build is using this to load a CA into the server
+ * for client authentication as an option. Have this return NULL in
+ * that case. If OPENSSL_EXTRA is enabled, go ahead and include
+ * the function. */
+ #ifdef OPENSSL_EXTRA
+ WOLFSSL_STACK *list = NULL;
+ WOLFSSL_STACK *node;
+ WOLFSSL_BIO* bio;
+ WOLFSSL_X509 *cert = NULL;
+ WOLFSSL_X509_NAME *subjectName = NULL;
+ unsigned long err;
+
+ WOLFSSL_ENTER("wolfSSL_load_client_CA_file");
+
+ bio = wolfSSL_BIO_new_file(fname, "r");
+ if (bio == NULL)
+ return NULL;
+
+ /* Read each certificate in the chain out of the file. */
+ while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) {
+ subjectName = wolfSSL_X509_get_subject_name(cert);
+ if (subjectName == NULL)
+ break;
+
+ node = wolfSSL_sk_new_node(NULL);
+ if (node == NULL)
+ break;
+ node->type = STACK_TYPE_X509_NAME;
+
+ /* Need a persistent copy of the subject name. */
+ node->data.name = wolfSSL_X509_NAME_dup(subjectName);
+ /*
+ * Original cert will be freed so make sure not to try to access
+ * it in the future.
+ */
+ node->data.name->x509 = NULL;
+
+ /* Put node on the front of the list. */
+ node->num = (list == NULL) ? 1 : list->num + 1;
+ node->next = list;
+ list = node;
+
+ wolfSSL_X509_free(cert);
+ cert = NULL;
+ }
+
+ err = wolfSSL_ERR_peek_last_error();
+
+ if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
+ ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
+ /*
+ * wolfSSL_PEM_read_bio_X509 pushes an ASN_NO_PEM_HEADER error
+ * to the error queue on file end. This should not be left
+ * for the caller to find so we clear the last error.
+ */
+ wc_RemoveErrorNode(-1);
+ }
+
+ wolfSSL_X509_free(cert);
+ wolfSSL_BIO_free(bio);
+ return list;
+ #else
(void)fname;
- return 0;
+ return NULL;
+ #endif
}
+ #endif
+#endif
+
+#ifdef OPENSSL_EXTRA
+ #if !defined(NO_RSA) && !defined(NO_CERTS)
+ int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
+ {
+ WOLFSSL_STACK *node = NULL;
+ WOLFSSL_X509_NAME *subjectName = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA");
+ if (ctx == NULL || x509 == NULL){
+ WOLFSSL_MSG("Bad argument");
+ return SSL_FAILURE;
+ }
+ subjectName = wolfSSL_X509_get_subject_name(x509);
+ if (subjectName == NULL){
+ WOLFSSL_MSG("invalid x509 data");
+ return SSL_FAILURE;
+ }
+
+ /* Alloc stack struct */
+ node = (WOLF_STACK_OF(WOLFSSL_X509_NAME)*)XMALLOC(
+ sizeof(WOLF_STACK_OF(WOLFSSL_X509_NAME)),
+ NULL, DYNAMIC_TYPE_OPENSSL);
+ if (node == NULL){
+ WOLFSSL_MSG("memory allocation error");
+ return SSL_FAILURE;
+ }
+ XMEMSET(node, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509_NAME)));
+
+ /* Alloc and copy WOLFSSL_X509_NAME */
+ node->data.name = (WOLFSSL_X509_NAME*)XMALLOC(
+ sizeof(WOLFSSL_X509_NAME),
+ NULL, DYNAMIC_TYPE_OPENSSL);
+ if (node->data.name == NULL) {
+ XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
+ WOLFSSL_MSG("memory allocation error");
+ return SSL_FAILURE;
+ }
+ XMEMCPY(node->data.name, subjectName, sizeof(WOLFSSL_X509_NAME));
+ XMEMSET(subjectName, 0, sizeof(WOLFSSL_X509_NAME));
+
+ /* push new node onto head of stack */
+ node->num = (ctx->ca_names == NULL) ? 1 : ctx->ca_names->num + 1;
+ node->next = ctx->ca_names;
+ ctx->ca_names = node;
+ return SSL_SUCCESS;
+ }
+ #endif
+
+ #ifndef NO_WOLFSSL_STUB
int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx)
{
/* TODO:, not needed in goahead */
(void)ctx;
+ WOLFSSL_STUB("SSL_CTX_set_default_verify_paths");
return SSL_NOT_IMPLEMENTED;
}
+ #endif
+
+ #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \
+ && !defined(WC_NO_RNG)
+ static const byte srp_N[] = {
+ 0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6, 0x9C, 0x33, 0xF8,
+ 0x0A, 0xFA, 0x8F, 0xC5, 0xE8, 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF,
+ 0x3C, 0x0B, 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76, 0xD6,
+ 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3, 0x38, 0x3B, 0x48, 0x13,
+ 0xD6, 0x92, 0xC6, 0xE0, 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B,
+ 0xE4, 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1, 0x5D, 0xC7,
+ 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6, 0xCE, 0x8E, 0xF4, 0xAD, 0x69,
+ 0xB1, 0x5D, 0x49, 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85,
+ 0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC, 0x68, 0xED, 0xBC,
+ 0x3C, 0x05, 0x72, 0x6C, 0xC0, 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E,
+ 0xAA, 0x9A, 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B, 0x9F,
+ 0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3
+ };
+ static const byte srp_g[] = {
+ 0x02
+ };
+
+ int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX* ctx, char* username)
+ {
+ int r = 0;
+ SrpSide srp_side = SRP_CLIENT_SIDE;
+ WC_RNG rng;
+ byte salt[SRP_SALT_SIZE];
+
+ WOLFSSL_ENTER("wolfSSL_CTX_set_srp_username");
+ if (ctx == NULL || ctx->srp == NULL || username==NULL)
+ return SSL_FAILURE;
+
+ if (ctx->method->side == WOLFSSL_SERVER_END){
+ srp_side = SRP_SERVER_SIDE;
+ } else if (ctx->method->side == WOLFSSL_CLIENT_END){
+ srp_side = SRP_CLIENT_SIDE;
+ } else {
+ WOLFSSL_MSG("Init CTX failed");
+ return SSL_FAILURE;
+ }
+
+ if (wc_SrpInit(ctx->srp, SRP_TYPE_SHA256, srp_side) < 0){
+ WOLFSSL_MSG("Init CTX failed");
+ XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
+ wolfSSL_CTX_free(ctx);
+ return SSL_FAILURE;
+ }
+ r = wc_SrpSetUsername(ctx->srp, (const byte*)username,
+ (word32)XSTRLEN(username));
+ if (r < 0) {
+ WOLFSSL_MSG("fail to set srp username.");
+ return SSL_FAILURE;
+ }
+
+ /* if wolfSSL_CTX_set_srp_password has already been called, */
+ /* execute wc_SrpSetPassword here */
+ if (ctx->srp_password != NULL){
+ if (wc_InitRng(&rng) < 0){
+ WOLFSSL_MSG("wc_InitRng failed");
+ return SSL_FAILURE;
+ }
+ XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
+ if (wc_RNG_GenerateBlock(&rng, salt,
+ sizeof(salt)/sizeof(salt[0])) < 0){
+ WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
+ wc_FreeRng(&rng);
+ return SSL_FAILURE;
+ }
+ if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]),
+ srp_g, sizeof(srp_g)/sizeof(srp_g[0]),
+ salt, sizeof(salt)/sizeof(salt[0])) < 0){
+ WOLFSSL_MSG("wc_SrpSetParam failed");
+ wc_FreeRng(&rng);
+ return SSL_FAILURE;
+ }
+ r = wc_SrpSetPassword(ctx->srp,
+ (const byte*)ctx->srp_password,
+ (word32)XSTRLEN((char *)ctx->srp_password));
+ if (r < 0) {
+ WOLFSSL_MSG("fail to set srp password.");
+ return SSL_FAILURE;
+ }
+ wc_FreeRng(&rng);
+ XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
+ ctx->srp_password = NULL;
+ }
+
+ return SSL_SUCCESS;
+ }
+
+ int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password)
+ {
+ int r;
+ WC_RNG rng;
+ byte salt[SRP_SALT_SIZE];
+ WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password");
+ if (ctx == NULL || ctx->srp == NULL || password == NULL)
+ return SSL_FAILURE;
+
+ if (ctx->srp->user != NULL){
+ if (wc_InitRng(&rng) < 0){
+ WOLFSSL_MSG("wc_InitRng failed");
+ return SSL_FAILURE;
+ }
+ XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
+ if (wc_RNG_GenerateBlock(&rng, salt,
+ sizeof(salt)/sizeof(salt[0])) < 0){
+ WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
+ wc_FreeRng(&rng);
+ return SSL_FAILURE;
+ }
+ if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]),
+ srp_g, sizeof(srp_g)/sizeof(srp_g[0]),
+ salt, sizeof(salt)/sizeof(salt[0])) < 0){
+ WOLFSSL_MSG("wc_SrpSetParam failed");
+ wc_FreeRng(&rng);
+ return SSL_FAILURE;
+ }
+ r = wc_SrpSetPassword(ctx->srp, (const byte*)password,
+ (word32)XSTRLEN(password));
+ if (r < 0) {
+ WOLFSSL_MSG("wc_SrpSetPassword failed.");
+ wc_FreeRng(&rng);
+ return SSL_FAILURE;
+ }
+ if (ctx->srp_password != NULL){
+ XFREE(ctx->srp_password,NULL,
+ DYNAMIC_TYPE_SRP);
+ ctx->srp_password = NULL;
+ }
+ wc_FreeRng(&rng);
+ } else {
+ /* save password for wolfSSL_set_srp_username */
+ if (ctx->srp_password != NULL)
+ XFREE(ctx->srp_password,ctx->heap, DYNAMIC_TYPE_SRP);
+
+ ctx->srp_password = (byte*)XMALLOC(XSTRLEN(password) + 1, ctx->heap,
+ DYNAMIC_TYPE_SRP);
+ if (ctx->srp_password == NULL){
+ WOLFSSL_MSG("memory allocation error");
+ return SSL_FAILURE;
+ }
+ XMEMCPY(ctx->srp_password, password, XSTRLEN(password) + 1);
+ }
+ return SSL_SUCCESS;
+ }
+ #endif /* WOLFCRYPT_HAVE_SRP && !NO_SHA256 && !WC_NO_RNG */
/* keyblock size in bytes or -1 */
int wolfSSL_get_keyblock_size(WOLFSSL* ssl)
{
if (ssl == NULL)
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
return 2 * (ssl->specs.key_size + ssl->specs.iv_size +
ssl->specs.hash_size);
}
- /* store keys returns SSL_SUCCESS or -1 on error */
+ /* store keys returns WOLFSSL_SUCCESS or -1 on error */
int wolfSSL_get_keys(WOLFSSL* ssl, unsigned char** ms, unsigned int* msLen,
unsigned char** sr, unsigned int* srLen,
unsigned char** cr, unsigned int* crLen)
{
if (ssl == NULL || ssl->arrays == NULL)
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
*ms = ssl->arrays->masterSecret;
*sr = ssl->arrays->serverRandom;
@@ -6912,31 +14473,48 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
*srLen = RAN_LEN;
*crLen = RAN_LEN;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
+#endif /* OPENSSL_EXTRA */
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
void wolfSSL_set_accept_state(WOLFSSL* ssl)
{
- byte haveRSA = 1;
- byte havePSK = 0;
+ WOLFSSL_ENTER("wolfSSL_set_accept_state");
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ #ifdef HAVE_ECC
+ ecc_key key;
+ word32 idx = 0;
- WOLFSSL_ENTER("SSL_set_accept_state");
- ssl->options.side = WOLFSSL_SERVER_END;
- /* reset suites in case user switched */
+ if (ssl->options.haveStaticECC && ssl->buffers.key != NULL) {
+ if (wc_ecc_init(&key) >= 0) {
+ if (wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, &key,
+ ssl->buffers.key->length) != 0) {
+ ssl->options.haveECDSAsig = 0;
+ ssl->options.haveECC = 0;
+ ssl->options.haveStaticECC = 0;
+ }
+ wc_ecc_free(&key);
+ }
+ }
+ #endif
- #ifdef NO_RSA
- haveRSA = 0;
- #endif
- #ifndef NO_PSK
- havePSK = ssl->options.havePSK;
- #endif
- InitSuites(ssl->suites, ssl->version, haveRSA, havePSK,
- ssl->options.haveDH, ssl->options.haveNTRU,
- ssl->options.haveECDSAsig, ssl->options.haveStaticECC,
- ssl->options.side);
+ #ifndef NO_DH
+ if (!ssl->options.haveDH && ssl->ctx->haveDH) {
+ ssl->buffers.serverDH_P = ssl->ctx->serverDH_P;
+ ssl->buffers.serverDH_G = ssl->ctx->serverDH_G;
+ ssl->options.haveDH = 1;
+ }
+ #endif
+ }
+
+ if (InitSSL_Side(ssl, WOLFSSL_SERVER_END) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error initializing server side");
+ }
}
-#endif
+
+#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */
/* return true if connection established */
int wolfSSL_is_init_finished(WOLFSSL* ssl)
@@ -6950,7 +14528,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
return 0;
}
-#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
+#ifdef OPENSSL_EXTRA
+
void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX* ctx,
WOLFSSL_RSA*(*f)(WOLFSSL*, int, int))
{
@@ -6962,19 +14541,55 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
void wolfSSL_set_shutdown(WOLFSSL* ssl, int opt)
{
- (void)ssl;
- (void)opt;
+ WOLFSSL_ENTER("wolfSSL_set_shutdown");
+ if(ssl==NULL) {
+ WOLFSSL_MSG("Shutdown not set. ssl is null");
+ return;
+ }
+
+ ssl->options.sentNotify = (opt&WOLFSSL_SENT_SHUTDOWN) > 0;
+ ssl->options.closeNotify = (opt&WOLFSSL_RECEIVED_SHUTDOWN) > 0;
}
+ long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx)
+ {
+ WOLFSSL_ENTER("wolfSSL_CTX_get_options");
+ WOLFSSL_MSG("wolfSSL options are set through API calls and macros");
+ if(ctx == NULL)
+ return BAD_FUNC_ARG;
+ return ctx->mask;
+ }
+
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+
+ static long wolf_set_options(long old_op, long op);
long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt)
{
- /* goahead calls with 0, do nothing */
WOLFSSL_ENTER("SSL_CTX_set_options");
- (void)ctx;
- return opt;
+
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ ctx->mask = wolf_set_options(ctx->mask, opt);
+
+ return ctx->mask;
}
+#endif
+
+#ifdef OPENSSL_EXTRA
+
+ long wolfSSL_CTX_clear_options(WOLFSSL_CTX* ctx, long opt)
+ {
+ WOLFSSL_ENTER("SSL_CTX_clear_options");
+ if(ctx == NULL)
+ return BAD_FUNC_ARG;
+ ctx->mask &= ~opt;
+ return ctx->mask;
+ }
int wolfSSL_set_rfd(WOLFSSL* ssl, int rfd)
{
@@ -6983,7 +14598,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
ssl->IOCB_ReadCtx = &ssl->rfd;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
@@ -6994,34 +14609,57 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
ssl->IOCB_WriteCtx = &ssl->wfd;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
+#ifndef NO_CERTS
- WOLFSSL_RSA* wolfSSL_RSA_generate_key(int len, unsigned long bits,
- void(*f)(int, int, void*), void* data)
+ WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx)
{
- /* no tmp key needed, actual generation not supported */
- WOLFSSL_ENTER("RSA_generate_key");
- (void)len;
- (void)bits;
- (void)f;
- (void)data;
- return NULL;
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ return &ctx->x509_store;
}
+ void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str)
+ {
+ if (ctx == NULL || str == NULL) {
+ return;
+ }
+
+ /* free cert manager if have one */
+ if (ctx->cm != NULL) {
+ wolfSSL_CertManagerFree(ctx->cm);
+ }
+ ctx->cm = str->cm;
+
+ /* free existing store if it exists */
+ if (ctx->x509_store_pt != NULL) {
+ /* cert manager was free'd a little earlier in this function */
+ ctx->x509_store_pt->cm = NULL;
+ }
+ wolfSSL_X509_STORE_free(ctx->x509_store_pt);
+ ctx->x509_store.cache = str->cache;
+ ctx->x509_store_pt = str; /* take ownership of store and free it
+ with CTX free */
+ }
WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert(
- WOLFSSL_X509_STORE_CTX* ctx)
+ WOLFSSL_X509_STORE_CTX* ctx)
{
- (void)ctx;
- return 0;
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_current_cert");
+ if (ctx)
+ return ctx->current_cert;
+ return NULL;
}
int wolfSSL_X509_STORE_CTX_get_error(WOLFSSL_X509_STORE_CTX* ctx)
{
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error");
if (ctx != NULL)
return ctx->error;
return 0;
@@ -7030,37 +14668,120 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
int wolfSSL_X509_STORE_CTX_get_error_depth(WOLFSSL_X509_STORE_CTX* ctx)
{
- (void)ctx;
- return 0;
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error_depth");
+ if(ctx)
+ return ctx->error_depth;
+ return WOLFSSL_FATAL_ERROR;
}
+ void wolfSSL_X509_STORE_CTX_set_verify_cb(WOLFSSL_X509_STORE_CTX *ctx,
+ WOLFSSL_X509_STORE_CTX_verify_cb verify_cb)
+ {
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_verify_cb");
+ if(ctx == NULL)
+ return;
+ ctx->verify_cb = verify_cb;
+ }
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ void wolfSSL_X509_STORE_set_verify_cb(WOLFSSL_X509_STORE *st,
+ WOLFSSL_X509_STORE_CTX_verify_cb verify_cb)
+ {
+ WOLFSSL_ENTER("WOLFSSL_X509_STORE_set_verify_cb");
+ if (st != NULL) {
+ st->verify_cb = verify_cb;
+ }
+ }
+#endif
+
+
+#endif /* !NO_CERTS */
+
+ WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_md(void)
+ {
+ static WOLFSSL_BIO_METHOD meth;
+
+ WOLFSSL_ENTER("wolfSSL_BIO_f_md");
+ meth.type = WOLFSSL_BIO_MD;
+
+ return &meth;
+ }
+
+ /* return the context and initialize the BIO state */
+ int wolfSSL_BIO_get_md_ctx(WOLFSSL_BIO *bio, WOLFSSL_EVP_MD_CTX **mdcp)
+ {
+ int ret = WOLFSSL_FAILURE;
+
+ if ((bio != NULL) && (mdcp != NULL)) {
+ *mdcp = (WOLFSSL_EVP_MD_CTX*)bio->ptr;
+ ret = WOLFSSL_SUCCESS;
+ }
+
+ return ret;
+ }
WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void)
{
static WOLFSSL_BIO_METHOD meth;
WOLFSSL_ENTER("BIO_f_buffer");
- meth.type = BIO_BUFFER;
+ meth.type = WOLFSSL_BIO_BUFFER;
return &meth;
}
-
+ #ifndef NO_WOLFSSL_STUB
long wolfSSL_BIO_set_write_buffer_size(WOLFSSL_BIO* bio, long size)
{
/* wolfSSL has internal buffer, compatibility only */
WOLFSSL_ENTER("BIO_set_write_buffer_size");
+ WOLFSSL_STUB("BIO_set_write_buffer_size");
(void)bio;
return size;
}
+ #endif
+
+ WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_bio(void)
+ {
+ static WOLFSSL_BIO_METHOD bio_meth;
+
+ WOLFSSL_ENTER("wolfSSL_BIO_s_bio");
+ bio_meth.type = WOLFSSL_BIO_BIO;
+
+ return &bio_meth;
+ }
+
+
+#ifndef NO_FILESYSTEM
+ WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void)
+ {
+ static WOLFSSL_BIO_METHOD file_meth;
+
+ WOLFSSL_ENTER("wolfSSL_BIO_s_file");
+ file_meth.type = WOLFSSL_BIO_FILE;
+
+ return &file_meth;
+ }
+#endif
WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void)
{
static WOLFSSL_BIO_METHOD meth;
- WOLFSSL_ENTER("BIO_f_ssl");
- meth.type = BIO_SSL;
+ WOLFSSL_ENTER("wolfSSL_BIO_f_ssl");
+ meth.type = WOLFSSL_BIO_SSL;
+
+ return &meth;
+ }
+
+
+ WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void)
+ {
+ static WOLFSSL_BIO_METHOD meth;
+
+ WOLFSSL_ENTER("wolfSSL_BIO_s_socket");
+ meth.type = WOLFSSL_BIO_SOCKET;
return &meth;
}
@@ -7068,20 +14789,13 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
WOLFSSL_BIO* wolfSSL_BIO_new_socket(int sfd, int closeF)
{
- WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0,
- DYNAMIC_TYPE_OPENSSL);
+ WOLFSSL_BIO* bio = wolfSSL_BIO_new(wolfSSL_BIO_s_socket());
WOLFSSL_ENTER("BIO_new_socket");
if (bio) {
- bio->type = BIO_SOCKET;
- bio->close = (byte)closeF;
- bio->eof = 0;
- bio->ssl = 0;
- bio->fd = sfd;
- bio->prev = 0;
- bio->next = 0;
- bio->mem = NULL;
- bio->memLen = 0;
+ bio->type = WOLFSSL_BIO_SOCKET;
+ bio->shutdown = (byte)closeF;
+ bio->num = sfd;
}
return bio;
}
@@ -7090,7 +14804,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
int wolfSSL_BIO_eof(WOLFSSL_BIO* b)
{
WOLFSSL_ENTER("BIO_eof");
- if (b->eof)
+ if ((b != NULL) && (b->eof))
return 1;
return 0;
@@ -7099,94 +14813,200 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
long wolfSSL_BIO_set_ssl(WOLFSSL_BIO* b, WOLFSSL* ssl, int closeF)
{
- WOLFSSL_ENTER("BIO_set_ssl");
- b->ssl = ssl;
- b->close = (byte)closeF;
+ WOLFSSL_ENTER("wolfSSL_BIO_set_ssl");
+
+ if (b != NULL) {
+ b->ptr = ssl;
+ b->shutdown = (byte)closeF;
/* add to ssl for bio free if SSL_free called before/instead of free_all? */
+ }
return 0;
}
+#ifndef NO_FILESYSTEM
+ long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int closeF)
+ {
+ WOLFSSL_ENTER("wolfSSL_BIO_set_fd");
- WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD* method)
+ if (b != NULL) {
+ b->num = fd;
+ b->shutdown = (byte)closeF;
+ }
+
+ return WOLFSSL_SUCCESS;
+ }
+#endif
+
+ /* Sets the close flag */
+ int wolfSSL_BIO_set_close(WOLFSSL_BIO *b, long flag)
{
- WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0,
- DYNAMIC_TYPE_OPENSSL);
- WOLFSSL_ENTER("BIO_new");
- if (bio) {
- bio->type = method->type;
- bio->close = 0;
- bio->eof = 0;
- bio->ssl = NULL;
- bio->mem = NULL;
- bio->memLen = 0;
- bio->fd = 0;
- bio->prev = NULL;
- bio->next = NULL;
+ WOLFSSL_ENTER("wolfSSL_BIO_set_close");
+ if (b != NULL) {
+ b->shutdown = (byte)flag;
}
- return bio;
+
+ return WOLFSSL_SUCCESS;
}
- int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, const byte** p)
+ WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD* method)
{
- if (bio == NULL || p == NULL)
- return SSL_FATAL_ERROR;
+ WOLFSSL_BIO* bio;
- *p = bio->mem;
+ WOLFSSL_ENTER("wolfSSL_BIO_new");
+ if (method == NULL) {
+ WOLFSSL_MSG("Bad method pointer passed in");
+ return NULL;
+ }
- return bio->memLen;
- }
+ bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0,
+ DYNAMIC_TYPE_OPENSSL);
+ if (bio) {
+ XMEMSET(bio, 0, sizeof(WOLFSSL_BIO));
+ bio->type = (byte)method->type;
+ bio->method = method;
+ bio->shutdown = BIO_CLOSE; /* default to close things */
+ bio->init = 1;
+ if (method->type != WOLFSSL_BIO_FILE &&
+ method->type != WOLFSSL_BIO_SOCKET &&
+ method->type != WOLFSSL_BIO_MD) {
+ bio->mem_buf =(WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM),
+ 0, DYNAMIC_TYPE_OPENSSL);
+ if (bio->mem_buf == NULL) {
+ WOLFSSL_MSG("Memory error");
+ wolfSSL_BIO_free(bio);
+ return NULL;
+ }
+ bio->mem_buf->data = (char*)bio->ptr;
+ }
+
+ if (method->type == WOLFSSL_BIO_MD) {
+ bio->ptr = wolfSSL_EVP_MD_CTX_new();
+ if (bio->ptr == NULL) {
+ WOLFSSL_MSG("Memory error");
+ wolfSSL_BIO_free(bio);
+ return NULL;
+ }
+ }
+ /* check if is custom method */
+ if (method->createCb) {
+ method->createCb(bio);
+ }
+ }
+ return bio;
+ }
- WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len)
+ WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(const void* buf, int len)
{
WOLFSSL_BIO* bio = NULL;
- if (buf == NULL)
+
+ if (buf == NULL || len < 0) {
return bio;
+ }
bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
- if (bio == NULL)
+ if (bio == NULL) {
return bio;
+ }
- bio->memLen = len;
- bio->mem = (byte*)XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL);
- if (bio->mem == NULL) {
- XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL);
+ bio->num = bio->wrSz = len;
+ bio->ptr = (byte*)XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL);
+ if (bio->ptr == NULL) {
+ wolfSSL_BIO_free(bio);
return NULL;
}
+ if (bio->mem_buf != NULL) {
+ bio->mem_buf->data = (char*)bio->ptr;
+ bio->mem_buf->length = bio->num;
+ }
- XMEMCPY(bio->mem, buf, len);
+ XMEMCPY(bio->ptr, buf, len);
return bio;
}
-
-#ifdef USE_WINDOWS_API
- #define CloseSocket(s) closesocket(s)
-#elif defined(WOLFSSL_MDK_ARM)
- #define CloseSocket(s) closesocket(s)
- extern int closesocket(int) ;
-#else
- #define CloseSocket(s) close(s)
-#endif
-
+ /*
+ * Note : If the flag BIO_NOCLOSE is set then freeing memory buffers is up
+ * to the application.
+ * Returns 1 on success, 0 on failure
+ */
int wolfSSL_BIO_free(WOLFSSL_BIO* bio)
{
+ int ret;
+
/* unchain?, doesn't matter in goahead since from free all */
- WOLFSSL_ENTER("BIO_free");
+ WOLFSSL_ENTER("wolfSSL_BIO_free");
if (bio) {
- if (bio->close) {
- if (bio->ssl)
- wolfSSL_free(bio->ssl);
- if (bio->fd)
- CloseSocket(bio->fd);
- }
- if (bio->mem)
- XFREE(bio->mem, 0, DYNAMIC_TYPE_OPENSSL);
+
+ if (bio->infoCb) {
+ /* info callback is called before free */
+ ret = (int)bio->infoCb(bio, WOLFSSL_BIO_CB_FREE, NULL, 0, 0, 1);
+ if (ret <= 0) {
+ return ret;
+ }
+ }
+
+ /* call custom set free callback */
+ if (bio->method && bio->method->freeCb) {
+ bio->method->freeCb(bio);
+ }
+
+ /* remove from pair by setting the paired bios pair to NULL */
+ if (bio->pair != NULL) {
+ bio->pair->pair = NULL;
+ }
+
+ if (bio->shutdown) {
+ if (bio->type == WOLFSSL_BIO_SSL && bio->ptr)
+ wolfSSL_free((WOLFSSL*)bio->ptr);
+ #ifdef CloseSocket
+ if (bio->type == WOLFSSL_BIO_SOCKET && bio->num)
+ CloseSocket(bio->num);
+ #endif
+ }
+
+ #ifndef NO_FILESYSTEM
+ if (bio->type == WOLFSSL_BIO_FILE && bio->shutdown == BIO_CLOSE) {
+ if (bio->ptr) {
+ XFCLOSE((XFILE)bio->ptr);
+ }
+ }
+ #endif
+
+ if (bio->shutdown != BIO_NOCLOSE) {
+ if (bio->type == WOLFSSL_BIO_MEMORY && bio->ptr != NULL) {
+ if (bio->mem_buf != NULL) {
+ if (bio->mem_buf->data != (char*)bio->ptr) {
+ XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ bio->ptr = NULL;
+ }
+ }
+ else {
+ XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ bio->ptr = NULL;
+ }
+ }
+ if (bio->mem_buf != NULL) {
+ wolfSSL_BUF_MEM_free(bio->mem_buf);
+ bio->mem_buf = NULL;
+ }
+ }
+
+ if (bio->type == WOLFSSL_BIO_MD) {
+ wolfSSL_EVP_MD_CTX_free((WOLFSSL_EVP_MD_CTX*)bio->ptr);
+ }
+
XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL);
}
- return 0;
+ return 1;
+ }
+
+ /* like BIO_free, but no return value */
+ void wolfSSL_BIO_vfree(WOLFSSL_BIO* bio)
+ {
+ wolfSSL_BIO_free(bio);
}
@@ -7202,238 +15022,357 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
}
- int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len)
+ WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO* top, WOLFSSL_BIO* append)
{
- int ret;
- WOLFSSL* ssl = 0;
- WOLFSSL_BIO* front = bio;
-
- WOLFSSL_ENTER("BIO_read");
- /* already got eof, again is error */
- if (front->eof)
- return SSL_FATAL_ERROR;
-
- while(bio && ((ssl = bio->ssl) == 0) )
- bio = bio->next;
-
- if (ssl == 0) return BAD_FUNC_ARG;
+ WOLFSSL_ENTER("BIO_push");
+ top->next = append;
+ append->prev = top;
- ret = wolfSSL_read(ssl, buf, len);
- if (ret == 0)
- front->eof = 1;
- else if (ret < 0) {
- int err = wolfSSL_get_error(ssl, 0);
- if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) )
- front->eof = 1;
- }
- return ret;
+ return top;
}
+#endif /* OPENSSL_EXTRA */
+#ifdef WOLFSSL_ENCRYPTED_KEYS
- int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len)
+ void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX* ctx,
+ void* userdata)
{
- int ret;
- WOLFSSL* ssl = 0;
- WOLFSSL_BIO* front = bio;
-
- WOLFSSL_ENTER("BIO_write");
- /* already got eof, again is error */
- if (front->eof)
- return SSL_FATAL_ERROR;
+ WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb_userdata");
+ if (ctx)
+ ctx->passwd_userdata = userdata;
+ }
- while(bio && ((ssl = bio->ssl) == 0) )
- bio = bio->next;
- if (ssl == 0) return BAD_FUNC_ARG;
+ void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx,pem_password_cb* cb)
+ {
+ WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb");
+ if (ctx)
+ ctx->passwd_cb = cb;
+ }
- ret = wolfSSL_write(ssl, data, len);
- if (ret == 0)
- front->eof = 1;
- else if (ret < 0) {
- int err = wolfSSL_get_error(ssl, 0);
- if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) )
- front->eof = 1;
+ pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx)
+ {
+ if (ctx == NULL || ctx->passwd_cb == NULL) {
+ return NULL;
}
- return ret;
+ return ctx->passwd_cb;
}
- WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO* top, WOLFSSL_BIO* append)
+ void* wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx)
{
- WOLFSSL_ENTER("BIO_push");
- top->next = append;
- append->prev = top;
+ if (ctx == NULL) {
+ return NULL;
+ }
- return top;
+ return ctx->passwd_userdata;
}
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
- int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+ int wolfSSL_num_locks(void)
{
- /* for wolfSSL no flushing needed */
- WOLFSSL_ENTER("BIO_flush");
- (void)bio;
- return 1;
+ return 0;
}
+ void wolfSSL_set_locking_callback(void (*f)(int, int, const char*, int))
+ {
+ WOLFSSL_ENTER("wolfSSL_set_locking_callback");
-#endif /* OPENSSL_EXTRA || GOAHEAD_WS */
+ if (wc_SetMutexCb(f) != 0) {
+ WOLFSSL_MSG("Error when setting mutex call back");
+ }
+ }
-#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+ typedef unsigned long (idCb)(void);
+ static idCb* inner_idCb = NULL;
- void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX* ctx,
- void* userdata)
+ unsigned long wolfSSL_thread_id(void)
{
- WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb_userdata");
- ctx->userdata = userdata;
+ if (inner_idCb != NULL) {
+ return inner_idCb();
+ }
+ else {
+ return 0;
+ }
}
- void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx, pem_password_cb cb)
+ void wolfSSL_set_id_callback(unsigned long (*f)(void))
{
- WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb");
- ctx->passwd_cb = cb;
+ inner_idCb = f;
}
- int wolfSSL_num_locks(void)
+ unsigned long wolfSSL_ERR_get_error(void)
{
- return 0;
+ WOLFSSL_ENTER("wolfSSL_ERR_get_error");
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+ {
+ unsigned long ret = wolfSSL_ERR_peek_error_line_data(NULL, NULL,
+ NULL, NULL);
+ wc_RemoveErrorNode(-1);
+ return ret;
+ }
+#elif (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE))
+ {
+ int ret = wc_PullErrorNode(NULL, NULL, NULL);
+
+ if (ret < 0) {
+ if (ret == BAD_STATE_E) return 0; /* no errors in queue */
+ WOLFSSL_MSG("Error with pulling error node!");
+ WOLFSSL_LEAVE("wolfSSL_ERR_get_error", ret);
+ ret = 0 - ret; /* return absolute value of error */
+
+ /* panic and try to clear out nodes */
+ wc_ClearErrorNodes();
+ }
+
+ return (unsigned long)ret;
+ }
+#else
+ return (unsigned long)(0 - NOT_COMPILED_IN);
+#endif
}
- void wolfSSL_set_locking_callback(void (*f)(int, int, const char*, int))
+#if (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE))
+ /* print out and clear all errors */
+ void wolfSSL_ERR_print_errors(WOLFSSL_BIO* bio)
{
- (void)f;
+ const char* file = NULL;
+ const char* reason = NULL;
+ int ret;
+ int line = 0;
+ char buf[WOLFSSL_MAX_ERROR_SZ * 2];
+
+ WOLFSSL_ENTER("wolfSSL_ERR_print_errors");
+
+ if (bio == NULL) {
+ WOLFSSL_MSG("BIO passed in was null");
+ return;
+ }
+
+ do {
+ ret = wc_PeekErrorNode(0, &file, &reason, &line);
+ if (ret >= 0) {
+ const char* r = wolfSSL_ERR_reason_error_string(0 - ret);
+ XSNPRINTF(buf, sizeof(buf), "error:%d:wolfSSL library:%s:%s:%d\n",
+ ret, r, file, line);
+ wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf));
+ wc_RemoveErrorNode(0);
+ }
+ } while (ret >= 0);
}
+#endif /* OPENSSL_EXTRA || DEBUG_WOLFSSL_VERBOSE */
- void wolfSSL_set_id_callback(unsigned long (*f)(void))
- {
- (void)f;
+#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
+
+#ifdef OPENSSL_EXTRA
+
+#if !defined(NO_WOLFSSL_SERVER)
+size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out,
+ size_t outSz)
+{
+ size_t size;
+
+ /* return max size of buffer */
+ if (outSz == 0) {
+ return RAN_LEN;
}
- unsigned long wolfSSL_ERR_get_error(void)
- {
- /* TODO: */
+ if (ssl == NULL || out == NULL) {
return 0;
}
-#ifndef NO_MD5
+ if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) {
+ WOLFSSL_MSG("Arrays struct not saved after handshake");
+ return 0;
+ }
- int wolfSSL_EVP_BytesToKey(const WOLFSSL_EVP_CIPHER* type,
- const WOLFSSL_EVP_MD* md, const byte* salt,
- const byte* data, int sz, int count, byte* key, byte* iv)
- {
- int keyLen = 0;
- int ivLen = 0;
- int j;
- int keyLeft;
- int ivLeft;
- int keyOutput = 0;
- byte digest[MD5_DIGEST_SIZE];
- #ifdef WOLFSSL_SMALL_STACK
- Md5* md5 = NULL;
- #else
- Md5 md5[1];
- #endif
+ if (outSz > RAN_LEN) {
+ size = RAN_LEN;
+ }
+ else {
+ size = outSz;
+ }
- #ifdef WOLFSSL_SMALL_STACK
- md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (md5 == NULL)
- return 0;
- #endif
+ XMEMCPY(out, ssl->arrays->serverRandom, size);
+ return size;
+}
- WOLFSSL_ENTER("EVP_BytesToKey");
- wc_InitMd5(md5);
- /* only support MD5 for now */
- if (XSTRNCMP(md, "MD5", 3) != 0) return 0;
+/* Used to get the peer ephemeral public key sent during the connection
+ * NOTE: currently wolfSSL_KeepHandshakeResources(WOLFSSL* ssl) must be called
+ * before the ephemeral key is stored.
+ * return WOLFSSL_SUCCESS on success */
+int wolfSSL_get_server_tmp_key(const WOLFSSL* ssl, WOLFSSL_EVP_PKEY** pkey)
+{
+ WOLFSSL_EVP_PKEY* ret = NULL;
- /* only support CBC DES and AES for now */
- if (XSTRNCMP(type, "DES-CBC", 7) == 0) {
- keyLen = DES_KEY_SIZE;
- ivLen = DES_IV_SIZE;
- }
- else if (XSTRNCMP(type, "DES-EDE3-CBC", 12) == 0) {
- keyLen = DES3_KEY_SIZE;
- ivLen = DES_IV_SIZE;
- }
- else if (XSTRNCMP(type, "AES-128-CBC", 11) == 0) {
- keyLen = AES_128_KEY_SIZE;
- ivLen = AES_IV_SIZE;
+ WOLFSSL_ENTER("wolfSSL_get_server_tmp_key");
+
+ if (ssl == NULL || pkey == NULL) {
+ WOLFSSL_MSG("Bad argument passed in");
+ return WOLFSSL_FAILURE;
+ }
+
+#ifdef HAVE_ECC
+ if (ssl->peerEccKey != NULL) {
+ unsigned char* der;
+ const unsigned char* pt;
+ unsigned int derSz = 0;
+ int sz;
+
+ if (wc_ecc_export_x963(ssl->peerEccKey, NULL, &derSz) !=
+ LENGTH_ONLY_E) {
+ WOLFSSL_MSG("get ecc der size failed");
+ return WOLFSSL_FAILURE;
}
- else if (XSTRNCMP(type, "AES-192-CBC", 11) == 0) {
- keyLen = AES_192_KEY_SIZE;
- ivLen = AES_IV_SIZE;
+
+ derSz += MAX_SEQ_SZ + (2 * MAX_ALGO_SZ) + MAX_SEQ_SZ + TRAILING_ZERO;
+ der = (unsigned char*)XMALLOC(derSz, ssl->heap, DYNAMIC_TYPE_KEY);
+ if (der == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return WOLFSSL_FAILURE;
}
- else if (XSTRNCMP(type, "AES-256-CBC", 11) == 0) {
- keyLen = AES_256_KEY_SIZE;
- ivLen = AES_IV_SIZE;
+
+ if ((sz = wc_EccPublicKeyToDer(ssl->peerEccKey, der, derSz, 1)) <= 0) {
+ WOLFSSL_MSG("get ecc der failed");
+ XFREE(der, ssl->heap, DYNAMIC_TYPE_KEY);
+ return WOLFSSL_FAILURE;
}
- else {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ pt = der; /* in case pointer gets advanced */
+ ret = wolfSSL_d2i_PUBKEY(NULL, &pt, sz);
+ XFREE(der, ssl->heap, DYNAMIC_TYPE_KEY);
+ }
+#endif
+
+ *pkey = ret;
+ if (ret == NULL)
+ return WOLFSSL_FAILURE;
+ else
+ return WOLFSSL_SUCCESS;
+}
+
+#endif /* !NO_WOLFSSL_SERVER */
+
+int wolfSSL_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version");
+
+ if (ctx == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ switch (version) {
+#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+ case SSL3_VERSION:
+ ctx->minDowngrade = SSLv3_MINOR;
+ break;
+#endif
+#ifndef NO_TLS
+ #ifndef NO_OLD_TLS
+ #ifdef WOLFSSL_ALLOW_TLSV10
+ case TLS1_VERSION:
+ ctx->minDowngrade = TLSv1_MINOR;
+ break;
#endif
- return 0;
- }
+ case TLS1_1_VERSION:
+ ctx->minDowngrade = TLSv1_1_MINOR;
+ break;
+ #endif
+ #ifndef WOLFSSL_NO_TLS12
+ case TLS1_2_VERSION:
+ ctx->minDowngrade = TLSv1_2_MINOR;
+ break;
+ #endif
+ #ifdef WOLFSSL_TLS13
+ case TLS1_3_VERSION:
+ ctx->minDowngrade = TLSv1_3_MINOR;
+ break;
+ #endif
+#endif
+#ifdef WOLFSSL_DTLS
+ #ifndef NO_OLD_TLS
+ case DTLS1_VERSION:
+ ctx->minDowngrade = DTLS_MINOR;
+ break;
+ #endif
+ case DTLS1_2_VERSION:
+ ctx->minDowngrade = DTLSv1_2_MINOR;
+ break;
+#endif
+ default:
+ return BAD_FUNC_ARG;
+ }
- keyLeft = keyLen;
- ivLeft = ivLen;
+ return WOLFSSL_SUCCESS;
+}
- while (keyOutput < (keyLen + ivLen)) {
- int digestLeft = MD5_DIGEST_SIZE;
- /* D_(i - 1) */
- if (keyOutput) /* first time D_0 is empty */
- wc_Md5Update(md5, digest, MD5_DIGEST_SIZE);
- /* data */
- wc_Md5Update(md5, data, sz);
- /* salt */
- if (salt)
- wc_Md5Update(md5, salt, EVP_SALT_SIZE);
- wc_Md5Final(md5, digest);
- /* count */
- for (j = 1; j < count; j++) {
- wc_Md5Update(md5, digest, MD5_DIGEST_SIZE);
- wc_Md5Final(md5, digest);
- }
+int wolfSSL_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int ver)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_max_proto_version");
- if (keyLeft) {
- int store = min(keyLeft, MD5_DIGEST_SIZE);
- XMEMCPY(&key[keyLen - keyLeft], digest, store);
+ /* supported only at compile-time only */
+ (void)ctx;
+ (void)ver;
+ return WOLFSSL_SUCCESS;
+}
- keyOutput += store;
- keyLeft -= store;
- digestLeft -= store;
- }
- if (ivLeft && digestLeft) {
- int store = min(ivLeft, digestLeft);
- XMEMCPY(&iv[ivLen - ivLeft], &digest[MD5_DIGEST_SIZE -
- digestLeft], store);
- keyOutput += store;
- ivLeft -= store;
- }
- }
+#if !defined(NO_WOLFSSL_CLIENT)
+/* Return the amount of random bytes copied over or error case.
+ * ssl : ssl struct after handshake
+ * out : buffer to hold random bytes
+ * outSz : either 0 (return max buffer sz) or size of out buffer
+ *
+ * NOTE: wolfSSL_KeepArrays(ssl) must be called to retain handshake information.
+ */
+size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out,
+ size_t outSz)
+{
+ size_t size;
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
+ /* return max size of buffer */
+ if (outSz == 0) {
+ return RAN_LEN;
+ }
- return keyOutput == (keyLen + ivLen) ? keyOutput : 0;
+ if (ssl == NULL || out == NULL) {
+ return 0;
}
-#endif /* NO_MD5 */
+ if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) {
+ WOLFSSL_MSG("Arrays struct not saved after handshake");
+ return 0;
+ }
-#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
+ if (outSz > RAN_LEN) {
+ size = RAN_LEN;
+ }
+ else {
+ size = outSz;
+ }
+ XMEMCPY(out, ssl->arrays->clientRandom, size);
+ return size;
+}
+#endif /* !NO_WOLFSSL_CLIENT */
-#ifdef OPENSSL_EXTRA
unsigned long wolfSSLeay(void)
{
return SSLEAY_VERSION_NUMBER;
}
+ unsigned long wolfSSL_OpenSSL_version_num(void)
+ {
+ return OPENSSL_VERSION_NUMBER;
+ }
const char* wolfSSLeay_version(int type)
{
@@ -7444,699 +15383,646 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
#ifndef NO_MD5
- void wolfSSL_MD5_Init(WOLFSSL_MD5_CTX* md5)
+ int wolfSSL_MD5_Init(WOLFSSL_MD5_CTX* md5)
{
- typedef char md5_test[sizeof(MD5_CTX) >= sizeof(Md5) ? 1 : -1];
+ int ret;
+ typedef char md5_test[sizeof(MD5_CTX) >= sizeof(wc_Md5) ? 1 : -1];
(void)sizeof(md5_test);
WOLFSSL_ENTER("MD5_Init");
- wc_InitMd5((Md5*)md5);
+ ret = wc_InitMd5((wc_Md5*)md5);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- void wolfSSL_MD5_Update(WOLFSSL_MD5_CTX* md5, const void* input,
+ int wolfSSL_MD5_Update(WOLFSSL_MD5_CTX* md5, const void* input,
unsigned long sz)
{
+ int ret;
+
WOLFSSL_ENTER("wolfSSL_MD5_Update");
- wc_Md5Update((Md5*)md5, (const byte*)input, (word32)sz);
+ ret = wc_Md5Update((wc_Md5*)md5, (const byte*)input, (word32)sz);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- void wolfSSL_MD5_Final(byte* input, WOLFSSL_MD5_CTX* md5)
+ int wolfSSL_MD5_Final(byte* input, WOLFSSL_MD5_CTX* md5)
{
+ int ret;
+
WOLFSSL_ENTER("MD5_Final");
- wc_Md5Final((Md5*)md5, input);
+ ret = wc_Md5Final((wc_Md5*)md5, input);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
-#endif /* NO_MD5 */
+#endif /* !NO_MD5 */
#ifndef NO_SHA
- void wolfSSL_SHA_Init(WOLFSSL_SHA_CTX* sha)
+ int wolfSSL_SHA_Init(WOLFSSL_SHA_CTX* sha)
{
- typedef char sha_test[sizeof(SHA_CTX) >= sizeof(Sha) ? 1 : -1];
+ int ret;
+
+ typedef char sha_test[sizeof(SHA_CTX) >= sizeof(wc_Sha) ? 1 : -1];
(void)sizeof(sha_test);
WOLFSSL_ENTER("SHA_Init");
- wc_InitSha((Sha*)sha); /* OpenSSL compat, no ret */
+ ret = wc_InitSha((wc_Sha*)sha);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- void wolfSSL_SHA_Update(WOLFSSL_SHA_CTX* sha, const void* input,
+ int wolfSSL_SHA_Update(WOLFSSL_SHA_CTX* sha, const void* input,
unsigned long sz)
{
+ int ret;
+
WOLFSSL_ENTER("SHA_Update");
- wc_ShaUpdate((Sha*)sha, (const byte*)input, (word32)sz);
+ ret = wc_ShaUpdate((wc_Sha*)sha, (const byte*)input, (word32)sz);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- void wolfSSL_SHA_Final(byte* input, WOLFSSL_SHA_CTX* sha)
+ int wolfSSL_SHA_Final(byte* input, WOLFSSL_SHA_CTX* sha)
{
+ int ret;
+
WOLFSSL_ENTER("SHA_Final");
- wc_ShaFinal((Sha*)sha, input);
+ ret = wc_ShaFinal((wc_Sha*)sha, input);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- void wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX* sha)
+ int wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX* sha)
{
WOLFSSL_ENTER("SHA1_Init");
- SHA_Init(sha);
+ return SHA_Init(sha);
}
- void wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX* sha, const void* input,
+ int wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX* sha, const void* input,
unsigned long sz)
{
WOLFSSL_ENTER("SHA1_Update");
- SHA_Update(sha, input, sz);
+ return SHA_Update(sha, input, sz);
}
- void wolfSSL_SHA1_Final(byte* input, WOLFSSL_SHA_CTX* sha)
+ int wolfSSL_SHA1_Final(byte* input, WOLFSSL_SHA_CTX* sha)
{
WOLFSSL_ENTER("SHA1_Final");
- SHA_Final(input, sha);
+ return SHA_Final(input, sha);
}
-#endif /* NO_SHA */
+#endif /* !NO_SHA */
+#ifdef WOLFSSL_SHA224
- void wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256)
+ int wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX* sha)
{
- typedef char sha_test[sizeof(SHA256_CTX) >= sizeof(Sha256) ? 1 : -1];
+ int ret;
+
+ typedef char sha_test[sizeof(SHA224_CTX) >= sizeof(wc_Sha224) ? 1 : -1];
(void)sizeof(sha_test);
- WOLFSSL_ENTER("SHA256_Init");
- wc_InitSha256((Sha256*)sha256); /* OpenSSL compat, no error */
+ WOLFSSL_ENTER("SHA224_Init");
+ ret = wc_InitSha224((wc_Sha224*)sha);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- void wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX* sha, const void* input,
- unsigned long sz)
+ int wolfSSL_SHA224_Update(WOLFSSL_SHA224_CTX* sha, const void* input,
+ unsigned long sz)
{
- WOLFSSL_ENTER("SHA256_Update");
- wc_Sha256Update((Sha256*)sha, (const byte*)input, (word32)sz);
- /* OpenSSL compat, no error */
+ int ret;
+
+ WOLFSSL_ENTER("SHA224_Update");
+ ret = wc_Sha224Update((wc_Sha224*)sha, (const byte*)input, (word32)sz);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- void wolfSSL_SHA256_Final(byte* input, WOLFSSL_SHA256_CTX* sha)
+ int wolfSSL_SHA224_Final(byte* input, WOLFSSL_SHA224_CTX* sha)
{
- WOLFSSL_ENTER("SHA256_Final");
- wc_Sha256Final((Sha256*)sha, input);
- /* OpenSSL compat, no error */
+ int ret;
+
+ WOLFSSL_ENTER("SHA224_Final");
+ ret = wc_Sha224Final((wc_Sha224*)sha, input);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
+#endif /* WOLFSSL_SHA224 */
- #ifdef WOLFSSL_SHA384
- void wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX* sha)
+ int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256)
{
- typedef char sha_test[sizeof(SHA384_CTX) >= sizeof(Sha384) ? 1 : -1];
+ int ret;
+
+ typedef char sha_test[sizeof(SHA256_CTX) >= sizeof(wc_Sha256) ? 1 : -1];
(void)sizeof(sha_test);
- WOLFSSL_ENTER("SHA384_Init");
- wc_InitSha384((Sha384*)sha); /* OpenSSL compat, no error */
+ WOLFSSL_ENTER("SHA256_Init");
+ ret = wc_InitSha256((wc_Sha256*)sha256);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- void wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX* sha, const void* input,
- unsigned long sz)
+ int wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX* sha, const void* input,
+ unsigned long sz)
{
- WOLFSSL_ENTER("SHA384_Update");
- wc_Sha384Update((Sha384*)sha, (const byte*)input, (word32)sz);
- /* OpenSSL compat, no error */
+ int ret;
+
+ WOLFSSL_ENTER("SHA256_Update");
+ ret = wc_Sha256Update((wc_Sha256*)sha, (const byte*)input, (word32)sz);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- void wolfSSL_SHA384_Final(byte* input, WOLFSSL_SHA384_CTX* sha)
+ int wolfSSL_SHA256_Final(byte* input, WOLFSSL_SHA256_CTX* sha)
{
- WOLFSSL_ENTER("SHA384_Final");
- wc_Sha384Final((Sha384*)sha, input);
- /* OpenSSL compat, no error */
- }
+ int ret;
- #endif /* WOLFSSL_SHA384 */
+ WOLFSSL_ENTER("SHA256_Final");
+ ret = wc_Sha256Final((wc_Sha256*)sha, input);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
+ }
- #ifdef WOLFSSL_SHA512
+#ifdef WOLFSSL_SHA384
- void wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX* sha)
+ int wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX* sha)
{
- typedef char sha_test[sizeof(SHA512_CTX) >= sizeof(Sha512) ? 1 : -1];
+ int ret;
+
+ typedef char sha_test[sizeof(SHA384_CTX) >= sizeof(wc_Sha384) ? 1 : -1];
(void)sizeof(sha_test);
- WOLFSSL_ENTER("SHA512_Init");
- wc_InitSha512((Sha512*)sha); /* OpenSSL compat, no error */
+ WOLFSSL_ENTER("SHA384_Init");
+ ret = wc_InitSha384((wc_Sha384*)sha);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- void wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX* sha, const void* input,
+ int wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX* sha, const void* input,
unsigned long sz)
{
- WOLFSSL_ENTER("SHA512_Update");
- wc_Sha512Update((Sha512*)sha, (const byte*)input, (word32)sz);
- /* OpenSSL compat, no error */
+ int ret;
+
+ WOLFSSL_ENTER("SHA384_Update");
+ ret = wc_Sha384Update((wc_Sha384*)sha, (const byte*)input, (word32)sz);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- void wolfSSL_SHA512_Final(byte* input, WOLFSSL_SHA512_CTX* sha)
+ int wolfSSL_SHA384_Final(byte* input, WOLFSSL_SHA384_CTX* sha)
{
- WOLFSSL_ENTER("SHA512_Final");
- wc_Sha512Final((Sha512*)sha, input);
- /* OpenSSL compat, no error */
+ int ret;
+
+ WOLFSSL_ENTER("SHA384_Final");
+ ret = wc_Sha384Final((wc_Sha384*)sha, input);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- #endif /* WOLFSSL_SHA512 */
+#endif /* WOLFSSL_SHA384 */
- #ifndef NO_MD5
+#ifdef WOLFSSL_SHA512
- const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void)
+ int wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX* sha)
{
- static const char* type = "MD5";
- WOLFSSL_ENTER("EVP_md5");
- return type;
- }
+ int ret;
- #endif /* NO_MD5 */
+ typedef char sha_test[sizeof(SHA512_CTX) >= sizeof(wc_Sha512) ? 1 : -1];
+ (void)sizeof(sha_test);
+ WOLFSSL_ENTER("SHA512_Init");
+ ret = wc_InitSha512((wc_Sha512*)sha);
-#ifndef NO_SHA
- const WOLFSSL_EVP_MD* wolfSSL_EVP_sha1(void)
- {
- static const char* type = "SHA";
- WOLFSSL_ENTER("EVP_sha1");
- return type;
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
-#endif /* NO_SHA */
- const WOLFSSL_EVP_MD* wolfSSL_EVP_sha256(void)
+ int wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX* sha, const void* input,
+ unsigned long sz)
{
- static const char* type = "SHA256";
- WOLFSSL_ENTER("EVP_sha256");
- return type;
+ int ret;
+
+ WOLFSSL_ENTER("SHA512_Update");
+ ret = wc_Sha512Update((wc_Sha512*)sha, (const byte*)input, (word32)sz);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- #ifdef WOLFSSL_SHA384
- const WOLFSSL_EVP_MD* wolfSSL_EVP_sha384(void)
+ int wolfSSL_SHA512_Final(byte* input, WOLFSSL_SHA512_CTX* sha)
{
- static const char* type = "SHA384";
- WOLFSSL_ENTER("EVP_sha384");
- return type;
- }
+ int ret;
- #endif /* WOLFSSL_SHA384 */
+ WOLFSSL_ENTER("SHA512_Final");
+ ret = wc_Sha512Final((wc_Sha512*)sha, input);
- #ifdef WOLFSSL_SHA512
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
- const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512(void)
- {
- static const char* type = "SHA512";
- WOLFSSL_ENTER("EVP_sha512");
- return type;
+ return 0;
}
- #endif /* WOLFSSL_SHA512 */
+#endif /* WOLFSSL_SHA512 */
+#ifdef WOLFSSL_SHA3
+#ifndef WOLFSSL_NOSHA3_224
- void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx)
+ int wolfSSL_SHA3_224_Init(WOLFSSL_SHA3_224_CTX* sha)
{
- WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_init");
- (void)ctx;
- /* do nothing */
- }
+ int ret;
+ typedef char sha_test[sizeof(SHA3_224_CTX) >= sizeof(wc_Sha3) ? 1 : -1];
+ (void)sizeof(sha_test);
- const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void)
- {
- static const char* type = "AES128-CBC";
- WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cbc");
- return type;
- }
+ WOLFSSL_ENTER("SHA3_224_Init");
+ ret = wc_InitSha3_224((wc_Sha3*)sha, NULL, 0);
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
- const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cbc(void)
- {
- static const char* type = "AES192-CBC";
- WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cbc");
- return type;
+ return 0;
}
- const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cbc(void)
+ int wolfSSL_SHA3_224_Update(WOLFSSL_SHA3_224_CTX* sha, const void* input,
+ unsigned long sz)
{
- static const char* type = "AES256-CBC";
- WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cbc");
- return type;
- }
+ int ret;
+ WOLFSSL_ENTER("SHA3_224_Update");
+ ret = wc_Sha3_224_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz);
- const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void)
- {
- static const char* type = "AES128-CTR";
- WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ctr");
- return type;
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ctr(void)
+ int wolfSSL_SHA3_224_Final(byte* input, WOLFSSL_SHA3_224_CTX* sha)
{
- static const char* type = "AES192-CTR";
- WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ctr");
- return type;
- }
+ int ret;
+ WOLFSSL_ENTER("SHA3_224_Final");
+ ret = wc_Sha3_224_Final((wc_Sha3*)sha, input);
- const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ctr(void)
- {
- static const char* type = "AES256-CTR";
- WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ctr");
- return type;
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
+#endif /* WOLFSSL_NOSHA3_224 */
+
- const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_cbc(void)
+#ifndef WOLFSSL_NOSHA3_256
+ int wolfSSL_SHA3_256_Init(WOLFSSL_SHA3_256_CTX* sha3_256)
{
- static const char* type = "DES-CBC";
- WOLFSSL_ENTER("wolfSSL_EVP_des_cbc");
- return type;
- }
+ int ret;
+ typedef char sha_test[sizeof(SHA3_256_CTX) >= sizeof(wc_Sha3) ? 1 : -1];
+ (void)sizeof(sha_test);
- const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void)
- {
- static const char* type = "DES-EDE3-CBC";
- WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_cbc");
- return type;
- }
+ WOLFSSL_ENTER("SHA3_256_Init");
+ ret = wc_InitSha3_256((wc_Sha3*)sha3_256, NULL, 0);
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
- const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void)
- {
- static const char* type = "ARC4";
- WOLFSSL_ENTER("wolfSSL_EVP_rc4");
- return type;
+ return 0;
}
- const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_enc_null(void)
+ int wolfSSL_SHA3_256_Update(WOLFSSL_SHA3_256_CTX* sha, const void* input,
+ unsigned long sz)
{
- static const char* type = "NULL";
- WOLFSSL_ENTER("wolfSSL_EVP_enc_null");
- return type;
- }
+ int ret;
+ WOLFSSL_ENTER("SHA3_256_Update");
+ ret = wc_Sha3_256_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
- int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx)
- {
- WOLFSSL_ENTER("EVP_MD_CTX_cleanup");
- (void)ctx;
return 0;
}
-
- void wolfSSL_EVP_CIPHER_CTX_init(WOLFSSL_EVP_CIPHER_CTX* ctx)
+ int wolfSSL_SHA3_256_Final(byte* input, WOLFSSL_SHA3_256_CTX* sha)
{
- WOLFSSL_ENTER("EVP_CIPHER_CTX_init");
- if (ctx) {
- ctx->cipherType = 0xff; /* no init */
- ctx->keyLen = 0;
- ctx->enc = 1; /* start in encrypt mode */
- }
- }
+ int ret;
+ WOLFSSL_ENTER("SHA3_256_Final");
+ ret = wc_Sha3_256_Final((wc_Sha3*)sha, input);
- /* SSL_SUCCESS on ok */
- int wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx)
- {
- WOLFSSL_ENTER("EVP_CIPHER_CTX_cleanup");
- if (ctx) {
- ctx->cipherType = 0xff; /* no more init */
- ctx->keyLen = 0;
- }
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
- return SSL_SUCCESS;
+ return 0;
}
+#endif /* WOLFSSL_NOSHA3_256 */
- /* SSL_SUCCESS on ok */
- int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
- const WOLFSSL_EVP_CIPHER* type, byte* key,
- byte* iv, int enc)
+ int wolfSSL_SHA3_384_Init(WOLFSSL_SHA3_384_CTX* sha)
{
-#if defined(NO_AES) && defined(NO_DES3)
- (void)iv;
- (void)enc;
-#else
- int ret = 0;
-#endif
+ int ret;
- WOLFSSL_ENTER("wolfSSL_EVP_CipherInit");
- if (ctx == NULL) {
- WOLFSSL_MSG("no ctx");
- return 0; /* failure */
- }
+ typedef char sha_test[sizeof(SHA3_384_CTX) >= sizeof(wc_Sha3) ? 1 : -1];
+ (void)sizeof(sha_test);
- if (type == NULL && ctx->cipherType == 0xff) {
- WOLFSSL_MSG("no type set");
- return 0; /* failure */
- }
+ WOLFSSL_ENTER("SHA3_384_Init");
+ ret = wc_InitSha3_384((wc_Sha3*)sha, NULL, 0);
-#ifndef NO_AES
- if (ctx->cipherType == AES_128_CBC_TYPE || (type &&
- XSTRNCMP(type, "AES128-CBC", 10) == 0)) {
- WOLFSSL_MSG("AES-128-CBC");
- ctx->cipherType = AES_128_CBC_TYPE;
- ctx->keyLen = 16;
- if (enc == 0 || enc == 1)
- ctx->enc = enc ? 1 : 0;
- if (key) {
- ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
- ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
- if (ret != 0)
- return ret;
- }
- if (iv && key == NULL) {
- ret = wc_AesSetIV(&ctx->cipher.aes, iv);
- if (ret != 0)
- return ret;
- }
- }
- else if (ctx->cipherType == AES_192_CBC_TYPE || (type &&
- XSTRNCMP(type, "AES192-CBC", 10) == 0)) {
- WOLFSSL_MSG("AES-192-CBC");
- ctx->cipherType = AES_192_CBC_TYPE;
- ctx->keyLen = 24;
- if (enc == 0 || enc == 1)
- ctx->enc = enc ? 1 : 0;
- if (key) {
- ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
- ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
- if (ret != 0)
- return ret;
- }
- if (iv && key == NULL) {
- ret = wc_AesSetIV(&ctx->cipher.aes, iv);
- if (ret != 0)
- return ret;
- }
- }
- else if (ctx->cipherType == AES_256_CBC_TYPE || (type &&
- XSTRNCMP(type, "AES256-CBC", 10) == 0)) {
- WOLFSSL_MSG("AES-256-CBC");
- ctx->cipherType = AES_256_CBC_TYPE;
- ctx->keyLen = 32;
- if (enc == 0 || enc == 1)
- ctx->enc = enc ? 1 : 0;
- if (key) {
- ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
- ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
- if (ret != 0)
- return ret;
- }
- if (iv && key == NULL) {
- ret = wc_AesSetIV(&ctx->cipher.aes, iv);
- if (ret != 0)
- return ret;
- }
- }
-#ifdef WOLFSSL_AES_COUNTER
- else if (ctx->cipherType == AES_128_CTR_TYPE || (type &&
- XSTRNCMP(type, "AES128-CTR", 10) == 0)) {
- WOLFSSL_MSG("AES-128-CTR");
- ctx->cipherType = AES_128_CTR_TYPE;
- ctx->keyLen = 16;
- if (enc == 0 || enc == 1)
- ctx->enc = enc ? 1 : 0;
- if (key) {
- ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
- AES_ENCRYPTION);
- if (ret != 0)
- return ret;
- }
- if (iv && key == NULL) {
- ret = wc_AesSetIV(&ctx->cipher.aes, iv);
- if (ret != 0)
- return ret;
- }
- }
- else if (ctx->cipherType == AES_192_CTR_TYPE || (type &&
- XSTRNCMP(type, "AES192-CTR", 10) == 0)) {
- WOLFSSL_MSG("AES-192-CTR");
- ctx->cipherType = AES_192_CTR_TYPE;
- ctx->keyLen = 24;
- if (enc == 0 || enc == 1)
- ctx->enc = enc ? 1 : 0;
- if (key) {
- ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
- AES_ENCRYPTION);
- if (ret != 0)
- return ret;
- }
- if (iv && key == NULL) {
- ret = wc_AesSetIV(&ctx->cipher.aes, iv);
- if (ret != 0)
- return ret;
- }
- }
- else if (ctx->cipherType == AES_256_CTR_TYPE || (type &&
- XSTRNCMP(type, "AES256-CTR", 10) == 0)) {
- WOLFSSL_MSG("AES-256-CTR");
- ctx->cipherType = AES_256_CTR_TYPE;
- ctx->keyLen = 32;
- if (enc == 0 || enc == 1)
- ctx->enc = enc ? 1 : 0;
- if (key) {
- ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
- AES_ENCRYPTION);
- if (ret != 0)
- return ret;
- }
- if (iv && key == NULL) {
- ret = wc_AesSetIV(&ctx->cipher.aes, iv);
- if (ret != 0)
- return ret;
- }
- }
-#endif /* WOLFSSL_AES_CTR */
-#endif /* NO_AES */
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
-#ifndef NO_DES3
- else if (ctx->cipherType == DES_CBC_TYPE || (type &&
- XSTRNCMP(type, "DES-CBC", 7) == 0)) {
- WOLFSSL_MSG("DES-CBC");
- ctx->cipherType = DES_CBC_TYPE;
- ctx->keyLen = 8;
- if (enc == 0 || enc == 1)
- ctx->enc = enc ? 1 : 0;
- if (key) {
- ret = wc_Des_SetKey(&ctx->cipher.des, key, iv,
- ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION);
- if (ret != 0)
- return ret;
- }
+ return 0;
+ }
- if (iv && key == NULL)
- wc_Des_SetIV(&ctx->cipher.des, iv);
- }
- else if (ctx->cipherType == DES_EDE3_CBC_TYPE || (type &&
- XSTRNCMP(type, "DES-EDE3-CBC", 11) == 0)) {
- WOLFSSL_MSG("DES-EDE3-CBC");
- ctx->cipherType = DES_EDE3_CBC_TYPE;
- ctx->keyLen = 24;
- if (enc == 0 || enc == 1)
- ctx->enc = enc ? 1 : 0;
- if (key) {
- ret = wc_Des3_SetKey(&ctx->cipher.des3, key, iv,
- ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION);
- if (ret != 0)
- return ret;
- }
- if (iv && key == NULL) {
- ret = wc_Des3_SetIV(&ctx->cipher.des3, iv);
- if (ret != 0)
- return ret;
- }
- }
-#endif /* NO_DES3 */
-#ifndef NO_RC4
- else if (ctx->cipherType == ARC4_TYPE || (type &&
- XSTRNCMP(type, "ARC4", 4) == 0)) {
- WOLFSSL_MSG("ARC4");
- ctx->cipherType = ARC4_TYPE;
- if (ctx->keyLen == 0) /* user may have already set */
- ctx->keyLen = 16; /* default to 128 */
- if (key)
- wc_Arc4SetKey(&ctx->cipher.arc4, key, ctx->keyLen);
- }
-#endif /* NO_RC4 */
- else if (ctx->cipherType == NULL_CIPHER_TYPE || (type &&
- XSTRNCMP(type, "NULL", 4) == 0)) {
- WOLFSSL_MSG("NULL cipher");
- ctx->cipherType = NULL_CIPHER_TYPE;
- ctx->keyLen = 0;
- }
- else
- return 0; /* failure */
+ int wolfSSL_SHA3_384_Update(WOLFSSL_SHA3_384_CTX* sha, const void* input,
+ unsigned long sz)
+ {
+ int ret;
+ WOLFSSL_ENTER("SHA3_384_Update");
+ ret = wc_Sha3_384_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz);
- return SSL_SUCCESS;
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
+
+ return 0;
}
- /* SSL_SUCCESS on ok */
- int wolfSSL_EVP_CIPHER_CTX_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx)
+ int wolfSSL_SHA3_384_Final(byte* input, WOLFSSL_SHA3_384_CTX* sha)
{
- WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_key_length");
- if (ctx)
- return ctx->keyLen;
+ int ret;
- return 0; /* failure */
- }
+ WOLFSSL_ENTER("SHA3_384_Final");
+ ret = wc_Sha3_384_Final((wc_Sha3*)sha, input);
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
- /* SSL_SUCCESS on ok */
- int wolfSSL_EVP_CIPHER_CTX_set_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx,
- int keylen)
- {
- WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_set_key_length");
- if (ctx)
- ctx->keyLen = keylen;
- else
- return 0; /* failure */
-
- return SSL_SUCCESS;
+ return 0;
}
- /* SSL_SUCCESS on ok */
- int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst, byte* src,
- word32 len)
+
+#ifndef WOLFSSL_NOSHA3_512
+
+ int wolfSSL_SHA3_512_Init(WOLFSSL_SHA3_512_CTX* sha)
{
- int ret = 0;
- WOLFSSL_ENTER("wolfSSL_EVP_Cipher");
+ int ret;
- if (ctx == NULL || dst == NULL || src == NULL) {
- WOLFSSL_MSG("Bad function argument");
- return 0; /* failure */
- }
+ typedef char sha_test[sizeof(SHA3_512_CTX) >= sizeof(wc_Sha3) ? 1 : -1];
+ (void)sizeof(sha_test);
- if (ctx->cipherType == 0xff) {
- WOLFSSL_MSG("no init");
- return 0; /* failure */
- }
+ WOLFSSL_ENTER("SHA3_512_Init");
+ ret = wc_InitSha3_512((wc_Sha3*)sha, NULL, 0);
- switch (ctx->cipherType) {
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
-#ifndef NO_AES
- case AES_128_CBC_TYPE :
- case AES_192_CBC_TYPE :
- case AES_256_CBC_TYPE :
- WOLFSSL_MSG("AES CBC");
- if (ctx->enc)
- ret = wc_AesCbcEncrypt(&ctx->cipher.aes, dst, src, len);
- else
- ret = wc_AesCbcDecrypt(&ctx->cipher.aes, dst, src, len);
- break;
+ return 0;
+ }
-#ifdef WOLFSSL_AES_COUNTER
- case AES_128_CTR_TYPE :
- case AES_192_CTR_TYPE :
- case AES_256_CTR_TYPE :
- WOLFSSL_MSG("AES CTR");
- wc_AesCtrEncrypt(&ctx->cipher.aes, dst, src, len);
- break;
-#endif
-#endif /* NO_AES */
-#ifndef NO_DES3
- case DES_CBC_TYPE :
- if (ctx->enc)
- wc_Des_CbcEncrypt(&ctx->cipher.des, dst, src, len);
- else
- wc_Des_CbcDecrypt(&ctx->cipher.des, dst, src, len);
- break;
+ int wolfSSL_SHA3_512_Update(WOLFSSL_SHA3_512_CTX* sha, const void* input,
+ unsigned long sz)
+ {
+ int ret;
- case DES_EDE3_CBC_TYPE :
- if (ctx->enc)
- ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, dst, src, len);
- else
- ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, dst, src, len);
- break;
-#endif
+ WOLFSSL_ENTER("SHA3_512_Update");
+ ret = wc_Sha3_512_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz);
-#ifndef NO_RC4
- case ARC4_TYPE :
- wc_Arc4Process(&ctx->cipher.arc4, dst, src, len);
- break;
-#endif
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
- case NULL_CIPHER_TYPE :
- XMEMCPY(dst, src, len);
- break;
+ return 0;
+ }
- default: {
- WOLFSSL_MSG("bad type");
- return 0; /* failure */
- }
- }
- if (ret != 0) {
- WOLFSSL_MSG("wolfSSL_EVP_Cipher failure");
- return 0; /* failuer */
- }
+ int wolfSSL_SHA3_512_Final(byte* input, WOLFSSL_SHA3_512_CTX* sha)
+ {
+ int ret;
+
+ WOLFSSL_ENTER("SHA3_512_Final");
+ ret = wc_Sha3_512_Final((wc_Sha3*)sha, input);
+
+ /* return 1 on success, 0 otherwise */
+ if (ret == 0)
+ return 1;
- WOLFSSL_MSG("wolfSSL_EVP_Cipher success");
- return SSL_SUCCESS; /* success */
+ return 0;
}
+#endif /* WOLFSSL_NOSHA3_512 */
+#endif /* WOLFSSL_SHA3 */
- /* store for external read of iv, SSL_SUCCESS on success */
+ /* store for external read of iv, WOLFSSL_SUCCESS on success */
int wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx)
{
WOLFSSL_ENTER("wolfSSL_StoreExternalIV");
if (ctx == NULL) {
WOLFSSL_MSG("Bad function argument");
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
switch (ctx->cipherType) {
#ifndef NO_AES
+#ifdef HAVE_AES_CBC
case AES_128_CBC_TYPE :
case AES_192_CBC_TYPE :
case AES_256_CBC_TYPE :
WOLFSSL_MSG("AES CBC");
- memcpy(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
+ XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
break;
-
+#endif
+#ifdef HAVE_AESGCM
+ case AES_128_GCM_TYPE :
+ case AES_192_GCM_TYPE :
+ case AES_256_GCM_TYPE :
+ WOLFSSL_MSG("AES GCM");
+ XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
+ break;
+#endif /* HAVE_AESGCM */
+#ifdef HAVE_AES_ECB
+ case AES_128_ECB_TYPE :
+ case AES_192_ECB_TYPE :
+ case AES_256_ECB_TYPE :
+ WOLFSSL_MSG("AES ECB");
+ break;
+#endif
#ifdef WOLFSSL_AES_COUNTER
case AES_128_CTR_TYPE :
case AES_192_CTR_TYPE :
case AES_256_CTR_TYPE :
WOLFSSL_MSG("AES CTR");
- memcpy(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
+ XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
break;
#endif /* WOLFSSL_AES_COUNTER */
-
+#ifdef WOLFSSL_AES_CFB
+#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS)
+ case AES_128_CFB1_TYPE:
+ case AES_192_CFB1_TYPE:
+ case AES_256_CFB1_TYPE:
+ WOLFSSL_MSG("AES CFB1");
+ break;
+ case AES_128_CFB8_TYPE:
+ case AES_192_CFB8_TYPE:
+ case AES_256_CFB8_TYPE:
+ WOLFSSL_MSG("AES CFB8");
+ break;
+#endif /* !HAVE_SELFTEST && !HAVE_FIPS */
+ case AES_128_CFB128_TYPE:
+ case AES_192_CFB128_TYPE:
+ case AES_256_CFB128_TYPE:
+ WOLFSSL_MSG("AES CFB128");
+ break;
+#endif /* WOLFSSL_AES_CFB */
+#if defined(WOLFSSL_AES_OFB)
+ case AES_128_OFB_TYPE:
+ case AES_192_OFB_TYPE:
+ case AES_256_OFB_TYPE:
+ WOLFSSL_MSG("AES OFB");
+ break;
+#endif /* WOLFSSL_AES_OFB */
+#ifdef WOLFSSL_AES_XTS
+ case AES_128_XTS_TYPE:
+ case AES_256_XTS_TYPE:
+ WOLFSSL_MSG("AES XTS");
+ break;
+#endif /* WOLFSSL_AES_XTS */
#endif /* NO_AES */
#ifndef NO_DES3
case DES_CBC_TYPE :
WOLFSSL_MSG("DES CBC");
- memcpy(ctx->iv, &ctx->cipher.des.reg, DES_BLOCK_SIZE);
+ XMEMCPY(ctx->iv, &ctx->cipher.des.reg, DES_BLOCK_SIZE);
break;
case DES_EDE3_CBC_TYPE :
WOLFSSL_MSG("DES EDE3 CBC");
- memcpy(ctx->iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE);
+ XMEMCPY(ctx->iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE);
+ break;
+#endif
+#ifdef WOLFSSL_DES_ECB
+ case DES_ECB_TYPE :
+ WOLFSSL_MSG("DES ECB");
+ break;
+ case DES_EDE3_ECB_TYPE :
+ WOLFSSL_MSG("DES3 ECB");
break;
#endif
+#ifdef HAVE_IDEA
+ case IDEA_CBC_TYPE :
+ WOLFSSL_MSG("IDEA CBC");
+ XMEMCPY(ctx->iv, &ctx->cipher.idea.reg, IDEA_BLOCK_SIZE);
+ break;
+#endif
case ARC4_TYPE :
WOLFSSL_MSG("ARC4");
break;
@@ -8147,14 +16033,13 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
default: {
WOLFSSL_MSG("bad type");
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
}
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
-
- /* set internal IV from external, SSL_SUCCESS on success */
+ /* set internal IV from external, WOLFSSL_SUCCESS on success */
int wolfSSL_SetInternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx)
{
@@ -8162,25 +16047,41 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
if (ctx == NULL) {
WOLFSSL_MSG("Bad function argument");
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
switch (ctx->cipherType) {
#ifndef NO_AES
+#ifdef HAVE_AES_CBC
case AES_128_CBC_TYPE :
case AES_192_CBC_TYPE :
case AES_256_CBC_TYPE :
WOLFSSL_MSG("AES CBC");
- memcpy(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
+ XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
break;
-
+#endif
+#ifdef HAVE_AESGCM
+ case AES_128_GCM_TYPE :
+ case AES_192_GCM_TYPE :
+ case AES_256_GCM_TYPE :
+ WOLFSSL_MSG("AES GCM");
+ XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
+ break;
+#endif
+#ifdef HAVE_AES_ECB
+ case AES_128_ECB_TYPE :
+ case AES_192_ECB_TYPE :
+ case AES_256_ECB_TYPE :
+ WOLFSSL_MSG("AES ECB");
+ break;
+#endif
#ifdef WOLFSSL_AES_COUNTER
case AES_128_CTR_TYPE :
case AES_192_CTR_TYPE :
case AES_256_CTR_TYPE :
WOLFSSL_MSG("AES CTR");
- memcpy(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
+ XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
break;
#endif
@@ -8189,15 +16090,29 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
#ifndef NO_DES3
case DES_CBC_TYPE :
WOLFSSL_MSG("DES CBC");
- memcpy(&ctx->cipher.des.reg, ctx->iv, DES_BLOCK_SIZE);
+ XMEMCPY(&ctx->cipher.des.reg, ctx->iv, DES_BLOCK_SIZE);
break;
case DES_EDE3_CBC_TYPE :
WOLFSSL_MSG("DES EDE3 CBC");
- memcpy(&ctx->cipher.des3.reg, ctx->iv, DES_BLOCK_SIZE);
+ XMEMCPY(&ctx->cipher.des3.reg, ctx->iv, DES_BLOCK_SIZE);
+ break;
+#endif
+#ifdef WOLFSSL_DES_ECB
+ case DES_ECB_TYPE :
+ WOLFSSL_MSG("DES ECB");
+ break;
+ case DES_EDE3_ECB_TYPE :
+ WOLFSSL_MSG("DES3 ECB");
break;
#endif
+#ifdef HAVE_IDEA
+ case IDEA_CBC_TYPE :
+ WOLFSSL_MSG("IDEA CBC");
+ XMEMCPY(&ctx->cipher.idea.reg, ctx->iv, IDEA_BLOCK_SIZE);
+ break;
+#endif
case ARC4_TYPE :
WOLFSSL_MSG("ARC4");
break;
@@ -8208,247 +16123,329 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
default: {
WOLFSSL_MSG("bad type");
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
}
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
-
- /* SSL_SUCCESS on ok */
- int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx, const WOLFSSL_EVP_MD* type)
+ unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, const void* key,
+ int key_len, const unsigned char* d, int n,
+ unsigned char* md, unsigned int* md_len)
{
- WOLFSSL_ENTER("EVP_DigestInit");
- if (XSTRNCMP(type, "SHA256", 6) == 0) {
- ctx->macType = SHA256;
- wolfSSL_SHA256_Init((SHA256_CTX*)&ctx->hash);
- }
- #ifdef WOLFSSL_SHA384
- else if (XSTRNCMP(type, "SHA384", 6) == 0) {
- ctx->macType = SHA384;
- wolfSSL_SHA384_Init((SHA384_CTX*)&ctx->hash);
- }
- #endif
- #ifdef WOLFSSL_SHA512
- else if (XSTRNCMP(type, "SHA512", 6) == 0) {
- ctx->macType = SHA512;
- wolfSSL_SHA512_Init((SHA512_CTX*)&ctx->hash);
- }
- #endif
- #ifndef NO_MD5
- else if (XSTRNCMP(type, "MD5", 3) == 0) {
- ctx->macType = MD5;
- wolfSSL_MD5_Init((MD5_CTX*)&ctx->hash);
- }
- #endif
- #ifndef NO_SHA
- /* has to be last since would pick or 256, 384, or 512 too */
- else if (XSTRNCMP(type, "SHA", 3) == 0) {
- ctx->macType = SHA;
- wolfSSL_SHA_Init((SHA_CTX*)&ctx->hash);
- }
- #endif /* NO_SHA */
- else
- return BAD_FUNC_ARG;
-
- return SSL_SUCCESS;
- }
-
+ int type;
+ int mdlen;
+ unsigned char* ret = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ Hmac* hmac = NULL;
+#else
+ Hmac hmac[1];
+#endif
+ void* heap = NULL;
- /* SSL_SUCCESS on ok */
- int wolfSSL_EVP_DigestUpdate(WOLFSSL_EVP_MD_CTX* ctx, const void* data,
- unsigned long sz)
- {
- WOLFSSL_ENTER("EVP_DigestUpdate");
+ WOLFSSL_ENTER("wolfSSL_HMAC");
+ if (!md) {
+ WOLFSSL_MSG("Static buffer not supported, pass in md buffer");
+ return NULL; /* no static buffer support */
+ }
- switch (ctx->macType) {
#ifndef NO_MD5
- case MD5:
- wolfSSL_MD5_Update((MD5_CTX*)&ctx->hash, data,
- (unsigned long)sz);
- break;
+ if (XSTRNCMP(evp_md, "MD5", 3) == 0) {
+ type = WC_MD5;
+ mdlen = WC_MD5_DIGEST_SIZE;
+ } else
#endif
-#ifndef NO_SHA
- case SHA:
- wolfSSL_SHA_Update((SHA_CTX*)&ctx->hash, data,
- (unsigned long)sz);
- break;
+#ifdef WOLFSSL_SHA224
+ if (XSTRNCMP(evp_md, "SHA224", 6) == 0) {
+ type = WC_SHA224;
+ mdlen = WC_SHA224_DIGEST_SIZE;
+ } else
#endif
#ifndef NO_SHA256
- case SHA256:
- wolfSSL_SHA256_Update((SHA256_CTX*)&ctx->hash, data,
- (unsigned long)sz);
- break;
+ if (XSTRNCMP(evp_md, "SHA256", 6) == 0) {
+ type = WC_SHA256;
+ mdlen = WC_SHA256_DIGEST_SIZE;
+ } else
#endif
#ifdef WOLFSSL_SHA384
- case SHA384:
- wolfSSL_SHA384_Update((SHA384_CTX*)&ctx->hash, data,
- (unsigned long)sz);
- break;
+ if (XSTRNCMP(evp_md, "SHA384", 6) == 0) {
+ type = WC_SHA384;
+ mdlen = WC_SHA384_DIGEST_SIZE;
+ } else
#endif
#ifdef WOLFSSL_SHA512
- case SHA512:
- wolfSSL_SHA512_Update((SHA512_CTX*)&ctx->hash, data,
- (unsigned long)sz);
- break;
+ if (XSTRNCMP(evp_md, "SHA512", 6) == 0) {
+ type = WC_SHA512;
+ mdlen = WC_SHA512_DIGEST_SIZE;
+ } else
#endif
- default:
- return BAD_FUNC_ARG;
- }
-
- return SSL_SUCCESS;
- }
-
-
- /* SSL_SUCCESS on ok */
- int wolfSSL_EVP_DigestFinal(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md,
- unsigned int* s)
- {
- WOLFSSL_ENTER("EVP_DigestFinal");
- switch (ctx->macType) {
-#ifndef NO_MD5
- case MD5:
- wolfSSL_MD5_Final(md, (MD5_CTX*)&ctx->hash);
- if (s) *s = MD5_DIGEST_SIZE;
- break;
+#ifdef WOLFSSL_SHA3
+ #ifndef WOLFSSL_NOSHA3_224
+ if (XSTRNCMP(evp_md, "SHA3_224", 8) == 0) {
+ type = WC_SHA3_224;
+ mdlen = WC_SHA3_224_DIGEST_SIZE;
+ } else
+ #endif
+ #ifndef WOLFSSL_NOSHA3_256
+ if (XSTRNCMP(evp_md, "SHA3_256", 8) == 0) {
+ type = WC_SHA3_256;
+ mdlen = WC_SHA3_256_DIGEST_SIZE;
+ } else
+ #endif
+ if (XSTRNCMP(evp_md, "SHA3_384", 8) == 0) {
+ type = WC_SHA3_384;
+ mdlen = WC_SHA3_384_DIGEST_SIZE;
+ } else
+ #ifndef WOLFSSL_NOSHA3_512
+ if (XSTRNCMP(evp_md, "SHA3_512", 8) == 0) {
+ type = WC_SHA3_512;
+ mdlen = WC_SHA3_512_DIGEST_SIZE;
+ } else
+ #endif
#endif
#ifndef NO_SHA
- case SHA:
- wolfSSL_SHA_Final(md, (SHA_CTX*)&ctx->hash);
- if (s) *s = SHA_DIGEST_SIZE;
- break;
-#endif
-#ifndef NO_SHA256
- case SHA256:
- wolfSSL_SHA256_Final(md, (SHA256_CTX*)&ctx->hash);
- if (s) *s = SHA256_DIGEST_SIZE;
- break;
-#endif
-#ifdef WOLFSSL_SHA384
- case SHA384:
- wolfSSL_SHA384_Final(md, (SHA384_CTX*)&ctx->hash);
- if (s) *s = SHA384_DIGEST_SIZE;
- break;
-#endif
-#ifdef WOLFSSL_SHA512
- case SHA512:
- wolfSSL_SHA512_Final(md, (SHA512_CTX*)&ctx->hash);
- if (s) *s = SHA512_DIGEST_SIZE;
- break;
-#endif
- default:
- return BAD_FUNC_ARG;
- }
-
- return SSL_SUCCESS;
- }
-
-
- /* SSL_SUCCESS on ok */
- int wolfSSL_EVP_DigestFinal_ex(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md,
- unsigned int* s)
- {
- WOLFSSL_ENTER("EVP_DigestFinal_ex");
- return EVP_DigestFinal(ctx, md, s);
- }
-
-
- unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, const void* key,
- int key_len, const unsigned char* d, int n,
- unsigned char* md, unsigned int* md_len)
- {
- int type;
- unsigned char* ret = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- Hmac* hmac = NULL;
-#else
- Hmac hmac[1];
+ if (XSTRNCMP(evp_md, "SHA", 3) == 0) {
+ type = WC_SHA;
+ mdlen = WC_SHA_DIGEST_SIZE;
+ } else
#endif
-
- WOLFSSL_ENTER("HMAC");
- if (!md)
- return NULL; /* no static buffer support */
-
- if (XSTRNCMP(evp_md, "MD5", 3) == 0)
- type = MD5;
- else if (XSTRNCMP(evp_md, "SHA", 3) == 0)
- type = SHA;
- else
+ {
return NULL;
+ }
#ifdef WOLFSSL_SMALL_STACK
- hmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC);
if (hmac == NULL)
return NULL;
#endif
- if (wc_HmacSetKey(hmac, type, (const byte*)key, key_len) == 0)
- if (wc_HmacUpdate(hmac, d, n) == 0)
- if (wc_HmacFinal(hmac, md) == 0) {
- if (md_len)
- *md_len = (type == MD5) ? (int)MD5_DIGEST_SIZE
- : (int)SHA_DIGEST_SIZE;
- ret = md;
+ if (wc_HmacInit(hmac, heap, INVALID_DEVID) == 0) {
+ if (wc_HmacSetKey(hmac, type, (const byte*)key, key_len) == 0) {
+ if (wc_HmacUpdate(hmac, d, n) == 0) {
+ if (wc_HmacFinal(hmac, md) == 0) {
+ if (md_len)
+ *md_len = mdlen;
+ ret = md;
+ }
}
+ }
+ wc_HmacFree(hmac);
+ }
#ifdef WOLFSSL_SMALL_STACK
- XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(hmac, heap, DYNAMIC_TYPE_HMAC);
#endif
+ (void)evp_md;
return ret;
}
void wolfSSL_ERR_clear_error(void)
{
- /* TODO: */
+ WOLFSSL_ENTER("wolfSSL_ERR_clear_error");
+
+#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX) || \
+ defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
+ wc_ClearErrorNodes();
+#endif
}
int wolfSSL_RAND_status(void)
{
- return SSL_SUCCESS; /* wolfCrypt provides enough seed internally */
+ return WOLFSSL_SUCCESS; /* wolfCrypt provides enough seed internally */
}
-
+ #ifndef NO_WOLFSSL_STUB
void wolfSSL_RAND_add(const void* add, int len, double entropy)
{
(void)add;
(void)len;
(void)entropy;
-
+ WOLFSSL_STUB("RAND_add");
/* wolfSSL seeds/adds internally, use explicit RNG if you want
to take control */
}
-
+ #endif
#ifndef NO_DES3
- /* SSL_SUCCESS on ok */
+ /* 0 on ok */
int wolfSSL_DES_key_sched(WOLFSSL_const_DES_cblock* key,
- WOLFSSL_DES_key_schedule* schedule)
+ WOLFSSL_DES_key_schedule* schedule)
{
- WOLFSSL_ENTER("DES_key_sched");
- XMEMCPY(schedule, key, sizeof(const_DES_cblock));
- return SSL_SUCCESS;
+ WOLFSSL_ENTER("wolfSSL_DES_key_sched");
+
+ if (key == NULL || schedule == NULL) {
+ WOLFSSL_MSG("Null argument passed in");
+ }
+ else {
+ XMEMCPY(schedule, key, sizeof(WOLFSSL_const_DES_cblock));
+ }
+
+ return 0;
+ }
+
+
+ /* intended to behave similar to Kerberos mit_des_cbc_cksum
+ * return the last 4 bytes of cipher text */
+ WOLFSSL_DES_LONG wolfSSL_DES_cbc_cksum(const unsigned char* in,
+ WOLFSSL_DES_cblock* out, long length, WOLFSSL_DES_key_schedule* sc,
+ WOLFSSL_const_DES_cblock* iv)
+ {
+ WOLFSSL_DES_LONG ret;
+ unsigned char* tmp;
+ unsigned char* data = (unsigned char*)in;
+ long dataSz = length;
+ byte dynamicFlag = 0; /* when padding the buffer created needs free'd */
+
+ WOLFSSL_ENTER("wolfSSL_DES_cbc_cksum");
+
+ if (in == NULL || out == NULL || sc == NULL || iv == NULL) {
+ WOLFSSL_MSG("Bad argument passed in");
+ return 0;
+ }
+
+ /* if input length is not a multiple of DES_BLOCK_SIZE pad with 0s */
+ if (dataSz % DES_BLOCK_SIZE) {
+ dataSz += DES_BLOCK_SIZE - (dataSz % DES_BLOCK_SIZE);
+ data = (unsigned char*)XMALLOC(dataSz, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (data == NULL) {
+ WOLFSSL_MSG("Issue creating temporary buffer");
+ return 0;
+ }
+ dynamicFlag = 1; /* set to free buffer at end */
+ XMEMCPY(data, in, length);
+ XMEMSET(data + length, 0, dataSz - length); /* padding */
+ }
+
+ tmp = (unsigned char*)XMALLOC(dataSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (tmp == NULL) {
+ WOLFSSL_MSG("Issue creating temporary buffer");
+ if (dynamicFlag == 1) {
+ XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ return 0;
+ }
+
+ wolfSSL_DES_cbc_encrypt(data, tmp, dataSz, sc,
+ (WOLFSSL_DES_cblock*)iv, 1);
+ XMEMCPY((unsigned char*)out, tmp + (dataSz - DES_BLOCK_SIZE),
+ DES_BLOCK_SIZE);
+
+ ret = (((*((unsigned char*)out + 4) & 0xFF) << 24)|
+ ((*((unsigned char*)out + 5) & 0xFF) << 16)|
+ ((*((unsigned char*)out + 6) & 0xFF) << 8) |
+ (*((unsigned char*)out + 7) & 0xFF));
+
+ XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (dynamicFlag == 1) {
+ XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+
+ return ret;
}
void wolfSSL_DES_cbc_encrypt(const unsigned char* input,
- unsigned char* output, long length,
- WOLFSSL_DES_key_schedule* schedule, WOLFSSL_DES_cblock* ivec,
- int enc)
+ unsigned char* output, long length,
+ WOLFSSL_DES_key_schedule* schedule,
+ WOLFSSL_DES_cblock* ivec, int enc)
{
Des myDes;
+ byte lastblock[DES_BLOCK_SIZE];
+ int lb_sz;
+ long blk;
WOLFSSL_ENTER("DES_cbc_encrypt");
/* OpenSSL compat, no ret */
wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec, !enc);
+ lb_sz = length%DES_BLOCK_SIZE;
+ blk = length/DES_BLOCK_SIZE;
+
+ if (enc){
+ wc_Des_CbcEncrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE);
+ if(lb_sz){
+ XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
+ XMEMCPY(lastblock, input+length-lb_sz, lb_sz);
+ wc_Des_CbcEncrypt(&myDes, output+blk*DES_BLOCK_SIZE,
+ lastblock, (word32)DES_BLOCK_SIZE);
+ }
+ }
+ else {
+ wc_Des_CbcDecrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE);
+ if(lb_sz){
+ wc_Des_CbcDecrypt(&myDes, lastblock, input+length-lb_sz, (word32)DES_BLOCK_SIZE);
+ XMEMCPY(output+length-lb_sz, lastblock, lb_sz);
+ }
+ }
+ }
- if (enc)
- wc_Des_CbcEncrypt(&myDes, output, input, (word32)length);
- else
- wc_Des_CbcDecrypt(&myDes, output, input, (word32)length);
+
+ /* WOLFSSL_DES_key_schedule is a unsigned char array of size 8 */
+ void wolfSSL_DES_ede3_cbc_encrypt(const unsigned char* input,
+ unsigned char* output, long sz,
+ WOLFSSL_DES_key_schedule* ks1,
+ WOLFSSL_DES_key_schedule* ks2,
+ WOLFSSL_DES_key_schedule* ks3,
+ WOLFSSL_DES_cblock* ivec, int enc)
+ {
+ int ret;
+ Des3 des;
+ byte key[24];/* EDE uses 24 size key */
+ byte lastblock[DES_BLOCK_SIZE];
+ int lb_sz;
+ long blk;
+
+ WOLFSSL_ENTER("wolfSSL_DES_ede3_cbc_encrypt");
+
+ XMEMSET(key, 0, sizeof(key));
+ XMEMCPY(key, *ks1, DES_BLOCK_SIZE);
+ XMEMCPY(&key[DES_BLOCK_SIZE], *ks2, DES_BLOCK_SIZE);
+ XMEMCPY(&key[DES_BLOCK_SIZE * 2], *ks3, DES_BLOCK_SIZE);
+ lb_sz = sz%DES_BLOCK_SIZE;
+ blk = sz/DES_BLOCK_SIZE;
+
+ /* OpenSSL compat, no ret */
+ (void)wc_Des3Init(&des, NULL, INVALID_DEVID);
+
+ if (enc) {
+ wc_Des3_SetKey(&des, key, (const byte*)ivec, DES_ENCRYPTION);
+ ret = wc_Des3_CbcEncrypt(&des, output, input, (word32)blk*DES_BLOCK_SIZE);
+ #if defined(WOLFSSL_ASYNC_CRYPT)
+ ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE);
+ #endif
+ (void)ret; /* ignore return codes for processing */
+ if(lb_sz){
+ XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
+ XMEMCPY(lastblock, input+sz-lb_sz, lb_sz);
+ ret = wc_Des3_CbcEncrypt(&des, output+blk*DES_BLOCK_SIZE,
+ lastblock, (word32)DES_BLOCK_SIZE);
+ #if defined(WOLFSSL_ASYNC_CRYPT)
+ ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE);
+ #endif
+ (void)ret; /* ignore return codes for processing */
+ }
+ }
+ else {
+ wc_Des3_SetKey(&des, key, (const byte*)ivec, DES_DECRYPTION);
+ ret = wc_Des3_CbcDecrypt(&des, output, input, (word32)blk*DES_BLOCK_SIZE);
+ #if defined(WOLFSSL_ASYNC_CRYPT)
+ ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE);
+ #endif
+ (void)ret; /* ignore return codes for processing */
+ if(lb_sz){
+ ret = wc_Des3_CbcDecrypt(&des, lastblock, input+sz-lb_sz, (word32)DES_BLOCK_SIZE);
+ #if defined(WOLFSSL_ASYNC_CRYPT)
+ ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE);
+ #endif
+ (void)ret; /* ignore return codes for processing */
+ XMEMCPY(output+sz-lb_sz, lastblock, lb_sz);
+ }
+ }
+ wc_Des3Free(&des);
}
@@ -8459,55 +16456,138 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
int enc)
{
Des myDes;
+ byte lastblock[DES_BLOCK_SIZE];
+ int lb_sz;
+ long idx = length;
+ long blk;
WOLFSSL_ENTER("DES_ncbc_encrypt");
/* OpenSSL compat, no ret */
wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec, !enc);
+ lb_sz = length%DES_BLOCK_SIZE;
+ blk = length/DES_BLOCK_SIZE;
+ idx -= sizeof(DES_cblock);
+ if (lb_sz) {
+ idx += DES_BLOCK_SIZE - lb_sz;
+ }
+ if (enc){
+ wc_Des_CbcEncrypt(&myDes, output, input,
+ (word32)blk * DES_BLOCK_SIZE);
+ if (lb_sz){
+ XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
+ XMEMCPY(lastblock, input+length-lb_sz, lb_sz);
+ wc_Des_CbcEncrypt(&myDes, output + blk * DES_BLOCK_SIZE,
+ lastblock, (word32)DES_BLOCK_SIZE);
+ }
+ XMEMCPY(ivec, output + idx, sizeof(DES_cblock));
+ } else {
+ WOLFSSL_DES_cblock tmp;
+ XMEMCPY(tmp, input + idx, sizeof(DES_cblock));
+ wc_Des_CbcDecrypt(&myDes, output, input,
+ (word32)blk * DES_BLOCK_SIZE);
+ if (lb_sz){
+ wc_Des_CbcDecrypt(&myDes, lastblock, input + length - lb_sz,
+ (word32)DES_BLOCK_SIZE);
+ XMEMCPY(output+length-lb_sz, lastblock, lb_sz);
+ }
+ XMEMCPY(ivec, tmp, sizeof(WOLFSSL_DES_cblock));
+ }
- if (enc)
- wc_Des_CbcEncrypt(&myDes, output, input, (word32)length);
- else
- wc_Des_CbcDecrypt(&myDes, output, input, (word32)length);
-
- XMEMCPY(ivec, output + length - sizeof(DES_cblock), sizeof(DES_cblock));
}
#endif /* NO_DES3 */
-
void wolfSSL_ERR_free_strings(void)
{
/* handled internally */
}
-
- void wolfSSL_ERR_remove_state(unsigned long state)
- {
- /* TODO: GetErrors().Remove(); */
- (void)state;
- }
-
-
- void wolfSSL_EVP_cleanup(void)
- {
- /* nothing to do here */
- }
-
-
void wolfSSL_cleanup_all_ex_data(void)
{
/* nothing to do here */
}
-
int wolfSSL_clear(WOLFSSL* ssl)
{
- (void)ssl;
- /* TODO: GetErrors().Remove(); */
- return SSL_SUCCESS;
- }
+ if (ssl == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ ssl->options.isClosed = 0;
+ ssl->options.connReset = 0;
+ ssl->options.sentNotify = 0;
+ ssl->options.sendVerify = 0;
+ ssl->options.serverState = NULL_STATE;
+ ssl->options.clientState = NULL_STATE;
+ ssl->options.connectState = CONNECT_BEGIN;
+ ssl->options.acceptState = ACCEPT_BEGIN;
+ ssl->options.handShakeState = NULL_STATE;
+ ssl->options.handShakeDone = 0;
+ /* ssl->options.processReply = doProcessInit; */
+
+ ssl->keys.encryptionOn = 0;
+ XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
+
+ if (ssl->hsHashes != NULL) {
+#ifndef NO_OLD_TLS
+#ifndef NO_MD5
+ if (wc_InitMd5_ex(&ssl->hsHashes->hashMd5, ssl->heap,
+ ssl->devId) != 0) {
+ return WOLFSSL_FAILURE;
+ }
+ #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+ wc_Md5SetFlags(&ssl->hsHashes->hashMd5, WC_HASH_FLAG_WILLCOPY);
+ #endif
+#endif
+#ifndef NO_SHA
+ if (wc_InitSha_ex(&ssl->hsHashes->hashSha, ssl->heap,
+ ssl->devId) != 0) {
+ return WOLFSSL_FAILURE;
+ }
+ #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+ wc_ShaSetFlags(&ssl->hsHashes->hashSha, WC_HASH_FLAG_WILLCOPY);
+ #endif
+#endif
+#endif
+#ifndef NO_SHA256
+ if (wc_InitSha256_ex(&ssl->hsHashes->hashSha256, ssl->heap,
+ ssl->devId) != 0) {
+ return WOLFSSL_FAILURE;
+ }
+ #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+ wc_Sha256SetFlags(&ssl->hsHashes->hashSha256, WC_HASH_FLAG_WILLCOPY);
+ #endif
+#endif
+#ifdef WOLFSSL_SHA384
+ if (wc_InitSha384_ex(&ssl->hsHashes->hashSha384, ssl->heap,
+ ssl->devId) != 0) {
+ return WOLFSSL_FAILURE;
+ }
+ #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+ wc_Sha384SetFlags(&ssl->hsHashes->hashSha384, WC_HASH_FLAG_WILLCOPY);
+ #endif
+#endif
+#ifdef WOLFSSL_SHA512
+ if (wc_InitSha512_ex(&ssl->hsHashes->hashSha512, ssl->heap,
+ ssl->devId) != 0) {
+ return WOLFSSL_FAILURE;
+ }
+ #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+ wc_Sha512SetFlags(&ssl->hsHashes->hashSha512, WC_HASH_FLAG_WILLCOPY);
+ #endif
+#endif
+ }
+#ifdef SESSION_CERTS
+ ssl->session.chain.count = 0;
+#endif
+#ifdef KEEP_PEER_CERT
+ FreeX509(&ssl->peerCert);
+ InitX509(&ssl->peerCert, 0, ssl->heap);
+#endif
+ return WOLFSSL_SUCCESS;
+ }
long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t)
{
@@ -8519,432 +16599,829 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
ses->timeout = tmptime;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
+#endif
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode)
{
- /* SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */
+ /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */
WOLFSSL_ENTER("SSL_CTX_set_mode");
- if (mode == SSL_MODE_ENABLE_PARTIAL_WRITE)
- ctx->partialWrite = 1;
+ switch(mode) {
+ case SSL_MODE_ENABLE_PARTIAL_WRITE:
+ ctx->partialWrite = 1;
+ break;
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ case SSL_MODE_RELEASE_BUFFERS:
+ WOLFSSL_MSG("SSL_MODE_RELEASE_BUFFERS not implemented.");
+ break;
+ #endif
+ default:
+ WOLFSSL_MSG("Mode Not Implemented");
+ }
+
+ /* SSL_MODE_AUTO_RETRY
+ * Should not return -1 with renegotiation on read/write */
return mode;
}
+#endif
+#ifdef OPENSSL_EXTRA
+ #ifndef NO_WOLFSSL_STUB
long wolfSSL_SSL_get_mode(WOLFSSL* ssl)
{
/* TODO: */
(void)ssl;
+ WOLFSSL_STUB("SSL_get_mode");
return 0;
}
+ #endif
-
+ #ifndef NO_WOLFSSL_STUB
long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx)
{
/* TODO: */
(void)ctx;
+ WOLFSSL_STUB("SSL_CTX_get_mode");
return 0;
}
+ #endif
-
+ #ifndef NO_WOLFSSL_STUB
void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m)
{
/* TODO: maybe? */
(void)ctx;
(void)m;
+ WOLFSSL_STUB("SSL_CTX_set_default_read_ahead");
}
+ #endif
+ /* Storing app session context id, this value is inherited by WOLFSSL
+ * objects created from WOLFSSL_CTX. Any session that is imported with a
+ * different session context id will be rejected.
+ *
+ * ctx structure to set context in
+ * sid_ctx value of context to set
+ * sid_ctx_len length of sid_ctx buffer
+ *
+ * Returns SSL_SUCCESS in success case and SSL_FAILURE when failing
+ */
int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX* ctx,
- const unsigned char* sid_ctx,
- unsigned int sid_ctx_len)
+ const unsigned char* sid_ctx,
+ unsigned int sid_ctx_len)
{
+ WOLFSSL_ENTER("SSL_CTX_set_session_id_context");
+
/* No application specific context needed for wolfSSL */
- (void)ctx;
- (void)sid_ctx;
- (void)sid_ctx_len;
+ if (sid_ctx_len > ID_LEN || ctx == NULL || sid_ctx == NULL) {
+ return SSL_FAILURE;
+ }
+ XMEMCPY(ctx->sessionCtx, sid_ctx, sid_ctx_len);
+ ctx->sessionCtxSz = (byte)sid_ctx_len;
+
return SSL_SUCCESS;
}
- long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX* ctx)
- {
- /* TODO: maybe? */
- (void)ctx;
- return (~0);
- }
- unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line,
- const char** data, int *flags)
+ /* Storing app session context id. Any session that is imported with a
+ * different session context id will be rejected.
+ *
+ * ssl structure to set context in
+ * id value of context to set
+ * len length of sid_ctx buffer
+ *
+ * Returns SSL_SUCCESS in success case and SSL_FAILURE when failing
+ */
+ int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id,
+ unsigned int len)
{
- /* Not implemented */
- (void)file;
- (void)line;
- (void)data;
- (void)flags;
- return 0;
- }
+ WOLFSSL_ENTER("wolfSSL_set_session_id_context");
-#endif /* OPENSSL_EXTRA */
+ if (len > ID_LEN || ssl == NULL || id == NULL) {
+ return SSL_FAILURE;
+ }
+ XMEMCPY(ssl->sessionCtx, id, len);
+ ssl->sessionCtxSz = (byte)len;
+ return SSL_SUCCESS;
+ }
-#if defined(KEEP_PEER_CERT)
- WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl)
+ long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX* ctx)
{
- WOLFSSL_ENTER("SSL_get_peer_certificate");
- if (ssl->peerCert.issuer.sz)
- return &ssl->peerCert;
- else
+ (void)ctx;
+ #ifndef NO_SESSION_CACHE
+ return (long)(SESSIONS_PER_ROW * SESSION_ROWS);
+ #else
return 0;
+ #endif
}
-#endif /* KEEP_PEER_CERT */
+ /* returns the unsigned error value and increments the pointer into the
+ * error queue.
+ *
+ * file pointer to file name
+ * line gets set to line number of error when not NULL
+ */
+ unsigned long wolfSSL_ERR_get_error_line(const char** file, int* line)
+ {
+ #ifdef DEBUG_WOLFSSL
+ int ret = wc_PullErrorNode(file, NULL, line);
+ if (ret < 0) {
+ if (ret == BAD_STATE_E) return 0; /* no errors in queue */
+ WOLFSSL_MSG("Issue getting error node");
+ WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line", ret);
+ ret = 0 - ret; /* return absolute value of error */
-#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
+ /* panic and try to clear out nodes */
+ wc_ClearErrorNodes();
+ }
+ return (unsigned long)ret;
+ #else
+ (void)file;
+ (void)line;
- void wolfSSL_FreeX509(WOLFSSL_X509* x509)
- {
- WOLFSSL_ENTER("wolfSSL_FreeX509");
- FreeX509(x509);
+ return 0;
+ #endif
}
- /* return the next, if any, altname from the peer cert */
- char* wolfSSL_X509_get_next_altname(WOLFSSL_X509* cert)
+#if (defined(DEBUG_WOLFSSL) || defined(OPENSSL_EXTRA)) && \
+ (!defined(_WIN32) && !defined(NO_ERROR_QUEUE))
+ static const char WOLFSSL_SYS_ACCEPT_T[] = "accept";
+ static const char WOLFSSL_SYS_BIND_T[] = "bind";
+ static const char WOLFSSL_SYS_CONNECT_T[] = "connect";
+ static const char WOLFSSL_SYS_FOPEN_T[] = "fopen";
+ static const char WOLFSSL_SYS_FREAD_T[] = "fread";
+ static const char WOLFSSL_SYS_GETADDRINFO_T[] = "getaddrinfo";
+ static const char WOLFSSL_SYS_GETSOCKOPT_T[] = "getsockopt";
+ static const char WOLFSSL_SYS_GETSOCKNAME_T[] = "getsockname";
+ static const char WOLFSSL_SYS_GETHOSTBYNAME_T[] = "gethostbyname";
+ static const char WOLFSSL_SYS_GETNAMEINFO_T[] = "getnameinfo";
+ static const char WOLFSSL_SYS_GETSERVBYNAME_T[] = "getservbyname";
+ static const char WOLFSSL_SYS_IOCTLSOCKET_T[] = "ioctlsocket";
+ static const char WOLFSSL_SYS_LISTEN_T[] = "listen";
+ static const char WOLFSSL_SYS_OPENDIR_T[] = "opendir";
+ static const char WOLFSSL_SYS_SETSOCKOPT_T[] = "setsockopt";
+ static const char WOLFSSL_SYS_SOCKET_T[] = "socket";
+
+ /* switch with int mapped to function name for compatibility */
+ static const char* wolfSSL_ERR_sys_func(int fun)
{
- char* ret = NULL;
- WOLFSSL_ENTER("wolfSSL_X509_get_next_altname");
-
- /* don't have any to work with */
- if (cert == NULL || cert->altNames == NULL)
- return NULL;
-
- /* already went through them */
- if (cert->altNamesNext == NULL)
- return NULL;
-
- ret = cert->altNamesNext->name;
- cert->altNamesNext = cert->altNamesNext->next;
-
- return ret;
+ switch (fun) {
+ case WOLFSSL_SYS_ACCEPT: return WOLFSSL_SYS_ACCEPT_T;
+ case WOLFSSL_SYS_BIND: return WOLFSSL_SYS_BIND_T;
+ case WOLFSSL_SYS_CONNECT: return WOLFSSL_SYS_CONNECT_T;
+ case WOLFSSL_SYS_FOPEN: return WOLFSSL_SYS_FOPEN_T;
+ case WOLFSSL_SYS_FREAD: return WOLFSSL_SYS_FREAD_T;
+ case WOLFSSL_SYS_GETADDRINFO: return WOLFSSL_SYS_GETADDRINFO_T;
+ case WOLFSSL_SYS_GETSOCKOPT: return WOLFSSL_SYS_GETSOCKOPT_T;
+ case WOLFSSL_SYS_GETSOCKNAME: return WOLFSSL_SYS_GETSOCKNAME_T;
+ case WOLFSSL_SYS_GETHOSTBYNAME: return WOLFSSL_SYS_GETHOSTBYNAME_T;
+ case WOLFSSL_SYS_GETNAMEINFO: return WOLFSSL_SYS_GETNAMEINFO_T;
+ case WOLFSSL_SYS_GETSERVBYNAME: return WOLFSSL_SYS_GETSERVBYNAME_T;
+ case WOLFSSL_SYS_IOCTLSOCKET: return WOLFSSL_SYS_IOCTLSOCKET_T;
+ case WOLFSSL_SYS_LISTEN: return WOLFSSL_SYS_LISTEN_T;
+ case WOLFSSL_SYS_OPENDIR: return WOLFSSL_SYS_OPENDIR_T;
+ case WOLFSSL_SYS_SETSOCKOPT: return WOLFSSL_SYS_SETSOCKOPT_T;
+ case WOLFSSL_SYS_SOCKET: return WOLFSSL_SYS_SOCKET_T;
+ default:
+ return "NULL";
+ }
}
+#endif /* DEBUG_WOLFSSL */
- WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509* cert)
+ /* @TODO when having an error queue this needs to push to the queue */
+ void wolfSSL_ERR_put_error(int lib, int fun, int err, const char* file,
+ int line)
{
- WOLFSSL_ENTER("X509_get_issuer_name");
- return &cert->issuer;
+ WOLFSSL_ENTER("wolfSSL_ERR_put_error");
+
+ #if !defined(DEBUG_WOLFSSL) && !defined(OPENSSL_EXTRA)
+ (void)fun;
+ (void)err;
+ (void)file;
+ (void)line;
+ WOLFSSL_MSG("Not compiled in debug mode");
+ #elif defined(OPENSSL_EXTRA) && \
+ (defined(_WIN32) || defined(NO_ERROR_QUEUE))
+ (void)fun;
+ (void)file;
+ (void)line;
+ WOLFSSL_ERROR(err);
+ #else
+ WOLFSSL_ERROR_LINE(err, wolfSSL_ERR_sys_func(fun), (unsigned int)line,
+ file, NULL);
+ #endif
+ (void)lib;
}
- WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509* cert)
+ /* Similar to wolfSSL_ERR_get_error_line but takes in a flags argument for
+ * more flexibility.
+ *
+ * file output pointer to file where error happened
+ * line output to line number of error
+ * data output data. Is a string if ERR_TXT_STRING flag is used
+ * flags bit flag to adjust data output
+ *
+ * Returns the error value or 0 if no errors are in the queue
+ */
+ unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line,
+ const char** data, int *flags)
{
- WOLFSSL_ENTER("X509_get_subject_name");
- return &cert->subject;
- }
+ int ret;
+ WOLFSSL_STUB("wolfSSL_ERR_get_error_line_data");
- int wolfSSL_X509_get_isCA(WOLFSSL_X509* x509)
- {
- int isCA = 0;
+ if (flags != NULL) {
+ if ((*flags & ERR_TXT_STRING) == ERR_TXT_STRING) {
+ ret = wc_PullErrorNode(file, data, line);
+ if (ret < 0) {
+ if (ret == BAD_STATE_E) return 0; /* no errors in queue */
+ WOLFSSL_MSG("Error with pulling error node!");
+ WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret);
+ ret = 0 - ret; /* return absolute value of error */
- WOLFSSL_ENTER("wolfSSL_X509_get_isCA");
+ /* panic and try to clear out nodes */
+ wc_ClearErrorNodes();
+ }
- if (x509 != NULL)
- isCA = x509->isCa;
+ return (unsigned long)ret;
+ }
+ }
- WOLFSSL_LEAVE("wolfSSL_X509_get_isCA", isCA);
+ ret = wc_PullErrorNode(file, NULL, line);
+ if (ret < 0) {
+ if (ret == BAD_STATE_E) return 0; /* no errors in queue */
+ WOLFSSL_MSG("Error with pulling error node!");
+ WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret);
+ ret = 0 - ret; /* return absolute value of error */
- return isCA;
+ /* panic and try to clear out nodes */
+ wc_ClearErrorNodes();
+ }
+
+ return (unsigned long)ret;
}
+#endif /* OPENSSL_EXTRA */
-#ifdef OPENSSL_EXTRA
- int wolfSSL_X509_ext_isSet_by_NID(WOLFSSL_X509* x509, int nid)
+
+#if (defined(KEEP_PEER_CERT) && defined(SESSION_CERTS)) || \
+ (defined(OPENSSL_ALL) && defined(HAVE_PKCS7))
+ /* Decode the X509 DER encoded certificate into a WOLFSSL_X509 object.
+ *
+ * x509 WOLFSSL_X509 object to decode into.
+ * in X509 DER data.
+ * len Length of the X509 DER data.
+ * returns the new certificate on success, otherwise NULL.
+ */
+ static int DecodeToX509(WOLFSSL_X509* x509, const byte* in, int len)
{
- int isSet = 0;
+ int ret;
+ #ifdef WOLFSSL_SMALL_STACK
+ DecodedCert* cert;
+ #else
+ DecodedCert cert[1];
+ #endif
+ if (x509 == NULL || in == NULL || len <= 0)
+ return BAD_FUNC_ARG;
- WOLFSSL_ENTER("wolfSSL_X509_ext_isSet_by_NID");
+ #ifdef WOLFSSL_SMALL_STACK
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+ DYNAMIC_TYPE_DCERT);
+ if (cert == NULL)
+ return MEMORY_E;
+ #endif
- if (x509 != NULL) {
- switch (nid) {
- case BASIC_CA_OID: isSet = x509->basicConstSet; break;
- case ALT_NAMES_OID: isSet = x509->subjAltNameSet; break;
- case AUTH_KEY_OID: isSet = x509->authKeyIdSet; break;
- case SUBJ_KEY_OID: isSet = x509->subjKeyIdSet; break;
- case KEY_USAGE_OID: isSet = x509->keyUsageSet; break;
- #ifdef WOLFSSL_SEP
- case CERT_POLICY_OID: isSet = x509->certPolicySet; break;
- #endif /* WOLFSSL_SEP */
- }
+ /* Create a DecodedCert object and copy fields into WOLFSSL_X509 object.
+ */
+ InitDecodedCert(cert, (byte*)in, len, NULL);
+ if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) == 0) {
+ /* Check if x509 was not previously initialized by wolfSSL_X509_new() */
+ if (x509->dynamicMemory != TRUE)
+ InitX509(x509, 0, NULL);
+ ret = CopyDecodedToX509(x509, cert);
+ FreeDecodedCert(cert);
}
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+ #endif
- WOLFSSL_LEAVE("wolfSSL_X509_ext_isSet_by_NID", isSet);
-
- return isSet;
+ return ret;
}
+#endif /* (KEEP_PEER_CERT && SESSION_CERTS) || (OPENSSL_ALL && HAVE_PKCS7) */
- int wolfSSL_X509_ext_get_critical_by_NID(WOLFSSL_X509* x509, int nid)
+#ifdef KEEP_PEER_CERT
+ WOLFSSL_ABI
+ WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl)
{
- int crit = 0;
-
- WOLFSSL_ENTER("wolfSSL_X509_ext_get_critical_by_NID");
+ WOLFSSL_ENTER("SSL_get_peer_certificate");
+ if (ssl == NULL)
+ return NULL;
- if (x509 != NULL) {
- switch (nid) {
- case BASIC_CA_OID: crit = x509->basicConstCrit; break;
- case ALT_NAMES_OID: crit = x509->subjAltNameCrit; break;
- case AUTH_KEY_OID: crit = x509->authKeyIdCrit; break;
- case SUBJ_KEY_OID: crit = x509->subjKeyIdCrit; break;
- case KEY_USAGE_OID: crit = x509->keyUsageCrit; break;
- #ifdef WOLFSSL_SEP
- case CERT_POLICY_OID: crit = x509->certPolicyCrit; break;
- #endif /* WOLFSSL_SEP */
+ if (ssl->peerCert.issuer.sz)
+ return &ssl->peerCert;
+#ifdef SESSION_CERTS
+ else if (ssl->session.chain.count > 0) {
+ if (DecodeToX509(&ssl->peerCert, ssl->session.chain.certs[0].buffer,
+ ssl->session.chain.certs[0].length) == 0) {
+ return &ssl->peerCert;
}
}
-
- WOLFSSL_LEAVE("wolfSSL_X509_ext_get_critical_by_NID", crit);
-
- return crit;
+#endif
+ return 0;
}
+#endif /* KEEP_PEER_CERT */
- int wolfSSL_X509_get_isSet_pathLength(WOLFSSL_X509* x509)
- {
- int isSet = 0;
-
- WOLFSSL_ENTER("wolfSSL_X509_get_isSet_pathLength");
+#if defined(SESSION_CERTS)
+/* Return stack of peer certs.
+ * If Qt or OPENSSL_ALL is defined then return ssl->peerCertChain.
+ * All other cases return &ssl->session.chain
+ * ssl->peerCertChain is type WOLFSSL_STACK*
+ * ssl->session.chain is type WOLFSSL_X509_CHAIN
+ * Caller does not need to free return. The stack is Free'd when WOLFSSL* ssl is.
+ */
+WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl)
+{
+ WOLFSSL_STACK* sk;
+ WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain");
- if (x509 != NULL)
- isSet = x509->basicConstPlSet;
+ if (ssl == NULL)
+ return NULL;
- WOLFSSL_LEAVE("wolfSSL_X509_get_isSet_pathLength", isSet);
+ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ if (ssl->peerCertChain == NULL)
+ wolfSSL_set_peer_cert_chain((WOLFSSL*) ssl);
+ sk = ssl->peerCertChain;
+ #else
+ sk = (WOLF_STACK_OF(WOLFSSL_X509)* )&ssl->session.chain;
+ #endif
- return isSet;
+ if (sk == NULL) {
+ WOLFSSL_MSG("Error: Null Peer Cert Chain");
}
+ return sk;
+}
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+/* Builds up and creates a stack of peer certificates for ssl->peerCertChain
+ based off of the ssl session chain. Returns stack of WOLFSSL_X509 certs or
+ NULL on failure */
+WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl)
+{
+ WOLFSSL_STACK* sk;
+ WOLFSSL_X509* x509;
+ int i = 0;
+ int ret;
- word32 wolfSSL_X509_get_pathLength(WOLFSSL_X509* x509)
- {
- word32 pathLength = 0;
-
- WOLFSSL_ENTER("wolfSSL_X509_get_pathLength");
+ WOLFSSL_ENTER("wolfSSL_set_peer_cert_chain");
+ if ((ssl == NULL) || (ssl->session.chain.count == 0))
+ return NULL;
- if (x509 != NULL)
- pathLength = x509->pathLength;
+ sk = wolfSSL_sk_X509_new();
+ i = ssl->session.chain.count-1;
+ for (; i >= 0; i--) {
+ /* For servers, the peer certificate chain does not include the peer
+ certificate, so do not add it to the stack */
+ if (ssl->options.side == WOLFSSL_SERVER_END && i == 0)
+ continue;
+ x509 = wolfSSL_X509_new();
+ if (x509 == NULL) {
+ WOLFSSL_MSG("Error Creating X509");
+ return NULL;
+ }
+ ret = DecodeToX509(x509, ssl->session.chain.certs[i].buffer,
+ ssl->session.chain.certs[i].length);
- WOLFSSL_LEAVE("wolfSSL_X509_get_pathLength", pathLength);
+ if (ret != 0 || wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error decoding cert");
+ wolfSSL_X509_free(x509);
+ wolfSSL_sk_X509_free(sk);
+ return NULL;
+ }
+ }
- return pathLength;
+ if (sk == NULL) {
+ WOLFSSL_MSG("Null session chain");
}
+ /* This is Free'd when ssl is Free'd */
+ ssl->peerCertChain = sk;
+ return sk;
+}
+#endif /* OPENSSL_ALL || WOLFSSL_QT */
+#endif /* SESSION_CERTS */
+#ifndef NO_CERTS
+#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \
+ defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- unsigned int wolfSSL_X509_get_keyUsage(WOLFSSL_X509* x509)
- {
- word16 usage = 0;
+/* user externally called free X509, if dynamic go ahead with free, otherwise
+ * don't */
+static void ExternalFreeX509(WOLFSSL_X509* x509)
+{
+ int doFree = 0;
- WOLFSSL_ENTER("wolfSSL_X509_get_keyUsage");
+ WOLFSSL_ENTER("ExternalFreeX509");
+ if (x509) {
+ if (x509->dynamicMemory) {
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+ if (wc_LockMutex(&x509->refMutex) != 0) {
+ WOLFSSL_MSG("Couldn't lock x509 mutex");
+ }
+ /* only free if all references to it are done */
+ x509->refCount--;
+ if (x509->refCount == 0)
+ doFree = 1;
+ wc_UnLockMutex(&x509->refMutex);
+ #else
+ doFree = 1;
+ #endif /* OPENSSL_EXTRA */
- if (x509 != NULL)
- usage = x509->keyUsage;
+ if (doFree) {
+ FreeX509(x509);
+ XFREE(x509, x509->heap, DYNAMIC_TYPE_X509);
+ }
+ } else {
+ WOLFSSL_MSG("free called on non dynamic object, not freeing");
+ }
+ }
+}
- WOLFSSL_LEAVE("wolfSSL_X509_get_keyUsage", usage);
+/* Frees an external WOLFSSL_X509 structure */
+WOLFSSL_ABI
+void wolfSSL_X509_free(WOLFSSL_X509* x509)
+{
+ WOLFSSL_ENTER("wolfSSL_FreeX509");
+ ExternalFreeX509(x509);
+}
- return usage;
+
+/* copy name into in buffer, at most sz bytes, if buffer is null will
+ malloc buffer, call responsible for freeing */
+WOLFSSL_ABI
+char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME* name, char* in, int sz)
+{
+ int copySz;
+
+ if (name == NULL) {
+ WOLFSSL_MSG("WOLFSSL_X509_NAME pointer was NULL");
+ return NULL;
}
+ copySz = min(sz, name->sz);
- byte* wolfSSL_X509_get_authorityKeyID(
- WOLFSSL_X509* x509, byte* dst, int* dstLen)
- {
- byte *id = NULL;
- int copySz = 0;
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_oneline");
+ if (!name->sz) return in;
- WOLFSSL_ENTER("wolfSSL_X509_get_authorityKeyID");
+ if (!in) {
+ #ifdef WOLFSSL_STATIC_MEMORY
+ WOLFSSL_MSG("Using static memory -- please pass in a buffer");
+ return NULL;
+ #else
+ in = (char*)XMALLOC(name->sz, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (!in ) return in;
+ copySz = name->sz;
+ #endif
+ }
- if (x509 != NULL) {
- if (x509->authKeyIdSet) {
- copySz = min(dstLen != NULL ? *dstLen : 0,
- (int)x509->authKeyIdSz);
- id = x509->authKeyId;
- }
+ if (copySz <= 0)
+ return in;
- if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) {
- XMEMCPY(dst, id, copySz);
- id = dst;
- *dstLen = copySz;
- }
- }
+ XMEMCPY(in, name->name, copySz - 1);
+ in[copySz - 1] = 0;
- WOLFSSL_LEAVE("wolfSSL_X509_get_authorityKeyID", copySz);
+ return in;
+}
- return id;
+#if defined(OPENSSL_EXTRA) && defined(XSNPRINTF)
+/* Copies X509 subject name into a buffer, with comma-separated name entries
+ * (matching OpenSSL v1.0.0 format)
+ * Example Output for Issuer:
+ *
+ * C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting,
+ * CN=www.wolfssl.com, emailAddress=info@wolfssl.com
+ */
+char* wolfSSL_X509_get_name_oneline(WOLFSSL_X509_NAME* name, char* in, int sz)
+{
+ WOLFSSL_X509_NAME_ENTRY* entry;
+ int nameSz, strSz, count, i, idx = 0;
+ int totalSz = 0;
+ char *str;
+ char tmpBuf[256];
+ char buf[80];
+ const char* sn;
+ WOLFSSL_ENTER("wolfSSL_X509_get_name_oneline");
+
+ if (name == NULL) {
+ WOLFSSL_MSG("wolfSSL_X509_get_subject_name failed");
+ return NULL;
}
+ #ifdef WOLFSSL_STATIC_MEMORY
+ if (!in) {
+ WOLFSSL_MSG("Using static memory -- please pass in a buffer");
+ return NULL;
+ }
+ #endif
+ tmpBuf[0] = '\0'; /* Make sure tmpBuf is NULL terminated */
+ /* Loop through X509 name entries and copy new format to buffer */
+ count = wolfSSL_X509_NAME_entry_count(name);
+ for (i = 0; i < count; i++) {
- byte* wolfSSL_X509_get_subjectKeyID(
- WOLFSSL_X509* x509, byte* dst, int* dstLen)
- {
- byte *id = NULL;
- int copySz = 0;
+ /* Get name entry and size */
+ entry = wolfSSL_X509_NAME_get_entry(name, i);
+ if (entry == NULL) {
+ WOLFSSL_MSG("X509_NAME_get_entry failed");
+ return NULL;
+ }
+ nameSz = wolfSSL_X509_NAME_get_text_by_NID(name, entry->nid, buf,
+ sizeof(buf));
+ if (nameSz < 0) {
+ WOLFSSL_MSG("X509_NAME_get_text_by_NID failed");
+ return NULL;
+ }
- WOLFSSL_ENTER("wolfSSL_X509_get_subjectKeyID");
+ /* Get short name */
+ sn = wolfSSL_OBJ_nid2sn(entry->nid);
+ if (sn == NULL) {
+ WOLFSSL_MSG("OBJ_nid2sn failed");
+ return NULL;
+ }
- if (x509 != NULL) {
- if (x509->subjKeyIdSet) {
- copySz = min(dstLen != NULL ? *dstLen : 0,
- (int)x509->subjKeyIdSz);
- id = x509->subjKeyId;
+ /* Copy sn and name text to buffer
+ * Add extra strSz for '=', ',', ' ' and '\0' characters in XSNPRINTF.
+ */
+ if (i != count - 1) {
+ strSz = (int)XSTRLEN(sn) + nameSz + 4;
+ totalSz+= strSz;
+ str = (char*)XMALLOC(strSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (str == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return NULL;
}
-
- if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) {
- XMEMCPY(dst, id, copySz);
- id = dst;
- *dstLen = copySz;
+ XSNPRINTF(str, strSz, "%s=%s, ", sn, buf);
+ }
+ else {
+ /* Copy last name entry
+ * Add extra strSz for '=' and '\0' characters in XSNPRINTF.
+ */
+ strSz = (int)XSTRLEN(sn) + nameSz + 2;
+ totalSz+= strSz;
+ str = (char*)XMALLOC(strSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (str == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return NULL;
}
+ XSNPRINTF(str, strSz, "%s=%s", sn, buf);
}
+ /* Copy string to tmpBuf */
+ XSTRNCAT(tmpBuf, str, strSz);
+ idx += strSz;
+ XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
- WOLFSSL_LEAVE("wolfSSL_X509_get_subjectKeyID", copySz);
-
- return id;
+ /* Allocate space based on total string size if no buffer was provided */
+ if (!in) {
+ in = (char*)XMALLOC(totalSz+1, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (in == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return in;
+ }
+ }
+ else {
+ if (totalSz > sz) {
+ WOLFSSL_MSG("Memory error");
+ return NULL;
+ }
}
+ XMEMCPY(in, tmpBuf, totalSz);
+ in[totalSz] = '\0';
- int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME* name)
- {
- int count = 0;
+ return in;
+}
+#endif
- WOLFSSL_ENTER("wolfSSL_X509_NAME_entry_count");
- if (name != NULL)
- count = name->fullName.entryCount;
+/* Wraps wolfSSL_X509_d2i
+ *
+ * returns a WOLFSSL_X509 structure pointer on success and NULL on fail
+ */
+WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509, const unsigned char** in,
+ int len)
+{
+ WOLFSSL_X509* newX509 = NULL;
- WOLFSSL_LEAVE("wolfSSL_X509_NAME_entry_count", count);
- return count;
+ newX509 = wolfSSL_X509_d2i(x509, *in, len);
+ if (newX509 != NULL) {
+ *in += newX509->derCert->length;
}
+ return newX509;
+}
- int wolfSSL_X509_NAME_get_text_by_NID(WOLFSSL_X509_NAME* name,
- int nid, char* buf, int len)
- {
- char *text = NULL;
- int textSz = 0;
+WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len)
+{
+ WOLFSSL_X509 *newX509 = NULL;
- WOLFSSL_ENTER("wolfSSL_X509_NAME_get_text_by_NID");
+ WOLFSSL_ENTER("wolfSSL_X509_d2i");
- switch (nid) {
- case ASN_COMMON_NAME:
- text = name->fullName.fullName + name->fullName.cnIdx;
- textSz = name->fullName.cnLen;
- break;
- case ASN_SUR_NAME:
- text = name->fullName.fullName + name->fullName.snIdx;
- textSz = name->fullName.snLen;
- break;
- case ASN_SERIAL_NUMBER:
- text = name->fullName.fullName + name->fullName.serialIdx;
- textSz = name->fullName.serialLen;
- break;
- case ASN_COUNTRY_NAME:
- text = name->fullName.fullName + name->fullName.cIdx;
- textSz = name->fullName.cLen;
- break;
- case ASN_LOCALITY_NAME:
- text = name->fullName.fullName + name->fullName.lIdx;
- textSz = name->fullName.lLen;
- break;
- case ASN_STATE_NAME:
- text = name->fullName.fullName + name->fullName.stIdx;
- textSz = name->fullName.stLen;
- break;
- case ASN_ORG_NAME:
- text = name->fullName.fullName + name->fullName.oIdx;
- textSz = name->fullName.oLen;
- break;
- case ASN_ORGUNIT_NAME:
- text = name->fullName.fullName + name->fullName.ouIdx;
- textSz = name->fullName.ouLen;
- break;
- default:
- break;
- }
+ if (in != NULL && len != 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ DecodedCert* cert;
+ #else
+ DecodedCert cert[1];
+ #endif
- if (buf != NULL && text != NULL) {
- textSz = min(textSz, len);
- XMEMCPY(buf, text, textSz);
- buf[textSz] = '\0';
- }
+ #ifdef WOLFSSL_SMALL_STACK
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+ DYNAMIC_TYPE_DCERT);
+ if (cert == NULL)
+ return NULL;
+ #endif
- WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_text_by_NID", textSz);
- return textSz;
+ InitDecodedCert(cert, (byte*)in, len, NULL);
+ if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) {
+ newX509 = wolfSSL_X509_new();
+ if (newX509 != NULL) {
+ if (CopyDecodedToX509(newX509, cert) != 0) {
+ wolfSSL_X509_free(newX509);
+ newX509 = NULL;
+ }
+ }
+ }
+ FreeDecodedCert(cert);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+ #endif
}
-#endif
+ if (x509 != NULL)
+ *x509 = newX509;
- /* copy name into in buffer, at most sz bytes, if buffer is null will
- malloc buffer, call responsible for freeing */
- char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME* name, char* in, int sz)
- {
- int copySz = min(sz, name->sz);
+ return newX509;
+}
+#endif /* KEEP_PEER_CERT || SESSION_CERTS || OPENSSL_EXTRA ||
+ OPENSSL_EXTRA_X509_SMALL */
- WOLFSSL_ENTER("wolfSSL_X509_NAME_oneline");
- if (!name->sz) return in;
- if (!in) {
- in = (char*)XMALLOC(name->sz, 0, DYNAMIC_TYPE_OPENSSL);
- if (!in ) return in;
- copySz = name->sz;
- }
- if (copySz == 0)
- return in;
+#if defined(OPENSSL_ALL) || defined(KEEP_OUR_CERT) || defined(KEEP_PEER_CERT) || \
+ defined(SESSION_CERTS)
+ /* return the next, if any, altname from the peer cert */
+ WOLFSSL_ABI
+ char* wolfSSL_X509_get_next_altname(WOLFSSL_X509* cert)
+ {
+ char* ret = NULL;
+ WOLFSSL_ENTER("wolfSSL_X509_get_next_altname");
- XMEMCPY(in, name->name, copySz - 1);
- in[copySz - 1] = 0;
+ /* don't have any to work with */
+ if (cert == NULL || cert->altNames == NULL)
+ return NULL;
- return in;
- }
+ /* already went through them */
+ if (cert->altNamesNext == NULL)
+ return NULL;
+ ret = cert->altNamesNext->name;
+ cert->altNamesNext = cert->altNamesNext->next;
- int wolfSSL_X509_get_signature_type(WOLFSSL_X509* x509)
+ return ret;
+ }
+
+ int wolfSSL_X509_get_isCA(WOLFSSL_X509* x509)
{
- int type = 0;
+ int isCA = 0;
- WOLFSSL_ENTER("wolfSSL_X509_get_signature_type");
+ WOLFSSL_ENTER("wolfSSL_X509_get_isCA");
if (x509 != NULL)
- type = x509->sigOID;
+ isCA = x509->isCa;
- return type;
- }
+ WOLFSSL_LEAVE("wolfSSL_X509_get_isCA", isCA);
+ return isCA;
+ }
int wolfSSL_X509_get_signature(WOLFSSL_X509* x509,
unsigned char* buf, int* bufSz)
{
WOLFSSL_ENTER("wolfSSL_X509_get_signature");
- if (x509 == NULL || bufSz == NULL || *bufSz < (int)x509->sig.length)
- return SSL_FATAL_ERROR;
+ if (x509 == NULL || bufSz == NULL || (*bufSz < (int)x509->sig.length &&
+ buf != NULL))
+ return WOLFSSL_FATAL_ERROR;
if (buf != NULL)
XMEMCPY(buf, x509->sig.buffer, x509->sig.length);
*bufSz = x509->sig.length;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
+ /* Getter function that copies over the DER public key buffer to "buf" and
+ * sets the size in bufSz. If "buf" is NULL then just bufSz is set to needed
+ * buffer size. "bufSz" passed in should initially be set by the user to be
+ * the size of "buf". This gets checked to make sure the buffer is large
+ * enough to hold the public key.
+ *
+ * Note: this is the X.509 form of key with "header" info.
+ * return WOLFSSL_SUCCESS on success
+ */
+ int wolfSSL_X509_get_pubkey_buffer(WOLFSSL_X509* x509,
+ unsigned char* buf, int* bufSz)
+ {
+ #ifdef WOLFSSL_SMALL_STACK
+ DecodedCert* cert;
+ #else
+ DecodedCert cert[1];
+ #endif
+ word32 idx;
+ const byte* der;
+ int length = 0;
+ int ret, derSz = 0;
+ int badDate = 0;
+ const byte* pubKeyX509 = NULL;
+ int pubKeyX509Sz = 0;
+
+ WOLFSSL_ENTER("wolfSSL_X509_get_pubkey_buffer");
+ if (x509 == NULL || bufSz == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", BAD_FUNC_ARG);
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+
+ #ifdef WOLFSSL_SMALL_STACK
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert),
+ x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (cert == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", MEMORY_E);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ #endif
+
+ der = wolfSSL_X509_get_der(x509, &derSz);
+ InitDecodedCert(cert, der, derSz, NULL);
+ ret = wc_GetPubX509(cert, 0, &badDate);
+ if (ret >= 0) {
+ idx = cert->srcIdx;
+ pubKeyX509 = cert->source + cert->srcIdx;
+ ret = GetSequence(cert->source, &cert->srcIdx, &length,
+ cert->maxIdx);
+ pubKeyX509Sz = length + (cert->srcIdx - idx);
+ }
+
+ FreeDecodedCert(cert);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(cert, x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+
+ if (ret < 0) {
+ WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", ret);
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (buf != NULL) {
+ if (pubKeyX509Sz > *bufSz) {
+ WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", BUFFER_E);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ XMEMCPY(buf, pubKeyX509, pubKeyX509Sz);
+ }
+ *bufSz = pubKeyX509Sz;
+
+ return WOLFSSL_SUCCESS;
+ }
+
+
+ /* Getter function for the public key OID value
+ * return public key OID stored in WOLFSSL_X509 structure */
+ int wolfSSL_X509_get_pubkey_type(WOLFSSL_X509* x509)
+ {
+ if (x509 == NULL)
+ return WOLFSSL_FAILURE;
+ return x509->pubKeyOID;
+ }
+
/* write X509 serial number in unsigned binary to buffer
buffer needs to be at least EXTERNAL_SERIAL_SIZE (32) for all cases
- return SSL_SUCCESS on success */
- int wolfSSL_X509_get_serial_number(WOLFSSL_X509* x509, byte* in, int* inOutSz)
+ return WOLFSSL_SUCCESS on success */
+ int wolfSSL_X509_get_serial_number(WOLFSSL_X509* x509,
+ byte* in, int* inOutSz)
{
WOLFSSL_ENTER("wolfSSL_X509_get_serial_number");
if (x509 == NULL || in == NULL ||
@@ -8954,54 +17431,111 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
XMEMCPY(in, x509->serial, x509->serialSz);
*inOutSz = x509->serialSz;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
-
+ /* not an openssl compatibility function - getting for derCert */
const byte* wolfSSL_X509_get_der(WOLFSSL_X509* x509, int* outSz)
{
WOLFSSL_ENTER("wolfSSL_X509_get_der");
- if (x509 == NULL || outSz == NULL)
+ if (x509 == NULL || x509->derCert == NULL || outSz == NULL)
return NULL;
- *outSz = (int)x509->derCert.length;
- return x509->derCert.buffer;
+ *outSz = (int)x509->derCert->length;
+ return x509->derCert->buffer;
}
-
- int wolfSSL_X509_version(WOLFSSL_X509* x509)
+ /* used by JSSE (not a standard compatibility function) */
+ /* this is not thread safe */
+ WOLFSSL_ABI
+ const byte* wolfSSL_X509_notBefore(WOLFSSL_X509* x509)
{
- WOLFSSL_ENTER("wolfSSL_X509_version");
+ static byte notBeforeData[CTC_DATE_SIZE]; /* temp buffer for date */
+ WOLFSSL_ENTER("wolfSSL_X509_notBefore");
if (x509 == NULL)
- return 0;
-
- return x509->version;
- }
+ return NULL;
+ XMEMSET(notBeforeData, 0, sizeof(notBeforeData));
+ notBeforeData[0] = (byte)x509->notBefore.type;
+ notBeforeData[1] = (byte)x509->notBefore.length;
+ XMEMCPY(&notBeforeData[2], x509->notBefore.data, x509->notBefore.length);
- const byte* wolfSSL_X509_notBefore(WOLFSSL_X509* x509)
+ return notBeforeData;
+ }
+ /* used by JSSE (not a standard compatibility function) */
+ /* this is not thread safe */
+ WOLFSSL_ABI
+ const byte* wolfSSL_X509_notAfter(WOLFSSL_X509* x509)
{
- WOLFSSL_ENTER("wolfSSL_X509_notBefore");
+ static byte notAfterData[CTC_DATE_SIZE]; /* temp buffer for date */
+ WOLFSSL_ENTER("wolfSSL_X509_notAfter");
if (x509 == NULL)
return NULL;
- return x509->notBefore;
+ XMEMSET(notAfterData, 0, sizeof(notAfterData));
+ notAfterData[0] = (byte)x509->notAfter.type;
+ notAfterData[1] = (byte)x509->notAfter.length;
+ XMEMCPY(&notAfterData[2], x509->notAfter.data, x509->notAfter.length);
+
+ return notAfterData;
}
+ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) && !defined(NO_WOLFSSL_STUB)
+ WOLFSSL_ASN1_TIME* wolfSSL_X509_gmtime_adj(WOLFSSL_ASN1_TIME *s, long adj)
+ {
+ (void) s;
+ (void) adj;
+ WOLFSSL_STUB("wolfSSL_X509_gmtime_adj");
+ return NULL;
+ }
+ #endif
- const byte* wolfSSL_X509_notAfter(WOLFSSL_X509* x509)
+ /* get the buffer to be signed (tbs) from the WOLFSSL_X509 certificate
+ *
+ * outSz : gets set to the size of the buffer
+ * returns a pointer to the internal buffer at the location of TBS on
+ * on success and NULL on failure.
+ */
+ const unsigned char* wolfSSL_X509_get_tbs(WOLFSSL_X509* x509, int* outSz)
{
- WOLFSSL_ENTER("wolfSSL_X509_notAfter");
+ int sz = 0, len;
+ unsigned int idx = 0, tmpIdx;
+ const unsigned char* der = NULL;
+ const unsigned char* tbs = NULL;
- if (x509 == NULL)
+ if (x509 == NULL || outSz == NULL) {
return NULL;
+ }
- return x509->notAfter;
+ der = wolfSSL_X509_get_der(x509, &sz);
+ if (der == NULL) {
+ return NULL;
+ }
+
+ if (GetSequence(der, &idx, &len, sz) < 0) {
+ return NULL;
+ }
+ tbs = der + idx;
+ tmpIdx = idx;
+ if (GetSequence(der, &idx, &len, sz) < 0) {
+ return NULL;
+ }
+ *outSz = len + (idx - tmpIdx);
+ return tbs;
}
+ int wolfSSL_X509_version(WOLFSSL_X509* x509)
+ {
+ WOLFSSL_ENTER("wolfSSL_X509_version");
+
+ if (x509 == NULL)
+ return 0;
+
+ return x509->version;
+ }
#ifdef WOLFSSL_SEP
@@ -9019,9 +17553,14 @@ byte* wolfSSL_X509_get_device_type(WOLFSSL_X509* x509, byte* in, int *inOutSz)
copySz = min(*inOutSz, x509->deviceTypeSz);
if (!in) {
+ #ifdef WOLFSSL_STATIC_MEMORY
+ WOLFSSL_MSG("Using static memory -- please pass in a buffer");
+ return NULL;
+ #else
in = (byte*)XMALLOC(x509->deviceTypeSz, 0, DYNAMIC_TYPE_OPENSSL);
if (!in) return in;
copySz = x509->deviceTypeSz;
+ #endif
}
XMEMCPY(in, x509->deviceType, copySz);
@@ -9042,9 +17581,14 @@ byte* wolfSSL_X509_get_hw_type(WOLFSSL_X509* x509, byte* in, int* inOutSz)
copySz = min(*inOutSz, x509->hwTypeSz);
if (!in) {
+ #ifdef WOLFSSL_STATIC_MEMORY
+ WOLFSSL_MSG("Using static memory -- please pass in a buffer");
+ return NULL;
+ #else
in = (byte*)XMALLOC(x509->hwTypeSz, 0, DYNAMIC_TYPE_OPENSSL);
if (!in) return in;
copySz = x509->hwTypeSz;
+ #endif
}
XMEMCPY(in, x509->hwType, copySz);
@@ -9054,7 +17598,8 @@ byte* wolfSSL_X509_get_hw_type(WOLFSSL_X509* x509, byte* in, int* inOutSz)
}
-byte* wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509* x509,byte* in,int* inOutSz)
+byte* wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509* x509,byte* in,
+ int* inOutSz)
{
int copySz;
@@ -9065,9 +17610,14 @@ byte* wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509* x509,byte* in,int* inOutSz
copySz = min(*inOutSz, x509->hwSerialNumSz);
if (!in) {
+ #ifdef WOLFSSL_STATIC_MEMORY
+ WOLFSSL_MSG("Using static memory -- please pass in a buffer");
+ return NULL;
+ #else
in = (byte*)XMALLOC(x509->hwSerialNumSz, 0, DYNAMIC_TYPE_OPENSSL);
if (!in) return in;
copySz = x509->hwSerialNumSz;
+ #endif
}
XMEMCPY(in, x509->hwSerialNum, copySz);
@@ -9078,51 +17628,981 @@ byte* wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509* x509,byte* in,int* inOutSz
#endif /* WOLFSSL_SEP */
+/* require OPENSSL_EXTRA since wolfSSL_X509_free is wrapped by OPENSSL_EXTRA */
+#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA)
-WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len)
+WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notBefore(const WOLFSSL_X509* x509)
{
- WOLFSSL_X509 *newX509 = NULL;
+ WOLFSSL_ENTER("wolfSSL_X509_get_notBefore");
- WOLFSSL_ENTER("wolfSSL_X509_d2i");
+ if (x509 == NULL)
+ return NULL;
- if (in != NULL && len != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert = NULL;
- #else
- DecodedCert cert[1];
- #endif
+ return (WOLFSSL_ASN1_TIME*)&x509->notBefore;
+}
- #ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (cert == NULL)
- return NULL;
- #endif
- InitDecodedCert(cert, (byte*)in, len, NULL);
- if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) {
- newX509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509),
- NULL, DYNAMIC_TYPE_X509);
- if (newX509 != NULL) {
- InitX509(newX509, 1);
- if (CopyDecodedToX509(newX509, cert) != 0) {
- XFREE(newX509, NULL, DYNAMIC_TYPE_X509);
- newX509 = NULL;
- }
+WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notAfter(const WOLFSSL_X509* x509)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_get_notAfter");
+
+ if (x509 == NULL)
+ return NULL;
+
+ return (WOLFSSL_ASN1_TIME*)&x509->notAfter;
+}
+
+
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, WOLFSSL_X509* x509)
+{
+ WOLFSSL_STACK* node;
+ WOLFSSL_ENTER("wolfSSL_sk_X509_push");
+
+ if (sk == NULL || x509 == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* no previous values in stack */
+ if (sk->data.x509 == NULL) {
+ sk->data.x509 = x509;
+ sk->num += 1;
+ return WOLFSSL_SUCCESS;
+ }
+
+ /* stack already has value(s) create a new node and add more */
+ node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+ DYNAMIC_TYPE_X509);
+ if (node == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return WOLFSSL_FAILURE;
+ }
+ XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+ /* push new x509 onto head of stack */
+ node->data.x509 = sk->data.x509;
+ node->next = sk->next;
+ node->type = sk->type;
+ sk->next = node;
+ sk->data.x509 = x509;
+ sk->num += 1;
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) {
+ WOLFSSL_STACK* node;
+ WOLFSSL_X509* x509;
+
+ if (sk == NULL) {
+ return NULL;
+ }
+
+ node = sk->next;
+ x509 = sk->data.x509;
+
+ if (node != NULL) { /* update sk and remove node from stack */
+ sk->data.x509 = node->data.x509;
+ sk->next = node->next;
+ XFREE(node, NULL, DYNAMIC_TYPE_X509);
+ }
+ else { /* last x509 in stack */
+ sk->data.x509 = NULL;
+ }
+
+ if (sk->num > 0) {
+ sk->num -= 1;
+ }
+
+ return x509;
+}
+
+/* Getter function for WOLFSSL_X509 pointer
+ *
+ * sk is the stack to retrieve pointer from
+ * i is the index value in stack
+ *
+ * returns a pointer to a WOLFSSL_X509 structure on success and NULL on
+ * fail
+ */
+WOLFSSL_X509* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)* sk, int i)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_X509_value");
+
+ for (; sk != NULL && i > 0; i--)
+ sk = sk->next;
+
+ if (i != 0 || sk == NULL)
+ return NULL;
+ return sk->data.x509;
+}
+
+WOLFSSL_X509* wolfSSL_sk_X509_shift(WOLF_STACK_OF(WOLFSSL_X509)* sk)
+{
+ return wolfSSL_sk_X509_pop(sk);
+}
+
+#ifndef NO_WOLFSSL_STUB
+void* wolfSSL_sk_X509_OBJECT_value(WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* sk, int x)
+{
+ (void) sk;
+ (void) x;
+ return NULL;
+}
+#endif
+
+
+/* Free's all nodes in X509 stack. This is different then wolfSSL_sk_X509_free
+ * in that it allows for choosing the function to use when freeing an X509s.
+ *
+ * sk stack to free nodes in
+ * f X509 free function
+ */
+void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk,
+ void (*f) (WOLFSSL_X509*))
+{
+ WOLFSSL_STACK* node;
+
+ WOLFSSL_ENTER("wolfSSL_sk_X509_pop_free");
+
+ if (sk == NULL) {
+ return;
+ }
+
+ /* parse through stack freeing each node */
+ node = sk->next;
+ while (node && sk->num > 1) {
+ WOLFSSL_STACK* tmp = node;
+ node = node->next;
+
+ if (f)
+ f(tmp->data.x509);
+ else
+ wolfSSL_X509_free(tmp->data.x509);
+ tmp->data.x509 = NULL;
+ XFREE(tmp, NULL, DYNAMIC_TYPE_X509);
+ sk->num -= 1;
+ }
+
+ /* free head of stack */
+ if (sk->num == 1) {
+ if (f)
+ f(sk->data.x509);
+ else
+ wolfSSL_X509_free(sk->data.x509);
+ sk->data.x509 = NULL;
+ }
+ XFREE(sk, NULL, DYNAMIC_TYPE_X509);
+}
+
+
+/* free structure for x509 stack */
+void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509)* sk)
+{
+ wolfSSL_sk_X509_pop_free(sk, NULL);
+}
+
+#endif /* NO_CERTS && OPENSSL_EXTRA */
+
+#if defined(OPENSSL_ALL) || defined (WOLFSSL_QT)
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_ACCESS_DESCRIPTION_push(WOLF_STACK_OF(ACCESS_DESCRIPTION)* sk,
+ WOLFSSL_ACCESS_DESCRIPTION* access)
+{
+ WOLFSSL_STACK* node;
+
+ WOLFSSL_ENTER("wolfSSL_sk_ACCESS_DESCRIPTION_push");
+
+ if (sk == NULL || access == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* no previous values in stack */
+ if (sk->data.access == NULL) {
+ sk->data.access = access;
+ sk->num += 1;
+ return WOLFSSL_SUCCESS;
+ }
+
+ /* stack already has value(s) create a new node and add more */
+ node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+ DYNAMIC_TYPE_ASN1);
+ if (node == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return WOLFSSL_FAILURE;
+ }
+ XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+ /* push new obj onto head of stack */
+ node->data.access = sk->data.access;
+ node->next = sk->next;
+ node->type = sk->type;
+ sk->next = node;
+ sk->data.access = access;
+ sk->num += 1;
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* Frees all nodes in ACCESS_DESCRIPTION stack
+*
+* sk stack of nodes to free
+* f free function to use, not called with wolfSSL
+*/
+void wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(WOLFSSL_STACK* sk,
+ void (*f) (WOLFSSL_ACCESS_DESCRIPTION*))
+{
+ WOLFSSL_STACK* node;
+
+ WOLFSSL_ENTER("wolfSSL_sk_ACCESS_DESCRIPTION_pop_free");
+
+ if (sk == NULL) {
+ return;
+ }
+
+ /* parse through stack freeing each node */
+ node = sk->next;
+ while (node && sk->num > 1) {
+ WOLFSSL_STACK* tmp = node;
+ node = node->next;
+
+ if (f)
+ f(tmp->data.access);
+ else
+ wolfSSL_ACCESS_DESCRIPTION_free(tmp->data.access);
+ tmp->data.access = NULL;
+ XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1);
+ sk->num -= 1;
+ }
+
+ /* free head of stack */
+ if (sk->num == 1) {
+ if (f)
+ f(sk->data.access);
+ else {
+ if(sk->data.access->method) {
+
+ wolfSSL_ASN1_OBJECT_free(sk->data.access->method);
+ }
+ if(sk->data.access->location) {
+ wolfSSL_GENERAL_NAME_free(sk->data.access->location);
}
}
- FreeDecodedCert(cert);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ sk->data.access = NULL;
+ }
+ XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
+}
+
+void wolfSSL_sk_ACCESS_DESCRIPTION_free(WOLFSSL_STACK* sk)
+{
+ wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(sk, NULL);
+}
+
+void wolfSSL_ACCESS_DESCRIPTION_free(WOLFSSL_ACCESS_DESCRIPTION* access)
+{
+ WOLFSSL_ENTER("wolfSSL_ACCESS_DESCRIPTION_free");
+ if (access == NULL)
+ return;
+
+ if (access->method)
+ wolfSSL_ASN1_OBJECT_free(access->method);
+ if (access->location)
+ wolfSSL_GENERAL_NAME_free(access->location);
+
+ /* access = NULL, don't try to access or double free it */
+}
+#endif
+
+#ifdef OPENSSL_EXTRA
+
+/* create a generic wolfSSL stack node
+ * returns a new WOLFSSL_STACK structure on success */
+WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap)
+{
+ WOLFSSL_STACK* sk;
+ WOLFSSL_ENTER("wolfSSL_sk_new_node");
+
+ sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), heap,
+ DYNAMIC_TYPE_OPENSSL);
+ if (sk != NULL) {
+ XMEMSET(sk, 0, sizeof(*sk));
+ sk->heap = heap;
+ }
+
+ return sk;
+}
+
+/* free's node but does not free internal data such as in->data.x509 */
+void wolfSSL_sk_free_node(WOLFSSL_STACK* in)
+{
+ if (in != NULL) {
+ XFREE(in, in->heap, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+
+/* pushes node "in" onto "stack" and returns pointer to the new stack on success
+ * also handles internal "num" for number of nodes on stack
+ * return WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* in)
+{
+ if (stack == NULL || in == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (*stack == NULL) {
+ in->num = 1;
+ *stack = in;
+ return WOLFSSL_SUCCESS;
+ }
+
+ in->num = (*stack)->num + 1;
+ in->next = *stack;
+ *stack = in;
+ return WOLFSSL_SUCCESS;
+}
+
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_push(WOLFSSL_STACK* sk, const void *data)
+{
+ int ret = WOLFSSL_FAILURE;
+ WOLFSSL_ENTER("wolfSSL_sk_push");
+
+ switch (sk->type) {
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ case STACK_TYPE_X509:
+ ret = wolfSSL_sk_X509_push(sk, (WOLFSSL_X509*) data);
+ break;
+ #ifndef NO_WOLFSSL_STUB
+ case STACK_TYPE_CIPHER:
+ ret = wolfSSL_sk_CIPHER_push(sk, (WOLFSSL_CIPHER*) data);
+ break;
+ #endif
+ case STACK_TYPE_GEN_NAME:
+ ret = wolfSSL_sk_ASN1_OBJECT_push(sk, (WOLFSSL_ASN1_OBJECT*) data);
+ break;
+ case STACK_TYPE_ACCESS_DESCRIPTION:
+ ret = wolfSSL_sk_ACCESS_DESCRIPTION_push(sk,
+ (WOLFSSL_ACCESS_DESCRIPTION*) data);
+ break;
+ case STACK_TYPE_NULL:
+ ret = wolfSSL_sk_GENERIC_push(sk, (void*) data);
+ break;
+ case STACK_TYPE_OBJ:
+ ret = wolfSSL_sk_ASN1_OBJECT_push(sk, (WOLFSSL_ASN1_OBJECT*) data);
+ break;
#endif
+ default:
+ ret = wolfSSL_sk_ASN1_OBJECT_push(sk, (WOLFSSL_ASN1_OBJECT*) data);
+ break;
}
- if (x509 != NULL)
- *x509 = newX509;
+ return ret;
+}
- return newX509;
+/* Creates and returns new GENERAL_NAME structure */
+WOLFSSL_GENERAL_NAME* wolfSSL_GENERAL_NAME_new(void)
+{
+ WOLFSSL_GENERAL_NAME* gn;
+ WOLFSSL_ENTER("GENERAL_NAME_new");
+
+ gn = (WOLFSSL_GENERAL_NAME*)XMALLOC(sizeof(WOLFSSL_GENERAL_NAME), NULL,
+ DYNAMIC_TYPE_ASN1);
+ if (gn == NULL) {
+ return NULL;
+ }
+ XMEMSET(gn, 0, sizeof(WOLFSSL_GENERAL_NAME));
+
+ gn->d.ia5 = wolfSSL_ASN1_STRING_new();
+ if (gn->d.ia5 == NULL) {
+ WOLFSSL_MSG("Issue creating ASN1_STRING struct");
+ wolfSSL_GENERAL_NAME_free(gn);
+ return NULL;
+ }
+ return gn;
+}
+
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_GENERAL_NAME_push(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)* sk,
+ WOLFSSL_GENERAL_NAME* gn)
+{
+ WOLFSSL_STACK* node;
+ WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_push");
+
+ if (sk == NULL || gn == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* no previous values in stack */
+ if (sk->data.gn == NULL) {
+ sk->data.gn = gn;
+ sk->num += 1;
+
+ return WOLFSSL_SUCCESS;
+ }
+
+ /* stack already has value(s) create a new node and add more */
+ node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+ DYNAMIC_TYPE_ASN1);
+ if (node == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return WOLFSSL_FAILURE;
+ }
+ XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+ /* push new obj onto head of stack */
+ node->data.gn = sk->data.gn;
+ node->next = sk->next;
+ sk->next = node;
+ sk->data.gn = gn;
+ sk->num += 1;
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* Returns the general name at index i from the stack
+ *
+ * sk stack to get general name from
+ * idx index to get
+ *
+ * return a pointer to the internal node of the stack
+ */
+WOLFSSL_GENERAL_NAME* wolfSSL_sk_GENERAL_NAME_value(WOLFSSL_STACK* sk, int idx)
+{
+ WOLFSSL_STACK* ret;
+
+ if (sk == NULL) {
+ return NULL;
+ }
+
+ ret = wolfSSL_sk_get_node(sk, idx);
+ if (ret != NULL) {
+ return ret->data.gn;
+ }
+ return NULL;
+}
+
+/* Gets the number of nodes in the stack
+ *
+ * sk stack to get the number of nodes from
+ *
+ * returns the number of nodes, -1 if no nodes
+ */
+int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_num");
+
+ if (sk == NULL) {
+ return -1;
+ }
+
+ return (int)sk->num;
+}
+
+/* Frees all nodes in a GENERAL NAME stack
+ *
+ * sk stack of nodes to free
+ * f free function to use, not called with wolfSSL
+ */
+void wolfSSL_sk_GENERAL_NAME_pop_free(WOLFSSL_STACK* sk,
+ void (*f) (WOLFSSL_GENERAL_NAME*))
+{
+ WOLFSSL_STACK* node;
+
+ WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_pop_free");
+
+ if (sk == NULL) {
+ return;
+ }
+
+ /* parse through stack freeing each node */
+ node = sk->next;
+ while (node && sk->num > 1) {
+ WOLFSSL_STACK* tmp = node;
+ node = node->next;
+
+ if (f)
+ f(tmp->data.gn);
+ else
+ wolfSSL_GENERAL_NAME_free(tmp->data.gn);
+ XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1);
+ sk->num -= 1;
+ }
+
+ /* free head of stack */
+ if (sk->num == 1) {
+ if (f)
+ f(sk->data.gn);
+ else
+ wolfSSL_GENERAL_NAME_free(sk->data.gn);
+ }
+ XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
+}
+
+void wolfSSL_sk_GENERAL_NAME_free(WOLFSSL_STACK* sk)
+{
+ WOLFSSL_ENTER("sk_GENERAL_NAME_free");
+ wolfSSL_sk_GENERAL_NAME_pop_free(sk, NULL);
+}
+
+
+/* returns the number of nodes in stack on success and WOLFSSL_FATAL_ERROR
+ * on fail */
+int wolfSSL_sk_ACCESS_DESCRIPTION_num(WOLFSSL_STACK* sk)
+{
+ if (sk == NULL) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ return (int)sk->num;
+}
+
+#ifndef NO_WOLFSSL_STUB
+/* similar to call to sk_ACCESS_DESCRIPTION_pop_free */
+void wolfSSL_AUTHORITY_INFO_ACCESS_free(
+ WOLF_STACK_OF(WOLFSSL_ACCESS_DESCRIPTION)* sk)
+{
+ WOLFSSL_STUB("wolfSSL_AUTHORITY_INFO_ACCESS_free");
+ (void)sk;
+}
+#endif
+
+/* returns the node at index "idx", NULL if not found */
+WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx)
+{
+ int i;
+ WOLFSSL_STACK* ret = NULL;
+ WOLFSSL_STACK* current;
+
+ current = sk;
+ for (i = 0; i <= idx && current != NULL; i++) {
+ if (i == idx) {
+ ret = current;
+ break;
+ }
+ current = current->next;
+ }
+ return ret;
+}
+
+/* returns NULL on fail and pointer to internal data on success */
+WOLFSSL_ACCESS_DESCRIPTION* wolfSSL_sk_ACCESS_DESCRIPTION_value(
+ WOLFSSL_STACK* sk, int idx)
+{
+ WOLFSSL_STACK* ret;
+
+ if (sk == NULL) {
+ return NULL;
+ }
+
+ ret = wolfSSL_sk_get_node(sk, idx);
+ if (ret != NULL) {
+ return ret->data.access;
+ }
+ return NULL;
+}
+
+/* Frees GENERAL_NAME objects.
+*/
+void wolfSSL_GENERAL_NAME_free(WOLFSSL_GENERAL_NAME* name)
+{
+ WOLFSSL_ENTER("wolfSSL_GENERAL_NAME_Free");
+ if(name != NULL) {
+ if (name->d.dNSName != NULL) {
+ wolfSSL_ASN1_STRING_free(name->d.dNSName);
+ name->d.dNSName = NULL;
+ }
+ if (name->d.uniformResourceIdentifier != NULL) {
+ wolfSSL_ASN1_STRING_free(name->d.uniformResourceIdentifier);
+ name->d.uniformResourceIdentifier = NULL;
+ }
+ if (name->d.iPAddress != NULL) {
+ wolfSSL_ASN1_STRING_free(name->d.iPAddress);
+ name->d.iPAddress = NULL;
+ }
+ if (name->d.registeredID != NULL) {
+ wolfSSL_ASN1_OBJECT_free(name->d.registeredID);
+ name->d.registeredID = NULL;
+ }
+ if (name->d.ia5 != NULL) {
+ wolfSSL_ASN1_STRING_free(name->d.ia5);
+ name->d.ia5 = NULL;
+ }
+ XFREE(name, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+
+void wolfSSL_GENERAL_NAMES_free(WOLFSSL_GENERAL_NAMES *gens)
+{
+ WOLFSSL_STACK* node;
+
+ WOLFSSL_ENTER("wolfSSL_GENERAL_NAMES_free");
+
+ if (gens == NULL) {
+ return;
+ }
+
+ /* parse through stack freeing each node */
+ node = gens->next;
+ while (gens->num > 1) {
+ WOLFSSL_STACK* tmp = node;
+ node = node->next;
+
+ wolfSSL_ASN1_OBJECT_free(tmp->data.obj);
+ XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1);
+ gens->num -= 1;
+ }
+
+ /* free head of stack */
+ if (gens->num == 1) {
+ wolfSSL_ASN1_OBJECT_free(gens->data.obj);
+ }
+ XFREE(gens, NULL, DYNAMIC_TYPE_ASN1);
+}
+
+#if defined(OPENSSL_ALL)
+WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* wolfSSL_sk_X509_EXTENSION_new_null(void)
+{
+ WOLFSSL_STACK* sk = wolfSSL_sk_new_node(NULL);
+ if (sk) {
+ sk->type = STACK_TYPE_X509_EXT;
+ }
+
+ return (WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)*)sk;;
+}
+
+/* returns the number of nodes on the stack */
+int wolfSSL_sk_X509_EXTENSION_num(WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk)
+{
+ if (sk != NULL) {
+ return (int)sk->num;
+ }
+ return WOLFSSL_FATAL_ERROR;
+}
+
+
+/* returns null on failure and pointer to internal value on success */
+WOLFSSL_X509_EXTENSION* wolfSSL_sk_X509_EXTENSION_value(
+ WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, int idx)
+{
+ WOLFSSL_STACK* ret;
+
+ if (sk == NULL) {
+ return NULL;
+ }
+
+ ret = wolfSSL_sk_get_node(sk, idx);
+ if (ret != NULL) {
+ return ret->data.ext;
+ }
+ return NULL;
+}
+
+/* frees all of the nodes and the values in stack */
+void wolfSSL_sk_X509_EXTENSION_pop_free(
+ WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk,
+ void (*f) (WOLFSSL_X509_EXTENSION*))
+{
+ WOLFSSL_STACK* current;
+
+ if (sk == NULL) {
+ return;
+ }
+
+ current = sk;
+ while (current != NULL) {
+ WOLFSSL_STACK* toFree = current;
+ current = current->next;
+
+ if (f)
+ f(toFree->data.ext);
+ wolfSSL_sk_free_node(toFree);
+ }
+}
+
+#if defined(HAVE_ECC)
+/* Copies ecc_key into new WOLFSSL_EC_KEY object
+ *
+ * src : EC_KEY to duplicate. If EC_KEY is not null, create new EC_KEY and copy
+ * internal ecc_key from src to dup.
+ *
+ * Returns pointer to duplicate EC_KEY.
+ */
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src)
+{
+ WOLFSSL_EC_KEY *dup;
+ ecc_key *key, *srcKey;
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_dup");
+
+ if (src == NULL || src->internal == NULL || src->group == NULL || \
+ src->pub_key == NULL || src->priv_key == NULL) {
+
+ WOLFSSL_MSG("src NULL error");
+ return NULL;
+ }
+
+ dup = wolfSSL_EC_KEY_new();
+ if (dup == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new error");
+ return NULL;
+ }
+
+ key = (ecc_key*)dup->internal;
+ if (key == NULL) {
+ WOLFSSL_MSG("ecc_key NULL error");
+ wolfSSL_EC_KEY_free(dup);
+ return NULL;
+ }
+ srcKey = (ecc_key*)src->internal;
+
+ /* ecc_key */
+ /* copy pubkey */
+ ret = wc_ecc_copy_point(&srcKey->pubkey, &key->pubkey);
+ if (ret != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_copy_point error");
+ wolfSSL_EC_KEY_free(dup);
+ return NULL;
+ }
+
+ /* copy private key k */
+ ret = mp_copy(&srcKey->k, &key->k);
+ if (ret != MP_OKAY) {
+ WOLFSSL_MSG("mp_copy error");
+ wolfSSL_EC_KEY_free(dup);
+ return NULL;
+ }
+
+ /* copy domain parameters */
+ if (srcKey->dp) {
+ ret = wc_ecc_set_curve(key, 0, srcKey->dp->id);
+ if (ret != 0) {
+ WOLFSSL_MSG("wc_ecc_set_curve error");
+ return NULL;
+ }
+ }
+
+ key->type = srcKey->type;
+ key->idx = srcKey->idx;
+ key->state = srcKey->state;
+ key->flags = srcKey->flags;
+
+ /* Copy group */
+ if (dup->group == NULL) {
+ WOLFSSL_MSG("EC_GROUP_new_by_curve_name error");
+ wolfSSL_EC_KEY_free(dup);
+ return NULL;
+ }
+
+ dup->group->curve_idx = src->group->curve_idx;
+ dup->group->curve_nid = src->group->curve_nid;
+ dup->group->curve_oid = src->group->curve_oid;
+
+ /* Copy public key */
+ if (src->pub_key->internal == NULL || dup->pub_key->internal == NULL) {
+ WOLFSSL_MSG("NULL pub_key error");
+ wolfSSL_EC_KEY_free(dup);
+ return NULL;
+ }
+
+ /* Copy public key internal */
+ ret = wc_ecc_copy_point((ecc_point*)src->pub_key->internal, \
+ (ecc_point*)dup->pub_key->internal);
+ if (ret != MP_OKAY) {
+ WOLFSSL_MSG("ecc_copy_point error");
+ wolfSSL_EC_KEY_free(dup);
+ return NULL;
+ }
+
+ /* Copy X, Y, Z */
+ dup->pub_key->X = wolfSSL_BN_dup(src->pub_key->X);
+ if (!dup->pub_key->X && src->pub_key->X) {
+ WOLFSSL_MSG("Error copying EC_POINT");
+ wolfSSL_EC_KEY_free(dup);
+ return NULL;
+ }
+ dup->pub_key->Y = wolfSSL_BN_dup(src->pub_key->Y);
+ if (!dup->pub_key->Y && src->pub_key->Y) {
+ WOLFSSL_MSG("Error copying EC_POINT");
+ wolfSSL_EC_KEY_free(dup);
+ return NULL;
+ }
+ dup->pub_key->Z = wolfSSL_BN_dup(src->pub_key->Z);
+ if (!dup->pub_key->Z && src->pub_key->Z) {
+ WOLFSSL_MSG("Error copying EC_POINT");
+ wolfSSL_EC_KEY_free(dup);
+ return NULL;
+ }
+
+ dup->pub_key->inSet = src->pub_key->inSet;
+ dup->pub_key->exSet = src->pub_key->exSet;
+
+ /* Copy private key */
+ if (src->priv_key->internal == NULL || dup->priv_key->internal == NULL) {
+ WOLFSSL_MSG("NULL priv_key error");
+ wolfSSL_EC_KEY_free(dup);
+ return NULL;
+ }
+
+ /* Free priv_key before call to dup function */
+ wolfSSL_BN_free(dup->priv_key);
+ dup->priv_key = wolfSSL_BN_dup(src->priv_key);
+ if (dup->priv_key == NULL) {
+ WOLFSSL_MSG("BN_dup error");
+ wolfSSL_EC_KEY_free(dup);
+ return NULL;
+ }
+
+ return dup;
+
+}
+#endif /* HAVE_ECC */
+
+#if !defined(NO_DH)
+int wolfSSL_DH_check(const WOLFSSL_DH *dh, int *codes)
+{
+ int isPrime = MP_NO, codeTmp = 0;
+ WC_RNG rng;
+
+ WOLFSSL_ENTER("wolfSSL_DH_check");
+ if (dh == NULL){
+ return WOLFSSL_FAILURE;
+ }
+
+ if (dh->g == NULL || dh->g->internal == NULL){
+ codeTmp = DH_NOT_SUITABLE_GENERATOR;
+ }
+
+ if (dh->p == NULL || dh->p->internal == NULL){
+ codeTmp = DH_CHECK_P_NOT_PRIME;
+ }
+ else
+ {
+ /* test if dh->p has prime */
+ if (wc_InitRng(&rng) == 0){
+ mp_prime_is_prime_ex((mp_int*)dh->p->internal,8,&isPrime,&rng);
+ }
+ else {
+ WOLFSSL_MSG("Error initializing rng\n");
+ return WOLFSSL_FAILURE;
+ }
+ wc_FreeRng(&rng);
+ if (isPrime != MP_YES){
+ codeTmp = DH_CHECK_P_NOT_PRIME;
+ }
+ }
+ /* User may choose to enter NULL for codes if they don't want to check it*/
+ if (codes != NULL){
+ *codes = codeTmp;
+ }
+
+ /* if codeTmp was set,some check was flagged invalid */
+ if (codeTmp){
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* Converts DER encoded DH parameters to a WOLFSSL_DH structure.
+ *
+ * dh : structure to copy DH parameters into.
+ * pp : DER encoded DH parameters
+ * length : length to copy
+ *
+ * Returns pointer to WOLFSSL_DH structure on success, or NULL on failure
+ */
+WOLFSSL_DH *wolfSSL_d2i_DHparams(WOLFSSL_DH **dh, const unsigned char **pp,
+ long length)
+{
+ WOLFSSL_DH *newDH = NULL;
+ int ret;
+ word32 idx = 0;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_DHparams");
+
+ if (pp == NULL || length <= 0) {
+ WOLFSSL_MSG("bad argument");
+ return NULL;
+ }
+
+ if ((newDH = wolfSSL_DH_new()) == NULL) {
+ WOLFSSL_MSG("wolfSSL_DH_new() failed");
+ return NULL;
+ }
+
+ ret = wc_DhKeyDecode(*pp, &idx, (DhKey*)newDH->internal, (word32)length);
+ if (ret != 0) {
+ WOLFSSL_MSG("DhKeyDecode() failed");
+ wolfSSL_DH_free(newDH);
+ return NULL;
+ }
+ newDH->inSet = 1;
+
+ if (SetDhExternal(newDH) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetDhExternal failed");
+ wolfSSL_DH_free(newDH);
+ return NULL;
+ }
+
+ *pp += length;
+ if (dh != NULL){
+ *dh = newDH;
+ }
+
+ return newDH;
+}
+
+/* Converts internal WOLFSSL_DH structure to DER encoded DH.
+ *
+ * dh : structure to copy DH parameters from.
+ * out : DER buffer for DH parameters
+ *
+ * Returns size of DER on success and WOLFSSL_FAILURE if error
+ */
+int wolfSSL_i2d_DHparams(const WOLFSSL_DH *dh, unsigned char **out)
+{
+ word32 len;
+ int ret = 0;
+
+ WOLFSSL_ENTER("wolfSSL_i2d_DHparams");
+
+ if (dh == NULL) {
+ WOLFSSL_MSG("Bad parameters");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Get total length */
+ len = 2 + mp_leading_bit((mp_int*)dh->p->internal) +
+ mp_unsigned_bin_size((mp_int*)dh->p->internal) +
+ 2 + mp_leading_bit((mp_int*)dh->g->internal) +
+ mp_unsigned_bin_size((mp_int*)dh->g->internal);
+
+ /* Two bytes required for length if ASN.1 SEQ data greater than 127 bytes
+ * and less than 256 bytes.
+ */
+ len = ((len > 127) ? 2 : 1) + len;
+
+ if (out != NULL && *out != NULL) {
+ ret = StoreDHparams(*out, &len, (mp_int*)dh->p->internal,
+ (mp_int*)dh->g->internal);
+ if (ret != MP_OKAY) {
+ WOLFSSL_MSG("StoreDHparams error");
+ len = 0;
+ }
+ else{
+ *out += len;
+ }
+ }
+ return (int)len;
}
+#endif /* !NO_DH */
+
+#endif /* OPENSSL_ALL */
+#endif /* OPENSSL_EXTRA */
#ifndef NO_FILESYSTEM
@@ -9138,19 +18618,20 @@ WOLFSSL_X509* wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file)
byte* fileBuffer = NULL;
long sz = 0;
- XFSEEK(file, 0, XSEEK_END);
+ if (XFSEEK(file, 0, XSEEK_END) != 0)
+ return NULL;
sz = XFTELL(file);
XREWIND(file);
- if (sz < 0) {
- WOLFSSL_MSG("Bad tell on FILE");
+ if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) {
+ WOLFSSL_MSG("X509_d2i file size error");
return NULL;
}
fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
if (fileBuffer != NULL) {
- int ret = (int)XFREAD(fileBuffer, sz, 1, file);
- if (ret > 0) {
+ int ret = (int)XFREAD(fileBuffer, 1, sz, file);
+ if (ret == sz) {
newX509 = wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz);
}
XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
@@ -9165,6 +18646,7 @@ WOLFSSL_X509* wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file)
#endif /* NO_STDIO_FILESYSTEM */
+WOLFSSL_ABI
WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format)
{
#ifdef WOLFSSL_SMALL_STACK
@@ -9179,23 +18661,29 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format)
XFILE file;
WOLFSSL_X509* x509 = NULL;
- buffer der;
-
- WOLFSSL_ENTER("wolfSSL_X509_load_certificate");
/* Check the inputs */
if ((fname == NULL) ||
- (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM))
+ (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM))
return NULL;
file = XFOPEN(fname, "rb");
if (file == XBADFILE)
return NULL;
- XFSEEK(file, 0, XSEEK_END);
+ if (XFSEEK(file, 0, XSEEK_END) != 0){
+ XFCLOSE(file);
+ return NULL;
+ }
sz = XFTELL(file);
XREWIND(file);
+ if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) {
+ WOLFSSL_MSG("X509_load_certificate_file size error");
+ XFCLOSE(file);
+ return NULL;
+ }
+
if (sz > (long)sizeof(staticBuffer)) {
fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
if (fileBuffer == NULL) {
@@ -9204,13 +18692,9 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format)
}
dynamic = 1;
}
- else if (sz < 0) {
- XFCLOSE(file);
- return NULL;
- }
- ret = (int)XFREAD(fileBuffer, sz, 1, file);
- if (ret < 0) {
+ ret = (int)XFREAD(fileBuffer, 1, sz, file);
+ if (ret != sz) {
XFCLOSE(file);
if (dynamic)
XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
@@ -9219,81 +18703,65 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format)
XFCLOSE(file);
- der.buffer = NULL;
- der.length = 0;
+ x509 = wolfSSL_X509_load_certificate_buffer(fileBuffer, (int)sz, format);
- if (format == SSL_FILETYPE_PEM) {
- int ecc = 0;
- #ifdef WOLFSSL_SMALL_STACK
- EncryptedInfo* info = NULL;
- #else
- EncryptedInfo info[1];
- #endif
+ if (dynamic)
+ XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
- #ifdef WOLFSSL_SMALL_STACK
- info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (info == NULL) {
- if (dynamic)
- XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
+ return x509;
+}
- return NULL;
- }
- #endif
+#endif /* NO_FILESYSTEM */
- info->set = 0;
- info->ctx = NULL;
- info->consumed = 0;
- if (PemToDer(fileBuffer, sz, CERT_TYPE, &der, NULL, info, &ecc) != 0)
- {
- /* Only time this should fail, and leave `der` with a buffer
- is when the Base64 Decode fails. Release `der.buffer` in
- that case. */
- if (der.buffer != NULL) {
- XFREE(der.buffer, NULL, DYNAMIC_TYPE_CERT);
- der.buffer = NULL;
- }
- }
+WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer(
+ const unsigned char* buf, int sz, int format)
+{
+ int ret;
+ WOLFSSL_X509* x509 = NULL;
+ DerBuffer* der = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ WOLFSSL_ENTER("wolfSSL_X509_load_certificate_ex");
+
+ if (format == WOLFSSL_FILETYPE_PEM) {
+ #ifdef WOLFSSL_PEM_TO_DER
+ if (PemToDer(buf, sz, CERT_TYPE, &der, NULL, NULL, NULL) != 0) {
+ FreeDer(&der);
+ }
+ #else
+ ret = NOT_COMPILED_IN;
#endif
}
else {
- der.buffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_CERT);
- if (der.buffer != NULL) {
- XMEMCPY(der.buffer, fileBuffer, sz);
- der.length = (word32)sz;
+ ret = AllocDer(&der, (word32)sz, CERT_TYPE, NULL);
+ if (ret == 0) {
+ XMEMCPY(der->buffer, buf, sz);
}
}
- if (dynamic)
- XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
-
/* At this point we want `der` to have the certificate in DER format */
/* ready to be decoded. */
- if (der.buffer != NULL) {
+ if (der != NULL && der->buffer != NULL) {
#ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert = NULL;
+ DecodedCert* cert;
#else
DecodedCert cert[1];
#endif
#ifdef WOLFSSL_SMALL_STACK
cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
+ DYNAMIC_TYPE_DCERT);
if (cert != NULL)
#endif
{
- InitDecodedCert(cert, der.buffer, der.length, NULL);
+ InitDecodedCert(cert, der->buffer, der->length, NULL);
if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) {
x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
DYNAMIC_TYPE_X509);
if (x509 != NULL) {
- InitX509(x509, 1);
+ InitX509(x509, 1, NULL);
if (CopyDecodedToX509(x509, cert) != 0) {
- XFREE(x509, NULL, DYNAMIC_TYPE_X509);
+ wolfSSL_X509_free(x509);
x509 = NULL;
}
}
@@ -9301,95 +18769,500 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format)
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
#endif
}
- XFREE(der.buffer, NULL, DYNAMIC_TYPE_CERT);
+ FreeDer(&der);
}
return x509;
}
-#endif /* NO_FILESYSTEM */
-
#endif /* KEEP_PEER_CERT || SESSION_CERTS */
+/* OPENSSL_EXTRA is needed for wolfSSL_X509_d21 function
+ KEEP_OUR_CERT is to insure ability for returning ssl certificate */
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+ defined(KEEP_OUR_CERT)
+WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl)
+{
+ if (ssl == NULL) {
+ return NULL;
+ }
+
+ if (ssl->buffers.weOwnCert) {
+ if (ssl->ourCert == NULL) {
+ if (ssl->buffers.certificate == NULL) {
+ WOLFSSL_MSG("Certificate buffer not set!");
+ return NULL;
+ }
+ #ifndef WOLFSSL_X509_STORE_CERTS
+ ssl->ourCert = wolfSSL_X509_d2i(NULL,
+ ssl->buffers.certificate->buffer,
+ ssl->buffers.certificate->length);
+ #endif
+ }
+ return ssl->ourCert;
+ }
+ else { /* if cert not owned get parent ctx cert or return null */
+ if (ssl->ctx) {
+ if (ssl->ctx->ourCert == NULL) {
+ if (ssl->ctx->certificate == NULL) {
+ WOLFSSL_MSG("Ctx Certificate buffer not set!");
+ return NULL;
+ }
+ #ifndef WOLFSSL_X509_STORE_CERTS
+ ssl->ctx->ourCert = wolfSSL_X509_d2i(NULL,
+ ssl->ctx->certificate->buffer,
+ ssl->ctx->certificate->length);
+ #endif
+ ssl->ctx->ownOurCert = 1;
+ }
+ return ssl->ctx->ourCert;
+ }
+ }
+
+ return NULL;
+}
+#endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */
+#endif /* NO_CERTS */
+
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+#ifndef NO_ASN
+void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj)
+{
+ if (obj == NULL) {
+ return;
+ }
+ if ((obj->obj != NULL) && ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0)) {
+ WOLFSSL_MSG("Freeing ASN1 data");
+ XFREE((void*)obj->obj, obj->heap, DYNAMIC_TYPE_ASN1);
+ obj->obj = NULL;
+ }
+ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ if (obj->pathlen != NULL) {
+ wolfSSL_ASN1_INTEGER_free(obj->pathlen);
+ obj->pathlen = NULL;
+ }
+ #endif
+ if ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC) != 0) {
+ WOLFSSL_MSG("Freeing ASN1 OBJECT");
+ XFREE(obj, NULL, DYNAMIC_TYPE_ASN1);
+ }
+}
+#endif /* NO_ASN */
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
#ifdef OPENSSL_EXTRA
-int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data)
+#ifndef NO_ASN
+WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void)
{
-#ifdef FORTRESS
- if (ssl != NULL && idx < MAX_EX_DATA)
- {
- ssl->ex_data[idx] = data;
- return SSL_SUCCESS;
+ WOLFSSL_ASN1_OBJECT* obj;
+
+ obj = (WOLFSSL_ASN1_OBJECT*)XMALLOC(sizeof(WOLFSSL_ASN1_OBJECT), NULL,
+ DYNAMIC_TYPE_ASN1);
+ if (obj == NULL) {
+ return NULL;
}
-#else
- (void)ssl;
- (void)idx;
- (void)data;
+
+ XMEMSET(obj, 0, sizeof(WOLFSSL_ASN1_OBJECT));
+ obj->d.ia5 = &(obj->d.ia5_internal);
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ obj->d.iPAddress = &(obj->d.iPAddress_internal);
#endif
- return SSL_FAILURE;
+ obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+ return obj;
}
+/* Creates and returns a new WOLFSSL_CIPHER stack. */
+WOLFSSL_STACK* wolfSSL_sk_new_asn1_obj(void)
+{
+ WOLFSSL_STACK* sk;
+ WOLFSSL_ENTER("wolfSSL_sk_new_asn1_obj");
+
+ sk = wolfSSL_sk_new_null();
+ if (sk == NULL)
+ return NULL;
+ sk->type = STACK_TYPE_OBJ;
+
+ return sk;
+}
-int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id,
- unsigned int len)
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk,
+ WOLFSSL_ASN1_OBJECT* obj)
{
- (void)ssl;
- (void)id;
- (void)len;
- return 0;
+ WOLFSSL_STACK* node;
+
+ WOLFSSL_ENTER("wolfSSL_sk_ASN1_OBJECT_push");
+
+ if (sk == NULL || obj == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* no previous values in stack */
+ if (sk->data.obj == NULL) {
+ sk->data.obj = obj;
+ sk->num += 1;
+ return WOLFSSL_SUCCESS;
+ }
+
+ /* stack already has value(s) create a new node and add more */
+ node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+ DYNAMIC_TYPE_ASN1);
+ if (node == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return WOLFSSL_FAILURE;
+ }
+ XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+ /* push new obj onto head of stack */
+ node->data.obj = sk->data.obj;
+ node->next = sk->next;
+ node->type = sk->type;
+ sk->next = node;
+ sk->data.obj = obj;
+ sk->num += 1;
+
+ return WOLFSSL_SUCCESS;
}
+WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJECT_pop(
+ WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk)
+{
+ WOLFSSL_STACK* node;
+ WOLFSSL_ASN1_OBJECT* obj;
+
+ if (sk == NULL) {
+ return NULL;
+ }
+
+ node = sk->next;
+ obj = sk->data.obj;
+
+ if (node != NULL) { /* update sk and remove node from stack */
+ sk->data.obj = node->data.obj;
+ sk->next = node->next;
+ XFREE(node, NULL, DYNAMIC_TYPE_ASN1);
+ }
+ else { /* last obj in stack */
+ sk->data.obj = NULL;
+ }
+
+ if (sk->num > 0) {
+ sk->num -= 1;
+ }
+
+ return obj;
+}
+
+
+/* Free the structure for ASN1_OBJECT stack
+ *
+ * sk stack to free nodes in
+ */
+void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk)
+{
+ wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL);
+}
+
+/* Free's all nodes in ASN1_OBJECT stack.
+ * This is different then wolfSSL_ASN1_OBJECT_free in that it allows for
+ * choosing the function to use when freeing an ASN1_OBJECT stack.
+ *
+ * sk stack to free nodes in
+ * f X509 free function
+ */
+void wolfSSL_sk_ASN1_OBJECT_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk,
+ void (*f) (WOLFSSL_ASN1_OBJECT*))
+{
+ WOLFSSL_STACK* node;
+
+ WOLFSSL_ENTER("wolfSSL_sk_ASN1_OBJECT_pop_free");
+
+ if (sk == NULL) {
+ WOLFSSL_MSG("Parameter error");
+ return;
+ }
+
+ /* parse through stack freeing each node */
+ node = sk->next;
+ while (node && sk->num > 1) {
+ WOLFSSL_STACK* tmp = node;
+ node = node->next;
+
+ if (f)
+ f(tmp->data.obj);
+ else
+ wolfSSL_ASN1_OBJECT_free(tmp->data.obj);
+ tmp->data.obj = NULL;
+ XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1);
+ sk->num -= 1;
+ }
+
+ /* free head of stack */
+ if (sk->num == 1) {
+ if (f)
+ f(sk->data.obj);
+ else
+ wolfSSL_ASN1_OBJECT_free(sk->data.obj);
+ sk->data.obj = NULL;
+ }
+ XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
+}
+
+int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in)
+{
+ /*
+ ASN1_STRING_to_UTF8() converts the string in to UTF8 format,
+ the converted data is allocated in a buffer in *out.
+ The length of out is returned or a negative error code.
+ The buffer *out should be free using OPENSSL_free().
+ */
+ unsigned char* buf;
+ unsigned char* inPtr;
+ int inLen;
+
+ if (!out || !in) {
+ return -1;
+ }
+
+ inPtr = wolfSSL_ASN1_STRING_data(in);
+ inLen = wolfSSL_ASN1_STRING_length(in);
+ if (!inPtr || inLen < 0) {
+ return -1;
+ }
+ buf = (unsigned char*)XMALLOC(inLen + 1, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (!buf) {
+ return -1;
+ }
+ XMEMCPY(buf, inPtr, inLen + 1);
+ *out = buf;
+ return inLen;
+}
+
+/* Returns string representation of ASN1_STRING */
+char* wolfSSL_i2s_ASN1_STRING(WOLFSSL_v3_ext_method *method,
+ const WOLFSSL_ASN1_STRING *s)
+{
+ int i;
+ int tmpSz = 100;
+ int valSz = 5;
+ char* tmp;
+ char val[5];
+ unsigned char* str;
+
+ WOLFSSL_ENTER("wolfSSL_i2s_ASN1_STRING");
+ (void)method;
+
+ if(s == NULL || s->data == NULL) {
+ WOLFSSL_MSG("Bad Function Argument");
+ return NULL;
+ }
+ str = (unsigned char*)XMALLOC(s->length, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (str == NULL) {
+ WOLFSSL_MSG("Memory Error");
+ return NULL;
+ }
+ XMEMCPY(str, (unsigned char*)s->data, s->length);
+
+ tmp = (char*)XMALLOC(tmpSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (tmp == NULL) {
+ WOLFSSL_MSG("Memory Error");
+ XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return NULL;
+ }
+ XMEMSET(tmp, 0, tmpSz);
+
+ for (i = 0; i < tmpSz && i < (s->length - 1); i++) {
+ XSNPRINTF(val, valSz - 1, "%02X:", str[i]);
+ XSTRNCAT(tmp, val, valSz);
+ }
+ XSNPRINTF(val, valSz - 1, "%02X", str[i]);
+ XSTRNCAT(tmp, val, valSz);
+ XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return tmp;
+}
+#endif /* NO_ASN */
+
void wolfSSL_set_connect_state(WOLFSSL* ssl)
{
- (void)ssl;
- /* client by default */
+ WOLFSSL_ENTER("wolfSSL_set_connect_state");
+ if (ssl == NULL) {
+ WOLFSSL_MSG("WOLFSSL struct pointer passed in was null");
+ return;
+ }
+
+ #ifndef NO_DH
+ /* client creates its own DH parameters on handshake */
+ if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) {
+ XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ }
+ ssl->buffers.serverDH_P.buffer = NULL;
+ if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) {
+ XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ }
+ ssl->buffers.serverDH_G.buffer = NULL;
+ #endif
+
+ if (InitSSL_Side(ssl, WOLFSSL_CLIENT_END) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error initializing client side");
+ }
}
-#endif
+#endif /* OPENSSL_EXTRA */
+
int wolfSSL_get_shutdown(const WOLFSSL* ssl)
{
- return (ssl->options.isClosed ||
- ssl->options.connReset ||
- ssl->options.sentNotify);
+ int isShutdown = 0;
+
+ WOLFSSL_ENTER("wolfSSL_get_shutdown");
+
+ if (ssl) {
+ /* in OpenSSL, WOLFSSL_SENT_SHUTDOWN = 1, when closeNotifySent *
+ * WOLFSSL_RECEIVED_SHUTDOWN = 2, from close notify or fatal err */
+ isShutdown = ((ssl->options.closeNotify||ssl->options.connReset) << 1)
+ | (ssl->options.sentNotify);
+ }
+ return isShutdown;
}
int wolfSSL_session_reused(WOLFSSL* ssl)
{
- return ssl->options.resuming;
+ int resuming = 0;
+ if (ssl)
+ resuming = ssl->options.resuming;
+ return resuming;
+}
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE)
+WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session)
+{
+#ifdef HAVE_EXT_CACHE
+ WOLFSSL_SESSION* copy;
+
+ WOLFSSL_ENTER("wolfSSL_SESSION_dup");
+
+ if (session == NULL)
+ return NULL;
+#ifdef HAVE_SESSION_TICKET
+ if (session->isDynamic && !session->ticket) {
+ WOLFSSL_MSG("Session dynamic flag is set but ticket pointer is null");
+ return NULL;
+ }
+#endif
+
+ copy = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (copy != NULL) {
+ XMEMCPY(copy, session, sizeof(WOLFSSL_SESSION));
+ copy->isAlloced = 1;
+#ifdef HAVE_SESSION_TICKET
+ if (session->isDynamic) {
+ copy->ticket = (byte*)XMALLOC(session->ticketLen, NULL,
+ DYNAMIC_TYPE_SESSION_TICK);
+ XMEMCPY(copy->ticket, session->ticket, session->ticketLen);
+ } else {
+ copy->ticket = copy->staticTicket;
+ }
+#endif
+#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
+ copy->peer = wolfSSL_X509_dup(session->peer);
+#endif
+ }
+ return copy;
+#else
+ WOLFSSL_MSG("wolfSSL_SESSION_dup was called "
+ "but HAVE_EXT_CACHE is not defined");
+ (void)session;
+ return NULL;
+#endif /* HAVE_EXT_CACHE */
}
-#ifdef OPENSSL_EXTRA
void wolfSSL_SESSION_free(WOLFSSL_SESSION* session)
{
+ if (session == NULL)
+ return;
+
+#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
+ if (session->peer) {
+ wolfSSL_X509_free(session->peer);
+ }
+#endif
+
+#ifdef HAVE_EXT_CACHE
+ if (session->isAlloced) {
+ #ifdef HAVE_SESSION_TICKET
+ if (session->isDynamic)
+ XFREE(session->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK);
+ #endif
+ XFREE(session, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+#else
+ /* No need to free since cache is static */
(void)session;
+#endif
}
#endif
-const char* wolfSSL_get_version(WOLFSSL* ssl)
+
+/* helper function that takes in a protocol version struct and returns string */
+static const char* wolfSSL_internal_get_version(ProtocolVersion* version)
{
- WOLFSSL_ENTER("SSL_get_version");
- if (ssl->version.major == SSLv3_MAJOR) {
- switch (ssl->version.minor) {
+ WOLFSSL_ENTER("wolfSSL_get_version");
+
+ if (version == NULL) {
+ return "Bad arg";
+ }
+
+ if (version->major == SSLv3_MAJOR) {
+ switch (version->minor) {
+ #ifndef NO_OLD_TLS
+ #ifdef WOLFSSL_ALLOW_SSLV3
case SSLv3_MINOR :
return "SSLv3";
+ #endif
+ #ifdef WOLFSSL_ALLOW_TLSV10
case TLSv1_MINOR :
return "TLSv1";
+ #endif
case TLSv1_1_MINOR :
return "TLSv1.1";
+ #endif
case TLSv1_2_MINOR :
return "TLSv1.2";
+ #ifdef WOLFSSL_TLS13
+ case TLSv1_3_MINOR :
+ #ifdef WOLFSSL_TLS13_DRAFT
+ #ifdef WOLFSSL_TLS13_DRAFT_18
+ return "TLSv1.3 (Draft 18)";
+ #elif defined(WOLFSSL_TLS13_DRAFT_22)
+ return "TLSv1.3 (Draft 22)";
+ #elif defined(WOLFSSL_TLS13_DRAFT_23)
+ return "TLSv1.3 (Draft 23)";
+ #elif defined(WOLFSSL_TLS13_DRAFT_26)
+ return "TLSv1.3 (Draft 26)";
+ #else
+ return "TLSv1.3 (Draft 28)";
+ #endif
+ #else
+ return "TLSv1.3";
+ #endif
+ #endif
default:
return "unknown";
}
}
- else if (ssl->version.major == DTLS_MAJOR) {
- switch (ssl->version.minor) {
+#ifdef WOLFSSL_DTLS
+ else if (version->major == DTLS_MAJOR) {
+ switch (version->minor) {
case DTLS_MINOR :
return "DTLS";
case DTLSv1_2_MINOR :
@@ -9398,10 +19271,22 @@ const char* wolfSSL_get_version(WOLFSSL* ssl)
return "unknown";
}
}
+#endif /* WOLFSSL_DTLS */
return "unknown";
}
+const char* wolfSSL_get_version(WOLFSSL* ssl)
+{
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Bad argument");
+ return "unknown";
+ }
+
+ return wolfSSL_internal_get_version(&ssl->version);
+}
+
+
/* current library version */
const char* wolfSSL_lib_version(void)
{
@@ -9427,8 +19312,11 @@ int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl)
WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL* ssl)
{
WOLFSSL_ENTER("SSL_get_current_cipher");
- if (ssl)
+ if (ssl) {
+ ssl->cipher.cipherSuite0 = ssl->options.cipherSuite0;
+ ssl->cipher.cipherSuite = ssl->options.cipherSuite;
return &ssl->cipher;
+ }
else
return NULL;
}
@@ -9436,381 +19324,2071 @@ WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL* ssl)
const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher)
{
+ WOLFSSL_ENTER("wolfSSL_CIPHER_get_name");
+
+ if (cipher == NULL) {
+ return NULL;
+ }
+
+ #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) && \
+ !defined(WOLFSSL_QT)
+ return GetCipherNameIana(cipher->cipherSuite0, cipher->cipherSuite);
+ #else
+ return wolfSSL_get_cipher_name_from_suite(cipher->cipherSuite0,
+ cipher->cipherSuite);
+ #endif
+}
+
+const char* wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher)
+{
+ WOLFSSL_ENTER("SSL_CIPHER_get_version");
+
+ if (cipher == NULL || cipher->ssl == NULL) {
+ return NULL;
+ }
+
+ return wolfSSL_get_version(cipher->ssl);
+}
+
+const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session)
+{
+ if (session == NULL) {
+ return NULL;
+ }
+
+#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
+ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+ #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS)
+ return GetCipherNameIana(session->cipherSuite0, session->cipherSuite);
+ #else
+ return GetCipherNameInternal(session->cipherSuite0, session->cipherSuite);
+ #endif
+#else
+ return NULL;
+#endif
+}
+
+const char* wolfSSL_get_cipher(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_get_cipher");
+ return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl));
+}
+
+/* gets cipher name in the format DHE-RSA-... rather then TLS_DHE... */
+const char* wolfSSL_get_cipher_name(WOLFSSL* ssl)
+{
+ /* get access to cipher_name_idx in internal.c */
+ return wolfSSL_get_cipher_name_internal(ssl);
+}
+
+const char* wolfSSL_get_cipher_name_from_suite(const byte cipherSuite0,
+ const byte cipherSuite)
+{
+ return GetCipherNameInternal(cipherSuite0, cipherSuite);
+}
+
+const char* wolfSSL_get_cipher_name_iana_from_suite(const byte cipherSuite0,
+ const byte cipherSuite)
+{
+ return GetCipherNameIana(cipherSuite0, cipherSuite);
+}
+
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+/* Creates and returns a new WOLFSSL_CIPHER stack. */
+WOLFSSL_STACK* wolfSSL_sk_new_cipher(void)
+{
+ WOLFSSL_STACK* sk;
+ WOLFSSL_ENTER("wolfSSL_sk_new_cipher");
+
+ sk = wolfSSL_sk_new_null();
+ if (sk == NULL)
+ return NULL;
+ sk->type = STACK_TYPE_CIPHER;
+
+ return sk;
+}
+
+#ifndef NO_WOLFSSL_STUB
+/* Keep as stubs for now */
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_CIPHER_push(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk,
+ WOLFSSL_CIPHER* cipher)
+{
+ WOLFSSL_STUB("wolfSSL_sk_CIPHER_push");
+ (void)sk;
(void)cipher;
+ return 0;
+}
- WOLFSSL_ENTER("SSL_CIPHER_get_name");
-#ifndef NO_ERROR_STRINGS
- if (cipher) {
-#if defined(HAVE_CHACHA)
- if (cipher->ssl->options.cipherSuite0 == CHACHA_BYTE) {
- /* ChaCha suites */
- switch (cipher->ssl->options.cipherSuite) {
-#ifdef HAVE_CHACHA
-#ifndef NO_RSA
- case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
- return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256";
- case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
- return "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256";
+WOLFSSL_CIPHER* wolfSSL_sk_CIPHER_pop(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
+{
+ WOLFSSL_STUB("wolfSSL_sk_CIPHER_pop");
+ (void)sk;
+ return NULL;
+}
+#endif /* NO_WOLFSSL_STUB */
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
+
+word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher)
+{
+ word16 cipher_id = 0;
+
+ WOLFSSL_ENTER("SSL_CIPHER_get_id");
+
+ if (cipher && cipher->ssl) {
+ cipher_id = (cipher->ssl->options.cipherSuite0 << 8) |
+ cipher->ssl->options.cipherSuite;
+ }
+
+ return cipher_id;
+}
+
+const WOLFSSL_CIPHER* wolfSSL_get_cipher_by_value(word16 value)
+{
+ const WOLFSSL_CIPHER* cipher = NULL;
+ byte cipherSuite0, cipherSuite;
+ WOLFSSL_ENTER("SSL_get_cipher_by_value");
+
+ /* extract cipher id information */
+ cipherSuite = (value & 0xFF);
+ cipherSuite0 = ((value >> 8) & 0xFF);
+
+ /* TODO: lookup by cipherSuite0 / cipherSuite */
+ (void)cipherSuite0;
+ (void)cipherSuite;
+
+ return cipher;
+}
+
+
+#if defined(OPENSSL_ALL)
+/* Free the structure for WOLFSSL_CIPHER stack
+ *
+ * sk stack to free nodes in
+ */
+void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
+{
+ WOLFSSL_STACK* node;
+ WOLFSSL_STACK* tmp;
+ WOLFSSL_ENTER("wolfSSL_sk_CIPHER_free");
+
+ if (sk == NULL)
+ return;
+
+ /* parse through stack freeing each node */
+ node = sk->next;
+ while (node) {
+ tmp = node;
+ node = node->next;
+ XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+
+ /* free head of stack */
+ XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
+}
#endif
- case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
- return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256";
+
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) || \
+ !defined(NO_DH)
+#ifdef HAVE_FFDHE
+static const char* wolfssl_ffdhe_name(word16 group)
+{
+ const char* str = NULL;
+ switch (group) {
+ case WOLFSSL_FFDHE_2048:
+ str = "FFDHE_2048";
+ break;
+ case WOLFSSL_FFDHE_3072:
+ str = "FFDHE_3072";
+ break;
+ case WOLFSSL_FFDHE_4096:
+ str = "FFDHE_4096";
+ break;
+ case WOLFSSL_FFDHE_6144:
+ str = "FFDHE_6144";
+ break;
+ case WOLFSSL_FFDHE_8192:
+ str = "FFDHE_8192";
+ break;
+ }
+ return str;
+}
#endif
- }
- }
+/* Return the name of the curve used for key exchange as a printable string.
+ *
+ * ssl The SSL/TLS object.
+ * returns NULL if ECDH was not used, otherwise the name as a string.
+ */
+const char* wolfSSL_get_curve_name(WOLFSSL* ssl)
+{
+ const char* cName = NULL;
+
+ if (ssl == NULL)
+ return NULL;
+
+#ifdef HAVE_FFDHE
+ if (ssl->namedGroup != 0) {
+ cName = wolfssl_ffdhe_name(ssl->namedGroup);
+ }
+#endif
+
+#ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID && cName == NULL) {
+ cName = "X25519";
+ }
+#endif
+
+#ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID && cName == NULL) {
+ cName = "X448";
+ }
#endif
-#if defined(HAVE_ECC) || defined(HAVE_AESCCM)
- /* Awkwardly, the ECC cipher suites use the ECC_BYTE as expected,
- * but the AES-CCM cipher suites also use it, even the ones that
- * aren't ECC. */
- if (cipher->ssl->options.cipherSuite0 == ECC_BYTE) {
- /* ECC suites */
- switch (cipher->ssl->options.cipherSuite) {
#ifdef HAVE_ECC
-#ifndef NO_RSA
- case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 :
- return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256";
+ if (ssl->ecdhCurveOID != 0 && cName == NULL) {
+ cName = wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL,
+ NULL));
+ }
#endif
- case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 :
- return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256";
-#ifndef NO_RSA
- case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 :
- return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256";
+
+ return cName;
+}
#endif
- case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 :
- return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256";
-#ifndef NO_RSA
- case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 :
- return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384";
+
+
+#if defined(OPENSSL_EXTRA_X509_SMALL) || defined(KEEP_PEER_CERT) || \
+ defined(SESSION_CERTS)
+/* Smaller subset of X509 compatibility functions. Avoid increasing the size of
+ * this subset and its memory usage */
+
+#if !defined(NO_CERTS)
+/* returns a pointer to a new WOLFSSL_X509 structure on success and NULL on
+ * fail
+ */
+WOLFSSL_X509* wolfSSL_X509_new(void)
+{
+ WOLFSSL_X509* x509;
+
+ x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
+ DYNAMIC_TYPE_X509);
+ if (x509 != NULL) {
+ InitX509(x509, 1, NULL);
+ }
+
+ return x509;
+}
+
+WOLFSSL_ABI
+WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509* cert)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_get_subject_name");
+ if (cert && cert->subject.sz != 0)
+ return &cert->subject;
+ return NULL;
+}
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_SHA)
+/******************************************************************************
+* wolfSSL_X509_subject_name_hash - compute the hash digest of the raw subject name
+*
+* RETURNS:
+* The beginning of the hash digest. Otherwise, returns zero.
+* Note:
+* Returns a different hash value from OpenSSL's X509_subject_name_hash() API
+* depending on the subject name.
+*/
+unsigned long wolfSSL_X509_subject_name_hash(const WOLFSSL_X509* x509)
+{
+ word32 ret = 0;
+ int retHash;
+ WOLFSSL_X509_NAME *subjectName = NULL;
+
+#ifdef WOLFSSL_PIC32MZ_HASH
+ byte digest[PIC32_DIGEST_SIZE];
+#else
+ byte digest[WC_SHA_DIGEST_SIZE];
#endif
- case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 :
- return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384";
-#ifndef NO_RSA
- case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 :
- return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384";
+
+ if (x509 == NULL){
+ return WOLFSSL_FAILURE;
+ }
+
+ subjectName = wolfSSL_X509_get_subject_name((WOLFSSL_X509*)x509);
+
+ if (subjectName != NULL){
+ retHash = wc_ShaHash((const byte*)subjectName->name,
+ (word32)subjectName->sz, digest);
+
+ if(retHash != 0){
+ WOLFSSL_MSG("Hash of X509 subjectName has failed");
+ return WOLFSSL_FAILURE;
+ }
+ ret = MakeWordFromHash(digest);
+ }
+
+ return (unsigned long)ret;
+}
#endif
- case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 :
- return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384";
-#ifndef NO_SHA
-#ifndef NO_RSA
- case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :
- return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
- case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :
- return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
-#endif
- case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :
- return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
- case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA :
- return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
-#ifndef NO_RC4
- #ifndef NO_RSA
- case TLS_ECDHE_RSA_WITH_RC4_128_SHA :
- return "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
+
+WOLFSSL_ABI
+WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509* cert)
+{
+ WOLFSSL_ENTER("X509_get_issuer_name");
+ if (cert && cert->issuer.sz != 0)
+ return &cert->issuer;
+ return NULL;
+}
+
+
+int wolfSSL_X509_get_signature_type(WOLFSSL_X509* x509)
+{
+ int type = 0;
+
+ WOLFSSL_ENTER("wolfSSL_X509_get_signature_type");
+
+ if (x509 != NULL)
+ type = x509->sigOID;
+
+ return type;
+}
+
+#if defined(OPENSSL_EXTRA_X509_SMALL)
+
+/* Used to get a string from the WOLFSSL_X509_NAME structure that
+ * corresponds with the NID value passed in.
+ *
+ * name structure to get string from
+ * nid NID value to search for
+ * buf [out] buffer to hold results. If NULL then the buffer size minus the
+ * null char is returned.
+ * len size of "buf" passed in
+ *
+ * returns the length of string found, not including the NULL terminator.
+ * It's possible the function could return a negative value in the
+ * case that len is less than or equal to 0. A negative value is
+ * considered an error case.
+ */
+int wolfSSL_X509_NAME_get_text_by_NID(WOLFSSL_X509_NAME* name,
+ int nid, char* buf, int len)
+{
+ char *text = NULL;
+ int textSz = 0;
+
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_get_text_by_NID");
+
+ switch (nid) {
+ case ASN_COMMON_NAME:
+ text = name->fullName.fullName + name->fullName.cnIdx;
+ textSz = name->fullName.cnLen;
+ break;
+ case ASN_SUR_NAME:
+ text = name->fullName.fullName + name->fullName.snIdx;
+ textSz = name->fullName.snLen;
+ break;
+ case ASN_SERIAL_NUMBER:
+ text = name->fullName.fullName + name->fullName.serialIdx;
+ textSz = name->fullName.serialLen;
+ break;
+ case ASN_COUNTRY_NAME:
+ text = name->fullName.fullName + name->fullName.cIdx;
+ textSz = name->fullName.cLen;
+ break;
+ case ASN_LOCALITY_NAME:
+ text = name->fullName.fullName + name->fullName.lIdx;
+ textSz = name->fullName.lLen;
+ break;
+ case ASN_STATE_NAME:
+ text = name->fullName.fullName + name->fullName.stIdx;
+ textSz = name->fullName.stLen;
+ break;
+ case ASN_ORG_NAME:
+ text = name->fullName.fullName + name->fullName.oIdx;
+ textSz = name->fullName.oLen;
+ break;
+ case ASN_ORGUNIT_NAME:
+ text = name->fullName.fullName + name->fullName.ouIdx;
+ textSz = name->fullName.ouLen;
+ break;
+ case ASN_DOMAIN_COMPONENT:
+ text = name->fullName.fullName + name->fullName.dcIdx[0];
+ textSz = name->fullName.dcLen[0];
+ break;
+ case NID_emailAddress:
+ text = name->fullName.fullName + name->fullName.emailIdx;
+ textSz = name->fullName.emailLen;
+ break;
+ #ifdef WOLFSSL_CERT_EXT
+ case ASN_BUS_CAT:
+ text = name->fullName.fullName + name->fullName.bcIdx;
+ textSz = name->fullName.bcLen;
+ break;
#endif
- case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA :
- return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
+ default:
+ WOLFSSL_MSG("Entry type not found");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* if buf is NULL return size of buffer needed (minus null char) */
+ if (buf == NULL) {
+ return textSz;
+ }
+
+ if (buf != NULL && text != NULL) {
+ textSz = min(textSz + 1, len); /* + 1 to account for null char */
+ if (textSz > 0) {
+ XMEMCPY(buf, text, textSz - 1);
+ buf[textSz - 1] = '\0';
+ }
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_text_by_NID", textSz);
+ return (textSz - 1); /* do not include null character in size */
+}
+
+/* Creates a new WOLFSSL_EVP_PKEY structure that has the public key from x509
+ *
+ * returns a pointer to the created WOLFSSL_EVP_PKEY on success and NULL on fail
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509)
+{
+ WOLFSSL_EVP_PKEY* key = NULL;
+ WOLFSSL_ENTER("X509_get_pubkey");
+ if (x509 != NULL) {
+ key = wolfSSL_EVP_PKEY_new_ex(x509->heap);
+ if (key != NULL) {
+ if (x509->pubKeyOID == RSAk) {
+ key->type = EVP_PKEY_RSA;
+ }
+ else if (x509->pubKeyOID == DSAk) {
+ key->type = EVP_PKEY_DSA;
+ }
+ else {
+ key->type = EVP_PKEY_EC;
+ }
+ key->save_type = 0;
+ key->pkey.ptr = (char*)XMALLOC(
+ x509->pubKey.length, x509->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (key->pkey.ptr == NULL) {
+ wolfSSL_EVP_PKEY_free(key);
+ return NULL;
+ }
+ XMEMCPY(key->pkey.ptr, x509->pubKey.buffer, x509->pubKey.length);
+ key->pkey_sz = x509->pubKey.length;
+
+ #ifdef HAVE_ECC
+ key->pkey_curve = (int)x509->pkCurveOID;
+ #endif /* HAVE_ECC */
+
+ /* decode RSA key */
+ #ifndef NO_RSA
+ if (key->type == EVP_PKEY_RSA) {
+ key->ownRsa = 1;
+ key->rsa = wolfSSL_RSA_new();
+ if (key->rsa == NULL) {
+ wolfSSL_EVP_PKEY_free(key);
+ return NULL;
+ }
+
+ if (wolfSSL_RSA_LoadDer_ex(key->rsa,
+ (const unsigned char*)key->pkey.ptr, key->pkey_sz,
+ WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) {
+ wolfSSL_EVP_PKEY_free(key);
+ return NULL;
+ }
+ }
+ #endif /* NO_RSA */
+
+ /* decode ECC key */
+ #if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
+ if (key->type == EVP_PKEY_EC) {
+ word32 idx = 0;
+
+ key->ownEcc = 1;
+ key->ecc = wolfSSL_EC_KEY_new();
+ if (key->ecc == NULL || key->ecc->internal == NULL) {
+ wolfSSL_EVP_PKEY_free(key);
+ return NULL;
+ }
+
+ /* not using wolfSSL_EC_KEY_LoadDer because public key in x509
+ * is in the format of x963 (no sequence at start of buffer) */
+ if (wc_EccPublicKeyDecode((const unsigned char*)key->pkey.ptr,
+ &idx, (ecc_key*)key->ecc->internal, key->pkey_sz) < 0) {
+ WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
+ wolfSSL_EVP_PKEY_free(key);
+ return NULL;
+ }
+
+ if (SetECKeyExternal(key->ecc) != SSL_SUCCESS) {
+ WOLFSSL_MSG("SetECKeyExternal failed");
+ wolfSSL_EVP_PKEY_free(key);
+ return NULL;
+ }
+
+ key->ecc->inSet = 1;
+ }
+ #endif /* HAVE_ECC */
+
+ #ifndef NO_DSA
+ if (key->type == EVP_PKEY_DSA) {
+ key->ownDsa = 1;
+ key->dsa = wolfSSL_DSA_new();
+ if (key->dsa == NULL) {
+ wolfSSL_EVP_PKEY_free(key);
+ return NULL;
+ }
+
+ if (wolfSSL_DSA_LoadDer_ex(key->dsa,
+ (const unsigned char*)key->pkey.ptr, key->pkey_sz, \
+ WOLFSSL_DSA_LOAD_PUBLIC) != SSL_SUCCESS) {
+ wolfSSL_DSA_free(key->dsa);
+ key->dsa = NULL;
+ wolfSSL_EVP_PKEY_free(key);
+ return NULL;
+ }
+ }
+ #endif /* NO_DSA */
+ }
+ }
+ return key;
+}
+#endif /* OPENSSL_EXTRA_X509_SMALL */
+#endif /* !NO_CERTS */
+
+/* End of smaller subset of X509 compatibility functions. Avoid increasing the
+ * size of this subset and its memory usage */
+#endif /* OPENSSL_EXTRA_X509_SMALL */
+
+#if defined(OPENSSL_ALL)
+/* Takes two WOLFSSL_X509* certificates and performs a Sha hash of each, if the
+ * has values are the same, then it will do an XMEMCMP to confirm they are
+ * identical. Returns a 0 when certificates match, returns a negative number
+ * when certificates are not a match.
+*/
+int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b)
+{
+ const byte* derA;
+ const byte* derB;
+ int retHashA;
+ int retHashB;
+ int outSzA = 0;
+ int outSzB = 0;
+
+ #ifdef WOLFSSL_PIC32MZ_HASH
+ byte digestA[PIC32_DIGEST_SIZE];
+ byte digestB[PIC32_DIGEST_SIZE];
+ #else
+ byte digestA[WC_SHA_DIGEST_SIZE];
+ byte digestB[WC_SHA_DIGEST_SIZE];
+ #endif
+
+ if (a == NULL || b == NULL){
+ return BAD_FUNC_ARG;
+ }
+
+ derA = wolfSSL_X509_get_der((WOLFSSL_X509*)a, &outSzA);
+ if(derA == NULL){
+ WOLFSSL_MSG("wolfSSL_X509_get_der - certificate A has failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ derB = wolfSSL_X509_get_der((WOLFSSL_X509*)b, &outSzB);
+ if(derB == NULL){
+ WOLFSSL_MSG("wolfSSL_X509_get_der - certificate B has failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ retHashA = wc_ShaHash(derA, (word32)outSzA, digestA);
+ if(retHashA != 0){
+ WOLFSSL_MSG("Hash of certificate A has failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ retHashB = wc_ShaHash(derB, (word32)outSzB, digestB);
+ if(retHashB != 0){
+ WOLFSSL_MSG("Hash of certificate B has failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (outSzA == outSzB){
+ #ifdef WOLFSSL_PIC32MZ_HASH
+ if(XMEMCMP(digestA, digestB, PIC32_DIGEST_SIZE) != 0){
+ return WOLFSSL_FATAL_ERROR;
+ }
+ #else
+ if(XMEMCMP(digestA, digestB, WC_SHA_DIGEST_SIZE) != 0){
+ return WOLFSSL_FATAL_ERROR;
+ }
+ #endif
+ else{
+ WOLFSSL_LEAVE("wolfSSL_X509_cmp", 0);
+ return 0;
+ }
+ }
+ else{
+ WOLFSSL_LEAVE("wolfSSL_X509_cmp", WOLFSSL_FATAL_ERROR);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
#endif
-#ifndef NO_DES3
- #ifndef NO_RSA
- case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA :
- return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
- #endif
- case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA :
- return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
+
+#if defined(OPENSSL_EXTRA)
+#if !defined(NO_CERTS)
+ int wolfSSL_X509_ext_isSet_by_NID(WOLFSSL_X509* x509, int nid)
+ {
+ int isSet = 0;
+
+ WOLFSSL_ENTER("wolfSSL_X509_ext_isSet_by_NID");
+
+ if (x509 != NULL) {
+ switch (nid) {
+ case BASIC_CA_OID: isSet = x509->basicConstSet; break;
+ case ALT_NAMES_OID: isSet = x509->subjAltNameSet; break;
+ case AUTH_KEY_OID: isSet = x509->authKeyIdSet; break;
+ case SUBJ_KEY_OID: isSet = x509->subjKeyIdSet; break;
+ case KEY_USAGE_OID: isSet = x509->keyUsageSet; break;
+ case CRL_DIST_OID: isSet = x509->CRLdistSet; break;
+ case EXT_KEY_USAGE_OID: isSet = ((x509->extKeyUsageSrc) ? 1 : 0);
+ break;
+ case AUTH_INFO_OID: isSet = x509->authInfoSet; break;
+ #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT)
+ case CERT_POLICY_OID: isSet = x509->certPolicySet; break;
+ #endif /* WOLFSSL_SEP || WOLFSSL_QT */
+ default:
+ WOLFSSL_MSG("NID not in table");
+ }
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_X509_ext_isSet_by_NID", isSet);
+
+ return isSet;
+ }
+
+
+ int wolfSSL_X509_ext_get_critical_by_NID(WOLFSSL_X509* x509, int nid)
+ {
+ int crit = 0;
+
+ WOLFSSL_ENTER("wolfSSL_X509_ext_get_critical_by_NID");
+
+ if (x509 != NULL) {
+ switch (nid) {
+ case BASIC_CA_OID: crit = x509->basicConstCrit; break;
+ case ALT_NAMES_OID: crit = x509->subjAltNameCrit; break;
+ case AUTH_KEY_OID: crit = x509->authKeyIdCrit; break;
+ case SUBJ_KEY_OID: crit = x509->subjKeyIdCrit; break;
+ case KEY_USAGE_OID: crit = x509->keyUsageCrit; break;
+ case CRL_DIST_OID: crit= x509->CRLdistCrit; break;
+ #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT)
+ case CERT_POLICY_OID: crit = x509->certPolicyCrit; break;
+ #endif /* WOLFSSL_SEP || WOLFSSL_QT */
+ }
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_X509_ext_get_critical_by_NID", crit);
+
+ return crit;
+ }
+
+
+ int wolfSSL_X509_get_isSet_pathLength(WOLFSSL_X509* x509)
+ {
+ int isSet = 0;
+
+ WOLFSSL_ENTER("wolfSSL_X509_get_isSet_pathLength");
+
+ if (x509 != NULL)
+ isSet = x509->basicConstPlSet;
+
+ WOLFSSL_LEAVE("wolfSSL_X509_get_isSet_pathLength", isSet);
+
+ return isSet;
+ }
+
+
+ word32 wolfSSL_X509_get_pathLength(WOLFSSL_X509* x509)
+ {
+ word32 pathLength = 0;
+
+ WOLFSSL_ENTER("wolfSSL_X509_get_pathLength");
+
+ if (x509 != NULL)
+ pathLength = x509->pathLength;
+
+ WOLFSSL_LEAVE("wolfSSL_X509_get_pathLength", pathLength);
+
+ return pathLength;
+ }
+
+
+ unsigned int wolfSSL_X509_get_keyUsage(WOLFSSL_X509* x509)
+ {
+ word16 usage = 0;
+
+ WOLFSSL_ENTER("wolfSSL_X509_get_keyUsage");
+
+ if (x509 != NULL)
+ usage = x509->keyUsage;
+
+ WOLFSSL_LEAVE("wolfSSL_X509_get_keyUsage", usage);
+
+ return usage;
+ }
+
+
+ byte* wolfSSL_X509_get_authorityKeyID(WOLFSSL_X509* x509,
+ byte* dst, int* dstLen)
+ {
+ byte *id = NULL;
+ int copySz = 0;
+
+ WOLFSSL_ENTER("wolfSSL_X509_get_authorityKeyID");
+
+ if (x509 != NULL) {
+ if (x509->authKeyIdSet) {
+ copySz = min(dstLen != NULL ? *dstLen : 0,
+ (int)x509->authKeyIdSz);
+ id = x509->authKeyId;
+ }
+
+ if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) {
+ XMEMCPY(dst, id, copySz);
+ id = dst;
+ *dstLen = copySz;
+ }
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_X509_get_authorityKeyID", copySz);
+
+ return id;
+ }
+
+
+ byte* wolfSSL_X509_get_subjectKeyID(WOLFSSL_X509* x509,
+ byte* dst, int* dstLen)
+ {
+ byte *id = NULL;
+ int copySz = 0;
+
+ WOLFSSL_ENTER("wolfSSL_X509_get_subjectKeyID");
+
+ if (x509 != NULL) {
+ if (x509->subjKeyIdSet) {
+ copySz = min(dstLen != NULL ? *dstLen : 0,
+ (int)x509->subjKeyIdSz);
+ id = x509->subjKeyId;
+ }
+
+ if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) {
+ XMEMCPY(dst, id, copySz);
+ id = dst;
+ *dstLen = copySz;
+ }
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_X509_get_subjectKeyID", copySz);
+
+ return id;
+ }
+
+
+ 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->fullName.locSz;
+
+ WOLFSSL_LEAVE("wolfSSL_X509_NAME_entry_count", count);
+ return count;
+ }
+
+
+
+ int wolfSSL_X509_NAME_get_index_by_NID(WOLFSSL_X509_NAME* name,
+ int nid, int pos)
+ {
+ int value = nid, i;
+
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_get_index_by_NID");
+
+ if (name == NULL || pos >= DN_NAMES_MAX + DOMAIN_COMPONENT_MAX) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (value == NID_emailAddress) {
+ value = ASN_EMAIL_NAME;
+ }
+
+ i = pos + 1; /* start search after index passed in */
+ if (i < 0) {
+ i = 0;
+ }
+
+ for (;i < name->fullName.locSz &&
+ i < DN_NAMES_MAX + DOMAIN_COMPONENT_MAX; i++) {
+ if (name->fullName.loc[i] == value) {
+ return i;
+ }
+ }
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+
+ WOLFSSL_ASN1_STRING* wolfSSL_X509_NAME_ENTRY_get_data(
+ WOLFSSL_X509_NAME_ENTRY* in)
+ {
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_data");
+ if (in == NULL)
+ return NULL;
+
+ return in->value;
+ }
+
+
+ /* Creates a new WOLFSSL_ASN1_STRING structure.
+ *
+ * returns a pointer to the new structure created on success or NULL if fail
+ */
+ WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new(void)
+ {
+ WOLFSSL_ASN1_STRING* asn1;
+
+ WOLFSSL_ENTER("wolfSSL_ASN1_STRING_new");
+
+ asn1 = (WOLFSSL_ASN1_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_STRING), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (asn1 != NULL) {
+ XMEMSET(asn1, 0, sizeof(WOLFSSL_ASN1_STRING));
+ }
+
+ return asn1; /* no check for null because error case is returning null*/
+ }
+
+
+ /* used to free a WOLFSSL_ASN1_STRING structure */
+ void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1)
+ {
+ WOLFSSL_ENTER("wolfSSL_ASN1_STRING_free");
+
+ if (asn1 != NULL) {
+ if (asn1->length > 0 && asn1->data != NULL && asn1->isDynamic) {
+ XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+ XFREE(asn1, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+ }
+
+
+ /* Creates a new WOLFSSL_ASN1_STRING structure given the input type.
+ *
+ * type is the type of set when WOLFSSL_ASN1_STRING is created
+ *
+ * returns a pointer to the new structure created on success or NULL if fail
+ */
+ WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type)
+ {
+ WOLFSSL_ASN1_STRING* asn1;
+
+ WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type_new");
+
+ asn1 = wolfSSL_ASN1_STRING_new();
+ if (asn1 == NULL) {
+ return NULL;
+ }
+ asn1->type = type;
+
+ return asn1;
+ }
+
+
+/******************************************************************************
+* wolfSSL_ASN1_STRING_type - returns the type of <asn1>
+*
+* RETURNS:
+* returns the type set for <asn1>. Otherwise, returns WOLFSSL_FAILURE.
+*/
+ int wolfSSL_ASN1_STRING_type(const WOLFSSL_ASN1_STRING* asn1)
+ {
+
+ WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type");
+
+ if (asn1 == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ return asn1->type;
+ }
+
+ /* if dataSz is negative then use XSTRLEN to find length of data
+ * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */
+ /* `data` can be NULL and only buffer will be allocated */
+ int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data,
+ int dataSz)
+ {
+ int sz;
+
+ WOLFSSL_ENTER("wolfSSL_ASN1_STRING_set");
+
+ if (asn1 == NULL || (data == NULL && dataSz < 0)) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (dataSz < 0) {
+ sz = (int)XSTRLEN((const char*)data) + 1; /* +1 for null */
+ }
+ else {
+ sz = dataSz;
+ }
+
+ if (sz < 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* free any existing data before copying */
+ if (asn1->data != NULL && asn1->isDynamic) {
+ XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
+ asn1->data = NULL;
+ }
+
+ if (sz > CTC_NAME_SIZE) {
+ /* create new data buffer and copy over */
+ asn1->data = (char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (asn1->data == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+ asn1->isDynamic = 1;
+ }
+ else {
+ XMEMSET(asn1->strData, 0, CTC_NAME_SIZE);
+ asn1->data = asn1->strData;
+ asn1->isDynamic = 0;
+ }
+ if (data != NULL) {
+ XMEMCPY(asn1->data, data, sz);
+ asn1->data[sz] = '\0';
+ }
+ asn1->length = sz;
+
+ return WOLFSSL_SUCCESS;
+ }
+
+
+ unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING* asn)
+ {
+ WOLFSSL_ENTER("wolfSSL_ASN1_STRING_data");
+
+ if (asn) {
+ return (unsigned char*)asn->data;
+ }
+ else {
+ return NULL;
+ }
+ }
+
+
+ int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING* asn)
+ {
+ WOLFSSL_ENTER("wolfSSL_ASN1_STRING_length");
+
+ if (asn) {
+ return asn->length;
+ }
+ else {
+ return 0;
+ }
+ }
+
+#ifndef NO_WOLFSSL_STUB
+ WOLFSSL_ASN1_STRING* wolfSSL_d2i_DISPLAYTEXT(WOLFSSL_ASN1_STRING **asn,
+ const unsigned char **in, long len)
+ {
+ WOLFSSL_STUB("d2i_DISPLAYTEXT");
+ (void)asn;
+ (void)in;
+ (void)len;
+ return NULL;
+ }
#endif
-#ifndef NO_RSA
- case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA :
- return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
- case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA :
- return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
-#endif
- case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA :
- return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
- case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA :
- return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
-#ifndef NO_RC4
- #ifndef NO_RSA
- case TLS_ECDH_RSA_WITH_RC4_128_SHA :
- return "TLS_ECDH_RSA_WITH_RC4_128_SHA";
+#ifdef XSNPRINTF /* a snprintf function needs to be available */
+ /* Writes the human readable form of x509 to bio.
+ *
+ * bio WOLFSSL_BIO to write to.
+ * x509 Certificate to write.
+ *
+ * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
+ */
+ int wolfSSL_X509_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509* x509,
+ unsigned long nmflags, unsigned long cflag)
+ {
+ WOLFSSL_ENTER("wolfSSL_X509_print_ex");
+
+ #ifndef NO_WOLFSSL_STUB
+ /* flags currently not supported */
+ (void)nmflags;
+ (void)cflag;
#endif
- case TLS_ECDH_ECDSA_WITH_RC4_128_SHA :
- return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
-#endif
-#ifndef NO_DES3
- #ifndef NO_RSA
- case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA :
- return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
+
+ if (bio == NULL || x509 == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_BIO_write(bio, "Certificate:\n",
+ (int)XSTRLEN("Certificate:\n")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_BIO_write(bio, " Data:\n",
+ (int)XSTRLEN(" Data:\n")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* print version of cert */
+ {
+ int version;
+ char tmp[20];
+
+ if ((version = wolfSSL_X509_version(x509)) < 0) {
+ WOLFSSL_MSG("Error getting X509 version");
+ return WOLFSSL_FAILURE;
+ }
+ if (wolfSSL_BIO_write(bio, " Version:",
+ (int)XSTRLEN(" Version:")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ XSNPRINTF(tmp, sizeof(tmp), " %d (0x%x)\n", version, (byte)version-1);
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ /* print serial number out */
+ {
+ unsigned char serial[32];
+ int sz = sizeof(serial);
+
+ XMEMSET(serial, 0, sz);
+ if (wolfSSL_X509_get_serial_number(x509, serial, &sz)
+ != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error getting x509 serial number");
+ return WOLFSSL_FAILURE;
+ }
+ if (wolfSSL_BIO_write(bio, " Serial Number:",
+ (int)XSTRLEN(" Serial Number:")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* if serial can fit into byte than print on the same line */
+ if (sz <= (int)sizeof(byte)) {
+ char tmp[17];
+ XSNPRINTF(tmp, sizeof(tmp), " %d (0x%x)\n", serial[0],serial[0]);
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+ else {
+ int i;
+ char tmp[100];
+ int tmpSz = 100;
+ char val[5];
+ int valSz = 5;
+
+ /* serial is larger than int size so print off hex values */
+ if (wolfSSL_BIO_write(bio, "\n ",
+ (int)XSTRLEN("\n ")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ tmp[0] = '\0';
+ for (i = 0; i < sz - 1 && (3 * i) < tmpSz - valSz; i++) {
+ XSNPRINTF(val, sizeof(val) - 1, "%02x:", serial[i]);
+ val[3] = '\0'; /* make sure is null terminated */
+ XSTRNCAT(tmp, val, valSz);
+ }
+ XSNPRINTF(val, sizeof(val) - 1, "%02x\n", serial[i]);
+ val[3] = '\0'; /* make sure is null terminated */
+ XSTRNCAT(tmp, val, valSz);
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+ }
+
+ /* print signature algo */
+ {
+ int oid;
+ const char* sig;
+
+ if ((oid = wolfSSL_X509_get_signature_type(x509)) <= 0) {
+ WOLFSSL_MSG("Error getting x509 signature type");
+ return WOLFSSL_FAILURE;
+ }
+ if (wolfSSL_BIO_write(bio, " Signature Algorithm: ",
+ (int)XSTRLEN(" Signature Algorithm: ")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ sig = GetSigName(oid);
+ if (wolfSSL_BIO_write(bio, sig, (int)XSTRLEN(sig)) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ if (wolfSSL_BIO_write(bio, "\n", (int)XSTRLEN("\n")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ /* print issuer */
+ {
+ char* issuer;
+ #ifdef WOLFSSL_SMALL_STACK
+ char* buff = NULL;
+ int issSz = 0;
+ #else
+ char buff[256];
+ int issSz = 256;
+ #endif
+
+ #if defined(WOLFSSL_QT)
+ issuer = wolfSSL_X509_get_name_oneline(
+ wolfSSL_X509_get_issuer_name(x509), buff, issSz);
+ #else
+ issuer = wolfSSL_X509_NAME_oneline(
+ wolfSSL_X509_get_issuer_name(x509), buff, issSz);
+ #endif
+
+ if (wolfSSL_BIO_write(bio, " Issuer: ",
+ (int)XSTRLEN(" Issuer: ")) <= 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
+ #endif
+ return WOLFSSL_FAILURE;
+ }
+ if (issuer != NULL) {
+ if (wolfSSL_BIO_write(bio, issuer, (int)XSTRLEN(issuer)) <= 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
+ #endif
+ return WOLFSSL_FAILURE;
+ }
+ }
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
+ #endif
+ if (wolfSSL_BIO_write(bio, "\n", (int)XSTRLEN("\n")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ #ifndef NO_ASN_TIME
+ /* print validity */
+ {
+ char tmp[80];
+
+ if (wolfSSL_BIO_write(bio, " Validity\n",
+ (int)XSTRLEN(" Validity\n")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_BIO_write(bio, " Not Before: ",
+ (int)XSTRLEN(" Not Before: ")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ if (x509->notBefore.length > 0) {
+ if (GetTimeString(x509->notBefore.data, ASN_UTC_TIME,
+ tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
+ if (GetTimeString(x509->notBefore.data, ASN_GENERALIZED_TIME,
+ tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error getting not before date");
+ return WOLFSSL_FAILURE;
+ }
+ }
+ }
+ else {
+ XSTRNCPY(tmp, "Not Set", sizeof(tmp)-1);
+ }
+ tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_BIO_write(bio, "\n Not After : ",
+ (int)XSTRLEN("\n Not After : ")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ if (x509->notAfter.length > 0) {
+ if (GetTimeString(x509->notAfter.data, ASN_UTC_TIME,
+ tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
+ if (GetTimeString(x509->notAfter.data, ASN_GENERALIZED_TIME,
+ tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error getting not after date");
+ return WOLFSSL_FAILURE;
+ }
+ }
+ }
+ else {
+ XSTRNCPY(tmp, "Not Set", sizeof(tmp)-1);
+ }
+ tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ }
#endif
- case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA :
- return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
-#endif
-#endif /* NO_SHA */
-#ifdef HAVE_AESGCM
-#ifndef NO_RSA
- case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 :
- return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
- case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 :
- return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
-#endif
- case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 :
- return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
- case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 :
- return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
-#ifndef NO_RSA
- case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 :
- return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256";
- case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 :
- return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384";
+ /* print subject */
+ {
+ char* subject;
+ #ifdef WOLFSSL_SMALL_STACK
+ char* buff = NULL;
+ int subSz = 0;
+ #else
+ char buff[256];
+ int subSz = 256;
+ #endif
+
+ #if defined(WOLFSSL_QT)
+ subject = wolfSSL_X509_get_name_oneline(
+ wolfSSL_X509_get_subject_name(x509), buff, subSz);
+ #else
+ subject = wolfSSL_X509_NAME_oneline(
+ wolfSSL_X509_get_subject_name(x509), buff, subSz);
+ #endif
+
+ if (wolfSSL_BIO_write(bio, "\n Subject: ",
+ (int)XSTRLEN("\n Subject: ")) <= 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL);
+ #endif
+ return WOLFSSL_FAILURE;
+ }
+ if (subject != NULL) {
+ if (wolfSSL_BIO_write(bio, subject, (int)XSTRLEN(subject)) <= 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL);
+ #endif
+ return WOLFSSL_FAILURE;
+ }
+ }
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL);
+ #endif
+ }
+
+ /* get and print public key */
+ if (wolfSSL_BIO_write(bio, "\n Subject Public Key Info:\n",
+ (int)XSTRLEN("\n Subject Public Key Info:\n")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ {
+ #if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || defined(HAVE_ECC)
+ char tmp[100];
+ #endif
+
+ switch (x509->pubKeyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ if (wolfSSL_BIO_write(bio,
+ " Public Key Algorithm: rsaEncryption\n",
+ (int)XSTRLEN(" Public Key Algorithm: rsaEncryption\n")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ #ifdef HAVE_USER_RSA
+ if (wolfSSL_BIO_write(bio,
+ " Build without user RSA to print key\n",
+ (int)XSTRLEN(" Build without user RSA to print key\n"))
+ <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ #else
+ {
+ RsaKey rsa;
+ word32 idx = 0;
+ int sz;
+ byte lbit = 0;
+ int rawLen;
+ unsigned char* rawKey;
+
+ if (wc_InitRsaKey(&rsa, NULL) != 0) {
+ WOLFSSL_MSG("wc_InitRsaKey failure");
+ return WOLFSSL_FAILURE;
+ }
+ if (wc_RsaPublicKeyDecode(x509->pubKey.buffer,
+ &idx, &rsa, x509->pubKey.length) != 0) {
+ WOLFSSL_MSG("Error decoding RSA key");
+ wc_FreeRsaKey(&rsa);
+ return WOLFSSL_FAILURE;
+ }
+ if ((sz = wc_RsaEncryptSize(&rsa)) < 0) {
+ WOLFSSL_MSG("Error getting RSA key size");
+ wc_FreeRsaKey(&rsa);
+ return WOLFSSL_FAILURE;
+ }
+ XSNPRINTF(tmp, sizeof(tmp) - 1, "%s%s: (%d bit)\n%s\n",
+ " ", "Public-Key", 8 * sz,
+ " Modulus:");
+ tmp[sizeof(tmp) - 1] = '\0';
+ if (wolfSSL_BIO_write(bio, tmp,
+ (int)XSTRLEN(tmp)) <= 0) {
+ wc_FreeRsaKey(&rsa);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* print out modulus */
+ XSNPRINTF(tmp, sizeof(tmp) - 1," ");
+ tmp[sizeof(tmp) - 1] = '\0';
+ if (mp_leading_bit(&rsa.n)) {
+ lbit = 1;
+ XSTRNCAT(tmp, "00", 3);
+ }
+
+ rawLen = mp_unsigned_bin_size(&rsa.n);
+ rawKey = (unsigned char*)XMALLOC(rawLen, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (rawKey == NULL) {
+ WOLFSSL_MSG("Memory error");
+ wc_FreeRsaKey(&rsa);
+ return WOLFSSL_FAILURE;
+ }
+ mp_to_unsigned_bin(&rsa.n, rawKey);
+ for (idx = 0; idx < (word32)rawLen; idx++) {
+ char val[5];
+ int valSz = 5;
+
+ if ((idx == 0) && !lbit) {
+ XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]);
+ }
+ else if ((idx != 0) && (((idx + lbit) % 15) == 0)) {
+ tmp[sizeof(tmp) - 1] = '\0';
+ if (wolfSSL_BIO_write(bio, tmp,
+ (int)XSTRLEN(tmp)) <= 0) {
+ XFREE(rawKey, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ wc_FreeRsaKey(&rsa);
+ return WOLFSSL_FAILURE;
+ }
+ XSNPRINTF(tmp, sizeof(tmp) - 1,
+ ":\n ");
+ XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]);
+ }
+ else {
+ XSNPRINTF(val, valSz - 1, ":%02x", rawKey[idx]);
+ }
+ XSTRNCAT(tmp, val, valSz);
+ }
+ XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ /* print out remaining modulus values */
+ if ((idx > 0) && (((idx - 1 + lbit) % 15) != 0)) {
+ tmp[sizeof(tmp) - 1] = '\0';
+ if (wolfSSL_BIO_write(bio, tmp,
+ (int)XSTRLEN(tmp)) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ /* print out exponent values */
+ rawLen = mp_unsigned_bin_size(&rsa.e);
+ if (rawLen < 0) {
+ WOLFSSL_MSG("Error getting exponent size");
+ wc_FreeRsaKey(&rsa);
+ return WOLFSSL_FAILURE;
+ }
+
+ if ((word32)rawLen < sizeof(word32)) {
+ rawLen = sizeof(word32);
+ }
+ rawKey = (unsigned char*)XMALLOC(rawLen, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (rawKey == NULL) {
+ WOLFSSL_MSG("Memory error");
+ wc_FreeRsaKey(&rsa);
+ return WOLFSSL_FAILURE;
+ }
+ XMEMSET(rawKey, 0, rawLen);
+ mp_to_unsigned_bin(&rsa.e, rawKey);
+ if ((word32)rawLen <= sizeof(word32)) {
+ idx = *(word32*)rawKey;
+ #ifdef BIG_ENDIAN_ORDER
+ idx = ByteReverseWord32(idx);
+ #endif
+ }
+ XSNPRINTF(tmp, sizeof(tmp) - 1,
+ "\n Exponent: %d (0x%x)\n",idx, idx);
+ if (wolfSSL_BIO_write(bio, tmp,
+ (int)XSTRLEN(tmp)) <= 0) {
+ XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ wc_FreeRsaKey(&rsa);
+ return WOLFSSL_FAILURE;
+ }
+ XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ wc_FreeRsaKey(&rsa);
+ }
+ #endif /* HAVE_USER_RSA */
+ break;
+ #endif /* NO_RSA */
+
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ {
+ word32 i;
+ ecc_key ecc;
+
+ if (wolfSSL_BIO_write(bio,
+ " Public Key Algorithm: EC\n",
+ (int)XSTRLEN(" Public Key Algorithm: EC\n")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ if (wc_ecc_init_ex(&ecc, x509->heap, INVALID_DEVID)
+ != 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ i = 0;
+ if (wc_EccPublicKeyDecode(x509->pubKey.buffer, &i,
+ &ecc, x509->pubKey.length) != 0) {
+ wc_ecc_free(&ecc);
+ return WOLFSSL_FAILURE;
+ }
+ XSNPRINTF(tmp, sizeof(tmp) - 1, "%s%s: (%d bit)\n%s\n",
+ " ", "Public-Key",
+ 8 * wc_ecc_size(&ecc),
+ " pub:");
+ tmp[sizeof(tmp) - 1] = '\0';
+ if (wolfSSL_BIO_write(bio, tmp,
+ (int)XSTRLEN(tmp)) <= 0) {
+ wc_ecc_free(&ecc);
+ return WOLFSSL_FAILURE;
+ }
+ XSNPRINTF(tmp, sizeof(tmp) - 1," ");
+ {
+ word32 derSz;
+ byte* der;
+
+ derSz = wc_ecc_size(&ecc) * WOLFSSL_BIT_SIZE;
+ der = (byte*)XMALLOC(derSz, x509->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (der == NULL) {
+ wc_ecc_free(&ecc);
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wc_ecc_export_x963(&ecc, der, &derSz) != 0) {
+ wc_ecc_free(&ecc);
+ XFREE(der, x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+ for (i = 0; i < derSz; i++) {
+ char val[5];
+ int valSz = 5;
+
+ if (i == 0) {
+ XSNPRINTF(val, valSz - 1, "%02x", der[i]);
+ }
+ else if ((i % 15) == 0) {
+ tmp[sizeof(tmp) - 1] = '\0';
+ if (wolfSSL_BIO_write(bio, tmp,
+ (int)XSTRLEN(tmp)) <= 0) {
+ wc_ecc_free(&ecc);
+ XFREE(der, x509->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+ XSNPRINTF(tmp, sizeof(tmp) - 1,
+ ":\n ");
+ XSNPRINTF(val, valSz - 1, "%02x", der[i]);
+ }
+ else {
+ XSNPRINTF(val, valSz - 1, ":%02x", der[i]);
+ }
+ XSTRNCAT(tmp, val, valSz);
+ }
+
+ /* print out remaining modulus values */
+ if ((i > 0) && (((i - 1) % 15) != 0)) {
+ tmp[sizeof(tmp) - 1] = '\0';
+ if (wolfSSL_BIO_write(bio, tmp,
+ (int)XSTRLEN(tmp)) <= 0) {
+ wc_ecc_free(&ecc);
+ XFREE(der, x509->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ XFREE(der, x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ XSNPRINTF(tmp, sizeof(tmp) - 1, "\n%s%s: %s\n",
+ " ", "ASN1 OID",
+ ecc.dp->name);
+ if (wolfSSL_BIO_write(bio, tmp,
+ (int)XSTRLEN(tmp)) <= 0) {
+ wc_ecc_free(&ecc);
+ return WOLFSSL_FAILURE;
+ }
+ wc_ecc_free(&ecc);
+ }
+ break;
+ #endif /* HAVE_ECC */
+ default:
+ WOLFSSL_MSG("Unknown key type");
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ /* print out extensions */
+ if (wolfSSL_BIO_write(bio, " X509v3 extensions:\n",
+ (int)XSTRLEN(" X509v3 extensions:\n")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* print subject key id */
+ if (x509->subjKeyIdSet && x509->subjKeyId != NULL &&
+ x509->subjKeyIdSz > 0) {
+ char tmp[100];
+ word32 i;
+ char val[5];
+ int valSz = 5;
+
+
+ if (wolfSSL_BIO_write(bio,
+ " X509v3 Subject Key Identifier: \n",
+ (int)XSTRLEN(" X509v3 Subject Key Identifier: \n"))
+ <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ XSNPRINTF(tmp, sizeof(tmp) - 1, " ");
+ for (i = 0; i < sizeof(tmp) && i < (x509->subjKeyIdSz - 1); i++) {
+ XSNPRINTF(val, valSz - 1, "%02X:", x509->subjKeyId[i]);
+ XSTRNCAT(tmp, val, valSz);
+ }
+ XSNPRINTF(val, valSz - 1, "%02X\n", x509->subjKeyId[i]);
+ XSTRNCAT(tmp, val, valSz);
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ /* printf out authority key id */
+ if (x509->authKeyIdSet && x509->authKeyId != NULL &&
+ x509->authKeyIdSz > 0) {
+ char tmp[100];
+ word32 i;
+ char val[5];
+ int valSz = 5;
+ int len = 0;
+
+ if (wolfSSL_BIO_write(bio,
+ " X509v3 Authority Key Identifier: \n",
+ (int)XSTRLEN(" X509v3 Authority Key Identifier: \n"))
+ <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ XSNPRINTF(tmp, sizeof(tmp) - 1, " keyid");
+ for (i = 0; i < x509->authKeyIdSz; i++) {
+ /* check if buffer is almost full */
+ if (XSTRLEN(tmp) >= sizeof(tmp) - valSz) {
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ tmp[0] = '\0';
+ }
+ XSNPRINTF(val, valSz - 1, ":%02X", x509->authKeyId[i]);
+ XSTRNCAT(tmp, val, valSz);
+ }
+ len = (int)XSTRLEN("\n");
+ XSTRNCAT(tmp, "\n", len + 1);
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ /* print basic constraint */
+ if (x509->basicConstSet) {
+ char tmp[100];
+
+ if (wolfSSL_BIO_write(bio,
+ "\n X509v3 Basic Constraints: \n",
+ (int)XSTRLEN("\n X509v3 Basic Constraints: \n"))
+ <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ XSNPRINTF(tmp, sizeof(tmp),
+ " CA:%s\n",
+ (x509->isCa)? "TRUE": "FALSE");
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ /* print out signature */
+ if (x509->sig.length > 0) {
+ unsigned char* sig;
+ int sigSz;
+ int i;
+ char tmp[100];
+ int sigOid = wolfSSL_X509_get_signature_type(x509);
+
+ if (wolfSSL_BIO_write(bio,
+ " Signature Algorithm: ",
+ (int)XSTRLEN(" Signature Algorithm: ")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ XSNPRINTF(tmp, sizeof(tmp) - 1,"%s\n", GetSigName(sigOid));
+ tmp[sizeof(tmp) - 1] = '\0';
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ sigSz = (int)x509->sig.length;
+ sig = (unsigned char*)XMALLOC(sigSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (sig == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_X509_get_signature(x509, sig, &sigSz) <= 0) {
+ XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+ XSNPRINTF(tmp, sizeof(tmp) - 1," ");
+ tmp[sizeof(tmp) - 1] = '\0';
+ for (i = 0; i < sigSz; i++) {
+ char val[5];
+ int valSz = 5;
+
+ if (i == 0) {
+ XSNPRINTF(val, valSz - 1, "%02x", sig[i]);
+ }
+ else if (((i % 18) == 0)) {
+ tmp[sizeof(tmp) - 1] = '\0';
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp))
+ <= 0) {
+ XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+ XSNPRINTF(tmp, sizeof(tmp) - 1,
+ ":\n ");
+ XSNPRINTF(val, valSz - 1, "%02x", sig[i]);
+ }
+ else {
+ XSNPRINTF(val, valSz - 1, ":%02x", sig[i]);
+ }
+ XSTRNCAT(tmp, val, valSz);
+ }
+ XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ /* print out remaining sig values */
+ if ((i > 0) && (((i - 1) % 18) != 0)) {
+ tmp[sizeof(tmp) - 1] = '\0';
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp))
+ <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+ }
+
+ /* done with print out */
+ if (wolfSSL_BIO_write(bio, "\n\0", (int)XSTRLEN("\n\0")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+ }
+ int wolfSSL_X509_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509)
+ {
+ return wolfSSL_X509_print_ex(bio, x509, 0, 0);
+ }
+
+#endif /* XSNPRINTF */
+
+#endif /* NO_CERTS */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+/* Creates cipher->description based on cipher->offset
+ * cipher->offset is set in wolfSSL_get_ciphers_compat when it is added
+ * to a stack of ciphers.
+ * @param [in] cipher: A cipher from a stack of ciphers.
+ * return WOLFSSL_SUCCESS if cipher->description is set, else WOLFSSL_FAILURE
+ */
+int wolfSSL_sk_CIPHER_description(WOLFSSL_CIPHER* cipher)
+{
+ int ret = WOLFSSL_FAILURE;
+ int i,j,k;
+ int strLen;
+ unsigned long offset;
+ char* dp;
+ const char* name;
+ const char *keaStr, *authStr, *encStr, *macStr, *protocol;
+ char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
+ unsigned char len = MAX_DESCRIPTION_SZ-1;
+ const CipherSuiteInfo* cipher_names;
+ ProtocolVersion pv;
+ WOLFSSL_ENTER("wolfSSL_sk_CIPHER_description");
+
+ if (cipher == NULL)
+ return WOLFSSL_FAILURE;
+
+ dp = cipher->description;
+ if (dp == NULL)
+ return WOLFSSL_FAILURE;
+
+ cipher_names = GetCipherNames();
+
+ offset = cipher->offset;
+ pv.major = cipher_names[offset].major;
+ pv.minor = cipher_names[offset].minor;
+ protocol = wolfSSL_internal_get_version(&pv);
+
+ name = cipher_names[offset].name;
+
+ if (name == NULL)
+ return ret;
+
+ /* Segment cipher name into n[n0,n1,n2,n4]
+ * These are used later for comparisons to create:
+ * keaStr, authStr, encStr, macStr
+ *
+ * If cipher_name = ECDHE-ECDSA-AES256-SHA
+ * then n0 = "ECDHE", n1 = "ECDSA", n2 = "AES256", n3 = "SHA"
+ * and n = [n0,n1,n2,n3,0]
+ */
+ strLen = (int)XSTRLEN(name);
+
+ for (i = 0, j = 0, k = 0; i <= strLen; i++) {
+ if (k > MAX_SEGMENTS || j > MAX_SEGMENT_SZ)
+ break;
+
+ if (name[i] != '-' && name[i] != '\0') {
+ n[k][j] = name[i]; /* Fill kth segment string until '-' */
+ j++;
+ }
+ else {
+ n[k][j] = '\0';
+ j = 0;
+ k++;
+ }
+ }
+ /* keaStr */
+ keaStr = GetCipherKeaStr(n);
+ /* authStr */
+ authStr = GetCipherAuthStr(n);
+ /* encStr */
+ encStr = GetCipherEncStr(n);
+ if ((cipher->bits = SetCipherBits(encStr)) == WOLFSSL_FAILURE) {
+ WOLFSSL_MSG("Cipher Bits Not Set.");
+ }
+ /* macStr */
+ macStr = GetCipherMacStr(n);
+
+
+ /* Build up the string by copying onto the end. */
+ XSTRNCPY(dp, name, len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= (int)strLen; dp += strLen;
+
+ XSTRNCPY(dp, " ", len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= (int)strLen; dp += strLen;
+ XSTRNCPY(dp, protocol, len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= (int)strLen; dp += strLen;
+
+ XSTRNCPY(dp, " Kx=", len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= (int)strLen; dp += strLen;
+ XSTRNCPY(dp, keaStr, len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= (int)strLen; dp += strLen;
+
+ XSTRNCPY(dp, " Au=", len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= (int)strLen; dp += strLen;
+ XSTRNCPY(dp, authStr, len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= (int)strLen; dp += strLen;
+
+ XSTRNCPY(dp, " Enc=", len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= (int)strLen; dp += strLen;
+ XSTRNCPY(dp, encStr, len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= (int)strLen; dp += strLen;
+
+ XSTRNCPY(dp, " Mac=", len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= (int)strLen; dp += strLen;
+ XSTRNCPY(dp, macStr, len);
+ dp[len-1] = '\0';
+
+ return WOLFSSL_SUCCESS;
+}
#endif
- case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 :
- return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256";
- case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 :
- return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384";
+
+char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in,
+ int len)
+{
+ char *ret = in;
+ const char *keaStr, *authStr, *encStr, *macStr;
+ size_t strLen;
+ WOLFSSL_ENTER("wolfSSL_CIPHER_description");
+
+ if (cipher == NULL || in == NULL)
+ return NULL;
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ /* if cipher is in the stack from wolfSSL_get_ciphers_compat then
+ * Return the description based on cipher_names[cipher->offset]
+ */
+ if (cipher->in_stack == TRUE) {
+ wolfSSL_sk_CIPHER_description((WOLFSSL_CIPHER*)cipher);
+ XSTRNCPY(in,cipher->description,len);
+ return ret;
+ }
#endif
-#endif /* HAVE_ECC */
-#ifdef HAVE_AESCCM
+ /* Get the cipher description based on the SSL session cipher */
+ switch (cipher->ssl->specs.kea) {
+ case no_kea:
+ keaStr = "None";
+ break;
#ifndef NO_RSA
- case TLS_RSA_WITH_AES_128_CCM_8 :
- return "TLS_RSA_WITH_AES_128_CCM_8";
- case TLS_RSA_WITH_AES_256_CCM_8 :
- return "TLS_RSA_WITH_AES_256_CCM_8";
+ case rsa_kea:
+ keaStr = "RSA";
+ break;
+#endif
+#ifndef NO_DH
+ case diffie_hellman_kea:
+ keaStr = "DHE";
+ break;
#endif
+ case fortezza_kea:
+ keaStr = "FZ";
+ break;
#ifndef NO_PSK
- case TLS_PSK_WITH_AES_128_CCM_8 :
- return "TLS_PSK_WITH_AES_128_CCM_8";
- case TLS_PSK_WITH_AES_256_CCM_8 :
- return "TLS_PSK_WITH_AES_256_CCM_8";
- case TLS_PSK_WITH_AES_128_CCM :
- return "TLS_PSK_WITH_AES_128_CCM";
- case TLS_PSK_WITH_AES_256_CCM :
- return "TLS_PSK_WITH_AES_256_CCM";
- case TLS_DHE_PSK_WITH_AES_128_CCM :
- return "TLS_DHE_PSK_WITH_AES_128_CCM";
- case TLS_DHE_PSK_WITH_AES_256_CCM :
- return "TLS_DHE_PSK_WITH_AES_256_CCM";
+ case psk_kea:
+ keaStr = "PSK";
+ break;
+ #ifndef NO_DH
+ case dhe_psk_kea:
+ keaStr = "DHEPSK";
+ break;
+ #endif
+ #ifdef HAVE_ECC
+ case ecdhe_psk_kea:
+ keaStr = "ECDHEPSK";
+ break;
+ #endif
#endif
-#ifdef HAVE_ECC
- case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
- return "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8";
- case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 :
- return "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8";
+#ifdef HAVE_NTRU
+ case ntru_kea:
+ keaStr = "NTRU";
+ break;
#endif
+#ifdef HAVE_ECC
+ case ecc_diffie_hellman_kea:
+ keaStr = "ECDHE";
+ break;
+ case ecc_static_diffie_hellman_kea:
+ keaStr = "ECDH";
+ break;
#endif
+ default:
+ keaStr = "unknown";
+ break;
+ }
- default:
- return "NONE";
- }
- }
-#endif /* ECC */
- if (cipher->ssl->options.cipherSuite0 != ECC_BYTE &&
- cipher->ssl->options.cipherSuite0 != CHACHA_BYTE) {
-
- /* normal suites */
- switch (cipher->ssl->options.cipherSuite) {
+ switch (cipher->ssl->specs.sig_algo) {
+ case anonymous_sa_algo:
+ authStr = "None";
+ break;
#ifndef NO_RSA
+ case rsa_sa_algo:
+ authStr = "RSA";
+ break;
+#endif
+#ifndef NO_DSA
+ case dsa_sa_algo:
+ authStr = "DSA";
+ break;
+#endif
+#ifdef HAVE_ECC
+ case ecc_dsa_sa_algo:
+ authStr = "ECDSA";
+ break;
+#endif
+ default:
+ authStr = "unknown";
+ break;
+ }
+
+ switch (cipher->ssl->specs.bulk_cipher_algorithm) {
+ case wolfssl_cipher_null:
+ encStr = "None";
+ break;
#ifndef NO_RC4
- #ifndef NO_SHA
- case SSL_RSA_WITH_RC4_128_SHA :
- return "SSL_RSA_WITH_RC4_128_SHA";
- #endif
- #ifndef NO_MD5
- case SSL_RSA_WITH_RC4_128_MD5 :
- return "SSL_RSA_WITH_RC4_128_MD5";
- #endif
+ case wolfssl_rc4:
+ encStr = "RC4(128)";
+ break;
#endif
-#ifndef NO_SHA
- #ifndef NO_DES3
- case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
- return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
- #endif
- case TLS_RSA_WITH_AES_128_CBC_SHA :
- return "TLS_RSA_WITH_AES_128_CBC_SHA";
- case TLS_RSA_WITH_AES_256_CBC_SHA :
- return "TLS_RSA_WITH_AES_256_CBC_SHA";
-#endif
- case TLS_RSA_WITH_AES_128_CBC_SHA256 :
- return "TLS_RSA_WITH_AES_128_CBC_SHA256";
- case TLS_RSA_WITH_AES_256_CBC_SHA256 :
- return "TLS_RSA_WITH_AES_256_CBC_SHA256";
- #ifdef HAVE_BLAKE2
- case TLS_RSA_WITH_AES_128_CBC_B2B256:
- return "TLS_RSA_WITH_AES_128_CBC_B2B256";
- case TLS_RSA_WITH_AES_256_CBC_B2B256:
- return "TLS_RSA_WITH_AES_256_CBC_B2B256";
- #endif
-#ifndef NO_SHA
- case TLS_RSA_WITH_NULL_SHA :
- return "TLS_RSA_WITH_NULL_SHA";
+#ifndef NO_DES3
+ case wolfssl_triple_des:
+ encStr = "3DES(168)";
+ break;
#endif
- case TLS_RSA_WITH_NULL_SHA256 :
- return "TLS_RSA_WITH_NULL_SHA256";
-#endif /* NO_RSA */
-#ifndef NO_PSK
-#ifndef NO_SHA
- case TLS_PSK_WITH_AES_128_CBC_SHA :
- return "TLS_PSK_WITH_AES_128_CBC_SHA";
- case TLS_PSK_WITH_AES_256_CBC_SHA :
- return "TLS_PSK_WITH_AES_256_CBC_SHA";
+#ifdef HAVE_IDEA
+ case wolfssl_idea:
+ encStr = "IDEA(128)";
+ break;
#endif
-#ifndef NO_SHA256
- case TLS_PSK_WITH_AES_128_CBC_SHA256 :
- return "TLS_PSK_WITH_AES_128_CBC_SHA256";
- case TLS_PSK_WITH_NULL_SHA256 :
- return "TLS_PSK_WITH_NULL_SHA256";
- case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 :
- return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256";
- case TLS_DHE_PSK_WITH_NULL_SHA256 :
- return "TLS_DHE_PSK_WITH_NULL_SHA256";
+#ifndef NO_AES
+ case wolfssl_aes:
+ if (cipher->ssl->specs.key_size == 128)
+ encStr = "AES(128)";
+ else if (cipher->ssl->specs.key_size == 256)
+ encStr = "AES(256)";
+ else
+ encStr = "AES(?)";
+ break;
#ifdef HAVE_AESGCM
- case TLS_PSK_WITH_AES_128_GCM_SHA256 :
- return "TLS_PSK_WITH_AES_128_GCM_SHA256";
- case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 :
- return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256";
+ case wolfssl_aes_gcm:
+ if (cipher->ssl->specs.key_size == 128)
+ encStr = "AESGCM(128)";
+ else if (cipher->ssl->specs.key_size == 256)
+ encStr = "AESGCM(256)";
+ else
+ encStr = "AESGCM(?)";
+ break;
#endif
-#endif
-#ifdef WOLFSSL_SHA384
- case TLS_PSK_WITH_AES_256_CBC_SHA384 :
- return "TLS_PSK_WITH_AES_256_CBC_SHA384";
- case TLS_PSK_WITH_NULL_SHA384 :
- return "TLS_PSK_WITH_NULL_SHA384";
- case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 :
- return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384";
- case TLS_DHE_PSK_WITH_NULL_SHA384 :
- return "TLS_DHE_PSK_WITH_NULL_SHA384";
- #ifdef HAVE_AESGCM
- case TLS_PSK_WITH_AES_256_GCM_SHA384 :
- return "TLS_PSK_WITH_AES_256_GCM_SHA384";
- case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 :
- return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384";
+ #ifdef HAVE_AESCCM
+ case wolfssl_aes_ccm:
+ if (cipher->ssl->specs.key_size == 128)
+ encStr = "AESCCM(128)";
+ else if (cipher->ssl->specs.key_size == 256)
+ encStr = "AESCCM(256)";
+ else
+ encStr = "AESCCM(?)";
+ break;
#endif
#endif
-#ifndef NO_SHA
- case TLS_PSK_WITH_NULL_SHA :
- return "TLS_PSK_WITH_NULL_SHA";
+#ifdef HAVE_CHACHA
+ case wolfssl_chacha:
+ encStr = "CHACHA20/POLY1305(256)";
+ break;
#endif
-#endif /* NO_PSK */
-#ifndef NO_RSA
- case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 :
- return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256";
- case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 :
- return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256";
-#ifndef NO_SHA
- case TLS_DHE_RSA_WITH_AES_128_CBC_SHA :
- return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
- case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
- return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
+#ifdef HAVE_CAMELLIA
+ case wolfssl_camellia:
+ if (cipher->ssl->specs.key_size == 128)
+ encStr = "Camellia(128)";
+ else if (cipher->ssl->specs.key_size == 256)
+ encStr = "Camellia(256)";
+ else
+ encStr = "Camellia(?)";
+ break;
+#endif
+#if defined(HAVE_HC128) && !defined(NO_HC128)
+ case wolfssl_hc128:
+ encStr = "HC128(128)";
+ break;
+#endif
+#if defined(HAVE_RABBIT) && !defined(NO_RABBIT)
+ case wolfssl_rabbit:
+ encStr = "RABBIT(128)";
+ break;
+#endif
+ default:
+ encStr = "unknown";
+ break;
+ }
+
+ switch (cipher->ssl->specs.mac_algorithm) {
+ case no_mac:
+ macStr = "None";
+ break;
+#ifndef NO_MD5
+ case md5_mac:
+ macStr = "MD5";
+ break;
#endif
-#ifndef NO_HC128
- #ifndef NO_MD5
- case TLS_RSA_WITH_HC_128_MD5 :
- return "TLS_RSA_WITH_HC_128_MD5";
- #endif
- #ifndef NO_SHA
- case TLS_RSA_WITH_HC_128_SHA :
- return "TLS_RSA_WITH_HC_128_SHA";
- #endif
- #ifdef HAVE_BLAKE2
- case TLS_RSA_WITH_HC_128_B2B256:
- return "TLS_RSA_WITH_HC_128_B2B256";
- #endif
-#endif /* NO_HC128 */
-#ifndef NO_SHA
- #ifndef NO_RABBIT
- case TLS_RSA_WITH_RABBIT_SHA :
- return "TLS_RSA_WITH_RABBIT_SHA";
- #endif
- #ifdef HAVE_NTRU
- #ifndef NO_RC4
- case TLS_NTRU_RSA_WITH_RC4_128_SHA :
- return "TLS_NTRU_RSA_WITH_RC4_128_SHA";
- #endif
- #ifndef NO_DES3
- case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
- return "TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA";
- #endif
- case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
- return "TLS_NTRU_RSA_WITH_AES_128_CBC_SHA";
- case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
- return "TLS_NTRU_RSA_WITH_AES_256_CBC_SHA";
- #endif /* HAVE_NTRU */
-#endif /* NO_SHA */
- case TLS_RSA_WITH_AES_128_GCM_SHA256 :
- return "TLS_RSA_WITH_AES_128_GCM_SHA256";
- case TLS_RSA_WITH_AES_256_GCM_SHA384 :
- return "TLS_RSA_WITH_AES_256_GCM_SHA384";
- case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 :
- return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
- case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 :
- return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";
-#ifndef NO_SHA
- case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA :
- return "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA";
- case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA :
- return "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA";
-#endif
- case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
- return "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256";
- case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
- return "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256";
#ifndef NO_SHA
- case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA :
- return "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA";
- case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA :
- return "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA";
-#endif
- case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
- return "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256";
- case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
- return "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256";
-#endif /* NO_RSA */
-#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
- case TLS_DH_anon_WITH_AES_128_CBC_SHA :
- return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
+ case sha_mac:
+ macStr = "SHA1";
+ break;
#endif
- default:
- return "NONE";
- } /* switch */
- } /* normal / ECC */
+#ifdef HAVE_SHA224
+ case sha224_mac:
+ macStr = "SHA224";
+ break;
+#endif
+#ifndef NO_SHA256
+ case sha256_mac:
+ macStr = "SHA256";
+ break;
+#endif
+#ifdef HAVE_SHA384
+ case sha384_mac:
+ macStr = "SHA384";
+ break;
+#endif
+#ifdef HAVE_SHA512
+ case sha512_mac:
+ macStr = "SHA512";
+ break;
+#endif
+ default:
+ macStr = "unknown";
+ break;
}
-#endif /* NO_ERROR_STRINGS */
- return "NONE";
-}
+ /* Build up the string by copying onto the end. */
+ XSTRNCPY(in, wolfSSL_CIPHER_get_name(cipher), len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
-const char* wolfSSL_get_cipher(WOLFSSL* ssl)
-{
- WOLFSSL_ENTER("wolfSSL_get_cipher");
- return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl));
-}
+ XSTRNCPY(in, " ", len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+ XSTRNCPY(in, wolfSSL_get_version(cipher->ssl), len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
-#ifdef OPENSSL_EXTRA
+ XSTRNCPY(in, " Kx=", len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+ XSTRNCPY(in, keaStr, len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+ XSTRNCPY(in, " Au=", len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+ XSTRNCPY(in, authStr, len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+ XSTRNCPY(in, " Enc=", len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+ XSTRNCPY(in, encStr, len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
-char* wolfSSL_CIPHER_description(WOLFSSL_CIPHER* cipher, char* in, int len)
-{
- (void)cipher;
- (void)in;
- (void)len;
- return 0;
+ XSTRNCPY(in, " Mac=", len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+ XSTRNCPY(in, macStr, len);
+ in[len-1] = '\0';
+
+ return ret;
}
-WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) /* what's ref count */
+#ifndef NO_SESSION_CACHE
+
+WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl)
{
- (void)ssl;
- return 0;
+ if (ssl == NULL) {
+ return NULL;
+ }
+
+ /* sessions are stored statically, no need for reference count */
+ return wolfSSL_get_session(ssl);
}
+#endif /* NO_SESSION_CACHE */
-void wolfSSL_X509_free(WOLFSSL_X509* buf)
-{
- FreeX509(buf);
-}
/* was do nothing */
@@ -9821,7 +21399,7 @@ void OPENSSL_free(void* buf)
}
*/
-
+#ifndef NO_WOLFSSL_STUB
int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path,
int* ssl)
{
@@ -9830,21 +21408,10 @@ int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path,
(void)port;
(void)path;
(void)ssl;
+ WOLFSSL_STUB("OCSP_parse_url");
return 0;
}
-
-
-WOLFSSL_METHOD* wolfSSLv2_client_method(void)
-{
- return 0;
-}
-
-
-WOLFSSL_METHOD* wolfSSLv2_server_method(void)
-{
- return 0;
-}
-
+#endif
#ifndef NO_MD4
@@ -9876,17 +21443,29 @@ void wolfSSL_MD4_Final(unsigned char* digest, WOLFSSL_MD4_CTX* md4)
#endif /* NO_MD4 */
-WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* top)
+/* Removes a WOLFSSL_BIO struct from the WOLFSSL_BIO linked list.
+ *
+ * bio is the WOLFSSL_BIO struct in the list and removed.
+ *
+ * The return WOLFSSL_BIO struct is the next WOLFSSL_BIO in the list or NULL if
+ * there is none.
+ */
+WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* bio)
{
- (void)top;
- return 0;
-}
+ if (bio == NULL) {
+ WOLFSSL_MSG("Bad argument passed in");
+ return NULL;
+ }
+ if (bio->prev != NULL) {
+ bio->prev->next = bio->next;
+ }
-int wolfSSL_BIO_pending(WOLFSSL_BIO* bio)
-{
- (void)bio;
- return 0;
+ if (bio->next != NULL) {
+ bio->next->prev = bio->prev;
+ }
+
+ return bio->next;
}
@@ -9895,8 +21474,8 @@ WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void)
{
static WOLFSSL_BIO_METHOD meth;
- WOLFSSL_ENTER("BIO_s_mem");
- meth.type = BIO_MEMORY;
+ WOLFSSL_ENTER("wolfSSL_BIO_s_mem");
+ meth.type = WOLFSSL_BIO_MEMORY;
return &meth;
}
@@ -9904,37 +21483,88 @@ WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void)
WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void)
{
- return 0;
-}
+ static WOLFSSL_BIO_METHOD meth;
+ WOLFSSL_ENTER("wolfSSL_BIO_f_base64");
+ meth.type = WOLFSSL_BIO_BASE64;
-void wolfSSL_BIO_set_flags(WOLFSSL_BIO* bio, int flags)
-{
- (void)bio;
- (void)flags;
+ return &meth;
}
-
-void wolfSSL_RAND_screen(void)
+/* Set the flag for the bio.
+ *
+ * bio the structure to set the flag in
+ * flags the flag to use
+ */
+void wolfSSL_BIO_set_flags(WOLFSSL_BIO* bio, int flags)
{
+ WOLFSSL_ENTER("wolfSSL_BIO_set_flags");
+ if (bio != NULL) {
+ bio->flags |= flags;
+ }
}
+void wolfSSL_BIO_clear_flags(WOLFSSL_BIO *bio, int flags)
+{
+ WOLFSSL_ENTER("wolfSSL_BIO_clear_flags");
+ if (bio != NULL) {
+ bio->flags &= ~flags;
+ }
+}
-const char* wolfSSL_RAND_file_name(char* fname, unsigned long len)
+/* Set ex_data for WOLFSSL_BIO
+ *
+ * bio : BIO structure to set ex_data in
+ * idx : Index of ex_data to set
+ * data : Data to set in ex_data
+ *
+ * Returns WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE on failure
+ */
+int wolfSSL_BIO_set_ex_data(WOLFSSL_BIO *bio, int idx, void *data)
{
- (void)fname;
- (void)len;
- return 0;
+ WOLFSSL_ENTER("wolfSSL_BIO_set_ex_data");
+ #ifdef HAVE_EX_DATA
+ if (bio != NULL && idx < MAX_EX_DATA) {
+ return wolfSSL_CRYPTO_set_ex_data(&bio->ex_data, idx, data);
+ }
+ #else
+ (void)bio;
+ (void)idx;
+ (void)data;
+ #endif
+ return WOLFSSL_FAILURE;
}
+/* Get ex_data in WOLFSSL_BIO at given index
+ *
+ * bio : BIO structure to get ex_data from
+ * idx : Index of ex_data to get data from
+ *
+ * Returns void pointer to ex_data on success or NULL on failure
+ */
+void *wolfSSL_BIO_get_ex_data(WOLFSSL_BIO *bio, int idx)
+{
+ WOLFSSL_ENTER("wolfSSL_BIO_get_ex_data");
+ #ifdef HAVE_EX_DATA
+ if (bio != NULL && idx < MAX_EX_DATA && idx >= 0) {
+ return wolfSSL_CRYPTO_get_ex_data(&bio->ex_data, idx);
+ }
+ #else
+ (void)bio;
+ (void)idx;
+ #endif
+ return NULL;
+}
-int wolfSSL_RAND_write_file(const char* fname)
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_RAND_screen(void)
{
- (void)fname;
- return 0;
+ WOLFSSL_STUB("RAND_screen");
}
+#endif
+
int wolfSSL_RAND_load_file(const char* fname, long len)
@@ -9948,177 +21578,1108 @@ int wolfSSL_RAND_load_file(const char* fname, long len)
}
-int wolfSSL_RAND_egd(const char* path)
-{
- (void)path;
- return 0;
-}
-
-
-
+#ifndef NO_WOLFSSL_STUB
WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void)
{
+ WOLFSSL_STUB("COMP_zlib");
return 0;
}
+#endif
-
+#ifndef NO_WOLFSSL_STUB
WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void)
{
+ WOLFSSL_STUB("COMP_rle");
return 0;
}
+#endif
-
+#ifndef NO_WOLFSSL_STUB
int wolfSSL_COMP_add_compression_method(int method, void* data)
{
(void)method;
(void)data;
+ WOLFSSL_STUB("COMP_add_compression_method");
return 0;
}
+#endif
-
-
-int wolfSSL_get_ex_new_index(long idx, void* data, void* cb1, void* cb2,
- void* cb3)
-{
- (void)idx;
- (void)data;
- (void)cb1;
- (void)cb2;
- (void)cb3;
- return 0;
-}
-
-
+#ifndef NO_WOLFSSL_STUB
void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f)(
const char*, int))
{
+ WOLFSSL_STUB("CRYPTO_set_dynlock_create_callback");
(void)f;
}
+#endif
-
+#ifndef NO_WOLFSSL_STUB
void wolfSSL_set_dynlock_lock_callback(
void (*f)(int, WOLFSSL_dynlock_value*, const char*, int))
{
+ WOLFSSL_STUB("CRYPTO_set_set_dynlock_lock_callback");
(void)f;
}
+#endif
-
+#ifndef NO_WOLFSSL_STUB
void wolfSSL_set_dynlock_destroy_callback(
void (*f)(WOLFSSL_dynlock_value*, const char*, int))
{
+ WOLFSSL_STUB("CRYPTO_set_set_dynlock_destroy_callback");
(void)f;
}
-
+#endif
const char* wolfSSL_X509_verify_cert_error_string(long err)
{
- (void)err;
- return 0;
+ return wolfSSL_ERR_reason_error_string(err);
}
-
+#ifndef NO_WOLFSSL_STUB
int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP* lookup, const char* dir,
long len)
{
(void)lookup;
(void)dir;
(void)len;
+ WOLFSSL_STUB("X509_LOOKUP_add_dir");
return 0;
}
-
+#endif
int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup,
- const char* file, long len)
-{
+ const char* file, long type)
+{
+#if !defined(NO_FILESYSTEM) && \
+ (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM))
+ int ret = WOLFSSL_FAILURE;
+ XFILE fp;
+ long sz;
+ byte* pem = NULL;
+ byte* curr = NULL;
+ byte* prev = NULL;
+ WOLFSSL_X509* x509;
+ const char* header = NULL;
+ const char* footer = NULL;
+
+ if (type != X509_FILETYPE_PEM)
+ return BAD_FUNC_ARG;
+
+ fp = XFOPEN(file, "r");
+ if (fp == XBADFILE)
+ return BAD_FUNC_ARG;
+
+ if(XFSEEK(fp, 0, XSEEK_END) != 0) {
+ XFCLOSE(fp);
+ return WOLFSSL_BAD_FILE;
+ }
+ sz = XFTELL(fp);
+ XREWIND(fp);
+
+ if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
+ WOLFSSL_MSG("X509_LOOKUP_load_file size error");
+ goto end;
+ }
+
+ pem = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_PEM);
+ if (pem == NULL) {
+ ret = MEMORY_ERROR;
+ goto end;
+ }
+
+ /* Read in file which may be CRLs or certificates. */
+ if (XFREAD(pem, (size_t)sz, 1, fp) != 1)
+ goto end;
+
+ prev = curr = pem;
+ do {
+ /* get PEM header and footer based on type */
+ if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 &&
+ XSTRNSTR((char*)curr, header, (unsigned int)sz) != NULL) {
+#ifdef HAVE_CRL
+ WOLFSSL_CERT_MANAGER* cm = lookup->store->cm;
+
+ if (cm->crl == NULL) {
+ if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Enable CRL failed");
+ goto end;
+ }
+ }
+
+ ret = BufferLoadCRL(cm->crl, curr, sz, WOLFSSL_FILETYPE_PEM,
+ NO_VERIFY);
+ if (ret != WOLFSSL_SUCCESS)
+ goto end;
+#endif
+ curr = (byte*)XSTRNSTR((char*)curr, footer, (unsigned int)sz);
+ }
+ else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 &&
+ XSTRNSTR((char*)curr, header, (unsigned int)sz) != NULL) {
+ x509 = wolfSSL_X509_load_certificate_buffer(curr, (int)sz,
+ WOLFSSL_FILETYPE_PEM);
+ if (x509 == NULL)
+ goto end;
+ ret = wolfSSL_X509_STORE_add_cert(lookup->store, x509);
+ wolfSSL_X509_free(x509);
+ if (ret != WOLFSSL_SUCCESS)
+ goto end;
+ curr = (byte*)XSTRNSTR((char*)curr, footer, (unsigned int)sz);
+ }
+ else
+ goto end;
+
+ if (curr == NULL)
+ goto end;
+
+ curr++;
+ sz -= (long)(curr - prev);
+ prev = curr;
+ }
+ while (ret == WOLFSSL_SUCCESS);
+
+end:
+ if (pem != NULL)
+ XFREE(pem, 0, DYNAMIC_TYPE_PEM);
+ XFCLOSE(fp);
+ return ret;
+#else
(void)lookup;
(void)file;
- (void)len;
- return 0;
+ (void)type;
+ return WOLFSSL_FAILURE;
+#endif
}
-
WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void)
{
- return 0;
+ /* Method implementation in functions. */
+ static WOLFSSL_X509_LOOKUP_METHOD meth = { 1 };
+ return &meth;
}
-
WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void)
{
- return 0;
+ /* Method implementation in functions. */
+ static WOLFSSL_X509_LOOKUP_METHOD meth = { 0 };
+ return &meth;
}
-
WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store,
WOLFSSL_X509_LOOKUP_METHOD* m)
{
- (void)store;
+ WOLFSSL_ENTER("SSL_X509_STORE_add_lookup");
+ if (store == NULL)
+ return NULL;
+
+ /* Method is a dummy value and is not needed. */
(void)m;
- return 0;
+ /* Make sure the lookup has a back reference to the store. */
+ store->lookup.store = store;
+ return &store->lookup;
+}
+
+
+#ifndef NO_CERTS
+/* Converts the X509 to DER format and outputs it into bio.
+ *
+ * bio is the structure to hold output DER
+ * x509 certificate to create DER from
+ *
+ * returns WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509)
+{
+ WOLFSSL_ENTER("wolfSSL_i2d_X509_bio");
+
+ if (bio == NULL || x509 == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (x509->derCert != NULL) {
+ word32 len = x509->derCert->length;
+ byte* der = x509->derCert->buffer;
+
+ if (wolfSSL_BIO_write(bio, der, len) == (int)len) {
+ return SSL_SUCCESS;
+ }
+ }
+
+ return WOLFSSL_FAILURE;
+}
+
+
+/* Converts an internal structure to a DER buffer
+ *
+ * x509 structure to get DER buffer from
+ * out buffer to hold result. If NULL then *out is NULL then a new buffer is
+ * created.
+ *
+ * returns the size of the DER result on success
+ */
+int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out)
+{
+ const unsigned char* der;
+ int derSz = 0;
+
+ WOLFSSL_ENTER("wolfSSL_i2d_X509");
+
+ if (x509 == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_i2d_X509", BAD_FUNC_ARG);
+ return BAD_FUNC_ARG;
+ }
+
+ der = wolfSSL_X509_get_der(x509, &derSz);
+ if (der == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_i2d_X509", MEMORY_E);
+ return MEMORY_E;
+ }
+
+ if (out != NULL && *out == NULL) {
+ *out = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (*out == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_i2d_X509", MEMORY_E);
+ return MEMORY_E;
+ }
+ }
+
+ if (out != NULL)
+ XMEMCPY(*out, der, derSz);
+
+ WOLFSSL_LEAVE("wolfSSL_i2d_X509", derSz);
+ return derSz;
+}
+
+
+/* Converts the DER from bio and creates a WOLFSSL_X509 structure from it.
+ *
+ * bio is the structure holding DER
+ * x509 certificate to create from DER. Can be NULL
+ *
+ * returns pointer to WOLFSSL_X509 structure on success and NULL on fail
+ */
+WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509)
+{
+ WOLFSSL_X509* localX509 = NULL;
+ unsigned char* mem = NULL;
+ int ret;
+ word32 size;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_X509_bio");
+
+ if (bio == NULL) {
+ WOLFSSL_MSG("Bad Function Argument bio is NULL");
+ return NULL;
+ }
+
+ ret = wolfSSL_BIO_get_mem_data(bio, &mem);
+ if (mem == NULL || ret <= 0) {
+ WOLFSSL_MSG("Failed to get data from bio struct");
+ return NULL;
+ }
+ size = ret;
+
+ localX509 = wolfSSL_X509_d2i(NULL, mem, size);
+ if (localX509 == NULL) {
+ return NULL;
+ }
+
+ if (x509 != NULL) {
+ *x509 = localX509;
+ }
+
+ return localX509;
+}
+
+
+#if !defined(NO_ASN) && !defined(NO_PWDBASED)
+WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12)
+{
+ WC_PKCS12* localPkcs12 = NULL;
+ unsigned char* mem = NULL;
+ int ret;
+ word32 size;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio");
+
+ if (bio == NULL) {
+ WOLFSSL_MSG("Bad Function Argument bio is NULL");
+ return NULL;
+ }
+
+ localPkcs12 = wc_PKCS12_new();
+ if (localPkcs12 == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return NULL;
+ }
+
+ if (pkcs12 != NULL) {
+ *pkcs12 = localPkcs12;
+ }
+
+ ret = wolfSSL_BIO_get_mem_data(bio, &mem);
+ if (mem == NULL || ret <= 0) {
+ WOLFSSL_MSG("Failed to get data from bio struct");
+ wc_PKCS12_free(localPkcs12);
+ if (pkcs12 != NULL) {
+ *pkcs12 = NULL;
+ }
+ return NULL;
+ }
+ size = ret;
+
+ ret = wc_d2i_PKCS12(mem, size, localPkcs12);
+ if (ret < 0) {
+ WOLFSSL_MSG("Failed to get PKCS12 sequence");
+ wc_PKCS12_free(localPkcs12);
+ if (pkcs12 != NULL) {
+ *pkcs12 = NULL;
+ }
+ return NULL;
+ }
+
+ return localPkcs12;
+}
+
+/* Converts the PKCS12 to DER format and outputs it into bio.
+ *
+ * bio is the structure to hold output DER
+ * pkcs12 structure to create DER from
+ *
+ * return 1 for success or 0 if an error occurs
+ */
+int wolfSSL_i2d_PKCS12_bio(WOLFSSL_BIO *bio, WC_PKCS12 *pkcs12)
+{
+ int ret = WOLFSSL_FAILURE;
+
+ WOLFSSL_ENTER("wolfSSL_i2d_PKCS12_bio");
+
+ if ((bio != NULL) && (pkcs12 != NULL)) {
+ word32 certSz = 0;
+ byte *certDer = NULL;
+
+ certSz = wc_i2d_PKCS12(pkcs12, &certDer, NULL);
+ if ((certSz > 0) && (certDer != NULL)) {
+ if (wolfSSL_BIO_write(bio, certDer, certSz) == (int)certSz) {
+ ret = SSL_SUCCESS;
+ }
+ }
+
+ if (certDer != NULL) {
+ XFREE(certDer, NULL, DYNAMIC_TYPE_PKCS);
+ }
+ }
+
+ return ret;
+}
+
+/* helper function to get raw pointer to DER buffer from WOLFSSL_EVP_PKEY */
+static int wolfSSL_EVP_PKEY_get_der(WOLFSSL_EVP_PKEY* key, unsigned char** der)
+{
+ if (!key)
+ return WOLFSSL_FAILURE;
+ if (der)
+ *der = (unsigned char*)key->pkey.ptr;
+ return key->pkey_sz;
+}
+
+/* Copies unencrypted DER key buffer into "der". If "der" is null then the size
+ * of buffer needed is returned
+ * NOTE: This also advances the "der" pointer to be at the end of buffer.
+ *
+ * Returns size of key buffer on success
+ */
+int wolfSSL_i2d_PrivateKey(WOLFSSL_EVP_PKEY* key, unsigned char** der)
+{
+ if (key == NULL) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (key->pkey_sz <= 0 || !key->pkey.ptr) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (der != NULL) {
+ /* since this function signature has no size value passed in it is
+ * assumed that the user has allocated a large enough buffer */
+ XMEMCPY(*der, key->pkey.ptr, key->pkey_sz);
+ *der += key->pkey_sz;
+ }
+ return key->pkey_sz;
+}
+
+/* Creates a new WC_PKCS12 structure
+ *
+ * pass password to use
+ * name friendlyName to use
+ * pkey private key to go into PKCS12 bundle
+ * cert certificate to go into PKCS12 bundle
+ * ca extra certificates that can be added to bundle. Can be NULL
+ * keyNID type of encryption to use on the key (-1 means no encryption)
+ * certNID type of encryption to use on the certificate
+ * itt number of iterations with encryption
+ * macItt number of iterations with mac creation
+ * keyType flag for signature and/or encryption key
+ *
+ * returns a pointer to a new WC_PKCS12 structure on success and NULL on fail
+ */
+WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name,
+ WOLFSSL_EVP_PKEY* pkey, WOLFSSL_X509* cert,
+ WOLF_STACK_OF(WOLFSSL_X509)* ca,
+ int keyNID, int certNID, int itt, int macItt, int keyType)
+{
+ WC_PKCS12* pkcs12;
+ WC_DerCertList* list = NULL;
+ word32 passSz;
+ byte* keyDer;
+ word32 keyDerSz;
+ byte* certDer;
+ int certDerSz;
+
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_PKCS12_create()");
+
+ if (pass == NULL || pkey == NULL || cert == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_PKCS12_create()", BAD_FUNC_ARG);
+ return NULL;
+ }
+ passSz = (word32)XSTRLEN(pass);
+
+ if ((ret = wolfSSL_EVP_PKEY_get_der(pkey, &keyDer)) < 0) {
+ WOLFSSL_LEAVE("wolfSSL_PKCS12_create", ret);
+ return NULL;
+ }
+ keyDerSz = ret;
+
+ certDer = (byte*)wolfSSL_X509_get_der(cert, &certDerSz);
+ if (certDer == NULL) {
+ return NULL;
+ }
+
+ if (ca != NULL) {
+ WC_DerCertList* cur;
+ unsigned long numCerts = ca->num;
+ byte* curDer;
+ int curDerSz = 0;
+ WOLFSSL_STACK* sk = ca;
+
+ while (numCerts > 0 && sk != NULL) {
+ cur = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), NULL,
+ DYNAMIC_TYPE_PKCS);
+ if (cur == NULL) {
+ wc_FreeCertList(list, NULL);
+ return NULL;
+ }
+
+ curDer = (byte*)wolfSSL_X509_get_der(sk->data.x509, &curDerSz);
+ if (curDer == NULL || curDerSz < 0) {
+ XFREE(cur, NULL, DYNAMIC_TYPE_PKCS);
+ wc_FreeCertList(list, NULL);
+ return NULL;
+ }
+
+ cur->buffer = (byte*)XMALLOC(curDerSz, NULL, DYNAMIC_TYPE_PKCS);
+ if (cur->buffer == NULL) {
+ XFREE(cur, NULL, DYNAMIC_TYPE_PKCS);
+ wc_FreeCertList(list, NULL);
+ return NULL;
+ }
+ XMEMCPY(cur->buffer, curDer, curDerSz);
+ cur->bufferSz = curDerSz;
+ cur->next = list;
+ list = cur;
+
+ sk = sk->next;
+ numCerts--;
+ }
+ }
+
+ pkcs12 = wc_PKCS12_create(pass, passSz, name, keyDer, keyDerSz,
+ certDer, certDerSz, list, keyNID, certNID, itt, macItt,
+ keyType, NULL);
+
+ if (ca != NULL) {
+ wc_FreeCertList(list, NULL);
+ }
+
+ return pkcs12;
+}
+
+
+/* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure */
+int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
+ WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, WOLF_STACK_OF(WOLFSSL_X509)** ca)
+{
+ DecodedCert DeCert;
+ void* heap = NULL;
+ int ret;
+ byte* certData = NULL;
+ word32 certDataSz;
+ byte* pk = NULL;
+ word32 pkSz;
+ WC_DerCertList* certList = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_PKCS12_parse");
+
+ /* make sure we init return args */
+ if (pkey) *pkey = NULL;
+ if (cert) *cert = NULL;
+ if (ca) *ca = NULL;
+
+ if (pkcs12 == NULL || psw == NULL || pkey == NULL || cert == NULL) {
+ WOLFSSL_MSG("Bad argument value");
+ return WOLFSSL_FAILURE;
+ }
+
+ heap = wc_PKCS12_GetHeap(pkcs12);
+
+ if (ca == NULL) {
+ ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
+ NULL);
+ }
+ else {
+ ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
+ &certList);
+ }
+ if (ret < 0) {
+ WOLFSSL_LEAVE("wolfSSL_PKCS12_parse", ret);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Decode cert and place in X509 stack struct */
+ if (certList != NULL) {
+ WC_DerCertList* current = certList;
+
+ *ca = (WOLF_STACK_OF(WOLFSSL_X509)*)XMALLOC(sizeof(WOLF_STACK_OF(WOLFSSL_X509)),
+ heap, DYNAMIC_TYPE_X509);
+ if (*ca == NULL) {
+ if (pk != NULL) {
+ XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ }
+ if (certData != NULL) {
+ XFREE(*cert, heap, DYNAMIC_TYPE_PKCS); *cert = NULL;
+ }
+ /* Free up WC_DerCertList and move on */
+ while (current != NULL) {
+ WC_DerCertList* next = current->next;
+
+ XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
+ XFREE(current, heap, DYNAMIC_TYPE_PKCS);
+ current = next;
+ }
+ return WOLFSSL_FAILURE;
+ }
+ XMEMSET(*ca, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509)));
+
+ /* add list of DER certs as X509's to stack */
+ while (current != NULL) {
+ WC_DerCertList* toFree = current;
+ WOLFSSL_X509* x509;
+
+ x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
+ DYNAMIC_TYPE_X509);
+ InitX509(x509, 1, heap);
+ InitDecodedCert(&DeCert, current->buffer, current->bufferSz, heap);
+ if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
+ WOLFSSL_MSG("Issue with parsing certificate");
+ FreeDecodedCert(&DeCert);
+ wolfSSL_X509_free(x509);
+ }
+ else {
+ if ((ret = CopyDecodedToX509(x509, &DeCert)) != 0) {
+ WOLFSSL_MSG("Failed to copy decoded cert");
+ FreeDecodedCert(&DeCert);
+ wolfSSL_X509_free(x509);
+ wolfSSL_sk_X509_free(*ca); *ca = NULL;
+ if (pk != NULL) {
+ XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ }
+ if (certData != NULL) {
+ XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
+ }
+ /* Free up WC_DerCertList */
+ while (current != NULL) {
+ WC_DerCertList* next = current->next;
+
+ XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
+ XFREE(current, heap, DYNAMIC_TYPE_PKCS);
+ current = next;
+ }
+ return WOLFSSL_FAILURE;
+ }
+ FreeDecodedCert(&DeCert);
+
+ if (wolfSSL_sk_X509_push(*ca, x509) != 1) {
+ WOLFSSL_MSG("Failed to push x509 onto stack");
+ wolfSSL_X509_free(x509);
+ wolfSSL_sk_X509_free(*ca); *ca = NULL;
+ if (pk != NULL) {
+ XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ }
+ if (certData != NULL) {
+ XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
+ }
+
+ /* Free up WC_DerCertList */
+ while (current != NULL) {
+ WC_DerCertList* next = current->next;
+
+ XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
+ XFREE(current, heap, DYNAMIC_TYPE_PKCS);
+ current = next;
+ }
+ return WOLFSSL_FAILURE;
+ }
+ }
+ current = current->next;
+ XFREE(toFree->buffer, heap, DYNAMIC_TYPE_PKCS);
+ XFREE(toFree, heap, DYNAMIC_TYPE_PKCS);
+ }
+ }
+
+
+ /* Decode cert and place in X509 struct */
+ if (certData != NULL) {
+ *cert = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
+ DYNAMIC_TYPE_X509);
+ if (*cert == NULL) {
+ if (pk != NULL) {
+ XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ }
+ if (ca != NULL) {
+ wolfSSL_sk_X509_free(*ca); *ca = NULL;
+ }
+ XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
+ return WOLFSSL_FAILURE;
+ }
+ InitX509(*cert, 1, heap);
+ InitDecodedCert(&DeCert, certData, certDataSz, heap);
+ if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
+ WOLFSSL_MSG("Issue with parsing certificate");
+ }
+ if ((ret = CopyDecodedToX509(*cert, &DeCert)) != 0) {
+ WOLFSSL_MSG("Failed to copy decoded cert");
+ FreeDecodedCert(&DeCert);
+ if (pk != NULL) {
+ XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ }
+ if (ca != NULL) {
+ wolfSSL_sk_X509_free(*ca); *ca = NULL;
+ }
+ wolfSSL_X509_free(*cert); *cert = NULL;
+ return WOLFSSL_FAILURE;
+ }
+ FreeDecodedCert(&DeCert);
+ XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
+ }
+
+
+ /* get key type */
+ ret = BAD_STATE_E;
+ if (pk != NULL) { /* decode key if present */
+ *pkey = wolfSSL_EVP_PKEY_new_ex(heap);
+ if (*pkey == NULL) {
+ wolfSSL_X509_free(*cert); *cert = NULL;
+ if (ca != NULL) {
+ wolfSSL_sk_X509_free(*ca); *ca = NULL;
+ }
+ XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ return WOLFSSL_FAILURE;
+ }
+ #ifndef NO_RSA
+ {
+ word32 keyIdx = 0;
+ RsaKey key;
+
+ if (wc_InitRsaKey(&key, heap) != 0) {
+ ret = BAD_STATE_E;
+ }
+ else {
+ if ((ret = wc_RsaPrivateKeyDecode(pk, &keyIdx, &key, pkSz))
+ == 0) {
+ (*pkey)->type = EVP_PKEY_RSA;
+ (*pkey)->rsa = wolfSSL_RSA_new();
+ (*pkey)->ownRsa = 1; /* we own RSA */
+ if ((*pkey)->rsa == NULL) {
+ WOLFSSL_MSG("issue creating EVP RSA key");
+ wolfSSL_X509_free(*cert); *cert = NULL;
+ if (ca != NULL) {
+ wolfSSL_sk_X509_free(*ca); *ca = NULL;
+ }
+ wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+ XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+ return WOLFSSL_FAILURE;
+ }
+ if ((ret = wolfSSL_RSA_LoadDer_ex((*pkey)->rsa, pk, pkSz,
+ WOLFSSL_RSA_LOAD_PRIVATE)) != SSL_SUCCESS) {
+ WOLFSSL_MSG("issue loading RSA key");
+ wolfSSL_X509_free(*cert); *cert = NULL;
+ if (ca != NULL) {
+ wolfSSL_sk_X509_free(*ca); *ca = NULL;
+ }
+ wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+ XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+ return WOLFSSL_FAILURE;
+ }
+
+ WOLFSSL_MSG("Found PKCS12 RSA key");
+ ret = 0; /* set in success state for upcoming ECC check */
+ }
+ wc_FreeRsaKey(&key);
+ }
+ }
+ #endif /* NO_RSA */
+
+ #ifdef HAVE_ECC
+ {
+ word32 keyIdx = 0;
+ ecc_key key;
+
+ if (ret != 0) { /* if is in fail state check if ECC key */
+ if (wc_ecc_init(&key) != 0) {
+ wolfSSL_X509_free(*cert); *cert = NULL;
+ if (ca != NULL) {
+ wolfSSL_sk_X509_free(*ca); *ca = NULL;
+ }
+ wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+ XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+ return WOLFSSL_FAILURE;
+ }
+
+ if ((ret = wc_EccPrivateKeyDecode(pk, &keyIdx, &key, pkSz))
+ != 0) {
+ wolfSSL_X509_free(*cert); *cert = NULL;
+ if (ca != NULL) {
+ wolfSSL_sk_X509_free(*ca); *ca = NULL;
+ }
+ wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+ XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+ WOLFSSL_MSG("Bad PKCS12 key format");
+ return WOLFSSL_FAILURE;
+ }
+ (*pkey)->type = EVP_PKEY_EC;
+ (*pkey)->pkey_curve = key.dp->oidSum;
+ wc_ecc_free(&key);
+ WOLFSSL_MSG("Found PKCS12 ECC key");
+ }
+ }
+ #else
+ if (ret != 0) { /* if is in fail state and no ECC then fail */
+ wolfSSL_X509_free(*cert); *cert = NULL;
+ if (ca != NULL) {
+ wolfSSL_sk_X509_free(*ca); *ca = NULL;
+ }
+ wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+ XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+ WOLFSSL_MSG("Bad PKCS12 key format");
+ return WOLFSSL_FAILURE;
+ }
+ #endif /* HAVE_ECC */
+
+ (*pkey)->save_type = 0;
+ (*pkey)->pkey_sz = pkSz;
+ (*pkey)->pkey.ptr = (char*)pk;
+ }
+
+ (void)ret;
+ (void)ca;
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* !defined(NO_ASN) && !defined(NO_PWDBASED) */
+
+
+/* no-op function. Was initially used for adding encryption algorithms available
+ * for PKCS12 */
+void wolfSSL_PKCS12_PBE_add(void)
+{
+ WOLFSSL_ENTER("wolfSSL_PKCS12_PBE_add");
+}
+
+
+
+WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(WOLFSSL_X509_STORE_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_chain");
+
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+#ifdef SESSION_CERTS
+ /* if chain is null but sesChain is available then populate stack */
+ if (ctx->chain == NULL && ctx->sesChain != NULL) {
+ int i;
+ WOLFSSL_X509_CHAIN* c = ctx->sesChain;
+ WOLFSSL_STACK* sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK),
+ NULL, DYNAMIC_TYPE_X509);
+
+ if (sk == NULL) {
+ return NULL;
+ }
+
+ XMEMSET(sk, 0, sizeof(WOLFSSL_STACK));
+ ctx->chain = sk;
+
+ for (i = 0; i < c->count && i < MAX_CHAIN_DEPTH; i++) {
+ WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, i);
+
+ if (x509 == NULL) {
+ WOLFSSL_MSG("Unable to get x509 from chain");
+ wolfSSL_sk_X509_free(sk);
+ return NULL;
+ }
+
+ if (wolfSSL_sk_X509_push(sk, x509) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Unable to load x509 into stack");
+ wolfSSL_sk_X509_free(sk);
+ wolfSSL_X509_free(x509);
+ return NULL;
+ }
+ }
+
+#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA)
+ /* add CA used to verify top of chain to the list */
+ if (c->count > 0) {
+ WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, c->count - 1);
+ if (x509 != NULL) {
+ WOLFSSL_X509* issuer = NULL;
+ if (wolfSSL_X509_STORE_CTX_get1_issuer(&issuer, ctx, x509)
+ == WOLFSSL_SUCCESS) {
+ /* check that the certificate being looked up is not self
+ * signed and that a issuer was found */
+ if (issuer != NULL && wolfSSL_X509_NAME_cmp(&x509->issuer,
+ &x509->subject) != 0) {
+ if (wolfSSL_sk_X509_push(sk, issuer) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Unable to load CA x509 into stack");
+ wolfSSL_sk_X509_free(sk);
+ wolfSSL_X509_free(issuer);
+ return NULL;
+ }
+ }
+ else {
+ WOLFSSL_MSG("Certificate is self signed");
+ if (issuer != NULL)
+ wolfSSL_X509_free(issuer);
+ }
+ }
+ else {
+ WOLFSSL_MSG("Could not find CA for certificate");
+ }
+ }
+ }
+#endif
+
+ }
+#endif /* SESSION_CERTS */
+
+ return ctx->chain;
+}
+
+/* make shallow copy of the stack, data pointers are copied by reference */
+WOLFSSL_STACK* wolfSSL_sk_X509_dup(WOLFSSL_STACK* sk)
+{
+ unsigned long i;
+ WOLFSSL_STACK* dup = NULL;
+ WOLFSSL_STACK* node = NULL;
+ WOLFSSL_STACK *dIdx = NULL, *sIdx = sk;
+
+ if (sk == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < sk->num; i++) {
+
+ node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+ DYNAMIC_TYPE_X509);
+ if (node == NULL) {
+ if (i != 0) {
+ wolfSSL_sk_free(dup);
+ }
+ WOLFSSL_MSG("Memory error");
+ return NULL;
+ }
+ XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+ /* copy sk node to new node, data by reference */
+ node->data.x509 = sIdx->data.x509;
+ node->num = sIdx->num;
+
+ /* insert node into list, progress idx */
+ if (i == 0) {
+ dup = node;
+ } else {
+ dIdx->next = node;
+ }
+
+ dIdx = node;
+ sIdx = sIdx->next;
+ }
+
+ return dup;
+}
+
+
+/* like X509_STORE_CTX_get_chain(), but return a copy with data reference
+ counts increased */
+WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get1_chain(WOLFSSL_X509_STORE_CTX* ctx)
+{
+ unsigned long i;
+ WOLFSSL_STACK* ref;
+ WOLFSSL_STACK* dup;
+
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ /* get chain in ctx */
+ ref = wolfSSL_X509_STORE_CTX_get_chain(ctx);
+ if (ref == NULL) {
+ return ref;
+ }
+
+ /* create duplicate of ctx chain */
+ dup = wolfSSL_sk_X509_dup(ref);
+ if (dup == NULL) {
+ return NULL;
+ }
+
+ /* increase ref counts of inner data X509 */
+ ref = dup;
+ for (i = 0; i < dup->num && ref != NULL; i++) {
+ if (wc_LockMutex(&ref->data.x509->refMutex) != 0) {
+ WOLFSSL_MSG("Failed to lock x509 mutex");
+ }
+ ref->data.x509->refCount++;
+ wc_UnLockMutex(&ref->data.x509->refMutex);
+ ref = ref->next;
+ }
+
+ return dup;
}
int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509)
{
- int result = SSL_FATAL_ERROR;
+ int result = WOLFSSL_FATAL_ERROR;
WOLFSSL_ENTER("wolfSSL_X509_STORE_add_cert");
- if (store != NULL && store->cm != NULL && x509 != NULL) {
- buffer derCert;
- derCert.buffer = (byte*)XMALLOC(x509->derCert.length,
- NULL, DYNAMIC_TYPE_CERT);
- if (derCert.buffer != NULL) {
- derCert.length = x509->derCert.length;
- /* AddCA() frees the buffer. */
- XMEMCPY(derCert.buffer,
- x509->derCert.buffer, x509->derCert.length);
- result = AddCA(store->cm, derCert, WOLFSSL_USER_CA, 1);
- if (result != SSL_SUCCESS) result = SSL_FATAL_ERROR;
+ if (store != NULL && store->cm != NULL && x509 != NULL
+ && x509->derCert != NULL) {
+ DerBuffer* derCert = NULL;
+
+ result = AllocDer(&derCert, x509->derCert->length,
+ x509->derCert->type, NULL);
+ if (result == 0) {
+ /* AddCA() frees the buffer. */
+ XMEMCPY(derCert->buffer,
+ x509->derCert->buffer, x509->derCert->length);
+ result = AddCA(store->cm, &derCert, WOLFSSL_USER_CA, VERIFY);
}
}
WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_cert", result);
+
+ if (result != WOLFSSL_SUCCESS) {
+ result = WOLFSSL_FATAL_ERROR;
+ }
+
return result;
}
-
WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void)
{
WOLFSSL_X509_STORE* store = NULL;
+ WOLFSSL_ENTER("SSL_X509_STORE_new");
- store = (WOLFSSL_X509_STORE*)XMALLOC(sizeof(WOLFSSL_X509_STORE), NULL, 0);
- if (store != NULL) {
- store->cm = wolfSSL_CertManagerNew();
- if (store->cm == NULL) {
- XFREE(store, NULL, 0);
- store = NULL;
- }
- }
+ if ((store = (WOLFSSL_X509_STORE*)XMALLOC(sizeof(WOLFSSL_X509_STORE), NULL,
+ DYNAMIC_TYPE_X509_STORE)) == NULL)
+ goto err_exit;
+
+ XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE));
+ store->isDynamic = 1;
+
+ if ((store->cm = wolfSSL_CertManagerNew()) == NULL)
+ goto err_exit;
+
+#ifdef HAVE_CRL
+ store->crl = NULL;
+ if ((store->crl = (WOLFSSL_X509_CRL *)XMALLOC(sizeof(WOLFSSL_X509_CRL),
+ NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL)
+ goto err_exit;
+ if (InitCRL(store->crl, NULL) < 0)
+ goto err_exit;
+#endif
+
+#ifdef OPENSSL_EXTRA
+ if ((store->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
+ sizeof(WOLFSSL_X509_VERIFY_PARAM),
+ NULL,DYNAMIC_TYPE_OPENSSL)) == NULL)
+ goto err_exit;
+
+#endif
return store;
+
+err_exit:
+ if (store == NULL)
+ return NULL;
+
+ wolfSSL_X509_STORE_free(store);
+
+ return NULL;
}
void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store)
{
- if (store != NULL) {
+ if (store != NULL && store->isDynamic) {
if (store->cm != NULL)
- wolfSSL_CertManagerFree(store->cm);
- XFREE(store, NULL, 0);
+ wolfSSL_CertManagerFree(store->cm);
+#ifdef HAVE_CRL
+ if (store->crl != NULL)
+ wolfSSL_X509_CRL_free(store->crl);
+#endif
+#ifdef OPENSSL_EXTRA
+ if (store->param != NULL)
+ XFREE(store->param, NULL, DYNAMIC_TYPE_OPENSSL);
+#endif
+ XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE);
}
}
-int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE* store)
+int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag)
{
+ int ret = WOLFSSL_SUCCESS;
+
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_set_flags");
+
+ if (store == NULL)
+ return WOLFSSL_FAILURE;
+
+ if ((flag & WOLFSSL_CRL_CHECKALL) || (flag & WOLFSSL_CRL_CHECK)) {
+ ret = wolfSSL_CertManagerEnableCRL(store->cm, (int)flag);
+ }
+
(void)store;
- return SSL_SUCCESS;
+ (void)flag;
+
+ return ret;
}
+int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE* store)
+{
+ (void)store;
+ return WOLFSSL_SUCCESS;
+}
+
+#ifndef NO_WOLFSSL_STUB
int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int idx,
WOLFSSL_X509_NAME* name, WOLFSSL_X509_OBJECT* obj)
{
@@ -10126,49 +22687,105 @@ int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int idx,
(void)idx;
(void)name;
(void)obj;
+ WOLFSSL_STUB("X509_STORE_get_by_subject");
return 0;
}
-
+#endif
WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void)
{
- WOLFSSL_X509_STORE_CTX* ctx = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
- sizeof(WOLFSSL_X509_STORE_CTX), NULL, 0);
+ WOLFSSL_X509_STORE_CTX* ctx;
+ WOLFSSL_ENTER("X509_STORE_CTX_new");
- if (ctx != NULL)
+ ctx = (WOLFSSL_X509_STORE_CTX*)XMALLOC(sizeof(WOLFSSL_X509_STORE_CTX), NULL,
+ DYNAMIC_TYPE_X509_CTX);
+ if (ctx != NULL) {
+ ctx->param = NULL;
wolfSSL_X509_STORE_CTX_init(ctx, NULL, NULL, NULL);
+ }
return ctx;
}
int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx,
- WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509, STACK_OF(WOLFSSL_X509)* sk)
+ WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509, WOLF_STACK_OF(WOLFSSL_X509)* sk)
{
+ WOLFSSL_X509* x509_cert;
+ int ret = 0;
(void)sk;
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_init");
+
if (ctx != NULL) {
ctx->store = store;
+ #ifndef WOLFSSL_X509_STORE_CERTS
ctx->current_cert = x509;
+ #else
+ if(x509 != NULL){
+ ctx->current_cert = wolfSSL_X509_d2i(NULL, x509->derCert->buffer,x509->derCert->length);
+ if(ctx->current_cert == NULL)
+ return WOLFSSL_FATAL_ERROR;
+ } else
+ ctx->current_cert = NULL;
+ #endif
+
+ ctx->chain = sk;
+ /* Add intermediate certificates from stack to store */
+ while (sk != NULL) {
+ x509_cert = sk->data.x509;
+ if (x509_cert != NULL && x509_cert->isCa) {
+ ret = wolfSSL_X509_STORE_add_cert(store, x509_cert);
+ if (ret < 0) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+ sk = sk->next;
+ }
+
+ ctx->sesChain = NULL;
ctx->domain = NULL;
- ctx->ex_data = NULL;
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+ XMEMSET(&ctx->ex_data, 0, sizeof(ctx->ex_data));
+#endif
ctx->userCtx = NULL;
ctx->error = 0;
ctx->error_depth = 0;
ctx->discardSessionCerts = 0;
+#ifdef OPENSSL_EXTRA
+ if (ctx->param == NULL) {
+ ctx->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
+ sizeof(WOLFSSL_X509_VERIFY_PARAM),
+ NULL,DYNAMIC_TYPE_OPENSSL);
+ if (ctx->param == NULL){
+ WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init failed");
+ return SSL_FATAL_ERROR;
+ }
+ }
+#endif
return SSL_SUCCESS;
}
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx)
{
+ WOLFSSL_ENTER("X509_STORE_CTX_free");
if (ctx != NULL) {
+ #if !defined(OPENSSL_ALL) && !defined(WOLFSSL_QT)
if (ctx->store != NULL)
wolfSSL_X509_STORE_free(ctx->store);
+ #ifndef WOLFSSL_KEEP_STORE_CERTS
if (ctx->current_cert != NULL)
wolfSSL_FreeX509(ctx->current_cert);
- XFREE(ctx, NULL, 0);
+ #endif
+ #endif /* !OPENSSL_ALL && !WOLFSSL_QT */
+#ifdef OPENSSL_EXTRA
+ if (ctx->param != NULL){
+ XFREE(ctx->param,NULL,DYNAMIC_TYPE_OPENSSL);
+ }
+#endif
+ XFREE(ctx, NULL, DYNAMIC_TYPE_X509_CTX);
}
}
@@ -10176,1100 +22793,5627 @@ void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx)
void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX* ctx)
{
(void)ctx;
+ /* Do nothing */
+}
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+/* Returns corresponding X509 error from internal ASN error <e> */
+static int GetX509Error(int e)
+{
+ switch (e) {
+ case ASN_BEFORE_DATE_E:
+ return X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
+ case ASN_AFTER_DATE_E:
+ return X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
+ case ASN_NO_SIGNER_E:
+ return X509_V_ERR_INVALID_CA;
+ case ASN_SELF_SIGNED_E:
+ return X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
+ case ASN_PATHLEN_INV_E:
+ case ASN_PATHLEN_SIZE_E:
+ return X509_V_ERR_PATH_LENGTH_EXCEEDED;
+ case ASN_SIG_OID_E:
+ case ASN_SIG_CONFIRM_E:
+ case ASN_SIG_HASH_E:
+ case ASN_SIG_KEY_E:
+ return X509_V_ERR_CERT_SIGNATURE_FAILURE;
+ default:
+ WOLFSSL_MSG("Error not configured or implemented yet");
+ return e;
+ }
}
+#endif
-
+/* Verifies certificate chain using WOLFSSL_X509_STORE_CTX
+ * returns 0 on success or < 0 on failure.
+ */
int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
{
+ int ret = 0;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ int depth = 0;
+ int error;
+ byte *afterDate, *beforeDate;
+#endif
+ WOLFSSL_ENTER("wolfSSL_X509_verify_cert");
+
if (ctx != NULL && ctx->store != NULL && ctx->store->cm != NULL
- && ctx->current_cert != NULL) {
- return wolfSSL_CertManagerVerifyBuffer(ctx->store->cm,
- ctx->current_cert->derCert.buffer,
- ctx->current_cert->derCert.length,
- SSL_FILETYPE_ASN1);
+ && ctx->current_cert != NULL && ctx->current_cert->derCert != NULL) {
+ ret = wolfSSL_CertManagerVerifyBuffer(ctx->store->cm,
+ ctx->current_cert->derCert->buffer,
+ ctx->current_cert->derCert->length,
+ WOLFSSL_FILETYPE_ASN1);
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ /* If there was an error, process it and add it to CTX */
+ if (ret < 0) {
+ /* Get corresponding X509 error */
+ error = GetX509Error(ret);
+ /* Set error depth */
+ if (ctx->chain)
+ depth = (int)ctx->chain->num;
+
+ wolfSSL_X509_STORE_CTX_set_error(ctx, error);
+ wolfSSL_X509_STORE_CTX_set_error_depth(ctx, depth);
+ ctx->store->verify_cb(0, ctx);
+ }
+
+ error = 0;
+ /* wolfSSL_CertManagerVerifyBuffer only returns ASN_AFTER_DATE_E or
+ ASN_BEFORE_DATE_E if there are no additional errors found in the
+ cert. Therefore, check if the cert is expired or not yet valid
+ in order to return the correct expected error. */
+ afterDate = ctx->current_cert->notAfter.data;
+ beforeDate = ctx->current_cert->notBefore.data;
+
+ if (ValidateDate(afterDate, ctx->current_cert->notAfter.type,
+ AFTER) < 1) {
+ error = X509_V_ERR_CERT_HAS_EXPIRED;
+ }
+ else if (ValidateDate(beforeDate, ctx->current_cert->notBefore.type,
+ BEFORE) < 1) {
+ error = X509_V_ERR_CERT_NOT_YET_VALID;
+ }
+
+ if (error != 0 ) {
+ wolfSSL_X509_STORE_CTX_set_error(ctx, error);
+ wolfSSL_X509_STORE_CTX_set_error_depth(ctx, depth);
+ if (ctx->store && ctx->store->verify_cb)
+ ctx->store->verify_cb(0, ctx);
+ }
+#endif /* OPENSSL_ALL || WOLFSSL_QT */
+ return ret;
}
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
-WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL* crl)
+/* Use the public key to verify the signature. Note: this only verifies
+ * the certificate signature.
+ * returns WOLFSSL_SUCCESS on successful signature verification */
+int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey)
{
- (void)crl;
- return 0;
+ int ret;
+ const byte* der;
+ int derSz = 0;
+ int type;
+
+ if (x509 == NULL || pkey == NULL) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ der = wolfSSL_X509_get_der(x509, &derSz);
+ if (der == NULL) {
+ WOLFSSL_MSG("Error getting WOLFSSL_X509 DER");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ switch (pkey->type) {
+ case EVP_PKEY_RSA:
+ type = RSAk;
+ break;
+
+ case EVP_PKEY_EC:
+ type = ECDSAk;
+ break;
+
+ case EVP_PKEY_DSA:
+ type = DSAk;
+ break;
+
+ default:
+ WOLFSSL_MSG("Unknown pkey key type");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ ret = CheckCertSignaturePubKey(der, derSz, x509->heap,
+ (unsigned char*)pkey->pkey.ptr, pkey->pkey_sz, type);
+ if (ret == 0) {
+ return WOLFSSL_SUCCESS;
+ }
+ return WOLFSSL_FAILURE;
}
+#endif /* NO_CERTS */
+#if !defined(NO_FILESYSTEM)
+static void *wolfSSL_d2i_X509_fp_ex(XFILE file, void **x509, int type)
+{
+ void *newx509 = NULL;
+ byte *fileBuffer = NULL;
+ long sz = 0;
-WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL* crl)
+ /* init variable */
+ if (x509)
+ *x509 = NULL;
+
+ /* argument check */
+ if (file == XBADFILE) {
+ return NULL;
+ }
+
+ /* determine file size */
+ if (XFSEEK(file, 0, XSEEK_END) != 0) {
+ return NULL;
+ }
+ sz = XFTELL(file);
+ XREWIND(file);
+
+ if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
+ WOLFSSL_MSG("d2i_X509_fp_ex file size error");
+ return NULL;
+ }
+
+ fileBuffer = (byte *)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
+ if (fileBuffer != NULL) {
+ if ((long)XFREAD(fileBuffer, 1, sz, file) != sz) {
+ WOLFSSL_MSG("File read failed");
+ goto err_exit;
+ }
+ if (type == CERT_TYPE) {
+ newx509 = (void *)wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz);
+ }
+ #ifdef HAVE_CRL
+ else if (type == CRL_TYPE) {
+ newx509 = (void *)wolfSSL_d2i_X509_CRL(NULL, fileBuffer, (int)sz);
+ }
+ #endif
+ #if !defined(NO_ASN) && !defined(NO_PWDBASED)
+ else if (type == PKCS12_TYPE) {
+ if ((newx509 = wc_PKCS12_new()) == NULL) {
+ goto err_exit;
+ }
+ if (wc_d2i_PKCS12(fileBuffer, (int)sz, (WC_PKCS12*)newx509) < 0) {
+ goto err_exit;
+ }
+ }
+ #endif
+ else {
+ goto err_exit;
+ }
+ if (newx509 == NULL) {
+ WOLFSSL_MSG("X509 failed");
+ goto err_exit;
+ }
+ }
+
+ if (x509)
+ *x509 = newx509;
+
+ goto _exit;
+
+err_exit:
+#if !defined(NO_ASN) && !defined(NO_PWDBASED)
+ if ((newx509 != NULL) && (type == PKCS12_TYPE)) {
+ wc_PKCS12_free((WC_PKCS12*)newx509);
+ newx509 = NULL;
+ }
+#endif
+_exit:
+ if (fileBuffer != NULL)
+ XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
+
+ return newx509;
+}
+
+WOLFSSL_X509_PKCS12 *wolfSSL_d2i_PKCS12_fp(XFILE fp, WOLFSSL_X509_PKCS12 **pkcs12)
{
- (void)crl;
- return 0;
+ WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_fp");
+ return (WOLFSSL_X509_PKCS12 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)pkcs12, PKCS12_TYPE);
}
+WOLFSSL_X509 *wolfSSL_d2i_X509_fp(XFILE fp, WOLFSSL_X509 **x509)
+{
+ WOLFSSL_ENTER("wolfSSL_d2i_X509_fp");
+ return (WOLFSSL_X509 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)x509, CERT_TYPE);
+}
+#endif /* !NO_FILESYSTEM */
-WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509)
+#ifdef HAVE_CRL
+#ifndef NO_FILESYSTEM
+WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE fp, WOLFSSL_X509_CRL **crl)
{
- WOLFSSL_EVP_PKEY* key = NULL;
- if (x509 != NULL) {
- key = (WOLFSSL_EVP_PKEY*)XMALLOC(
- sizeof(WOLFSSL_EVP_PKEY), NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- if (key != NULL) {
- key->type = x509->pubKeyOID;
- key->save_type = 0;
- key->pkey.ptr = (char*)XMALLOC(
- x509->pubKey.length, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- if (key->pkey.ptr == NULL) {
- XFREE(key, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- return NULL;
+ WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL_fp");
+ return (WOLFSSL_X509_CRL *)wolfSSL_d2i_X509_fp_ex(fp, (void **)crl, CRL_TYPE);
+}
+#endif /* !NO_FILESYSTEM */
+
+
+WOLFSSL_X509_CRL* wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL** crl,
+ const unsigned char* in, int len)
+{
+ WOLFSSL_X509_CRL *newcrl = NULL;
+ int ret = WOLFSSL_SUCCESS;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL");
+
+ if (in == NULL) {
+ WOLFSSL_MSG("Bad argument value");
+ } else {
+ newcrl = (WOLFSSL_X509_CRL*)XMALLOC(sizeof(WOLFSSL_X509_CRL), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (newcrl == NULL){
+ WOLFSSL_MSG("New CRL allocation failed");
+ } else {
+ ret = InitCRL(newcrl, NULL);
+ if (ret < 0) {
+ WOLFSSL_MSG("Init tmp CRL failed");
+ } else {
+ ret = BufferLoadCRL(newcrl, in, len, WOLFSSL_FILETYPE_ASN1,
+ NO_VERIFY);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Buffer Load CRL failed");
+ } else {
+ if (crl) {
+ *crl = newcrl;
+ }
+ }
}
- XMEMCPY(key->pkey.ptr,
- x509->pubKey.buffer, x509->pubKey.length);
- key->pkey_sz = x509->pubKey.length;
- #ifdef HAVE_ECC
- key->pkey_curve = (int)x509->pkCurveOID;
- #endif /* HAVE_ECC */
}
}
- return key;
+
+ if((ret != WOLFSSL_SUCCESS) && (newcrl != NULL)) {
+ wolfSSL_X509_CRL_free(newcrl);
+ newcrl = NULL;
+ }
+
+ return newcrl;
}
+void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_CRL_free");
+ FreeCRL(crl, 1);
+ return;
+}
+#endif /* HAVE_CRL */
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL* crl)
+{
+ (void)crl;
+ WOLFSSL_STUB("X509_CRL_get_lastUpdate");
+ return 0;
+}
+#endif
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL* crl)
+{
+ (void)crl;
+ WOLFSSL_STUB("X509_CRL_get_nextUpdate");
+ return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* key)
{
(void)crl;
(void)key;
+ WOLFSSL_STUB("X509_CRL_verify");
return 0;
}
+#endif
+#endif /* OPENSSL_EXTRA */
+
+#ifdef OPENSSL_EXTRA
+
+/* Gets pointer to X509_STORE that was used to create context.
+ *
+ * Return valid pointer on success, NULL if ctx was NULL or not initialized
+ */
+WOLFSSL_X509_STORE* wolfSSL_X509_STORE_CTX_get0_store(
+ WOLFSSL_X509_STORE_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get0_store");
+
+ if (ctx == NULL)
+ return NULL;
+
+ return ctx->store;
+}
+WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get0_cert(WOLFSSL_X509_STORE_CTX* ctx)
+{
+ if (ctx == NULL)
+ return NULL;
+
+ return ctx->current_cert;
+}
-void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX* ctx, int err)
+void wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX* ctx,
+ unsigned long flags,
+ time_t t)
+{
+ (void)flags;
+
+ if (ctx == NULL || ctx->param == NULL)
+ return;
+
+ ctx->param->check_time = t;
+ ctx->param->flags |= WOLFSSL_USE_CHECK_TIME;
+}
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_X509_STORE_CTX_set_purpose(WOLFSSL_X509_STORE_CTX *ctx,
+ int purpose)
{
(void)ctx;
- (void)err;
+ (void)purpose;
+ WOLFSSL_STUB("wolfSSL_X509_STORE_CTX_set_purpose");
+ return 0;
}
+#endif
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
+#ifndef NO_WOLFSSL_STUB
+/* Returns default file name and path of config file. However
+ a wolfssl.cnf file is not currently supported */
+char* wolfSSL_CONF_get1_default_config_file(void)
+{
+ WOLFSSL_ENTER("wolfSSL_CONF_get1_default_config_file");
+ WOLFSSL_STUB("CONF_get1_default_config_file");
+ return NULL;
+}
+#endif
+/******************************************************************************
+* wolfSSL_X509_VERIFY_PARAM_set1_host - sets the DNS hostname to name
+* hostnames is cleared if name is NULL or empty.
+*
+* RETURNS:
+*
+*/
+int wolfSSL_X509_VERIFY_PARAM_set1_host(WOLFSSL_X509_VERIFY_PARAM* pParam,
+ const char* name,
+ unsigned int nameSz)
+{
+ unsigned int sz = 0;
-void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj)
+ if (pParam == NULL)
+ return WOLFSSL_FAILURE;
+
+ XMEMSET(pParam->hostName, 0, WOLFSSL_HOST_NAME_MAX);
+
+ if (name == NULL)
+ return WOLFSSL_SUCCESS;
+
+ sz = (unsigned int)XSTRLEN(name);
+
+ /* If name is NUL-terminated, namelen can be set to zero. */
+ if(nameSz == 0 || nameSz > sz)
+ nameSz = sz;
+
+ if (nameSz > 0 && name[nameSz - 1] == '\0')
+ nameSz--;
+
+ if (nameSz > WOLFSSL_HOST_NAME_MAX-1)
+ nameSz = WOLFSSL_HOST_NAME_MAX-1;
+
+ if (nameSz > 0)
+ XMEMCPY(pParam->hostName, name, nameSz);
+
+ pParam->hostName[nameSz] = '\0';
+
+ return WOLFSSL_SUCCESS;
+}
+/******************************************************************************
+* wolfSSL_get0_param - return a pointer to the SSL verification parameters
+*
+* RETURNS:
+* returns pointer to the SSL verification parameters on success,
+* otherwise returns NULL
+*/
+WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl)
{
- (void)obj;
+ if (ssl == NULL) {
+ return NULL;
+ }
+ return ssl->param;
}
+/* Set the host flag in the X509_VERIFY_PARAM structure */
+void wolfSSL_X509_VERIFY_PARAM_set_hostflags(WOLFSSL_X509_VERIFY_PARAM* param,
+ unsigned int flags)
+{
+ if (param != NULL) {
+ param->hostFlags = flags;
+ }
+}
-void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key)
+/* Sets the expected IP address to ipasc.
+ *
+ * param is a pointer to the X509_VERIFY_PARAM structure
+ * ipasc is a NULL-terminated string with N.N.N.N for IPv4 and
+ * HH:HH ... HH:HH for IPv6. There is no validation performed on the
+ * parameter, and it must be an exact match with the IP in the cert.
+ *
+ * return 1 for success and 0 for failure*/
+int wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(WOLFSSL_X509_VERIFY_PARAM *param,
+ const char *ipasc)
{
- if (key != NULL) {
- if (key->pkey.ptr != NULL)
- XFREE(key->pkey.ptr, NULL, 0);
- XFREE(key, NULL, 0);
+ int ret = WOLFSSL_FAILURE;
+
+ if (param != NULL) {
+ if (ipasc == NULL) {
+ param->ipasc[0] = '\0';
+ }
+ else {
+ XSTRNCPY(param->ipasc, ipasc, WOLFSSL_MAX_IPSTR-1);
+ param->ipasc[WOLFSSL_MAX_IPSTR-1] = '\0';
+ }
+ ret = WOLFSSL_SUCCESS;
}
+
+ return ret;
}
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj)
+{
+ (void)obj;
+ WOLFSSL_STUB("X509_OBJECT_free_contents");
+}
+#endif
+#ifndef NO_ASN_TIME
int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME* asnTime)
{
- (void)asnTime;
- return 0;
+ return wolfSSL_X509_cmp_time(asnTime, NULL);
}
+/* return -1 if asnTime is earlier than or equal to cmpTime, and 1 otherwise
+ * return 0 on error
+ */
+int wolfSSL_X509_cmp_time(const WOLFSSL_ASN1_TIME* asnTime, time_t* cmpTime)
+{
+ int ret = WOLFSSL_FAILURE, i = 0;
+ time_t tmpTime, *pTime = &tmpTime;
+ byte data_ptr[MAX_TIME_STRING_SZ], inv = 0;
+ struct tm ts, *tmpTs, *ct;
+#if defined(NEED_TMP_TIME)
+ /* for use with gmtime_r */
+ struct tm tmpTimeStorage;
+ tmpTs = &tmpTimeStorage;
+#else
+ tmpTs = NULL;
+#endif
+ (void)tmpTs;
+
+ if (asnTime == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (cmpTime == NULL) {
+ /* Use current time */
+ *pTime = XTIME(0);
+ }
+ else {
+ pTime = cmpTime;
+ }
+
+ /* Convert ASN1_time to time_t */
+ XMEMSET(&ts, 0, sizeof(struct tm));
+
+ /* Check type */
+ if (asnTime->type == ASN_UTC_TIME) {
+ /* 2-digit year */
+ XMEMCPY(data_ptr, &asnTime->data[i], ASN_UTC_TIME_SIZE);
+ ts.tm_year = (data_ptr[i] - '0') * 10; i++;
+ ts.tm_year += data_ptr[i] - '0'; i++;
+ if (ts.tm_year < 70) {
+ ts.tm_year += 100;
+ }
+ }
+ else if (asnTime->type == ASN_GENERALIZED_TIME) {
+ /* 4-digit year */
+ XMEMCPY(data_ptr, &asnTime->data[i], ASN_GENERALIZED_TIME_SIZE);
+ ts.tm_year = (data_ptr[i] - '0') * 1000; i++;
+ ts.tm_year += (data_ptr[i] - '0') * 100; i++;
+ ts.tm_year += (data_ptr[i] - '0') * 10; i++;
+ ts.tm_year += data_ptr[i] - '0'; i++;
+ ts.tm_year -= 1900;
+ }
+ else {
+ /* Invalid type */
+ inv = 1;
+ }
+
+ if (inv != 1) {
+ ts.tm_mon = (data_ptr[i] - '0') * 10; i++;
+ ts.tm_mon += (data_ptr[i] - '0') - 1; i++; /* January is 0 not 1 */
+ ts.tm_mday = (data_ptr[i] - '0') * 10; i++;
+ ts.tm_mday += (data_ptr[i] - '0'); i++;
+ ts.tm_hour = (data_ptr[i] - '0') * 10; i++;
+ ts.tm_hour += (data_ptr[i] - '0'); i++;
+ ts.tm_min = (data_ptr[i] - '0') * 10; i++;
+ ts.tm_min += (data_ptr[i] - '0'); i++;
+ ts.tm_sec = (data_ptr[i] - '0') * 10; i++;
+ ts.tm_sec += (data_ptr[i] - '0');
+
+ /* Convert to time struct*/
+ ct = XGMTIME(pTime, tmpTs);
+
+ if (ct == NULL)
+ return GETTIME_ERROR;
+
+ /* DateGreaterThan returns 1 for >; 0 for <= */
+ ret = DateGreaterThan(&ts, ct) ? 1 : -1;
+ }
+
+ return ret;
+}
+#endif /* !NO_ASN_TIME */
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) && !defined(USER_TIME) && \
+ !defined(TIME_OVERRIDES)
+WOLFSSL_ASN1_TIME *wolfSSL_X509_time_adj_ex(WOLFSSL_ASN1_TIME *asnTime,
+ int offset_day, long offset_sec, time_t *in_tm)
+{
+ /* get current time if in_tm is null */
+ time_t t = in_tm ? *in_tm : XTIME(0);
+ return wolfSSL_ASN1_TIME_adj(asnTime, t, offset_day, offset_sec);
+}
+
+WOLFSSL_ASN1_TIME *wolfSSL_X509_time_adj(WOLFSSL_ASN1_TIME *asnTime,
+ long offset_sec, time_t *in_tm)
+{
+ return wolfSSL_X509_time_adj_ex(asnTime, 0, offset_sec, in_tm);
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED* revoked)
{
(void)revoked;
+ WOLFSSL_STUB("sk_X509_REVOKED_num");
return 0;
}
+#endif
-
-
+#ifndef NO_WOLFSSL_STUB
WOLFSSL_X509_REVOKED* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL* crl)
{
(void)crl;
+ WOLFSSL_STUB("X509_CRL_get_REVOKED");
return 0;
}
+#endif
-
+#ifndef NO_WOLFSSL_STUB
WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value(
WOLFSSL_X509_REVOKED* revoked, int value)
{
(void)revoked;
(void)value;
+ WOLFSSL_STUB("sk_X509_REVOKED_value");
return 0;
}
+#endif
+/* Used to create a new WOLFSSL_ASN1_INTEGER structure.
+ * returns a pointer to new structure on success and NULL on failure
+ */
+WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void)
+{
+ WOLFSSL_ASN1_INTEGER* a;
+
+ a = (WOLFSSL_ASN1_INTEGER*)XMALLOC(sizeof(WOLFSSL_ASN1_INTEGER), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (a == NULL) {
+ return NULL;
+ }
+
+ XMEMSET(a, 0, sizeof(WOLFSSL_ASN1_INTEGER));
+ a->data = a->intData;
+ a->dataMax = WOLFSSL_ASN1_INTEGER_MAX;
+ a->length = 0;
+ return a;
+}
+
+
+/* free's internal elements of WOLFSSL_ASN1_INTEGER and free's "in" itself */
+void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER* in)
+{
+ if (in != NULL) {
+ if (in->isDynamic) {
+ XFREE(in->data, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+ XFREE(in, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+
+
+/* Duplicate all WOLFSSL_ASN1_INTEGER members from src to dup
+ * src : WOLFSSL_ASN1_INTEGER to duplicate
+ * Returns pointer to duplicate WOLFSSL_ASN1_INTEGER
+ */
+WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_dup(const WOLFSSL_ASN1_INTEGER* src)
+{
+ WOLFSSL_ASN1_INTEGER* dup;
+ WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_dup");
+ if (!src)
+ return NULL;
+
+ dup = wolfSSL_ASN1_INTEGER_new();
+
+ if (dup == NULL)
+ return NULL;
+
+ dup->negative = src->negative;
+ dup->dataMax = src->dataMax;
+ dup->isDynamic = src->isDynamic;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ dup->length = src->length;
+#endif
+ XSTRNCPY((char*)dup->intData,(const char*)src->intData,WOLFSSL_ASN1_INTEGER_MAX);
+
+ if (dup->isDynamic && src->data && dup->dataMax) {
+ dup->data = (unsigned char*)
+ XMALLOC(src->dataMax,NULL,DYNAMIC_TYPE_OPENSSL);
+ if (dup->data == NULL) {
+ wolfSSL_ASN1_INTEGER_free(dup);
+ return NULL;
+ }
+ XMEMCPY(dup->data,src->data,dup->dataMax);
+ }
+ return dup;
+}
+
+
+/* sets the value of WOLFSSL_ASN1_INTEGER a to the long value v. */
+int wolfSSL_ASN1_INTEGER_set(WOLFSSL_ASN1_INTEGER *a, long v)
+{
+ int ret = WOLFSSL_SUCCESS; /* return 1 for success and 0 for failure */
+ int j;
+ unsigned int i = 0;
+ unsigned char tmp[sizeof(long)+1] = {0};
+
+ if (a != NULL) {
+ /* dynamically create data buffer, +2 for type and length */
+ a->data = (unsigned char*)XMALLOC((sizeof(long)+1) + 2, NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (a->data == NULL) {
+ wolfSSL_ASN1_INTEGER_free(a);
+ ret = WOLFSSL_FAILURE;
+ }
+ else {
+ a->dataMax = (int)(sizeof(long)+1) + 2;
+ a->isDynamic = 1;
+ }
+ }
+ else {
+ /* Invalid parameter */
+ ret = WOLFSSL_FAILURE;
+ }
+
+
+ if (ret != WOLFSSL_FAILURE) {
+ /* Set type */
+ a->data[i++] = ASN_INTEGER;
+
+ /* Check for negative */
+ if (v < 0) {
+ a->negative = 1;
+ v *= -1;
+ }
+
+ /* Create char buffer */
+ for (j = 0; j < (int)sizeof(long); j++) {
+ if (v == 0) {
+ break;
+ }
+ tmp[j] = (unsigned char)(v & 0xff);
+ v >>= 8;
+ }
+
+ /* Set length */
+ a->data[i++] = (unsigned char)((j == 0) ? ++j : j);
+ /* +2 for type and length */
+ a->length = j + 2;
+
+ /* Copy to data */
+ for (; j > 0; j--) {
+ a->data[i++] = tmp[j-1];
+ }
+ }
+
+ return ret;
+}
WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509)
{
- (void)x509;
- return 0;
+ WOLFSSL_ASN1_INTEGER* a;
+ int i = 0;
+
+ WOLFSSL_ENTER("wolfSSL_X509_get_serialNumber");
+
+ a = wolfSSL_ASN1_INTEGER_new();
+ if (a == NULL)
+ return NULL;
+
+ /* Make sure there is space for the data, ASN.1 type and length. */
+ if (x509->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) {
+ /* dynamically create data buffer, +2 for type and length */
+ a->data = (unsigned char*)XMALLOC(x509->serialSz + 2, NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (a->data == NULL) {
+ wolfSSL_ASN1_INTEGER_free(a);
+ return NULL;
+ }
+ a->dataMax = x509->serialSz + 2;
+ a->isDynamic = 1;
+ } else {
+ /* Use array instead of dynamic memory */
+ a->data = a->intData;
+ a->dataMax = WOLFSSL_ASN1_INTEGER_MAX;
+ }
+
+ #ifdef WOLFSSL_QT
+ XMEMCPY(&a->data[i], x509->serial, x509->serialSz);
+ a->length = x509->serialSz;
+ #else
+ a->data[i++] = ASN_INTEGER;
+ i += SetLength(x509->serialSz, a->data + i);
+ XMEMCPY(&a->data[i], x509->serial, x509->serialSz);
+ a->length = x509->serialSz + 2;
+ #endif
+
+ x509->serialNumber = a;
+
+ return a;
}
+#endif /* OPENSSL_EXTRA */
+#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \
+ defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+#ifndef NO_ASN_TIME
int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_TIME* asnTime)
{
- (void)bio;
- (void)asnTime;
- return 0;
+ char buf[MAX_TIME_STRING_SZ];
+ int ret = WOLFSSL_SUCCESS;
+
+ WOLFSSL_ENTER("wolfSSL_ASN1_TIME_print");
+
+ if (bio == NULL || asnTime == NULL) {
+ WOLFSSL_MSG("NULL function argument");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)asnTime, buf,
+ sizeof(buf)) == NULL) {
+ XMEMSET(buf, 0, MAX_TIME_STRING_SZ);
+ XMEMCPY(buf, "Bad time value", 14);
+ ret = WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf)) <= 0) {
+ WOLFSSL_MSG("Unable to write to bio");
+ return WOLFSSL_FAILURE;
+ }
+
+ return ret;
}
+char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len)
+{
+ WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_string");
+
+ if (t == NULL || buf == NULL || len < 5) {
+ WOLFSSL_MSG("Bad argument");
+ return NULL;
+ }
+
+ if (t->length > len) {
+ WOLFSSL_MSG("Length of date is longer then buffer");
+ return NULL;
+ }
+
+ if (!GetTimeString(t->data, t->type, buf, len)) {
+ return NULL;
+ }
+
+ return buf;
+}
+#endif /* !NO_ASN_TIME */
+#endif /* WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY ||
+ OPENSSL_EXTRA*/
+#ifdef OPENSSL_EXTRA
+
+#ifndef NO_WOLFSSL_STUB
int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER* a,
const WOLFSSL_ASN1_INTEGER* b)
{
(void)a;
(void)b;
+ WOLFSSL_STUB("ASN1_INTEGER_cmp");
return 0;
}
+#endif
-
+#ifndef NO_WOLFSSL_STUB
long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER* i)
{
(void)i;
+ WOLFSSL_STUB("ASN1_INTEGER_get");
return 0;
}
+#endif
+/* get X509_STORE_CTX ex_data, max idx is MAX_EX_DATA */
+void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_ex_data");
+ #if defined(HAVE_EX_DATA) || defined(FORTRESS)
+ if (ctx != NULL) {
+ return wolfSSL_CRYPTO_get_ex_data(&ctx->ex_data, idx);
+ }
+ #else
+ (void)ctx;
+ (void)idx;
+ #endif
+ return NULL;
+}
-void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx)
+/* set X509_STORE_CTX ex_data, max idx is MAX_EX_DATA. Return WOLFSSL_SUCCESS
+ * on success, WOLFSSL_FAILURE on error. */
+int wolfSSL_X509_STORE_CTX_set_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx,
+ void *data)
{
-#ifdef FORTRESS
- if (ctx != NULL && idx == 0)
- return ctx->ex_data;
-#else
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_ex_data");
+ #if defined(HAVE_EX_DATA) || defined(FORTRESS)
+ if (ctx != NULL)
+ {
+ return wolfSSL_CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
+ }
+ #else
(void)ctx;
(void)idx;
+ (void)data;
+ #endif
+ return WOLFSSL_FAILURE;
+}
+
+#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL)
+void wolfSSL_X509_STORE_CTX_set_depth(WOLFSSL_X509_STORE_CTX* ctx, int depth)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_depth");
+ if (ctx)
+ ctx->depth = depth;
+}
#endif
- return 0;
+
+
+WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get0_current_issuer(
+ WOLFSSL_X509_STORE_CTX* ctx)
+{
+ int ret;
+ WOLFSSL_X509* issuer;
+
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get0_current_issuer");
+
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ ret = wolfSSL_X509_STORE_CTX_get1_issuer(&issuer, ctx, ctx->current_cert);
+ if (ret == WOLFSSL_SUCCESS) {
+ return issuer;
+ }
+
+ return NULL;
}
+/* Gets an index to store SSL structure at.
+ *
+ * Returns positive index on success and negative values on failure
+ */
int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void)
{
+ WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx");
+
+ /* store SSL at index 0 */
return 0;
}
-void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx)
+/* Set an error stat in the X509 STORE CTX
+ *
+ */
+void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX* ctx, int er)
{
-#ifdef FORTRESS
- if (ssl != NULL && idx < MAX_EX_DATA)
- return ssl->ex_data[idx];
-#else
- (void)ssl;
- (void)idx;
-#endif
- return 0;
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_error");
+
+ if (ctx != NULL) {
+ ctx->error = er;
+ }
}
+/* Set the error depth in the X509 STORE CTX */
+void wolfSSL_X509_STORE_CTX_set_error_depth(WOLFSSL_X509_STORE_CTX* ctx,
+ int depth)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_error_depth");
+
+ if (ctx != NULL) {
+ ctx->error_depth = depth;
+ }
+}
-void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx, void (*f)(void))
+/* Sets a function callback that will send information about the state of all
+ * WOLFSSL objects that have been created by the WOLFSSL_CTX structure passed
+ * in.
+ *
+ * ctx WOLFSSL_CTX structure to set callback function in
+ * f callback function to use
+ */
+void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx,
+ void (*f)(const WOLFSSL* ssl, int type, int val))
{
- (void)ctx;
- (void)f;
+ WOLFSSL_ENTER("wolfSSL_CTX_set_info_callback");
+ if (ctx == NULL) {
+ WOLFSSL_MSG("Bad function argument");
+ }
+ else {
+ ctx->CBIS = f;
+ }
}
unsigned long wolfSSL_ERR_peek_error(void)
{
- return 0;
+ WOLFSSL_ENTER("wolfSSL_ERR_peek_error");
+
+ return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL);
}
+int wolfSSL_ERR_GET_LIB(unsigned long err)
+{
+ switch (err) {
+ case PEM_R_NO_START_LINE:
+ case PEM_R_PROBLEMS_GETTING_PASSWORD:
+ case PEM_R_BAD_PASSWORD_READ:
+ case PEM_R_BAD_DECRYPT:
+ return ERR_LIB_PEM;
+ case EVP_R_BAD_DECRYPT:
+ case EVP_R_BN_DECODE_ERROR:
+ case EVP_R_DECODE_ERROR:
+ case EVP_R_PRIVATE_KEY_DECODE_ERROR:
+ return ERR_LIB_EVP;
+ default:
+ return 0;
+ }
+}
-int wolfSSL_ERR_GET_REASON(int err)
+/* This function is to find global error values that are the same through out
+ * all library version. With wolfSSL having only one set of error codes the
+ * return value is pretty straight forward. The only thing needed is all wolfSSL
+ * error values are typically negative.
+ *
+ * Returns the error reason
+ */
+int wolfSSL_ERR_GET_REASON(unsigned long err)
{
- (void)err;
- return 0;
+ int ret = (int)err;
+
+ WOLFSSL_ENTER("wolfSSL_ERR_GET_REASON");
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+ /* Nginx looks for this error to know to stop parsing certificates. */
+ if (err == ((ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE))
+ return PEM_R_NO_START_LINE;
+#endif
+
+ /* check if error value is in range of wolfSSL errors */
+ ret = 0 - ret; /* setting as negative value */
+ /* wolfCrypt range is less than MAX (-100)
+ wolfSSL range is MIN (-300) and lower */
+ if (ret < MAX_CODE_E && ret > MIN_CODE_E) {
+ return ret;
+ }
+ else {
+ WOLFSSL_MSG("Not in range of typical error values");
+ ret = (int)err;
+ }
+
+ return ret;
}
-char* wolfSSL_alert_type_string_long(int alertID)
+/* returns a string that describes the alert
+ *
+ * alertID the alert value to look up
+ */
+const char* wolfSSL_alert_type_string_long(int alertID)
{
- (void)alertID;
- return 0;
+ WOLFSSL_ENTER("wolfSSL_alert_type_string_long");
+
+ switch (alertID) {
+ case close_notify:
+ {
+ static const char close_notify_str[] =
+ "close_notify";
+ return close_notify_str;
+ }
+
+ case unexpected_message:
+ {
+ static const char unexpected_message_str[] =
+ "unexpected_message";
+ return unexpected_message_str;
+ }
+
+ case bad_record_mac:
+ {
+ static const char bad_record_mac_str[] =
+ "bad_record_mac";
+ return bad_record_mac_str;
+ }
+
+ case record_overflow:
+ {
+ static const char record_overflow_str[] =
+ "record_overflow";
+ return record_overflow_str;
+ }
+
+ case decompression_failure:
+ {
+ static const char decompression_failure_str[] =
+ "decompression_failure";
+ return decompression_failure_str;
+ }
+
+ case handshake_failure:
+ {
+ static const char handshake_failure_str[] =
+ "handshake_failure";
+ return handshake_failure_str;
+ }
+
+ case no_certificate:
+ {
+ static const char no_certificate_str[] =
+ "no_certificate";
+ return no_certificate_str;
+ }
+
+ case bad_certificate:
+ {
+ static const char bad_certificate_str[] =
+ "bad_certificate";
+ return bad_certificate_str;
+ }
+
+ case unsupported_certificate:
+ {
+ static const char unsupported_certificate_str[] =
+ "unsupported_certificate";
+ return unsupported_certificate_str;
+ }
+
+ case certificate_revoked:
+ {
+ static const char certificate_revoked_str[] =
+ "certificate_revoked";
+ return certificate_revoked_str;
+ }
+
+ case certificate_expired:
+ {
+ static const char certificate_expired_str[] =
+ "certificate_expired";
+ return certificate_expired_str;
+ }
+
+ case certificate_unknown:
+ {
+ static const char certificate_unknown_str[] =
+ "certificate_unknown";
+ return certificate_unknown_str;
+ }
+
+ case illegal_parameter:
+ {
+ static const char illegal_parameter_str[] =
+ "illegal_parameter";
+ return illegal_parameter_str;
+ }
+
+ case unknown_ca:
+ {
+ static const char unknown_ca_str[] =
+ "unknown_ca";
+ return unknown_ca_str;
+ }
+
+ case decode_error:
+ {
+ static const char decode_error_str[] =
+ "decode_error";
+ return decode_error_str;
+ }
+
+ case decrypt_error:
+ {
+ static const char decrypt_error_str[] =
+ "decrypt_error";
+ return decrypt_error_str;
+ }
+
+ #ifdef WOLFSSL_MYSQL_COMPATIBLE
+ /* catch name conflict for enum protocol with MYSQL build */
+ case wc_protocol_version:
+ {
+ static const char wc_protocol_version_str[] =
+ "wc_protocol_version";
+ return wc_protocol_version_str;
+ }
+
+ #else
+ case protocol_version:
+ {
+ static const char protocol_version_str[] =
+ "protocol_version";
+ return protocol_version_str;
+ }
+
+ #endif
+ case no_renegotiation:
+ {
+ static const char no_renegotiation_str[] =
+ "no_renegotiation";
+ return no_renegotiation_str;
+ }
+
+ case unrecognized_name:
+ {
+ static const char unrecognized_name_str[] =
+ "unrecognized_name";
+ return unrecognized_name_str;
+ }
+
+ case bad_certificate_status_response:
+ {
+ static const char bad_certificate_status_response_str[] =
+ "bad_certificate_status_response";
+ return bad_certificate_status_response_str;
+ }
+
+ case no_application_protocol:
+ {
+ static const char no_application_protocol_str[] =
+ "no_application_protocol";
+ return no_application_protocol_str;
+ }
+
+ default:
+ WOLFSSL_MSG("Unknown Alert");
+ return NULL;
+ }
}
-char* wolfSSL_alert_desc_string_long(int alertID)
+const char* wolfSSL_alert_desc_string_long(int alertID)
{
- (void)alertID;
- return 0;
+ WOLFSSL_ENTER("wolfSSL_alert_desc_string_long");
+ return wolfSSL_alert_type_string_long(alertID);
}
-char* wolfSSL_state_string_long(WOLFSSL* ssl)
+/* Gets the current state of the WOLFSSL structure
+ *
+ * ssl WOLFSSL structure to get state of
+ *
+ * Returns a human readable string of the WOLFSSL structure state
+ */
+const char* wolfSSL_state_string_long(const WOLFSSL* ssl)
{
- (void)ssl;
- return 0;
-}
+ static const char* OUTPUT_STR[14][6][3] = {
+ {
+ {"SSLv3 Initialization","SSLv3 Initialization","SSLv3 Initialization"},
+ {"TLSv1 Initialization","TLSv2 Initialization","TLSv2 Initialization"},
+ {"TLSv1_1 Initialization","TLSv1_1 Initialization","TLSv1_1 Initialization"},
+ {"TLSv1_2 Initialization","TLSv1_2 Initialization","TLSv1_2 Initialization"},
+ {"DTLSv1 Initialization","DTLSv1 Initialization","DTLSv1 Initialization"},
+ {"DTLSv1_2 Initialization","DTLSv1_2 Initialization","DTLSv1_2 Initialization"},
+ },
+ {
+ {"SSLv3 read Server Hello Verify Request",
+ "SSLv3 write Server Hello Verify Request",
+ "SSLv3 Server Hello Verify Request"},
+ {"TLSv1 read Server Hello Verify Request",
+ "TLSv1 write Server Hello Verify Request",
+ "TLSv1 Server Hello Verify Request"},
+ {"TLSv1_1 read Server Hello Verify Request",
+ "TLSv1_1 write Server Hello Verify Request",
+ "TLSv1_1 Server Hello Verify Request"},
+ {"TLSv1_2 read Server Hello Verify Request",
+ "TLSv1_2 write Server Hello Verify Request",
+ "TLSv1_2 Server Hello Verify Request"},
+ {"DTLSv1 read Server Hello Verify Request",
+ "DTLSv1 write Server Hello Verify Request",
+ "DTLSv1 Server Hello Verify Request"},
+ {"DTLSv1_2 read Server Hello Verify Request",
+ "DTLSv1_2 write Server Hello Verify Request",
+ "DTLSv1_2 Server Hello Verify Request"},
+ },
+ {
+ {"SSLv3 read Server Hello",
+ "SSLv3 write Server Hello",
+ "SSLv3 Server Hello"},
+ {"TLSv1 read Server Hello",
+ "TLSv1 write Server Hello",
+ "TLSv1 Server Hello"},
+ {"TLSv1_1 read Server Hello",
+ "TLSv1_1 write Server Hello",
+ "TLSv1_1 Server Hello"},
+ {"TLSv1_2 read Server Hello",
+ "TLSv1_2 write Server Hello",
+ "TLSv1_2 Server Hello"},
+ {"DTLSv1 read Server Hello",
+ "DTLSv1 write Server Hello",
+ "DTLSv1 Server Hello"},
+ {"DTLSv1_2 read Server Hello"
+ "DTLSv1_2 write Server Hello",
+ "DTLSv1_2 Server Hello",
+ },
+ },
+ {
+ {"SSLv3 read Server Session Ticket",
+ "SSLv3 write Server Session Ticket",
+ "SSLv3 Server Session Ticket"},
+ {"TLSv1 read Server Session Ticket",
+ "TLSv1 write Server Session Ticket",
+ "TLSv1 Server Session Ticket"},
+ {"TLSv1_1 read Server Session Ticket",
+ "TLSv1_1 write Server Session Ticket",
+ "TLSv1_1 Server Session Ticket"},
+ {"TLSv1_2 read Server Session Ticket",
+ "TLSv1_2 write Server Session Ticket",
+ "TLSv1_2 Server Session Ticket"},
+ {"DTLSv1 read Server Session Ticket",
+ "DTLSv1 write Server Session Ticket",
+ "DTLSv1 Server Session Ticket"},
+ {"DTLSv1_2 read Server Session Ticket",
+ "DTLSv1_2 write Server Session Ticket",
+ "DTLSv1_2 Server Session Ticket"},
+ },
+ {
+ {"SSLv3 read Server Cert",
+ "SSLv3 write Server Cert",
+ "SSLv3 Server Cert"},
+ {"TLSv1 read Server Cert",
+ "TLSv1 write Server Cert",
+ "TLSv1 Server Cert"},
+ {"TLSv1_1 read Server Cert",
+ "TLSv1_1 write Server Cert",
+ "TLSv1_1 Server Cert"},
+ {"TLSv1_2 read Server Cert",
+ "TLSv1_2 write Server Cert",
+ "TLSv1_2 Server Cert"},
+ {"DTLSv1 read Server Cert",
+ "DTLSv1 write Server Cert",
+ "DTLSv1 Server Cert"},
+ {"DTLSv1_2 read Server Cert",
+ "DTLSv1_2 write Server Cert",
+ "DTLSv1_2 Server Cert"},
+ },
+ {
+ {"SSLv3 read Server Key Exchange",
+ "SSLv3 write Server Key Exchange",
+ "SSLv3 Server Key Exchange"},
+ {"TLSv1 read Server Key Exchange",
+ "TLSv1 write Server Key Exchange",
+ "TLSv1 Server Key Exchange"},
+ {"TLSv1_1 read Server Key Exchange",
+ "TLSv1_1 write Server Key Exchange",
+ "TLSv1_1 Server Key Exchange"},
+ {"TLSv1_2 read Server Key Exchange",
+ "TLSv1_2 write Server Key Exchange",
+ "TLSv1_2 Server Key Exchange"},
+ {"DTLSv1 read Server Key Exchange",
+ "DTLSv1 write Server Key Exchange",
+ "DTLSv1 Server Key Exchange"},
+ {"DTLSv1_2 read Server Key Exchange",
+ "DTLSv1_2 write Server Key Exchange",
+ "DTLSv1_2 Server Key Exchange"},
+ },
+ {
+ {"SSLv3 read Server Hello Done",
+ "SSLv3 write Server Hello Done",
+ "SSLv3 Server Hello Done"},
+ {"TLSv1 read Server Hello Done",
+ "TLSv1 write Server Hello Done",
+ "TLSv1 Server Hello Done"},
+ {"TLSv1_1 read Server Hello Done",
+ "TLSv1_1 write Server Hello Done",
+ "TLSv1_1 Server Hello Done"},
+ {"TLSv1_2 read Server Hello Done",
+ "TLSv1_2 write Server Hello Done",
+ "TLSv1_2 Server Hello Done"},
+ {"DTLSv1 read Server Hello Done",
+ "DTLSv1 write Server Hello Done",
+ "DTLSv1 Server Hello Done"},
+ {"DTLSv1_2 read Server Hello Done",
+ "DTLSv1_2 write Server Hello Done",
+ "DTLSv1_2 Server Hello Done"},
+ },
+ {
+ {"SSLv3 read Server Change CipherSpec",
+ "SSLv3 write Server Change CipherSpec",
+ "SSLv3 Server Change CipherSpec"},
+ {"TLSv1 read Server Change CipherSpec",
+ "TLSv1 write Server Change CipherSpec",
+ "TLSv1 Server Change CipherSpec"},
+ {"TLSv1_1 read Server Change CipherSpec",
+ "TLSv1_1 write Server Change CipherSpec",
+ "TLSv1_1 Server Change CipherSpec"},
+ {"TLSv1_2 read Server Change CipherSpec",
+ "TLSv1_2 write Server Change CipherSpec",
+ "TLSv1_2 Server Change CipherSpec"},
+ {"DTLSv1 read Server Change CipherSpec",
+ "DTLSv1 write Server Change CipherSpec",
+ "DTLSv1 Server Change CipherSpec"},
+ {"DTLSv1_2 read Server Change CipherSpec",
+ "DTLSv1_2 write Server Change CipherSpec",
+ "DTLSv1_2 Server Change CipherSpec"},
+ },
+ {
+ {"SSLv3 read Server Finished",
+ "SSLv3 write Server Finished",
+ "SSLv3 Server Finished"},
+ {"TLSv1 read Server Finished",
+ "TLSv1 write Server Finished",
+ "TLSv1 Server Finished"},
+ {"TLSv1_1 read Server Finished",
+ "TLSv1_1 write Server Finished",
+ "TLSv1_1 Server Finished"},
+ {"TLSv1_2 read Server Finished",
+ "TLSv1_2 write Server Finished",
+ "TLSv1_2 Server Finished"},
+ {"DTLSv1 read Server Finished",
+ "DTLSv1 write Server Finished",
+ "DTLSv1 Server Finished"},
+ {"DTLSv1_2 read Server Finished",
+ "DTLSv1_2 write Server Finished",
+ "DTLSv1_2 Server Finished"},
+ },
+ {
+ {"SSLv3 read Client Hello",
+ "SSLv3 write Client Hello",
+ "SSLv3 Client Hello"},
+ {"TLSv1 read Client Hello",
+ "TLSv1 write Client Hello",
+ "TLSv1 Client Hello"},
+ {"TLSv1_1 read Client Hello",
+ "TLSv1_1 write Client Hello",
+ "TLSv1_1 Client Hello"},
+ {"TLSv1_2 read Client Hello",
+ "TLSv1_2 write Client Hello",
+ "TLSv1_2 Client Hello"},
+ {"DTLSv1 read Client Hello",
+ "DTLSv1 write Client Hello",
+ "DTLSv1 Client Hello"},
+ {"DTLSv1_2 read Client Hello",
+ "DTLSv1_2 write Client Hello",
+ "DTLSv1_2 Client Hello"},
+ },
+ {
+ {"SSLv3 read Client Key Exchange",
+ "SSLv3 write Client Key Exchange",
+ "SSLv3 Client Key Exchange"},
+ {"TLSv1 read Client Key Exchange",
+ "TLSv1 write Client Key Exchange",
+ "TLSv1 Client Key Exchange"},
+ {"TLSv1_1 read Client Key Exchange",
+ "TLSv1_1 write Client Key Exchange",
+ "TLSv1_1 Client Key Exchange"},
+ {"TLSv1_2 read Client Key Exchange",
+ "TLSv1_2 write Client Key Exchange",
+ "TLSv1_2 Client Key Exchange"},
+ {"DTLSv1 read Client Key Exchange",
+ "DTLSv1 write Client Key Exchange",
+ "DTLSv1 Client Key Exchange"},
+ {"DTLSv1_2 read Client Key Exchange",
+ "DTLSv1_2 write Client Key Exchange",
+ "DTLSv1_2 Client Key Exchange"},
+ },
+ {
+ {"SSLv3 read Client Change CipherSpec",
+ "SSLv3 write Client Change CipherSpec",
+ "SSLv3 Client Change CipherSpec"},
+ {"TLSv1 read Client Change CipherSpec",
+ "TLSv1 write Client Change CipherSpec",
+ "TLSv1 Client Change CipherSpec"},
+ {"TLSv1_1 read Client Change CipherSpec",
+ "TLSv1_1 write Client Change CipherSpec",
+ "TLSv1_1 Client Change CipherSpec"},
+ {"TLSv1_2 read Client Change CipherSpec",
+ "TLSv1_2 write Client Change CipherSpec",
+ "TLSv1_2 Client Change CipherSpec"},
+ {"DTLSv1 read Client Change CipherSpec",
+ "DTLSv1 write Client Change CipherSpec",
+ "DTLSv1 Client Change CipherSpec"},
+ {"DTLSv1_2 read Client Change CipherSpec",
+ "DTLSv1_2 write Client Change CipherSpec",
+ "DTLSv1_2 Client Change CipherSpec"},
+ },
+ {
+ {"SSLv3 read Client Finished",
+ "SSLv3 write Client Finished",
+ "SSLv3 Client Finished"},
+ {"TLSv1 read Client Finished",
+ "TLSv1 write Client Finished",
+ "TLSv1 Client Finished"},
+ {"TLSv1_1 read Client Finished",
+ "TLSv1_1 write Client Finished",
+ "TLSv1_1 Client Finished"},
+ {"TLSv1_2 read Client Finished",
+ "TLSv1_2 write Client Finished",
+ "TLSv1_2 Client Finished"},
+ {"DTLSv1 read Client Finished",
+ "DTLSv1 write Client Finished",
+ "DTLSv1 Client Finished"},
+ {"DTLSv1_2 read Client Finished",
+ "DTLSv1_2 write Client Finished",
+ "DTLSv1_2 Client Finished"},
+ },
+ {
+ {"SSLv3 Handshake Done",
+ "SSLv3 Handshake Done",
+ "SSLv3 Handshake Done"},
+ {"TLSv1 Handshake Done",
+ "TLSv1 Handshake Done",
+ "TLSv1 Handshake Done"},
+ {"TLSv1_1 Handshake Done",
+ "TLSv1_1 Handshake Done",
+ "TLSv1_1 Handshake Done"},
+ {"TLSv1_2 Handshake Done",
+ "TLSv1_2 Handshake Done",
+ "TLSv1_2 Handshake Done"},
+ {"DTLSv1 Handshake Done",
+ "DTLSv1 Handshake Done",
+ "DTLSv1 Handshake Done"},
+ {"DTLSv1_2 Handshake Done"
+ "DTLSv1_2 Handshake Done"
+ "DTLSv1_2 Handshake Done"}
+ }
+ };
+ enum ProtocolVer {
+ SSL_V3 = 0,
+ TLS_V1,
+ TLS_V1_1,
+ TLS_V1_2,
+ DTLS_V1,
+ DTLS_V1_2,
+ UNKNOWN = 100
+ };
+
+ enum IOMode {
+ SS_READ = 0,
+ SS_WRITE,
+ SS_NEITHER
+ };
+
+ enum SslState {
+ ss_null_state = 0,
+ ss_server_helloverify,
+ ss_server_hello,
+ ss_sessionticket,
+ ss_server_cert,
+ ss_server_keyexchange,
+ ss_server_hellodone,
+ ss_server_changecipherspec,
+ ss_server_finished,
+ ss_client_hello,
+ ss_client_keyexchange,
+ ss_client_changecipherspec,
+ ss_client_finished,
+ ss_handshake_done
+ };
+
+ int protocol = 0;
+ int cbmode = 0;
+ int state = 0;
+
+ WOLFSSL_ENTER("wolfSSL_state_string_long");
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Null argument passed in");
+ return NULL;
+ }
+ /* Get state of callback */
+ if (ssl->cbmode == SSL_CB_MODE_WRITE){
+ cbmode = SS_WRITE;
+ } else if (ssl->cbmode == SSL_CB_MODE_READ){
+ cbmode = SS_READ;
+ } else {
+ cbmode = SS_NEITHER;
+ }
+
+ /* Get protocol version */
+ switch (ssl->version.major){
+ case SSLv3_MAJOR:
+ switch (ssl->version.minor){
+ case TLSv1_MINOR:
+ protocol = TLS_V1;
+ break;
+ case TLSv1_1_MINOR:
+ protocol = TLS_V1_1;
+ break;
+ case TLSv1_2_MINOR:
+ protocol = TLS_V1_2;
+ break;
+ case SSLv3_MINOR:
+ protocol = SSL_V3;
+ break;
+ default:
+ protocol = UNKNOWN;
+ }
+ break;
+ case DTLS_MAJOR:
+ switch (ssl->version.minor){
+ case DTLS_MINOR:
+ protocol = DTLS_V1;
+ break;
+ case DTLSv1_2_MINOR:
+ protocol = DTLS_V1_2;
+ break;
+ default:
+ protocol = UNKNOWN;
+ }
+ break;
+ default:
+ protocol = UNKNOWN;
+ }
+
+ /* accept process */
+ if (ssl->cbmode == SSL_CB_MODE_READ){
+ state = ssl->cbtype;
+ switch (state) {
+ case hello_verify_request:
+ state = ss_server_helloverify;
+ break;
+ case session_ticket:
+ state = ss_sessionticket;
+ break;
+ case server_hello:
+ state = ss_server_hello;
+ break;
+ case server_hello_done:
+ state = ss_server_hellodone;
+ break;
+ case certificate:
+ state = ss_server_cert;
+ break;
+ case server_key_exchange:
+ state = ss_server_keyexchange;
+ break;
+ case client_hello:
+ state = ss_client_hello;
+ break;
+ case client_key_exchange:
+ state = ss_client_keyexchange;
+ break;
+ case finished:
+ if (ssl->options.side == WOLFSSL_SERVER_END)
+ state = ss_client_finished;
+ else if (ssl->options.side == WOLFSSL_CLIENT_END)
+ state = ss_server_finished;
+ else {
+ WOLFSSL_MSG("Unknown State");
+ state = ss_null_state;
+ }
+ break;
+ default:
+ WOLFSSL_MSG("Unknown State");
+ state = ss_null_state;
+ }
+ } else {
+ /* Send process */
+ if (ssl->options.side == WOLFSSL_SERVER_END)
+ state = ssl->options.serverState;
+ else
+ state = ssl->options.clientState;
+
+ switch(state){
+ case SERVER_HELLOVERIFYREQUEST_COMPLETE:
+ state = ss_server_helloverify;
+ break;
+ case SERVER_HELLO_COMPLETE:
+ state = ss_server_hello;
+ break;
+ case SERVER_CERT_COMPLETE:
+ state = ss_server_cert;
+ break;
+ case SERVER_KEYEXCHANGE_COMPLETE:
+ state = ss_server_keyexchange;
+ break;
+ case SERVER_HELLODONE_COMPLETE:
+ state = ss_server_hellodone;
+ break;
+ case SERVER_CHANGECIPHERSPEC_COMPLETE:
+ state = ss_server_changecipherspec;
+ break;
+ case SERVER_FINISHED_COMPLETE:
+ state = ss_server_finished;
+ break;
+ case CLIENT_HELLO_COMPLETE:
+ state = ss_client_hello;
+ break;
+ case CLIENT_KEYEXCHANGE_COMPLETE:
+ state = ss_client_keyexchange;
+ break;
+ case CLIENT_CHANGECIPHERSPEC_COMPLETE:
+ state = ss_client_changecipherspec;
+ break;
+ case CLIENT_FINISHED_COMPLETE:
+ state = ss_client_finished;
+ break;
+ case HANDSHAKE_DONE:
+ state = ss_handshake_done;
+ break;
+ default:
+ WOLFSSL_MSG("Unknown State");
+ state = ss_null_state;
+ }
+ }
+
+ if (protocol == UNKNOWN)
+ return NULL;
+ else
+ return OUTPUT_STR[state][protocol][cbmode];
+}
+
+/*
+ * Sets default PEM callback password if null is passed into
+ * the callback parameter of a PEM_read_bio_* function.
+ *
+ * Returns callback phrase size on success or WOLFSSL_FAILURE otherwise.
+ */
int wolfSSL_PEM_def_callback(char* name, int num, int w, void* key)
{
- (void)name;
- (void)num;
+ int sz;
(void)w;
- (void)key;
- return 0;
+ WOLFSSL_ENTER("wolfSSL_PEM_def_callback");
+
+ /* We assume that the user passes a default password as userdata */
+ if (key) {
+ sz = (int)XSTRLEN((const char*)key);
+ sz = (sz > num) ? num : sz;
+ XMEMCPY(name, key, sz);
+ return sz;
+ } else {
+ WOLFSSL_MSG("Error, default password cannot be created.");
+ return WOLFSSL_FAILURE;
+ }
+}
+
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+static long wolf_set_options(long old_op, long op)
+{
+ /* if SSL_OP_ALL then turn all bug workarounds on */
+ if ((op & SSL_OP_ALL) == SSL_OP_ALL) {
+ WOLFSSL_MSG("\tSSL_OP_ALL");
+ }
+
+ /* by default cookie exchange is on with DTLS */
+ if ((op & SSL_OP_COOKIE_EXCHANGE) == SSL_OP_COOKIE_EXCHANGE) {
+ WOLFSSL_MSG("\tSSL_OP_COOKIE_EXCHANGE : on by default");
+ }
+
+ if ((op & WOLFSSL_OP_NO_SSLv2) == WOLFSSL_OP_NO_SSLv2) {
+ WOLFSSL_MSG("\tWOLFSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2");
+ }
+
+#ifdef SSL_OP_NO_TLSv1_3
+ if ((op & SSL_OP_NO_TLSv1_3) == SSL_OP_NO_TLSv1_3) {
+ WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_3");
+ }
+#endif
+
+ if ((op & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
+ WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2");
+ }
+
+ if ((op & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
+ WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1");
+ }
+
+ if ((op & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
+ WOLFSSL_MSG("\tSSL_OP_NO_TLSv1");
+ }
+
+ if ((op & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) {
+ WOLFSSL_MSG("\tSSL_OP_NO_SSLv3");
+ }
+
+ if ((op & SSL_OP_CIPHER_SERVER_PREFERENCE) == SSL_OP_CIPHER_SERVER_PREFERENCE) {
+ WOLFSSL_MSG("\tSSL_OP_CIPHER_SERVER_PREFERENCE");
+ }
+
+ if ((op & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) {
+ #ifdef HAVE_LIBZ
+ WOLFSSL_MSG("SSL_OP_NO_COMPRESSION");
+ #else
+ WOLFSSL_MSG("SSL_OP_NO_COMPRESSION: compression not compiled in");
+ #endif
+ }
+
+ return old_op | op;
+}
+#endif
+
+#ifdef OPENSSL_EXTRA
+long wolfSSL_set_options(WOLFSSL* ssl, long op)
+{
+ word16 haveRSA = 1;
+ word16 havePSK = 0;
+ int keySz = 0;
+
+ WOLFSSL_ENTER("wolfSSL_set_options");
+
+ if (ssl == NULL) {
+ return 0;
+ }
+
+ ssl->options.mask = wolf_set_options(ssl->options.mask, op);
+
+#ifdef SSL_OP_NO_TLSv1_3
+ if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == SSL_OP_NO_TLSv1_3) {
+ if (ssl->version.minor == TLSv1_3_MINOR)
+ ssl->version.minor = TLSv1_2_MINOR;
+ }
+#endif
+
+ if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
+ if (ssl->version.minor == TLSv1_2_MINOR)
+ ssl->version.minor = TLSv1_1_MINOR;
+ }
+
+ if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
+ if (ssl->version.minor == TLSv1_1_MINOR)
+ ssl->version.minor = TLSv1_MINOR;
+ }
+
+ if ((ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
+ if (ssl->version.minor == TLSv1_MINOR)
+ ssl->version.minor = SSLv3_MINOR;
+ }
+
+ if ((ssl->options.mask & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) {
+ #ifdef HAVE_LIBZ
+ ssl->options.usingCompression = 0;
+ #endif
+ }
+
+ /* in the case of a version change the cipher suites should be reset */
+#ifndef NO_PSK
+ havePSK = ssl->options.havePSK;
+#endif
+#ifdef NO_RSA
+ haveRSA = 0;
+#endif
+#ifndef NO_CERTS
+ keySz = ssl->buffers.keySz;
+#endif
+
+ InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+ ssl->options.haveDH, ssl->options.haveNTRU,
+ ssl->options.haveECDSAsig, ssl->options.haveECC,
+ ssl->options.haveStaticECC, ssl->options.side);
+
+ return ssl->options.mask;
+}
+
+
+long wolfSSL_get_options(const WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_get_options");
+ if(ssl == NULL)
+ return WOLFSSL_FAILURE;
+ return ssl->options.mask;
+}
+
+long wolfSSL_clear_options(WOLFSSL* ssl, long opt)
+{
+ WOLFSSL_ENTER("SSL_clear_options");
+ if(ssl == NULL)
+ return WOLFSSL_FAILURE;
+ ssl->options.mask &= ~opt;
+ return ssl->options.mask;
+}
+
+
+#if defined(HAVE_SECURE_RENEGOTIATION) \
+ || defined(HAVE_SERVER_RENEGOTIATION_INFO)
+/* clears the counter for number of renegotiations done
+ * returns the current count before it is cleared */
+long wolfSSL_clear_num_renegotiations(WOLFSSL *s)
+{
+ long total;
+
+ WOLFSSL_ENTER("wolfSSL_clear_num_renegotiations");
+ if (s == NULL)
+ return 0;
+
+ total = s->secure_rene_count;
+ s->secure_rene_count = 0;
+ return total;
+}
+
+
+/* return the number of renegotiations since wolfSSL_new */
+long wolfSSL_total_renegotiations(WOLFSSL *s)
+{
+ WOLFSSL_ENTER("wolfSSL_total_renegotiations");
+ return wolfSSL_num_renegotiations(s);
+}
+
+
+/* return the number of renegotiations since wolfSSL_new */
+long wolfSSL_num_renegotiations(WOLFSSL* s)
+{
+ if (s == NULL) {
+ return 0;
+ }
+
+ return s->secure_rene_count;
+}
+#endif /* HAVE_SECURE_RENEGOTIATION || HAVE_SERVER_RENEGOTIATION_INFO */
+
+#ifndef NO_DH
+long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh)
+{
+ int pSz, gSz;
+ byte *p, *g;
+ int ret = 0;
+
+ WOLFSSL_ENTER("wolfSSL_set_tmp_dh");
+
+ if (!ssl || !dh)
+ return BAD_FUNC_ARG;
+
+ /* Get needed size for p and g */
+ pSz = wolfSSL_BN_bn2bin(dh->p, NULL);
+ gSz = wolfSSL_BN_bn2bin(dh->g, NULL);
+
+ if (pSz <= 0 || gSz <= 0)
+ return WOLFSSL_FATAL_ERROR;
+
+ p = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ if (!p)
+ return MEMORY_E;
+
+ g = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ if (!g) {
+ XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ return MEMORY_E;
+ }
+
+ pSz = wolfSSL_BN_bn2bin(dh->p, p);
+ gSz = wolfSSL_BN_bn2bin(dh->g, g);
+
+ if (pSz >= 0 && gSz >= 0) /* Conversion successful */
+ ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz);
+
+ XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE(g, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+
+ return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR;
+}
+#endif /* !NO_DH */
+
+
+#ifdef HAVE_PK_CALLBACKS
+long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg)
+{
+ if (ssl == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ ssl->loggingCtx = arg;
+ return WOLFSSL_SUCCESS;
+}
+#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 byte *c = wolfSSL_SESSION_get_id((SSL_SESSION *)sess, sid_ctx_length);
+ return c;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st)
+{
+ (void)st;
+ WOLFSSL_STUB("wolfSSL_sk_SSL_COMP_zero");
+ /* wolfSSL_set_options(ssl, SSL_OP_NO_COMPRESSION); */
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type)
+{
+ WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type");
+
+ if (s == NULL){
+ return BAD_FUNC_ARG;
+ }
+
+ if (type == TLSEXT_STATUSTYPE_ocsp){
+ int r = 0;
+ r = TLSX_UseCertificateStatusRequest(&s->extensions, type, 0, s,
+ s->heap, s->devId);
+ return (long)r;
+ } else {
+ WOLFSSL_MSG(
+ "SSL_set_tlsext_status_type only supports TLSEXT_STATUSTYPE_ocsp type.");
+ return SSL_FAILURE;
+ }
+
+}
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg)
+{
+ (void)s;
+ (void)arg;
+ WOLFSSL_STUB("wolfSSL_get_tlsext_status_exts");
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg)
+{
+ (void)s;
+ (void)arg;
+ WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts");
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg)
+{
+ (void)s;
+ (void)arg;
+ WOLFSSL_STUB("wolfSSL_get_tlsext_status_ids");
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg)
+{
+ (void)s;
+ (void)arg;
+ WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids");
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len)
+{
+ (void)s;
+ (void)sid;
+ (void)sid_len;
+ WOLFSSL_STUB("SSL_SESSION_set1_id");
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len)
+{
+ (void)s;
+ (void)sid_ctx;
+ (void)sid_ctx_len;
+ WOLFSSL_STUB("SSL_SESSION_set1_id_context");
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD) \
+ || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS)
+WOLFSSL_X509_ALGOR* wolfSSL_X509_ALGOR_new(void)
+{
+ WOLFSSL_X509_ALGOR* ret;
+ ret = (WOLFSSL_X509_ALGOR*)XMALLOC(sizeof(WOLFSSL_X509_ALGOR), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (ret) {
+ XMEMSET(ret, 0, sizeof(WOLFSSL_X509_ALGOR));
+ }
+ return ret;
+}
+
+void wolfSSL_X509_ALGOR_free(WOLFSSL_X509_ALGOR *alg)
+{
+ if (alg) {
+ wolfSSL_ASN1_OBJECT_free(alg->algorithm);
+ wolfSSL_ASN1_TYPE_free(alg->parameter);
+ XFREE(alg, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+
+/* Returns X509_ALGOR struct with signature algorithm */
+const WOLFSSL_X509_ALGOR* wolfSSL_X509_get0_tbs_sigalg(const WOLFSSL_X509 *x509)
+{
+ WOLFSSL_ENTER("X509_get0_tbs_sigalg");
+
+ if (x509 == NULL) {
+ WOLFSSL_MSG("x509 struct NULL error");
+ return NULL;
+ }
+
+ return &x509->algor;
+}
+
+/* Sets paobj pointer to X509_ALGOR signature algorithm */
+void wolfSSL_X509_ALGOR_get0(const WOLFSSL_ASN1_OBJECT **paobj, int *pptype,
+ const void **ppval, const WOLFSSL_X509_ALGOR *algor)
+{
+ WOLFSSL_ENTER("X509_ALGOR_get0");
+
+ if (!algor) {
+ WOLFSSL_MSG("algor object is NULL");
+ return;
+ }
+
+ if (paobj)
+ *paobj = algor->algorithm;
+ if (ppval)
+ *ppval = algor->algorithm;
+ if (pptype) {
+ if (algor->parameter) {
+ *pptype = algor->parameter->type;
+ }
+ else {
+ /* Default to V_ASN1_OBJECT */
+ *pptype = V_ASN1_OBJECT;
+ }
+ }
+}
+
+/**
+ * Populate algor members.
+ *
+ * @param algor The object to be set
+ * @param aobj The value to be set in algor->algorithm
+ * @param ptype The type of algor->parameter
+ * @param pval The value of algor->parameter
+ * @return WOLFSSL_SUCCESS on success
+ * WOLFSSL_FAILURE on missing parameters or bad malloc
+ */
+int wolfSSL_X509_ALGOR_set0(WOLFSSL_X509_ALGOR *algor, WOLFSSL_ASN1_OBJECT *aobj,
+ int ptype, void *pval)
+{
+ if (!algor) {
+ return WOLFSSL_FAILURE;
+ }
+ if (aobj) {
+ algor->algorithm = aobj;
+ }
+ if (pval) {
+ if (!algor->parameter) {
+ algor->parameter = wolfSSL_ASN1_TYPE_new();
+ if (!algor->parameter) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+ wolfSSL_ASN1_TYPE_set(algor->parameter, ptype, pval);
+ }
+ return WOLFSSL_SUCCESS;
+}
+
+/**
+ * Set `a` in a smart way.
+ *
+ * @param a Object to set
+ * @param type The type of object in value
+ * @param value Object to set
+ */
+void wolfSSL_ASN1_TYPE_set(WOLFSSL_ASN1_TYPE *a, int type, void *value)
+{
+ if (!a || !value) {
+ return;
+ }
+ switch (type) {
+ case V_ASN1_OBJECT:
+ a->value.object = value;
+ break;
+ case V_ASN1_UTCTIME:
+ a->value.utctime = value;
+ break;
+ case V_ASN1_GENERALIZEDTIME:
+ a->value.generalizedtime = value;
+ break;
+ default:
+ WOLFSSL_MSG("Unknown or unsupported ASN1_TYPE");
+ return;
+ }
+ a->type = type;
+}
+
+/**
+ * Allocate a new WOLFSSL_ASN1_TYPE object.
+ *
+ * @return New zero'ed WOLFSSL_ASN1_TYPE object
+ */
+WOLFSSL_ASN1_TYPE* wolfSSL_ASN1_TYPE_new(void)
+{
+ WOLFSSL_ASN1_TYPE* ret = (WOLFSSL_ASN1_TYPE*)XMALLOC(sizeof(WOLFSSL_ASN1_TYPE),
+ NULL, DYNAMIC_TYPE_OPENSSL);
+ if (!ret)
+ return NULL;
+ XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TYPE));
+ return ret;
+}
+
+/**
+ * Free WOLFSSL_ASN1_TYPE and all its members.
+ *
+ * @param at Object to free
+ */
+void wolfSSL_ASN1_TYPE_free(WOLFSSL_ASN1_TYPE* at)
+{
+ if (at) {
+ switch (at->type) {
+ case V_ASN1_OBJECT:
+ wolfSSL_ASN1_OBJECT_free(at->value.object);
+ break;
+ case V_ASN1_UTCTIME:
+ wolfSSL_ASN1_TIME_free(at->value.utctime);
+ break;
+ case V_ASN1_GENERALIZEDTIME:
+ wolfSSL_ASN1_TIME_free(at->value.generalizedtime);
+ break;
+ default:
+ WOLFSSL_MSG("Unknown or unsupported ASN1_TYPE");
+ break;
+ }
+ XFREE(at, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+
+/**
+ * Allocate a new WOLFSSL_X509_PUBKEY object.
+ *
+ * @return New zero'ed WOLFSSL_X509_PUBKEY object
+ */
+WOLFSSL_X509_PUBKEY *wolfSSL_X509_PUBKEY_new(void)
+{
+ WOLFSSL_X509_PUBKEY *ret;
+ ret = (WOLFSSL_X509_PUBKEY*)XMALLOC(sizeof(WOLFSSL_X509_PUBKEY), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (!ret) {
+ return NULL;
+ }
+ XMEMSET(ret, 0, sizeof(WOLFSSL_X509_PUBKEY));
+ ret->algor = wolfSSL_X509_ALGOR_new();
+ if (!ret->algor) {
+ wolfSSL_X509_PUBKEY_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+/**
+ * Free WOLFSSL_X509_PUBKEY and all its members.
+ *
+ * @param at Object to free
+ */
+void wolfSSL_X509_PUBKEY_free(WOLFSSL_X509_PUBKEY *x)
+{
+ if (x) {
+ if (x->algor) {
+ wolfSSL_X509_ALGOR_free(x->algor);
+ }
+ if (x->pkey) {
+ wolfSSL_EVP_PKEY_free(x->pkey);
+ }
+ XFREE(x, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+
+/* Returns X509_PUBKEY structure containing X509_ALGOR and EVP_PKEY */
+WOLFSSL_X509_PUBKEY* wolfSSL_X509_get_X509_PUBKEY(const WOLFSSL_X509* x509)
+{
+ WOLFSSL_ENTER("X509_get_X509_PUBKEY");
+
+ if (x509 == NULL) {
+ WOLFSSL_MSG("x509 struct NULL error");
+ return NULL;
+ }
+
+ return (WOLFSSL_X509_PUBKEY*)&x509->key;
+}
+
+/* Sets ppkalg pointer to X509_PUBKEY algorithm. Returns WOLFSSL_SUCCESS on
+ success or WOLFSSL_FAILURE on error. */
+int wolfSSL_X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg,
+ const unsigned char **pk, int *ppklen, WOLFSSL_X509_ALGOR **pa,
+ WOLFSSL_X509_PUBKEY *pub)
+{
+ WOLFSSL_ENTER("X509_PUBKEY_get0_param");
+
+ if (!pub || !pub->pubKeyOID) {
+ WOLFSSL_MSG("X509_PUBKEY struct not populated");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (!pub->algor) {
+ if (!(pub->algor = wolfSSL_X509_ALGOR_new())) {
+ return WOLFSSL_FAILURE;
+ }
+ pub->algor->algorithm = wolfSSL_OBJ_nid2obj(pub->pubKeyOID);
+ if (pub->algor->algorithm == NULL) {
+ WOLFSSL_MSG("Failed to create object from NID");
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ if (pa)
+ *pa = pub->algor;
+ if (ppkalg)
+ *ppkalg = pub->algor->algorithm;
+ if (pk)
+ wolfSSL_EVP_PKEY_get_der(pub->pkey, (unsigned char **)pk);
+ if (ppklen)
+ *ppklen = wolfSSL_EVP_PKEY_get_der(pub->pkey, NULL);
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* Returns a pointer to the pkey when passed a key */
+WOLFSSL_EVP_PKEY* wolfSSL_X509_PUBKEY_get(WOLFSSL_X509_PUBKEY* key)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_PUBKEY_get");
+ if(key == NULL || key->pkey == NULL){
+ WOLFSSL_LEAVE("wolfSSL_X509_PUBKEY_get", BAD_FUNC_ARG);
+ return NULL;
+ }
+ WOLFSSL_LEAVE("wolfSSL_X509_PUBKEY_get", WOLFSSL_SUCCESS);
+ return key->pkey;
+}
+
+int wolfSSL_X509_PUBKEY_set(WOLFSSL_X509_PUBKEY **x, WOLFSSL_EVP_PKEY *key)
+{
+ WOLFSSL_X509_PUBKEY *pk = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_X509_PUBKEY_set");
+
+ if (!x || !key) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (!(pk = wolfSSL_X509_PUBKEY_new())) {
+ return WOLFSSL_FAILURE;
+ }
+
+ switch (key->type) {
+#ifndef NO_RSA
+ case EVP_PKEY_RSA:
+ pk->algor->algorithm= wolfSSL_OBJ_nid2obj(RSAk);
+ break;
+#endif
+#ifndef NO_DSA
+ case EVP_PKEY_DSA:
+ pk->algor->algorithm = wolfSSL_OBJ_nid2obj(DSAk);
+ break;
+#endif
+#ifdef HAVE_ECC
+ case EVP_PKEY_EC:
+ pk->algor->algorithm = wolfSSL_OBJ_nid2obj(ECDSAk);
+ break;
+#endif
+ default:
+ WOLFSSL_MSG("Unknown key type");
+ goto error;
+ }
+
+ if (!pk->algor->algorithm) {
+ WOLFSSL_MSG("Failed to create algorithm object");
+ goto error;
+ }
+
+ if (!wolfSSL_EVP_PKEY_up_ref(key)) {
+ WOLFSSL_MSG("Failed to up key reference");
+ goto error;
+ }
+ pk->pkey = key;
+
+ wolfSSL_X509_PUBKEY_free(*x);
+ *x = pk;
+ return WOLFSSL_SUCCESS;
+error:
+ if (pk) {
+ wolfSSL_X509_PUBKEY_free(pk);
+ }
+ return WOLFSSL_FAILURE;
+}
+
+#endif /* OPENSSL_ALL || WOLFSSL_APACHE_HTTPD || WOLFSSL_HAPROXY*/
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl)
+{
+ (void)ssl;
+ WOLFSSL_STUB("SSL_get_privatekey");
+ return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a)
+{
+ (void)buf;
+ (void)buf_len;
+ (void)a;
+ WOLFSSL_STUB("i2t_ASN1_OBJECT");
+ return -1;
+}
+#endif
+
+/* Return number of bytes written to BIO on success. 0 on failure. */
+WOLFSSL_API int wolfSSL_i2a_ASN1_OBJECT(WOLFSSL_BIO *bp,
+ WOLFSSL_ASN1_OBJECT *a)
+{
+ int length = 0;
+ word32 idx = 0;
+ const char null_str[] = "NULL";
+
+ WOLFSSL_ENTER("wolfSSL_i2a_ASN1_OBJECT");
+
+ if (bp == NULL)
+ return WOLFSSL_FAILURE;
+
+ if (a == NULL) {
+ /* Write "NULL" */
+ if (wolfSSL_BIO_write(bp, null_str, (int)XSTRLEN(null_str)) ==
+ (int)XSTRLEN(null_str)) {
+ return (int)XSTRLEN(null_str);
+ }
+ else {
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+
+ if ((a->obj == NULL) || (a->obj[idx++] != ASN_OBJECT_ID)) {
+ WOLFSSL_MSG("Bad ASN1 Object");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (GetLength((const byte*)a->obj, &idx, &length,
+ a->objSz) < 0 || length < 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_BIO_write(bp, a->obj + idx, length) == (int)length) {
+ return length;
+ }
+
+ return WOLFSSL_FAILURE;
+}
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count)
+{
+ (void)s;
+ (void)buf;
+ (void)count;
+ WOLFSSL_STUB("SSL_get_finished");
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count)
+{
+ (void)s;
+ (void)buf;
+ (void)count;
+ WOLFSSL_STUB("SSL_get_peer_finished");
+ return WOLFSSL_FAILURE;
+}
+#endif
+#endif /* WOLFSSL_HAPROXY */
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength))
+{
+ (void)ctx;
+ (void)dh;
+ WOLFSSL_STUB("SSL_CTX_set_tmp_dh_callback");
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void)
+{
+ WOLFSSL_STUB("SSL_COMP_get_compression_methods");
+ return NULL;
+}
+#endif
+
+
+int wolfSSL_sk_SSL_CIPHER_num(const WOLF_STACK_OF(WOLFSSL_CIPHER)* p)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_num");
+ if (p == NULL) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+ return (int)p->num;
+}
+
+#if !defined(NO_FILESYSTEM)
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PrivateKey(XFILE fp, WOLFSSL_EVP_PKEY **x, pem_password_cb *cb, void *u)
+{
+ (void)fp;
+ (void)x;
+ (void)cb;
+ (void)u;
+ WOLFSSL_STUB("PEM_read_PrivateKey");
+ return NULL;
+}
+#endif
+#endif
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+/* Loads certificate(s) files in pem format into X509_STORE struct from either
+ * a file or directory.
+ * Returns WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE if an error occurs.
+ */
+WOLFSSL_API int wolfSSL_X509_STORE_load_locations(WOLFSSL_X509_STORE *str,
+ const char *file, const char *dir)
+{
+ WOLFSSL_CTX* ctx;
+ char *name = NULL;
+ int ret = WOLFSSL_SUCCESS;
+ int successes = 0;
+#ifdef WOLFSSL_SMALL_STACK
+ ReadDirCtx* readCtx = NULL;
+#else
+ ReadDirCtx readCtx[1];
+#endif
+
+ WOLFSSL_ENTER("X509_STORE_load_locations");
+
+ if (str == NULL || str->cm == NULL || (file == NULL && dir == NULL))
+ return WOLFSSL_FAILURE;
+
+ /* tmp ctx for setting our cert manager */
+ ctx = wolfSSL_CTX_new(cm_pick_method());
+ if (ctx == NULL)
+ return WOLFSSL_FAILURE;
+
+ wolfSSL_CertManagerFree(ctx->cm);
+ ctx->cm = str->cm;
+
+#ifdef HAVE_CRL
+ if (str->cm->crl == NULL) {
+ if (wolfSSL_CertManagerEnableCRL(str->cm, 0) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Enable CRL failed");
+ wolfSSL_CTX_free(ctx);
+ return WOLFSSL_FAILURE;
+ }
+ }
+#endif
+
+ /* Load individual file */
+ if (file) {
+ /* Try to process file with type DETECT_CERT_TYPE to parse the
+ correct certificate header and footer type */
+ ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, DETECT_CERT_TYPE,
+ NULL, 0, str->cm->crl, 0);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Failed to load file");
+ ret = WOLFSSL_FAILURE;
+ }
+ }
+
+ /* Load files in dir */
+ if (dir && ret == WOLFSSL_SUCCESS) {
+ #ifdef WOLFSSL_SMALL_STACK
+ readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (readCtx == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return WOLFSSL_FAILURE;
+ }
+ #endif
+
+ /* try to load each regular file in dir */
+ ret = wc_ReadDirFirst(readCtx, dir, &name);
+ while (ret == 0 && name) {
+ WOLFSSL_MSG(name);
+ /* Try to process file with type DETECT_CERT_TYPE to parse the
+ correct certificate header and footer type */
+ ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, DETECT_CERT_TYPE,
+ NULL, 0, str->cm->crl, 0);
+ /* Not failing on load errors */
+ if (ret != WOLFSSL_SUCCESS)
+ WOLFSSL_MSG("Failed to load file in path, continuing");
+ else
+ successes++;
+
+ ret = wc_ReadDirNext(readCtx, dir, &name);
+ }
+ wc_ReadDirClose(readCtx);
+
+ /* Success if at least one file in dir was loaded */
+ if (successes > 0)
+ ret = WOLFSSL_SUCCESS;
+ else {
+ WOLFSSL_ERROR(ret);
+ ret = WOLFSSL_FAILURE;
+ }
+
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX);
+ #endif
+ }
+
+ ctx->cm = NULL;
+ wolfSSL_CTX_free(ctx);
+
+ return ret;
+}
+#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx)
+{
+ (void)ciphers;
+ (void)idx;
+ WOLFSSL_STUB("wolfSSL_sk_SSL_CIPHER_value");
+ return NULL;
+}
+#endif
+
+WOLFSSL_API void ERR_load_SSL_strings(void)
+{
+
+}
+
+#ifdef HAVE_OCSP
+WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp)
+{
+ if (s == NULL || resp == NULL)
+ return 0;
+
+ *resp = s->ocspResp;
+ return s->ocspRespSz;
+}
+
+WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len)
+{
+ if (s == NULL)
+ return WOLFSSL_FAILURE;
+
+ s->ocspResp = resp;
+ s->ocspRespSz = len;
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_OCSP */
+
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+long wolfSSL_get_verify_result(const WOLFSSL *ssl)
+{
+ if (ssl == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ return ssl->peerVerifyRet;
}
+#endif
+#ifdef OPENSSL_EXTRA
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of accepts attempted by CTX in it's lifetime */
long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx)
{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_accept");
(void)ctx;
return 0;
}
+#endif
-
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of connects attempted CTX in it's lifetime */
long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx)
{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_connect");
(void)ctx;
return 0;
}
+#endif
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of accepts completed by CTX in it's lifetime */
long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX* ctx)
{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_accept_good");
(void)ctx;
return 0;
}
+#endif
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of connects completed by CTX in it's lifetime */
long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX* ctx)
{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_connect_good");
(void)ctx;
return 0;
}
+#endif
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of renegotiation accepts attempted by CTX */
long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX* ctx)
{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_accept_renegotiate");
(void)ctx;
return 0;
}
+#endif
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of renegotiation accepts attempted by CTX */
long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx)
{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_connect_renegotiate");
(void)ctx;
return 0;
}
+#endif
+#ifndef NO_WOLFSSL_STUB
long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx)
{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_hits");
(void)ctx;
return 0;
}
+#endif
+#ifndef NO_WOLFSSL_STUB
long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx)
{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_cb_hits");
(void)ctx;
return 0;
}
+#endif
+#ifndef NO_WOLFSSL_STUB
long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx)
{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_cache_full");
(void)ctx;
return 0;
}
+#endif
+#ifndef NO_WOLFSSL_STUB
long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx)
{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_misses");
(void)ctx;
return 0;
}
+#endif
+#ifndef NO_WOLFSSL_STUB
long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx)
{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_timeouts");
(void)ctx;
return 0;
}
+#endif
+/* Return the total number of sessions */
long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx)
{
+ word32 total = 0;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_sess_number");
(void)ctx;
- return 0;
+
+#ifdef WOLFSSL_SESSION_STATS
+ if (wolfSSL_get_session_stats(NULL, &total, NULL, NULL) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Error getting session stats");
+ }
+#else
+ WOLFSSL_MSG("Please use macro WOLFSSL_SESSION_STATS for session stats");
+#endif
+
+ return (long)total;
}
-#ifndef NO_DES3
-void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock* myDes,
- WOLFSSL_DES_key_schedule* key)
+#ifndef NO_CERTS
+long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
{
- (void)myDes;
- (void)key;
+ byte* chain = NULL;
+ long chainSz = 0;
+ int derSz;
+ const byte* der;
+ int ret;
+ int idx = 0;
+ DerBuffer *derBuffer = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert");
+
+ if (ctx == NULL || x509 == NULL) {
+ WOLFSSL_MSG("Bad Argument");
+ return WOLFSSL_FAILURE;
+ }
+
+ der = wolfSSL_X509_get_der(x509, &derSz);
+ if (der == NULL || derSz <= 0) {
+ WOLFSSL_MSG("Error getting X509 DER");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (ctx->certificate == NULL) {
+ WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format");
+
+ /* Process buffer makes first certificate the leaf. */
+ ret = ProcessBuffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE,
+ NULL, NULL, 1, GET_VERIFY_SETTING_CTX(ctx));
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret);
+ return WOLFSSL_FAILURE;
+ }
+ }
+ else {
+ /* TODO: Do this elsewhere. */
+ ret = AllocDer(&derBuffer, derSz, CERT_TYPE, ctx->heap);
+ if (ret != 0) {
+ WOLFSSL_MSG("Memory Error");
+ return WOLFSSL_FAILURE;
+ }
+ XMEMCPY(derBuffer->buffer, der, derSz);
+ ret = AddCA(ctx->cm, &derBuffer, WOLFSSL_USER_CA,
+ GET_VERIFY_SETTING_CTX(ctx));
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* adding cert to existing chain */
+ if (ctx->certChain != NULL && ctx->certChain->length > 0) {
+ chainSz += ctx->certChain->length;
+ }
+ chainSz += OPAQUE24_LEN + derSz;
+
+ chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_DER);
+ if (chain == NULL) {
+ WOLFSSL_MSG("Memory Error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (ctx->certChain != NULL && ctx->certChain->length > 0) {
+ XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length);
+ idx = ctx->certChain->length;
+ }
+ c32to24(derSz, chain + idx);
+ idx += OPAQUE24_LEN,
+ XMEMCPY(chain + idx, der, derSz);
+ idx += derSz;
+#ifdef WOLFSSL_TLS13
+ ctx->certChainCnt++;
+#endif
+
+ FreeDer(&ctx->certChain);
+ ret = AllocDer(&ctx->certChain, idx, CERT_TYPE, ctx->heap);
+ if (ret == 0) {
+ XMEMCPY(ctx->certChain->buffer, chain, idx);
+ }
+ }
+
+ /* on success WOLFSSL_X509 memory is responsibility of ctx */
+ wolfSSL_X509_free(x509);
+ if (chain != NULL)
+ XFREE(chain, ctx->heap, DYNAMIC_TYPE_DER);
+
+ return WOLFSSL_SUCCESS;
}
-void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock* myDes)
+long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg)
{
- (void)myDes;
+ if (ctx == NULL || ctx->cm == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ ctx->cm->ocspIOCtx = arg;
+ return WOLFSSL_SUCCESS;
}
+#endif /* NO_CERTS */
+
-void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* desa,
- WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int len)
+/* Get the session cache mode for CTX
+ *
+ * ctx WOLFSSL_CTX struct to get cache mode from
+ *
+ * Returns a bit mask that has the session cache mode */
+WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX* ctx)
{
- (void)desa;
- (void)desb;
- (void)key;
- (void)len;
+ long m = 0;
+
+ WOLFSSL_ENTER("SSL_CTX_set_session_cache_mode");
+
+ if (ctx == NULL) {
+ return m;
+ }
+
+ if (ctx->sessionCacheOff != 1) {
+ m |= SSL_SESS_CACHE_SERVER;
+ }
+
+ if (ctx->sessionCacheFlushOff == 1) {
+ m |= SSL_SESS_CACHE_NO_AUTO_CLEAR;
+ }
+
+#ifdef HAVE_EXT_CACHE
+ if (ctx->internalCacheOff == 1) {
+ m |= SSL_SESS_CACHE_NO_INTERNAL_STORE;
+ }
+#endif
+
+ return m;
}
-#endif /* NO_DES3 */
-int wolfSSL_BIO_printf(WOLFSSL_BIO* bio, const char* format, ...)
+int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx)
{
- (void)bio;
- (void)format;
- return 0;
+ if (ctx == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ return ctx->readAhead;
}
-int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a)
+int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v)
{
- (void)bio;
- (void)a;
- return 0;
+ if (ctx == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ ctx->readAhead = (byte)v;
+
+ return WOLFSSL_SUCCESS;
}
-int wolfSSL_sk_num(WOLFSSL_X509_REVOKED* rev)
+long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx,
+ void* arg)
{
- (void)rev;
- return 0;
+ if (ctx == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ ctx->userPRFArg = arg;
+ return WOLFSSL_SUCCESS;
}
-void* wolfSSL_sk_value(WOLFSSL_X509_REVOKED* rev, int i)
+#ifndef NO_DES3
+/* 0 on success */
+int wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes,
+ WOLFSSL_DES_key_schedule* key)
{
- (void)rev;
- (void)i;
+#ifdef WOLFSSL_CHECK_DESKEY
+ return wolfSSL_DES_set_key_checked(myDes, key);
+#else
+ wolfSSL_DES_set_key_unchecked(myDes, key);
return 0;
+#endif
}
-/* stunnel 4.28 needs */
-void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int d)
+
+/* return true in fail case (1) */
+static int DES_check(word32 mask, word32 mask2, unsigned char* key)
{
- (void)ctx;
- (void)d;
- return 0;
+ word32 value[2];
+
+ /* sanity check on length made in wolfSSL_DES_set_key_checked */
+ value[0] = mask;
+ value[1] = mask2;
+ return (XMEMCMP(value, key, sizeof(value)) == 0)? 1: 0;
}
-int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int d, void* p)
+/* check that the key is odd parity and is not a weak key
+ * returns -1 if parity is wrong, -2 if weak/null key and 0 on success */
+int wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes,
+ WOLFSSL_DES_key_schedule* key)
{
- (void)ctx;
- (void)d;
- (void)p;
- return SSL_SUCCESS;
+ if (myDes == NULL || key == NULL) {
+ WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_set_key_checked");
+ return -2;
+ }
+ else {
+ word32 sz = sizeof(WOLFSSL_DES_key_schedule);
+
+ /* sanity check before call to DES_check */
+ if (sz != (sizeof(word32) * 2)) {
+ WOLFSSL_MSG("Unexpected WOLFSSL_DES_key_schedule size");
+ return -2;
+ }
+
+ /* check odd parity */
+ if (wolfSSL_DES_check_key_parity(myDes) != 1) {
+ WOLFSSL_MSG("Odd parity test fail");
+ return -1;
+ }
+
+ if (wolfSSL_DES_is_weak_key(myDes) == 1) {
+ WOLFSSL_MSG("Weak key found");
+ return -2;
+ }
+
+ /* passed tests, now copy over key */
+ XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock));
+
+ return 0;
+ }
}
-void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx,
- WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*))
+/* check is not weak. Weak key list from Nist "Recommendation for the Triple
+ * Data Encryption Algorithm (TDEA) Block Cipher"
+ *
+ * returns 1 if is weak 0 if not
+ */
+int wolfSSL_DES_is_weak_key(WOLFSSL_const_DES_cblock* key)
{
- (void)ctx;
- (void)f;
+ word32 mask, mask2;
+
+ WOLFSSL_ENTER("wolfSSL_DES_is_weak_key");
+
+ if (key == NULL) {
+ WOLFSSL_MSG("NULL key passed in");
+ return 1;
+ }
+
+ mask = 0x01010101; mask2 = 0x01010101;
+ if (DES_check(mask, mask2, *key)) {
+ WOLFSSL_MSG("Weak key found");
+ return 1;
+ }
+
+ mask = 0xFEFEFEFE; mask2 = 0xFEFEFEFE;
+ if (DES_check(mask, mask2, *key)) {
+ WOLFSSL_MSG("Weak key found");
+ return 1;
+ }
+
+ mask = 0xE0E0E0E0; mask2 = 0xF1F1F1F1;
+ if (DES_check(mask, mask2, *key)) {
+ WOLFSSL_MSG("Weak key found");
+ return 1;
+ }
+
+ mask = 0x1F1F1F1F; mask2 = 0x0E0E0E0E;
+ if (DES_check(mask, mask2, *key)) {
+ WOLFSSL_MSG("Weak key found");
+ return 1;
+ }
+
+ /* semi-weak *key check (list from same Nist paper) */
+ mask = 0x011F011F; mask2 = 0x010E010E;
+ if (DES_check(mask, mask2, *key) ||
+ DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+ WOLFSSL_MSG("Weak key found");
+ return 1;
+ }
+
+ mask = 0x01E001E0; mask2 = 0x01F101F1;
+ if (DES_check(mask, mask2, *key) ||
+ DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+ WOLFSSL_MSG("Weak key found");
+ return 1;
+ }
+
+ mask = 0x01FE01FE; mask2 = 0x01FE01FE;
+ if (DES_check(mask, mask2, *key) ||
+ DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+ WOLFSSL_MSG("Weak key found");
+ return 1;
+ }
+
+ mask = 0x1FE01FE0; mask2 = 0x0EF10EF1;
+ if (DES_check(mask, mask2, *key) ||
+ DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+ WOLFSSL_MSG("Weak key found");
+ return 1;
+ }
+
+ mask = 0x1FFE1FFE; mask2 = 0x0EFE0EFE;
+ if (DES_check(mask, mask2, *key) ||
+ DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+ WOLFSSL_MSG("Weak key found");
+ return 1;
+ }
+
+ return 0;
}
-void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx,
- int (*f)(WOLFSSL*, WOLFSSL_SESSION*))
+void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock* myDes,
+ WOLFSSL_DES_key_schedule* key)
{
- (void)ctx;
- (void)f;
+ if (myDes != NULL && key != NULL) {
+ XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock));
+ }
}
-void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*,
- WOLFSSL_SESSION*))
+/* Sets the parity of the DES key for use */
+void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock* myDes)
{
- (void)ctx;
- (void)f;
+ word32 i;
+ word32 sz = sizeof(WOLFSSL_DES_cblock);
+
+ WOLFSSL_ENTER("wolfSSL_DES_set_odd_parity");
+
+ for (i = 0; i < sz; i++) {
+ unsigned char c = (*myDes)[i];
+ if ((
+ ((c >> 1) & 0x01) ^
+ ((c >> 2) & 0x01) ^
+ ((c >> 3) & 0x01) ^
+ ((c >> 4) & 0x01) ^
+ ((c >> 5) & 0x01) ^
+ ((c >> 6) & 0x01) ^
+ ((c >> 7) & 0x01)) == (c & 0x01)) {
+ WOLFSSL_MSG("Flipping parity bit");
+ (*myDes)[i] = c ^ 0x01;
+ }
+ }
}
-
-int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p)
+int wolfSSL_DES_check_key_parity(WOLFSSL_DES_cblock *myDes)
{
- (void)sess;
- (void)p;
- return sizeof(WOLFSSL_SESSION);
+ word32 i;
+ word32 sz = sizeof(WOLFSSL_DES_cblock);
+
+ WOLFSSL_ENTER("wolfSSL_DES_check_key_parity");
+
+ for (i = 0; i < sz; i++) {
+ unsigned char c = (*myDes)[i];
+ if ((
+ ((c >> 1) & 0x01) ^
+ ((c >> 2) & 0x01) ^
+ ((c >> 3) & 0x01) ^
+ ((c >> 4) & 0x01) ^
+ ((c >> 5) & 0x01) ^
+ ((c >> 6) & 0x01) ^
+ ((c >> 7) & 0x01)) == (c & 0x01)) {
+ return 0;
+ }
+ }
+ return 1;
}
+#ifdef WOLFSSL_DES_ECB
+/* Encrypt or decrypt input message desa with key and get output in desb.
+ * if enc is DES_ENCRYPT,input message is encrypted or
+ * if enc is DES_DECRYPT,input message is decrypted.
+ * */
+void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* desa,
+ WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int enc)
+{
+ Des myDes;
-WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess,
- const unsigned char** p, long i)
+ WOLFSSL_ENTER("wolfSSL_DES_ecb_encrypt");
+
+ if (desa == NULL || key == NULL || desb == NULL ||
+ (enc != DES_ENCRYPT && enc != DES_DECRYPT)) {
+ WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_ecb_encrypt");
+ } else {
+ if (wc_Des_SetKey(&myDes, (const byte*) key,
+ (const byte*) NULL, !enc) != 0) {
+ WOLFSSL_MSG("wc_Des_SetKey return error.");
+ return;
+ }
+ if (enc){
+ if (wc_Des_EcbEncrypt(&myDes, (byte*) desb, (const byte*) desa,
+ sizeof(WOLFSSL_DES_cblock)) != 0){
+ WOLFSSL_MSG("wc_Des_EcbEncrypt return error.");
+ }
+ } else {
+ if (wc_Des_EcbDecrypt(&myDes, (byte*) desb, (const byte*) desa,
+ sizeof(WOLFSSL_DES_cblock)) != 0){
+ WOLFSSL_MSG("wc_Des_EcbDecrpyt return error.");
+ }
+ }
+ }
+}
+#endif
+#endif /* NO_DES3 */
+
+#ifndef NO_RC4
+/* Set the key state for Arc4 structure.
+ *
+ * key Arc4 structure to use
+ * len length of data buffer
+ * data initial state to set Arc4 structure
+ */
+void wolfSSL_RC4_set_key(WOLFSSL_RC4_KEY* key, int len,
+ const unsigned char* data)
{
- (void)p;
- (void)i;
- if (sess)
- return *sess;
- return NULL;
+ typedef char rc4_test[sizeof(WOLFSSL_RC4_KEY) >= sizeof(Arc4) ? 1 : -1];
+ (void)sizeof(rc4_test);
+
+ WOLFSSL_ENTER("wolfSSL_RC4_set_key");
+
+ if (key == NULL || len < 0) {
+ WOLFSSL_MSG("bad argument passed in");
+ return;
+ }
+
+ XMEMSET(key, 0, sizeof(WOLFSSL_RC4_KEY));
+ wc_Arc4SetKey((Arc4*)key, data, (word32)len);
}
-long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess)
+/* Encrypt/decrypt with Arc4 structure.
+ *
+ * len length of buffer to encrypt/decrypt (in/out)
+ * in buffer to encrypt/decrypt
+ * out results of encryption/decryption
+ */
+void wolfSSL_RC4(WOLFSSL_RC4_KEY* key, size_t len,
+ const unsigned char* in, unsigned char* out)
{
- WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout");
- return sess->timeout;
+ WOLFSSL_ENTER("wolfSSL_RC4");
+
+ if (key == NULL || in == NULL || out == NULL) {
+ WOLFSSL_MSG("Bad argument passed in");
+ return;
+ }
+
+ wc_Arc4Process((Arc4*)key, out, in, (word32)len);
}
+#endif /* NO_RC4 */
+#ifndef NO_AES
-long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess)
+#ifdef WOLFSSL_AES_DIRECT
+/* AES encrypt direct, it is expected to be blocks of AES_BLOCK_SIZE for input.
+ *
+ * input Data to encrypt
+ * output Encrypted data after done
+ * key AES key to use for encryption
+ */
+void wolfSSL_AES_encrypt(const unsigned char* input, unsigned char* output,
+ AES_KEY *key)
{
- WOLFSSL_ENTER("wolfSSL_SESSION_get_time");
- return sess->bornOn;
+ WOLFSSL_ENTER("wolfSSL_AES_encrypt");
+
+ if (input == NULL || output == NULL || key == NULL) {
+ WOLFSSL_MSG("Null argument passed in");
+ return;
+ }
+
+ wc_AesEncryptDirect((Aes*)key, output, input);
}
-int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b,
- void* c)
+/* AES decrypt direct, it is expected to be blocks of AES_BLOCK_SIZE for input.
+ *
+ * input Data to decrypt
+ * output Decrypted data after done
+ * key AES key to use for encryption
+ */
+void wolfSSL_AES_decrypt(const unsigned char* input, unsigned char* output,
+ AES_KEY *key)
{
- (void)idx;
- (void)arg;
- (void)a;
- (void)b;
- (void)c;
- return 0;
+ WOLFSSL_ENTER("wolfSSL_AES_decrypt");
+
+ if (input == NULL || output == NULL || key == NULL) {
+ WOLFSSL_MSG("Null argument passed in");
+ return;
+ }
+
+ wc_AesDecryptDirect((Aes*)key, output, input);
}
+#endif /* WOLFSSL_AES_DIRECT */
-#endif /* OPENSSL_EXTRA */
+/* Setup of an AES key to use for encryption.
+ *
+ * key key in bytes to use for encryption
+ * bits size of key in bits
+ * aes AES structure to initialize
+ */
+int wolfSSL_AES_set_encrypt_key(const unsigned char *key, const int bits,
+ AES_KEY *aes)
+{
+ typedef char aes_test[sizeof(AES_KEY) >= sizeof(Aes) ? 1 : -1];
+ (void)sizeof(aes_test);
+ WOLFSSL_ENTER("wolfSSL_AES_set_encrypt_key");
-#ifdef KEEP_PEER_CERT
-char* wolfSSL_X509_get_subjectCN(WOLFSSL_X509* x509)
+ if (key == NULL || aes == NULL) {
+ WOLFSSL_MSG("Null argument passed in");
+ return -1;
+ }
+
+ XMEMSET(aes, 0, sizeof(AES_KEY));
+ if (wc_AesSetKey((Aes*)aes, key, ((bits)/8), NULL, AES_ENCRYPTION) != 0) {
+ WOLFSSL_MSG("Error in setting AES key");
+ return -1;
+ }
+ return 0;
+}
+
+
+/* Setup of an AES key to use for decryption.
+ *
+ * key key in bytes to use for decryption
+ * bits size of key in bits
+ * aes AES structure to initialize
+ */
+int wolfSSL_AES_set_decrypt_key(const unsigned char *key, const int bits,
+ AES_KEY *aes)
{
- if (x509 == NULL)
- return NULL;
+ typedef char aes_test[sizeof(AES_KEY) >= sizeof(Aes) ? 1 : -1];
+ (void)sizeof(aes_test);
- return x509->subjectCN;
+ WOLFSSL_ENTER("wolfSSL_AES_set_decrypt_key");
+
+ if (key == NULL || aes == NULL) {
+ WOLFSSL_MSG("Null argument passed in");
+ return -1;
+ }
+
+ XMEMSET(aes, 0, sizeof(AES_KEY));
+ if (wc_AesSetKey((Aes*)aes, key, ((bits)/8), NULL, AES_DECRYPTION) != 0) {
+ WOLFSSL_MSG("Error in setting AES key");
+ return -1;
+ }
+ return 0;
}
-#endif /* KEEP_PEER_CERT */
-#ifdef OPENSSL_EXTRA
-#ifdef FORTRESS
-int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname)
+#ifdef HAVE_AES_ECB
+/* Encrypt/decrypt a 16 byte block of data using the key passed in.
+ *
+ * in buffer to encrypt/decrypt
+ * out buffer to hold result of encryption/decryption
+ * key AES structure to use with encryption/decryption
+ * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption
+ */
+void wolfSSL_AES_ecb_encrypt(const unsigned char *in, unsigned char* out,
+ AES_KEY *key, const int enc)
{
- int ret = SSL_FATAL_ERROR;
+ Aes* aes;
- WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file");
- if (ssl != NULL && fname != NULL)
- {
- #ifdef WOLFSSL_SMALL_STACK
- EncryptedInfo* info = NULL;
- byte staticBuffer[1]; /* force heap usage */
+ WOLFSSL_ENTER("wolfSSL_AES_ecb_encrypt");
+
+ if (key == NULL || in == NULL || out == NULL) {
+ WOLFSSL_MSG("Error, Null argument passed in");
+ return;
+ }
+
+ aes = (Aes*)key;
+ if (enc == AES_ENCRYPT) {
+ if (wc_AesEcbEncrypt(aes, out, in, AES_BLOCK_SIZE) != 0) {
+ WOLFSSL_MSG("Error with AES CBC encrypt");
+ }
+ }
+ else {
+ #ifdef HAVE_AES_DECRYPT
+ if (wc_AesEcbDecrypt(aes, out, in, AES_BLOCK_SIZE) != 0) {
+ WOLFSSL_MSG("Error with AES CBC decrypt");
+ }
#else
- EncryptedInfo info[1];
- byte staticBuffer[FILE_BUFFER_SIZE];
+ WOLFSSL_MSG("AES decryption not compiled in");
#endif
- byte* myBuffer = staticBuffer;
- int dynamic = 0;
- XFILE file = XBADFILE;
- long sz = 0;
- int eccKey = 0;
- WOLFSSL_CTX* ctx = ssl->ctx;
- WOLFSSL_X509* peer_cert = &ssl->peerCert;
- buffer fileDer;
+ }
+}
+#endif /* HAVE_AES_ECB */
- file = XFOPEN(fname, "rb");
- if (file == XBADFILE)
- return SSL_BAD_FILE;
+#ifdef HAVE_AES_CBC
+/* Encrypt data using key and iv passed in. iv gets updated to most recent iv
+ * state after encryption/decryption.
+ *
+ * in buffer to encrypt/decrypt
+ * out buffer to hold result of encryption/decryption
+ * len length of input buffer
+ * key AES structure to use with encryption/decryption
+ * iv iv to use with operation
+ * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption
+ */
+void wolfSSL_AES_cbc_encrypt(const unsigned char *in, unsigned char* out,
+ size_t len, AES_KEY *key, unsigned char* iv, const int enc)
+{
+ Aes* aes;
- XFSEEK(file, 0, XSEEK_END);
- sz = XFTELL(file);
- XREWIND(file);
+ WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt");
- if (sz > (long)sizeof(staticBuffer)) {
- WOLFSSL_MSG("Getting dynamic buffer");
- myBuffer = (byte*)XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE);
- dynamic = 1;
+ if (key == NULL || in == NULL || out == NULL || iv == NULL || len == 0) {
+ WOLFSSL_MSG("Error, Null argument passed in");
+ return;
+ }
+
+ aes = (Aes*)key;
+ if (wc_AesSetIV(aes, (const byte*)iv) != 0) {
+ WOLFSSL_MSG("Error with setting iv");
+ return;
+ }
+
+ if (enc == AES_ENCRYPT) {
+ if (wc_AesCbcEncrypt(aes, out, in, (word32)len) != 0) {
+ WOLFSSL_MSG("Error with AES CBC encrypt");
+ }
+ }
+ else {
+ if (wc_AesCbcDecrypt(aes, out, in, (word32)len) != 0) {
+ WOLFSSL_MSG("Error with AES CBC decrypt");
}
+ }
- #ifdef WOLFSSL_SMALL_STACK
- info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (info == NULL)
- ret = MEMORY_E;
- else
+ /* to be compatible copy iv to iv buffer after completing operation */
+ XMEMCPY(iv, (byte*)(aes->reg), AES_BLOCK_SIZE);
+}
+#endif /* HAVE_AES_CBC */
+
+
+/* Encrypt data using CFB mode with key and iv passed in. iv gets updated to
+ * most recent iv state after encryption/decryption.
+ *
+ * in buffer to encrypt/decrypt
+ * out buffer to hold result of encryption/decryption
+ * len length of input buffer
+ * key AES structure to use with encryption/decryption
+ * iv iv to use with operation
+ * num contains the amount of block used
+ * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption
+ */
+void wolfSSL_AES_cfb128_encrypt(const unsigned char *in, unsigned char* out,
+ size_t len, AES_KEY *key, unsigned char* iv, int* num,
+ const int enc)
+{
+#ifndef WOLFSSL_AES_CFB
+ WOLFSSL_MSG("CFB mode not enabled please use macro WOLFSSL_AES_CFB");
+ (void)in;
+ (void)out;
+ (void)len;
+ (void)key;
+ (void)iv;
+ (void)num;
+ (void)enc;
+
+ return;
+#else
+ Aes* aes;
+
+ WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt");
+ if (key == NULL || in == NULL || out == NULL || iv == NULL) {
+ WOLFSSL_MSG("Error, Null argument passed in");
+ return;
+ }
+
+ aes = (Aes*)key;
+ if (wc_AesSetIV(aes, (const byte*)iv) != 0) {
+ WOLFSSL_MSG("Error with setting iv");
+ return;
+ }
+
+ if (enc == AES_ENCRYPT) {
+ if (wc_AesCfbEncrypt(aes, out, in, (word32)len) != 0) {
+ WOLFSSL_MSG("Error with AES CBC encrypt");
+ }
+ }
+ else {
+ if (wc_AesCfbDecrypt(aes, out, in, (word32)len) != 0) {
+ WOLFSSL_MSG("Error with AES CBC decrypt");
+ }
+ }
+
+ /* to be compatible copy iv to iv buffer after completing operation */
+ XMEMCPY(iv, (byte*)(aes->reg), AES_BLOCK_SIZE);
+
+ /* store number of left over bytes to num */
+ *num = (aes->left)? AES_BLOCK_SIZE - aes->left : 0;
+#endif /* WOLFSSL_AES_CFB */
+}
+#endif /* NO_AES */
+
+#ifndef NO_FILESYSTEM
+ #ifdef __clang__
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wformat-nonliteral"
#endif
- {
- info->set = 0;
- info->ctx = ctx;
- info->consumed = 0;
- fileDer.buffer = 0;
-
- if ((myBuffer != NULL) &&
- (sz > 0) &&
- (XFREAD(myBuffer, sz, 1, file) > 0) &&
- (PemToDer(myBuffer, sz, CERT_TYPE,
- &fileDer, ctx->heap, info, &eccKey) == 0) &&
- (fileDer.length != 0) &&
- (fileDer.length == peer_cert->derCert.length) &&
- (XMEMCMP(peer_cert->derCert.buffer, fileDer.buffer,
- fileDer.length) == 0))
- {
- ret = 0;
+#endif
+
+#if !defined(NO_FILESYSTEM) && defined (OPENSSL_EXTRA)
+/* returns amount printed on success, negative in fail case */
+int wolfSSL_BIO_vprintf(WOLFSSL_BIO* bio, const char* format, va_list args)
+{
+ int ret = -1;
+
+ if (bio == NULL)
+ return WOLFSSL_FATAL_ERROR;
+
+ switch (bio->type) {
+ case WOLFSSL_BIO_FILE:
+ if (bio->ptr == NULL) {
+ va_end(args);
+ return -1;
}
+ ret = vfprintf((XFILE)bio->ptr, format, args);
+ break;
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- }
+ case WOLFSSL_BIO_MEMORY:
+ #if defined(OPENSSL_EXTRA) && !defined(_WIN32)
+ case WOLFSSL_BIO_SSL:
+ {
+ int count;
+ char* pt = NULL;
+ va_list copy;
- XFREE(fileDer.buffer, ctx->heap, DYNAMIC_TYPE_CERT);
- if (dynamic)
- XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE);
+ va_copy(copy, args);
+ count = vsnprintf(NULL, 0, format, args);
+ if (count >= 0)
+ {
+ pt = (char*)XMALLOC(count + 1, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (pt != NULL)
+ {
+ count = vsnprintf(pt, count + 1, format, copy);
+ if (count >= 0)
+ {
+ ret = wolfSSL_BIO_write(bio, pt, count);
+ }
+ XFREE(pt, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ }
+ va_end(copy);
+ }
+ break;
+ #endif
- XFCLOSE(file);
+ default:
+ WOLFSSL_MSG("Unsupported WOLFSSL_BIO type for wolfSSL_BIO_printf");
+ break;
}
return ret;
}
-#endif
+/* returns amount printed on success, negative in fail case */
+int wolfSSL_BIO_printf(WOLFSSL_BIO* bio, const char* format, ...)
+{
+ int ret;
+ va_list args;
+ va_start(args, format);
-static RNG globalRNG;
-static int initGlobalRNG = 0;
+ ret = wolfSSL_BIO_vprintf(bio, format, args);
-/* SSL_SUCCESS on ok */
-int wolfSSL_RAND_seed(const void* seed, int len)
+ va_end(args);
+
+ return ret;
+}
+
+#endif /* !defined(NO_FILESYSTEM) && defined (OPENSSL_EXTRA) */
+
+#if !defined(NO_FILESYSTEM) && defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
+#undef LINE_LEN
+#define LINE_LEN 16
+int wolfSSL_BIO_dump(WOLFSSL_BIO *bio, const char *buf, int length)
{
+ int ret = 0;
- WOLFSSL_MSG("wolfSSL_RAND_seed");
+ if (bio == NULL)
+ return 0;
- (void)seed;
- (void)len;
+#ifndef NO_FILESYSTEM
+ if (bio->type == WOLFSSL_BIO_FILE) {
+ int i;
+ char line[80];
- if (initGlobalRNG == 0) {
- if (wc_InitRng(&globalRNG) < 0) {
- WOLFSSL_MSG("wolfSSL Init Global RNG failed");
- return 0;
+ if (!buf) {
+ return fputs("\tNULL", (XFILE)bio->ptr);
}
- initGlobalRNG = 1;
+
+ sprintf(line, "\t");
+ for (i = 0; i < LINE_LEN; i++) {
+ if (i < length)
+ sprintf(line + 1 + i * 3,"%02x ", buf[i]);
+ else
+ sprintf(line + 1 + i * 3, " ");
+ }
+ sprintf(line + 1 + LINE_LEN * 3, "| ");
+ for (i = 0; i < LINE_LEN; i++) {
+ if (i < length) {
+ sprintf(line + 3 + LINE_LEN * 3 + i,
+ "%c", 31 < buf[i] && buf[i] < 127 ? buf[i] : '.');
+ }
+ }
+ ret += fputs(line, (XFILE)bio->ptr);
+
+ if (length > LINE_LEN)
+ ret += wolfSSL_BIO_dump(bio, buf + LINE_LEN, length - LINE_LEN);
}
+#else
+ (void)buf;
+ (void)length;
+#endif
- return SSL_SUCCESS;
+ return ret;
}
-
-/* SSL_SUCCESS on ok */
-int wolfSSL_RAND_bytes(unsigned char* buf, int num)
+#ifndef NO_ASN_TIME
+int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a)
{
- int ret = 0;
- int initTmpRng = 0;
- RNG* rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- RNG* tmpRNG = NULL;
-#else
- RNG tmpRNG[1];
-#endif
+ WOLFSSL_ENTER("ASN1_UTCTIME_print");
+ if (bio == NULL || a == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+ if (a->type != ASN_UTC_TIME) {
+ WOLFSSL_MSG("Error, not UTC_TIME");
+ return WOLFSSL_FAILURE;
+ }
- WOLFSSL_ENTER("RAND_bytes");
+ return wolfSSL_ASN1_TIME_print(bio, a);
+}
-#ifdef WOLFSSL_SMALL_STACK
- tmpRNG = (RNG*)XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (tmpRNG == NULL)
- return ret;
-#endif
+/* Checks the ASN1 syntax of "a"
+ * returns WOLFSSL_SUCCESS (1) if correct otherwise WOLFSSL_FAILURE (0) */
+int wolfSSL_ASN1_TIME_check(const WOLFSSL_ASN1_TIME* a)
+{
+ char buf[MAX_TIME_STRING_SZ];
- if (wc_InitRng(tmpRNG) == 0) {
- rng = tmpRNG;
- initTmpRng = 1;
- }
- else if (initGlobalRNG)
- rng = &globalRNG;
+ WOLFSSL_ENTER("wolfSSL_ASN1_TIME_check");
- if (rng) {
- if (wc_RNG_GenerateBlock(rng, buf, num) != 0)
- WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
- else
- ret = SSL_SUCCESS;
+ /* if can parse the WOLFSSL_ASN1_TIME passed in then consider syntax good */
+ if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)a, buf,
+ MAX_TIME_STRING_SZ) == NULL) {
+ return WOLFSSL_FAILURE;
}
+ return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_ASN_TIME */
- if (initTmpRng)
- wc_FreeRng(tmpRNG);
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_ASN1_TIME_diff(int *pday, int *psec,
+ const WOLFSSL_ASN1_TIME *from, const WOLFSSL_ASN1_TIME *to)
+{
+ WOLFSSL_STUB("wolfSSL_ASN1_TIME_diff");
+ (void)pday;
+ (void)psec;
+ (void)from;
+ (void)to;
+ return 0;
+}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_set(WOLFSSL_ASN1_TIME *s, time_t t)
+{
+ WOLFSSL_STUB("wolfSSL_ASN1_TIME_set");
+ (void)s;
+ (void)t;
+ return s;
+}
+#endif /* !NO_WOLFSSL_STUB */
- return ret;
+/* Return the month as a string.
+ *
+ * n The number of the month as a two characters (1 based).
+ * returns the month as a string.
+ */
+static WC_INLINE const char* MonthStr(const char* n)
+{
+ static const char monthStr[12][4] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+ return monthStr[(n[0] - '0') * 10 + (n[1] - '0') - 1];
}
-WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void)
+int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO* bio,
+ const WOLFSSL_ASN1_GENERALIZEDTIME* asnTime)
{
- static int ctx; /* wolfcrypt doesn't now need ctx */
+ const char* p;
+ WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_print");
- WOLFSSL_MSG("wolfSSL_BN_CTX_new");
+ if (bio == NULL || asnTime == NULL)
+ return BAD_FUNC_ARG;
- return (WOLFSSL_BN_CTX*)&ctx;
+ if (asnTime->type != ASN_GENERALIZED_TIME) {
+ WOLFSSL_MSG("Error, not GENERALIZED_TIME");
+ return WOLFSSL_FAILURE;
+ }
+ p = (const char *)(asnTime->data);
+ /* GetTimeString not always available. */
+ wolfSSL_BIO_write(bio, MonthStr(p + 4), 3);
+ wolfSSL_BIO_write(bio, " ", 1);
+ /* Day */
+ wolfSSL_BIO_write(bio, p + 6, 2);
+ wolfSSL_BIO_write(bio, " ", 1);
+ /* Hour */
+ wolfSSL_BIO_write(bio, p + 8, 2);
+ wolfSSL_BIO_write(bio, ":", 1);
+ /* Min */
+ wolfSSL_BIO_write(bio, p + 10, 2);
+ wolfSSL_BIO_write(bio, ":", 1);
+ /* Secs */
+ wolfSSL_BIO_write(bio, p + 12, 2);
+ wolfSSL_BIO_write(bio, " ", 1);
+ wolfSSL_BIO_write(bio, p, 4);
+
+ return 0;
}
-void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx)
+void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_TIME* asn1Time)
{
- (void)ctx;
- WOLFSSL_MSG("wolfSSL_BN_CTX_init");
+ WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_free");
+ if (asn1Time == NULL)
+ return;
+ XMEMSET(asn1Time->data, 0, sizeof(asn1Time->data));
}
+int wolfSSL_sk_num(WOLFSSL_STACK* sk)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_num");
+ if (sk == NULL)
+ return 0;
+ return (int)sk->num;
+}
-void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx)
+void* wolfSSL_sk_value(WOLFSSL_STACK* sk, int i)
{
- (void)ctx;
- WOLFSSL_MSG("wolfSSL_BN_CTX_free");
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ int offset = i;
+#endif
+ WOLFSSL_ENTER("wolfSSL_sk_value");
- /* do free since static ctx that does nothing */
-}
+ for (; sk != NULL && i > 0; i--)
+ sk = sk->next;
+ if (sk == NULL)
+ return NULL;
+ switch (sk->type) {
+ case STACK_TYPE_X509:
+ return (void*)sk->data.x509;
+ case STACK_TYPE_CIPHER:
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ sk->data.cipher.offset = offset;
+ #endif
+ return (void*)&sk->data.cipher;
+ case STACK_TYPE_GEN_NAME:
+ return (void*)sk->data.gn;
+ case STACK_TYPE_ACCESS_DESCRIPTION:
+ return (void*)sk->data.access;
+ case STACK_TYPE_OBJ:
+ return (void*)sk->data.obj;
+ case STACK_TYPE_X509_EXT:
+ return (void*)sk->data.ext;
+ case STACK_TYPE_CONF_VALUE:
+ return (void*)sk->data.conf->value;
+ case STACK_TYPE_NULL:
+ default:
+ return (void*)sk->data.generic;
+ }
+}
-static void InitwolfSSL_BigNum(WOLFSSL_BIGNUM* bn)
+/* Free the structure for ASN1_OBJECT stack */
+void wolfSSL_sk_free(WOLFSSL_STACK* sk)
{
- WOLFSSL_MSG("InitwolfSSL_BigNum");
- if (bn) {
- bn->neg = 0;
- bn->internal = NULL;
+ WOLFSSL_ENTER("wolfSSL_sk_free");
+
+ if (sk == NULL) {
+ WOLFSSL_MSG("Error, BAD_FUNC_ARG");
+ return;
+ }
+
+ switch (sk->type) {
+ case STACK_TYPE_X509:
+ wolfSSL_sk_X509_free(sk);
+ break;
+ #if defined(OPENSSL_ALL)
+ case STACK_TYPE_CIPHER:
+ wolfSSL_sk_CIPHER_free(sk);
+ break;
+ #endif
+ case STACK_TYPE_GEN_NAME:
+ wolfSSL_sk_GENERAL_NAME_free(sk);
+ break;
+ #if defined(OPENSSL_ALL) || defined (WOLFSSL_QT)
+ case STACK_TYPE_ACCESS_DESCRIPTION:
+ wolfSSL_sk_ACCESS_DESCRIPTION_free(sk);
+ break;
+ #endif
+ case STACK_TYPE_OBJ:
+ wolfSSL_sk_ASN1_OBJECT_free(sk);
+ break;
+ #ifdef OPENSSL_ALL
+ case STACK_TYPE_X509_INFO:
+ wolfSSL_sk_X509_INFO_free(sk);
+ break;
+ case STACK_TYPE_X509_NAME:
+ wolfSSL_sk_X509_NAME_free(sk);
+ break;
+ case STACK_TYPE_CONF_VALUE:
+ wolfSSL_sk_CONF_VALUE_free(sk);
+ break;
+ #endif
+ case STACK_TYPE_NULL:
+ default:
+ wolfSSL_sk_GENERIC_free(sk);
}
}
+/* Frees each node in the stack and frees the stack.
+ * Does not free any internal members of the stack nodes.
+ */
+void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk,
+ void (*f) (void*))
+{
+ WOLFSSL_STACK* node;
+ WOLFSSL_STACK* tmp;
+ WOLFSSL_ENTER("wolfSSL_sk_GENERIC_pop_free");
+ if (sk == NULL)
+ return;
-WOLFSSL_BIGNUM* wolfSSL_BN_new(void)
+ /* parse through stack freeing each node */
+ node = sk->next;
+ while (node) {
+ tmp = node;
+ node = node->next;
+ if (f)
+ f(tmp->data.generic);
+ tmp->data.generic = NULL;
+ XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+
+ /* free head of stack */
+ XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
+}
+
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK* sk, void* generic)
{
- WOLFSSL_BIGNUM* external;
- mp_int* mpi;
+ WOLFSSL_STACK* node;
- WOLFSSL_MSG("wolfSSL_BN_new");
+ WOLFSSL_ENTER("wolfSSL_sk_GENERIC_push");
- mpi = (mp_int*) XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
- if (mpi == NULL) {
- WOLFSSL_MSG("wolfSSL_BN_new malloc mpi failure");
- return NULL;
+ if (sk == NULL || generic == NULL) {
+ return WOLFSSL_FAILURE;
}
- external = (WOLFSSL_BIGNUM*) XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL,
- DYNAMIC_TYPE_BIGINT);
- if (external == NULL) {
- WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure");
- XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT);
- return NULL;
+ /* no previous values in stack */
+ if (sk->data.generic == NULL) {
+ sk->data.generic = generic;
+ sk->num += 1;
+ return WOLFSSL_SUCCESS;
}
- InitwolfSSL_BigNum(external);
- external->internal = mpi;
- if (mp_init(mpi) != MP_OKAY) {
- wolfSSL_BN_free(external);
- return NULL;
+ /* stack already has value(s) create a new node and add more */
+ node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK),NULL,DYNAMIC_TYPE_SSL);
+ if (node == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return WOLFSSL_FAILURE;
}
+ XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
- return external;
+ /* push new node onto head of stack */
+ node->type = sk->type;
+ node->data.generic = sk->data.generic;
+ node->next = sk->next;
+ sk->next = node;
+ sk->data.generic = generic;
+ sk->num += 1;
+
+ return WOLFSSL_SUCCESS;
+}
+void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK* sk)
+{
+ wolfSSL_sk_GENERIC_pop_free(sk, NULL);
}
-void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn)
+/* Free all nodes in a stack */
+void wolfSSL_sk_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk,
+ wolfSSL_sk_freefunc func)
{
- WOLFSSL_MSG("wolfSSL_BN_free");
- if (bn) {
- if (bn->internal) {
- mp_clear((mp_int*)bn->internal);
- XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT);
- bn->internal = NULL;
- }
- XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT);
+ WOLFSSL_ENTER("wolfSSL_sk_pop_free");
+
+ if (sk == NULL) {
+ WOLFSSL_MSG("Error, BAD_FUNC_ARG");
+ return;
+ }
+
+ switch(sk->type) {
+ #if defined(OPENSSL_ALL) || defined (WOLFSSL_QT)
+ case STACK_TYPE_ACCESS_DESCRIPTION:
+ wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(sk,
+ wolfSSL_ACCESS_DESCRIPTION_free);
+ break;
+ #endif
+ case STACK_TYPE_X509:
+ wolfSSL_sk_X509_pop_free(sk,(void (*)(WOLFSSL_X509*))func);
+ break;
+ case STACK_TYPE_OBJ:
+ wolfSSL_sk_ASN1_OBJECT_pop_free(sk,
+ (void (*)(WOLFSSL_ASN1_OBJECT*))func);
+ break;
+ case STACK_TYPE_GEN_NAME:
+ wolfSSL_sk_GENERAL_NAME_pop_free(sk,
+ (void (*)(WOLFSSL_GENERAL_NAME*))func);
+ break;
+ #ifdef OPENSSL_ALL
+ case STACK_TYPE_X509_NAME:
+ wolfSSL_sk_X509_NAME_pop_free(sk,
+ (void (*)(WOLFSSL_X509_NAME*))func);
+ break;
+ case STACK_TYPE_X509_EXT:
+ wolfSSL_sk_X509_EXTENSION_pop_free(sk,
+ (void (*)(WOLFSSL_X509_EXTENSION*))func);
+ break;
+ #endif
+ #if defined(OPENSSL_ALL)
+ case STACK_TYPE_X509_INFO:
+ wolfSSL_sk_X509_INFO_pop_free(sk,
+ (void (*)(WOLFSSL_X509_INFO*))func);
+ break;
+ #endif
+ default:
+ wolfSSL_sk_GENERIC_pop_free(sk,
+ (void (*)(void*))func);
+ break;
}
}
+#if defined(OPENSSL_ALL)
+/* Free the structure for WOLFSSL_CONF_VALUE stack
+ *
+ * sk stack to free nodes in
+ */
+void wolfSSL_sk_CONF_VALUE_free(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk)
+{
+ WOLFSSL_STACK* node;
+ WOLFSSL_STACK* tmp;
+ WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_free");
-void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn)
+ if (sk == NULL)
+ return;
+
+ /* parse through stack freeing each node */
+ node = sk->next;
+ while (node) {
+ tmp = node;
+ node = node->next;
+ XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+
+ /* free head of stack */
+ XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
+}
+#endif
+
+/* Creates and returns a new null stack. */
+WOLFSSL_STACK* wolfSSL_sk_new_null(void)
{
- WOLFSSL_MSG("wolfSSL_BN_clear_free");
+ WOLFSSL_STACK* sk;
+ WOLFSSL_ENTER("wolfSSL_sk_new_null");
- wolfSSL_BN_free(bn);
+ sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (sk == NULL) {
+ WOLFSSL_MSG("WOLFSSL_STACK memory error");
+ return NULL;
+ }
+
+ XMEMSET(sk, 0, sizeof(WOLFSSL_STACK));
+ sk->type = STACK_TYPE_NULL;
+
+ return sk;
}
+/* frees the wolfSSL_BASIC_CONSTRAINTS object */
+void wolfSSL_BASIC_CONSTRAINTS_free(WOLFSSL_BASIC_CONSTRAINTS *bc)
+{
+ WOLFSSL_ENTER("wolfSSL_BASIC_CONSTRAINTS_free");
+ if (bc == NULL) {
+ WOLFSSL_MSG("Argument is NULL");
+ return;
+ }
+ if (bc->pathlen) {
+ wolfSSL_ASN1_INTEGER_free(bc->pathlen);
+ }
+ XFREE(bc, NULL, DYNAMIC_TYPE_OPENSSL);
+}
-/* SSL_SUCCESS on ok */
-int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
- const WOLFSSL_BIGNUM* b)
+/* frees the wolfSSL_AUTHORITY_KEYID object */
+void wolfSSL_AUTHORITY_KEYID_free(WOLFSSL_AUTHORITY_KEYID *id)
{
- WOLFSSL_MSG("wolfSSL_BN_sub");
+ WOLFSSL_ENTER("wolfSSL_AUTHORITY_KEYID_free");
+ if(id == NULL) {
+ WOLFSSL_MSG("Argument is NULL");
+ return;
+ }
+ if (id->keyid) {
+ wolfSSL_ASN1_STRING_free(id->keyid);
+ }
+ if (id->issuer) {
+ wolfSSL_ASN1_OBJECT_free(id->issuer);
+ }
+ if (id->serial) {
+ wolfSSL_ASN1_INTEGER_free(id->serial);
+ }
+ XFREE(id, NULL, DYNAMIC_TYPE_OPENSSL);
+}
- if (r == NULL || a == NULL || b == NULL)
+int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* sk)
+{
+ if (sk == NULL)
return 0;
+ return (int)sk->num;
+}
- if (mp_sub((mp_int*)a->internal,(mp_int*)b->internal,
- (mp_int*)r->internal) == MP_OKAY)
- return SSL_SUCCESS;
+#endif /* OPENSSL_EXTRA */
- WOLFSSL_MSG("wolfSSL_BN_sub mp_sub failed");
- return 0;
-}
+#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE)
+/* stunnel 4.28 needs
+ *
+ * Callback that is called if a session tries to resume but could not find
+ * the session to resume it.
+ */
+void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx,
+ WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*))
+{
+ if (ctx == NULL)
+ return;
+#ifdef HAVE_EXT_CACHE
+ ctx->get_sess_cb = f;
+#else
+ (void)f;
+#endif
+}
-/* SSL_SUCCESS on ok */
-int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
- const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c)
+void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx,
+ int (*f)(WOLFSSL*, WOLFSSL_SESSION*))
{
- (void)c;
- WOLFSSL_MSG("wolfSSL_BN_mod");
+ if (ctx == NULL)
+ return;
- if (r == NULL || a == NULL || b == NULL)
- return 0;
+#ifdef HAVE_EXT_CACHE
+ ctx->new_sess_cb = f;
+#else
+ (void)f;
+#endif
+}
- if (mp_mod((mp_int*)a->internal,(mp_int*)b->internal,
- (mp_int*)r->internal) == MP_OKAY)
- return SSL_SUCCESS;
+void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*,
+ WOLFSSL_SESSION*))
+{
+ if (ctx == NULL)
+ return;
- WOLFSSL_MSG("wolfSSL_BN_mod mp_mod failed");
- return 0;
+#ifdef HAVE_EXT_CACHE
+ ctx->rem_sess_cb = f;
+#else
+ (void)f;
+#endif
}
+#endif /* OPENSSL_EXTRA || HAVE_EXT_CACHE */
+#ifdef OPENSSL_EXTRA
-const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void)
+/*
+ *
+ * Note: It is expected that the importing and exporting function have been
+ * built with the same settings. For example if session tickets was
+ * enabled with the wolfSSL library exporting a session then it is
+ * expected to be turned on with the wolfSSL library importing the session.
+ */
+int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p)
{
- static WOLFSSL_BIGNUM* bn_one = NULL;
+ int size = 0;
+#ifdef HAVE_EXT_CACHE
+ int idx = 0;
+#ifdef SESSION_CERTS
+ int i;
+#endif
+ unsigned char *data;
- WOLFSSL_MSG("wolfSSL_BN_value_one");
+ if (sess == NULL) {
+ return BAD_FUNC_ARG;
+ }
- if (bn_one == NULL) {
- bn_one = wolfSSL_BN_new();
- if (bn_one)
- mp_set_int((mp_int*)bn_one->internal, 1);
+ /* bornOn | timeout | sessionID len | sessionID | masterSecret | haveEMS */
+ size += OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN + sess->sessionIDSz +
+ SECRET_LEN + OPAQUE8_LEN;
+#ifdef SESSION_CERTS
+ /* Peer chain */
+ size += OPAQUE8_LEN;
+ for (i = 0; i < sess->chain.count; i++)
+ size += OPAQUE16_LEN + sess->chain.certs[i].length;
+#endif
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+ defined(HAVE_SESSION_TICKET))
+ /* Protocol version */
+ size += OPAQUE16_LEN;
+#endif
+#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
+ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+ /* cipher suite */
+ size += OPAQUE16_LEN;
+#endif
+#ifndef NO_CLIENT_CACHE
+ /* ServerID len | ServerID */
+ size += OPAQUE16_LEN + sess->idLen;
+#endif
+#ifdef OPENSSL_EXTRA
+ /* session context ID len | session context ID */
+ size += OPAQUE8_LEN + sess->sessionCtxSz;
+#endif
+#ifdef WOLFSSL_TLS13
+ /* namedGroup */
+ size += OPAQUE16_LEN;
+#endif
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+#ifdef WOLFSSL_TLS13
+ /* ticketSeen | ticketAdd */
+ size += OPAQUE32_LEN + OPAQUE32_LEN;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+ /* ticketNonce */
+ size += OPAQUE8_LEN + sess->ticketNonce.len;
+#endif
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+ size += OPAQUE32_LEN;
+#endif
+#endif
+#ifdef HAVE_SESSION_TICKET
+ /* ticket len | ticket */
+ size += OPAQUE16_LEN + sess->ticketLen;
+#endif
+
+ if (p != NULL) {
+ if (*p == NULL)
+ *p = (unsigned char*)XMALLOC(size, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (*p == NULL)
+ return 0;
+ data = *p;
+
+ c32toa(sess->bornOn, data + idx); idx += OPAQUE32_LEN;
+ c32toa(sess->timeout, data + idx); idx += OPAQUE32_LEN;
+ data[idx++] = sess->sessionIDSz;
+ XMEMCPY(data + idx, sess->sessionID, sess->sessionIDSz);
+ idx += sess->sessionIDSz;
+ XMEMCPY(data + idx, sess->masterSecret, SECRET_LEN); idx += SECRET_LEN;
+ data[idx++] = (byte)sess->haveEMS;
+#ifdef SESSION_CERTS
+ data[idx++] = (byte)sess->chain.count;
+ for (i = 0; i < sess->chain.count; i++) {
+ c16toa((word16)sess->chain.certs[i].length, data + idx);
+ idx += OPAQUE16_LEN;
+ XMEMCPY(data + idx, sess->chain.certs[i].buffer,
+ sess->chain.certs[i].length);
+ idx += sess->chain.certs[i].length;
+ }
+#endif
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+ defined(HAVE_SESSION_TICKET))
+ data[idx++] = sess->version.major;
+ data[idx++] = sess->version.minor;
+#endif
+#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
+ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+ data[idx++] = sess->cipherSuite0;
+ data[idx++] = sess->cipherSuite;
+#endif
+#ifndef NO_CLIENT_CACHE
+ c16toa(sess->idLen, data + idx); idx += OPAQUE16_LEN;
+ XMEMCPY(data + idx, sess->serverID, sess->idLen);
+ idx += sess->idLen;
+#endif
+#ifdef OPENSSL_EXTRA
+ data[idx++] = sess->sessionCtxSz;
+ XMEMCPY(data + idx, sess->sessionCtx, sess->sessionCtxSz);
+ idx += sess->sessionCtxSz;
+#endif
+#ifdef WOLFSSL_TLS13
+ c16toa(sess->namedGroup, data + idx);
+ idx += OPAQUE16_LEN;
+#endif
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+#ifdef WOLFSSL_TLS13
+ c32toa(sess->ticketSeen, data + idx);
+ idx += OPAQUE32_LEN;
+ c32toa(sess->ticketAdd, data + idx);
+ idx += OPAQUE32_LEN;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+ data[idx++] = sess->ticketNonce.len;
+ XMEMCPY(data + idx, sess->ticketNonce.data, sess->ticketNonce.len);
+ idx += sess->ticketNonce.len;
+#endif
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+ c32toa(sess->maxEarlyDataSz, data + idx);
+ idx += OPAQUE32_LEN;
+#endif
+#endif
+#ifdef HAVE_SESSION_TICKET
+ c16toa(sess->ticketLen, data + idx); idx += OPAQUE16_LEN;
+ XMEMCPY(data + idx, sess->ticket, sess->ticketLen);
+ idx += sess->ticketLen;
+#endif
}
+#endif
- return bn_one;
+ (void)sess;
+ (void)p;
+#ifdef HAVE_EXT_CACHE
+ (void)idx;
+#endif
+
+ return size;
}
-int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn)
+/* TODO: no function to free new session.
+ *
+ * Note: It is expected that the importing and exporting function have been
+ * built with the same settings. For example if session tickets was
+ * enabled with the wolfSSL library exporting a session then it is
+ * expected to be turned on with the wolfSSL library importing the session.
+ */
+WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess,
+ const unsigned char** p, long i)
{
- WOLFSSL_MSG("wolfSSL_BN_num_bytes");
+ WOLFSSL_SESSION* s = NULL;
+ int ret = 0;
+#if defined(HAVE_EXT_CACHE)
+ int idx;
+ byte* data;
+#ifdef SESSION_CERTS
+ int j;
+ word16 length;
+#endif
+#endif
- if (bn == NULL || bn->internal == NULL)
- return 0;
+ (void)p;
+ (void)i;
+ (void)ret;
- return mp_unsigned_bin_size((mp_int*)bn->internal);
+ if (sess != NULL)
+ s = *sess;
+
+#ifdef HAVE_EXT_CACHE
+ if (p == NULL || *p == NULL)
+ return NULL;
+
+ if (s == NULL) {
+ s = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (s == NULL)
+ return NULL;
+ XMEMSET(s, 0, sizeof(WOLFSSL_SESSION));
+ s->isAlloced = 1;
+#ifdef HAVE_SESSION_TICKET
+ s->isDynamic = 0;
+#endif
+ }
+
+ idx = 0;
+ data = (byte*)*p;
+
+ /* bornOn | timeout | sessionID len */
+ if (i < OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ ato32(data + idx, &s->bornOn); idx += OPAQUE32_LEN;
+ ato32(data + idx, &s->timeout); idx += OPAQUE32_LEN;
+ s->sessionIDSz = data[idx++];
+
+ /* sessionID | secret | haveEMS */
+ if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_LEN) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ XMEMCPY(s->sessionID, data + idx, s->sessionIDSz);
+ idx += s->sessionIDSz;
+ XMEMCPY(s->masterSecret, data + idx, SECRET_LEN); idx += SECRET_LEN;
+ s->haveEMS = data[idx++];
+
+#ifdef SESSION_CERTS
+ /* Certificate chain */
+ if (i - idx == 0) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ s->chain.count = data[idx++];
+ for (j = 0; j < s->chain.count; j++) {
+ if (i - idx < OPAQUE16_LEN) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ ato16(data + idx, &length); idx += OPAQUE16_LEN;
+ s->chain.certs[j].length = length;
+ if (i - idx < length) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ XMEMCPY(s->chain.certs[j].buffer, data + idx, length);
+ idx += length;
+ }
+#endif
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+ defined(HAVE_SESSION_TICKET))
+ /* Protocol Version */
+ if (i - idx < OPAQUE16_LEN) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ s->version.major = data[idx++];
+ s->version.minor = data[idx++];
+#endif
+#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
+ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+ /* Cipher suite */
+ if (i - idx < OPAQUE16_LEN) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ s->cipherSuite0 = data[idx++];
+ s->cipherSuite = data[idx++];
+#endif
+#ifndef NO_CLIENT_CACHE
+ /* ServerID len */
+ if (i - idx < OPAQUE16_LEN) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ ato16(data + idx, &s->idLen); idx += OPAQUE16_LEN;
+
+ /* ServerID */
+ if (i - idx < s->idLen) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ XMEMCPY(s->serverID, data + idx, s->idLen); idx += s->idLen;
+#endif
+#ifdef OPENSSL_EXTRA
+ /* byte for length of session context ID */
+ if (i - idx < OPAQUE8_LEN) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ s->sessionCtxSz = data[idx++];
+
+ /* app session context ID */
+ if (i - idx < s->sessionCtxSz) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ XMEMCPY(s->sessionCtx, data + idx, s->sessionCtxSz); idx += s->sessionCtxSz;
+#endif
+#ifdef WOLFSSL_TLS13
+ if (i - idx < OPAQUE16_LEN) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ ato16(data + idx, &s->namedGroup);
+ idx += OPAQUE16_LEN;
+#endif
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+#ifdef WOLFSSL_TLS13
+ if (i - idx < (OPAQUE32_LEN * 2)) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ ato32(data + idx, &s->ticketSeen);
+ idx += OPAQUE32_LEN;
+ ato32(data + idx, &s->ticketAdd);
+ idx += OPAQUE32_LEN;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+ if (i - idx < OPAQUE8_LEN) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ s->ticketNonce.len = data[idx++];
+
+ if (i - idx < s->ticketNonce.len) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ XMEMCPY(s->ticketNonce.data, data + idx, s->ticketNonce.len);
+ idx += s->ticketNonce.len;
+#endif
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+ if (i - idx < OPAQUE32_LEN) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ ato32(data + idx, &s->maxEarlyDataSz);
+ idx += OPAQUE32_LEN;
+#endif
+#endif
+#ifdef HAVE_SESSION_TICKET
+ /* ticket len */
+ if (i - idx < OPAQUE16_LEN) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ ato16(data + idx, &s->ticketLen); idx += OPAQUE16_LEN;
+
+ /* Dispose of ol dynamic ticket and ensure space for new ticket. */
+ if (s->isDynamic)
+ XFREE(s->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK);
+ if (s->ticketLen <= SESSION_TICKET_LEN)
+ s->ticket = s->staticTicket;
+ else {
+ s->ticket = (byte*)XMALLOC(s->ticketLen, NULL,
+ DYNAMIC_TYPE_SESSION_TICK);
+ if (s->ticket == NULL) {
+ ret = MEMORY_ERROR;
+ goto end;
+ }
+ s->isDynamic = 1;
+ }
+
+ /* ticket */
+ if (i - idx < s->ticketLen) {
+ ret = BUFFER_ERROR;
+ goto end;
+ }
+ XMEMCPY(s->ticket, data + idx, s->ticketLen); idx += s->ticketLen;
+#endif
+ (void)idx;
+
+ if (sess != NULL)
+ *sess = s;
+
+ *p += idx;
+
+end:
+ if (ret != 0 && (sess == NULL || *sess != s))
+ wolfSSL_SESSION_free(s);
+#endif
+ return s;
}
-int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn)
+long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess)
{
- WOLFSSL_MSG("wolfSSL_BN_num_bits");
+ long timeout = 0;
+ WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout");
+ if (sess)
+ timeout = sess->timeout;
+ return timeout;
+}
- if (bn == NULL || bn->internal == NULL)
- return 0;
- return mp_count_bits((mp_int*)bn->internal);
+long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess)
+{
+ long bornOn = 0;
+ WOLFSSL_ENTER("wolfSSL_SESSION_get_time");
+ if (sess)
+ bornOn = sess->bornOn;
+ return bornOn;
}
-int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn)
-{
- WOLFSSL_MSG("wolfSSL_BN_is_zero");
+#endif /* OPENSSL_EXTRA */
- if (bn == NULL || bn->internal == NULL)
- return 0;
- return mp_iszero((mp_int*)bn->internal);
+#ifdef KEEP_PEER_CERT
+char* wolfSSL_X509_get_subjectCN(WOLFSSL_X509* x509)
+{
+ if (x509 == NULL)
+ return NULL;
+
+ return x509->subjectCN;
}
+#endif /* KEEP_PEER_CERT */
+#ifdef OPENSSL_EXTRA
-int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn)
+#if defined(FORTRESS) && !defined(NO_FILESYSTEM)
+int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname)
{
- WOLFSSL_MSG("wolfSSL_BN_is_one");
+ int ret = WOLFSSL_FATAL_ERROR;
- if (bn == NULL || bn->internal == NULL)
- return 0;
+ WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file");
+ if (ssl != NULL && fname != NULL)
+ {
+ #ifdef WOLFSSL_SMALL_STACK
+ byte staticBuffer[1]; /* force heap usage */
+ #else
+ byte staticBuffer[FILE_BUFFER_SIZE];
+ #endif
+ byte* myBuffer = staticBuffer;
+ int dynamic = 0;
+ XFILE file;
+ long sz = 0;
+ WOLFSSL_CTX* ctx = ssl->ctx;
+ WOLFSSL_X509* peer_cert = &ssl->peerCert;
+ DerBuffer* fileDer = NULL;
- if (mp_cmp_d((mp_int*)bn->internal, 1) == 0)
- return 1;
+ file = XFOPEN(fname, "rb");
+ if (file == XBADFILE)
+ return WOLFSSL_BAD_FILE;
- return 0;
+ if (XFSEEK(file, 0, XSEEK_END) != 0) {
+ XFCLOSE(file);
+ return WOLFSSL_BAD_FILE;
+ }
+ sz = XFTELL(file);
+ XREWIND(file);
+
+ if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) {
+ WOLFSSL_MSG("cmp_peer_cert_to_file size error");
+ XFCLOSE(file);
+ return WOLFSSL_BAD_FILE;
+ }
+
+ if (sz > (long)sizeof(staticBuffer)) {
+ WOLFSSL_MSG("Getting dynamic buffer");
+ myBuffer = (byte*)XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE);
+ dynamic = 1;
+ }
+
+ if ((myBuffer != NULL) &&
+ (sz > 0) &&
+ (XFREAD(myBuffer, 1, sz, file) == (size_t)sz) &&
+ (PemToDer(myBuffer, (long)sz, CERT_TYPE,
+ &fileDer, ctx->heap, NULL, NULL) == 0) &&
+ (fileDer->length != 0) &&
+ (fileDer->length == peer_cert->derCert->length) &&
+ (XMEMCMP(peer_cert->derCert->buffer, fileDer->buffer,
+ fileDer->length) == 0))
+ {
+ ret = 0;
+ }
+
+ FreeDer(&fileDer);
+
+ if (dynamic)
+ XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE);
+
+ XFCLOSE(file);
+ }
+
+ return ret;
}
+#endif
+#endif /* OPENSSL_EXTRA */
+#endif /* !WOLFCRYPT_ONLY */
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+const WOLFSSL_ObjectInfo wolfssl_object_info[] = {
+#ifndef NO_CERTS
+ /* oidCertExtType */
+ { NID_basic_constraints, BASIC_CA_OID, oidCertExtType, "basicConstraints",
+ "X509v3 Basic Constraints"},
+ { NID_subject_alt_name, ALT_NAMES_OID, oidCertExtType, "subjectAltName",
+ "X509v3 Subject Alternative Name"},
+ { CRL_DIST_OID, CRL_DIST_OID, oidCertExtType, "crlDistributionPoints",
+ "X509v3 CRL Distribution Points"},
+ { NID_info_access, AUTH_INFO_OID, oidCertExtType, "authorityInfoAccess",
+ "Authority Information Access"},
+ { NID_authority_key_identifier, AUTH_KEY_OID, oidCertExtType,
+ "authorityKeyIdentifier", "X509v3 Authority Key Identifier"},
+ { NID_subject_key_identifier, SUBJ_KEY_OID, oidCertExtType,
+ "subjectKeyIdentifier", "X509v3 Subject Key Identifier"},
+ { NID_key_usage, KEY_USAGE_OID, oidCertExtType, "keyUsage",
+ "X509v3 Key Usage"},
+ { NID_inhibit_any_policy, INHIBIT_ANY_OID, oidCertExtType,
+ "inhibitAnyPolicy", "X509v3 Inhibit Any Policy"},
+ { NID_ext_key_usage, KEY_USAGE_OID, oidCertExtType,
+ "extendedKeyUsage", "X509v3 Extended Key Usage"},
+ { NID_name_constraints, NAME_CONS_OID, oidCertExtType,
+ "nameConstraints", "X509v3 Name Constraints"},
+ { NID_certificate_policies, CERT_POLICY_OID, oidCertExtType,
+ "certificatePolicies", "X509v3 Certificate Policies"},
+
+ /* oidCertAuthInfoType */
+ { AIA_OCSP_OID, AIA_OCSP_OID, oidCertAuthInfoType, "authorityInfoAccess",
+ "Authority Information Access"},
+ { AIA_CA_ISSUER_OID, AIA_CA_ISSUER_OID, oidCertAuthInfoType,
+ "caIssuers", "CA Issuers"},
+
+ /* oidCertPolicyType */
+ { NID_any_policy, CP_ANY_OID, oidCertPolicyType, "anyPolicy",
+ "X509v3 Any Policy"},
+
+ /* oidCertAltNameType */
+ { NID_hw_name_oid, HW_NAME_OID, oidCertAltNameType, "Hardware name",""},
+
+ /* oidCertKeyUseType */
+ { NID_anyExtendedKeyUsage, EKU_ANY_OID, oidCertKeyUseType,
+ "anyExtendedKeyUsage", "Any Extended Key Usage"},
+ { EKU_SERVER_AUTH_OID, EKU_SERVER_AUTH_OID, oidCertKeyUseType,
+ "serverAuth", "TLS Web Server Authentication"},
+ { EKU_CLIENT_AUTH_OID, EKU_CLIENT_AUTH_OID, oidCertKeyUseType,
+ "clientAuth", "TLS Web Client Authentication"},
+ { EKU_OCSP_SIGN_OID, EKU_OCSP_SIGN_OID, oidCertKeyUseType,
+ "OCSPSigning", "OCSP Signing"},
+
+ /* oidCertNameType */
+ { NID_commonName, NID_commonName, oidCertNameType, "CN", "commonName"},
+ { NID_surname, NID_surname, oidCertNameType, "SN", "surname"},
+ { NID_serialNumber, NID_serialNumber, oidCertNameType, "serialNumber",
+ "serialNumber"},
+ { NID_countryName, NID_countryName, oidCertNameType, "C", "countryName"},
+ { NID_localityName, NID_localityName, oidCertNameType, "L", "localityName"},
+ { NID_stateOrProvinceName, NID_stateOrProvinceName, oidCertNameType, "ST",
+ "stateOrProvinceName"},
+ { NID_organizationName, NID_organizationName, oidCertNameType, "O",
+ "organizationName"},
+ { NID_organizationalUnitName, NID_organizationalUnitName, oidCertNameType,
+ "OU", "organizationalUnitName"},
+ { NID_emailAddress, NID_emailAddress, oidCertNameType, "emailAddress",
+ "emailAddress"},
+ { NID_domainComponent, NID_domainComponent, oidCertNameType, "DC",
+ "domainComponent"},
+ { NID_businessCategory, NID_businessCategory, oidCertNameType, "businessCategory",
+ "businessCategory"},
+ { NID_jurisdictionCountryName, NID_jurisdictionCountryName, oidCertNameType, "jurisdictionC",
+ "jurisdictionCountryName"},
+ { NID_jurisdictionStateOrProvinceName, NID_jurisdictionStateOrProvinceName,
+ oidCertNameType, "jurisdictionST", "jurisdictionStateOrProvinceName"},
+#endif
+#ifdef OPENSSL_EXTRA /* OPENSSL_EXTRA_X509_SMALL only needs the above */
+ /* oidHashType */
+ #ifdef WOLFSSL_MD2
+ { NID_md2, MD2h, oidHashType, "MD2", "md2"},
+ #endif
+ #ifdef WOLFSSL_MD5
+ { NID_md5, MD5h, oidHashType, "MD5", "md5"},
+ #endif
+ #ifndef NO_SHA
+ { NID_sha1, SHAh, oidHashType, "SHA1", "sha1"},
+ #endif
+ #ifdef WOLFSSL_SHA224
+ { NID_sha224, SHA224h, oidHashType, "SHA224", "sha224"},
+ #endif
+ #ifndef NO_SHA256
+ { NID_sha256, SHA256h, oidHashType, "SHA256", "sha256"},
+ #endif
+ #ifdef WOLFSSL_SHA384
+ { NID_sha384, SHA384h, oidHashType, "SHA384", "sha384"},
+ #endif
+ #ifdef WOLFSSL_SHA512
+ { NID_sha512, SHA512h, oidHashType, "SHA512", "sha512"},
+ #endif
+ /* oidSigType */
+ #ifndef NO_DSA
+ #ifndef NO_SHA
+ { CTC_SHAwDSA, CTC_SHAwDSA, oidSigType, "DSA-SHA1", "dsaWithSHA1"},
+ #endif
+ #endif /* NO_DSA */
+ #ifndef NO_RSA
+ #ifdef WOLFSSL_MD2
+ { CTC_MD2wRSA, CTC_MD2wRSA, oidSigType, "RSA-MD2",
+ "md2WithRSAEncryption"},
+ #endif
+ #ifndef NO_MD5
+ { CTC_MD5wRSA, CTC_MD5wRSA, oidSigType, "RSA-MD5",
+ "md5WithRSAEncryption"},
+ #endif
+ #ifndef NO_SHA
+ { CTC_SHAwRSA, CTC_SHAwRSA, oidSigType, "RSA-SHA1",
+ "sha1WithRSAEncryption"},
+ #endif
+ #ifdef WOLFSSL_SHA224
+ { CTC_SHA224wRSA, CTC_SHA224wRSA, oidSigType, "RSA-SHA224",
+ "sha224WithRSAEncryption"},
+ #endif
+ #ifndef NO_SHA256
+ { CTC_SHA256wRSA, CTC_SHA256wRSA, oidSigType, "RSA-SHA256",
+ "sha256WithRSAEncryption"},
+ #endif
+ #ifdef WOLFSSL_SHA384
+ { CTC_SHA384wRSA, CTC_SHA384wRSA, oidSigType, "RSA-SHA384",
+ "sha384WithRSAEncryption"},
+ #endif
+ #ifdef WOLFSSL_SHA512
+ { CTC_SHA512wRSA, CTC_SHA512wRSA, oidSigType, "RSA-SHA512",
+ "sha512WithRSAEncryption"},
+ #endif
+ #endif /* NO_RSA */
+ #ifdef HAVE_ECC
+ #ifndef NO_SHA
+ { CTC_SHAwECDSA, CTC_SHAwECDSA, oidSigType, "ecdsa-with-SHA1", "shaWithECDSA"},
+ #endif
+ #ifdef WOLFSSL_SHA224
+ { CTC_SHA224wECDSA, CTC_SHA224wECDSA, oidSigType, "ecdsa-with-SHA224","sha224WithECDSA"},
+ #endif
+ #ifndef NO_SHA256
+ { CTC_SHA256wECDSA, CTC_SHA256wECDSA, oidSigType, "ecdsa-with-SHA256","sha256WithECDSA"},
+ #endif
+ #ifdef WOLFSSL_SHA384
+ { CTC_SHA384wECDSA, CTC_SHA384wECDSA, oidSigType, "ecdsa-with-SHA384","sha384WithECDSA"},
+ #endif
+ #ifdef WOLFSSL_SHA512
+ { CTC_SHA512wECDSA, CTC_SHA512wECDSA, oidSigType, "ecdsa-with-SHA512","sha512WithECDSA"},
+ #endif
+ #endif /* HAVE_ECC */
-int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn)
+ /* oidKeyType */
+ #ifndef NO_DSA
+ { DSAk, DSAk, oidKeyType, "DSA", "dsaEncryption"},
+ { NID_dsa, DSAk, oidKeyType, "DSA", "dsaEncryption"},
+ #endif /* NO_DSA */
+ #ifndef NO_RSA
+ { RSAk, RSAk, oidKeyType, "RSA", "rsaEncryption"},
+ { NID_rsaEncryption, RSAk, oidKeyType, "RSA", "rsaEncryption"},
+ #endif /* NO_RSA */
+ #ifdef HAVE_NTRU
+ { NTRUk, NTRUk, oidKeyType, "NTRU", "ntruEncryption"},
+ #endif /* HAVE_NTRU */
+ #ifdef HAVE_ECC
+ { ECDSAk, ECDSAk, oidKeyType, "ECDSA", "ecdsaEncryption"},
+ { NID_X9_62_id_ecPublicKey, ECDSAk, oidKeyType, "id-ecPublicKey",
+ "id-ecPublicKey"},
+ #endif /* HAVE_ECC */
+ #ifndef NO_DH
+ { NID_dhKeyAgreement, DHk, oidKeyType, "dhKeyAgreement", "dhKeyAgreement"},
+ #endif
+
+ /* oidCurveType */
+ #ifdef HAVE_ECC
+ { NID_X9_62_prime192v1, ECC_SECP192R1_OID, oidCurveType, "prime192v1", "prime192v1"},
+ { NID_X9_62_prime192v2, ECC_PRIME192V2_OID, oidCurveType, "prime192v2", "prime192v2"},
+ { NID_X9_62_prime192v3, ECC_PRIME192V3_OID, oidCurveType, "prime192v3", "prime192v3"},
+
+ { NID_X9_62_prime239v1, ECC_PRIME239V1_OID, oidCurveType, "prime239v1", "prime239v1"},
+ { NID_X9_62_prime239v2, ECC_PRIME239V2_OID, oidCurveType, "prime239v2", "prime239v2"},
+ { NID_X9_62_prime239v3, ECC_PRIME239V3_OID, oidCurveType, "prime239v3", "prime239v3"},
+
+ { NID_X9_62_prime256v1, ECC_SECP256R1_OID, oidCurveType, "prime256v1", "prime256v1"},
+
+ { NID_secp112r1, ECC_SECP112R1_OID, oidCurveType, "secp112r1", "secp112r1"},
+ { NID_secp112r2, ECC_SECP112R2_OID, oidCurveType, "secp112r2", "secp112r2"},
+
+ { NID_secp128r1, ECC_SECP128R1_OID, oidCurveType, "secp128r1", "secp128r1"},
+ { NID_secp128r2, ECC_SECP128R2_OID, oidCurveType, "secp128r2", "secp128r2"},
+
+ { NID_secp160r1, ECC_SECP160R1_OID, oidCurveType, "secp160r1", "secp160r1"},
+ { NID_secp160r2, ECC_SECP160R2_OID, oidCurveType, "secp160r2", "secp160r2"},
+
+ { NID_secp224r1, ECC_SECP224R1_OID, oidCurveType, "secp224r1", "secp224r1"},
+ { NID_secp384r1, ECC_SECP384R1_OID, oidCurveType, "secp384r1", "secp384r1"},
+ { NID_secp521r1, ECC_SECP521R1_OID, oidCurveType, "secp521r1", "secp521r1"},
+
+ { NID_secp160k1, ECC_SECP160K1_OID, oidCurveType, "secp160k1", "secp160k1"},
+ { NID_secp192k1, ECC_SECP192K1_OID, oidCurveType, "secp192k1", "secp192k1"},
+ { NID_secp224k1, ECC_SECP224K1_OID, oidCurveType, "secp224k1", "secp224k1"},
+ { NID_secp256k1, ECC_SECP256K1_OID, oidCurveType, "secp256k1", "secp256k1"},
+
+ { NID_brainpoolP160r1, ECC_BRAINPOOLP160R1_OID, oidCurveType, "brainpoolP160r1", "brainpoolP160r1"},
+ { NID_brainpoolP192r1, ECC_BRAINPOOLP192R1_OID, oidCurveType, "brainpoolP192r1", "brainpoolP192r1"},
+ { NID_brainpoolP224r1, ECC_BRAINPOOLP224R1_OID, oidCurveType, "brainpoolP224r1", "brainpoolP224r1"},
+ { NID_brainpoolP256r1, ECC_BRAINPOOLP256R1_OID, oidCurveType, "brainpoolP256r1", "brainpoolP256r1"},
+ { NID_brainpoolP320r1, ECC_BRAINPOOLP320R1_OID, oidCurveType, "brainpoolP320r1", "brainpoolP320r1"},
+ { NID_brainpoolP384r1, ECC_BRAINPOOLP384R1_OID, oidCurveType, "brainpoolP384r1", "brainpoolP384r1"},
+ { NID_brainpoolP512r1, ECC_BRAINPOOLP512R1_OID, oidCurveType, "brainpoolP512r1", "brainpoolP512r1"},
+ #endif /* HAVE_ECC */
+
+ /* oidBlkType */
+ #ifdef WOLFSSL_AES_128
+ { AES128CBCb, AES128CBCb, oidBlkType, "AES-128-CBC", "aes-128-cbc"},
+ #endif
+ #ifdef WOLFSSL_AES_192
+ { AES192CBCb, AES192CBCb, oidBlkType, "AES-192-CBC", "aes-192-cbc"},
+ #endif
+ #ifdef WOLFSSL_AES_256
+ { AES256CBCb, AES256CBCb, oidBlkType, "AES-256-CBC", "aes-256-cbc"},
+ #endif
+ #ifndef NO_DES3
+ { NID_des, DESb, oidBlkType, "DES-CBC", "des-cbc"},
+ { NID_des3, DES3b, oidBlkType, "DES-EDE3-CBC", "des-ede3-cbc"},
+ #endif /* !NO_DES3 */
+
+ /* oidOcspType */
+ #ifdef HAVE_OCSP
+ { NID_id_pkix_OCSP_basic, OCSP_BASIC_OID, oidOcspType, "basicOCSPResponse",
+ "Basic OCSP Response"},
+ { OCSP_NONCE_OID, OCSP_NONCE_OID, oidOcspType, "Nonce",
+ "OCSP Nonce"},
+ #endif /* HAVE_OCSP */
+
+ #ifndef NO_PWDBASED
+ /* oidKdfType */
+ { PBKDF2_OID, PBKDF2_OID, oidKdfType, "PBKDFv2", "PBKDF2"},
+
+ /* oidPBEType */
+ { PBE_SHA1_RC4_128, PBE_SHA1_RC4_128, oidPBEType,
+ "PBE-SHA1-RC4-128", "pbeWithSHA1And128BitRC4"},
+ { PBE_SHA1_DES, PBE_SHA1_DES, oidPBEType, "PBE-SHA1-DES",
+ "pbeWithSHA1AndDES-CBC"},
+ { PBE_SHA1_DES3, PBE_SHA1_DES3, oidPBEType, "PBE-SHA1-3DES",
+ "pbeWithSHA1And3-KeyTripleDES-CBC"},
+ #endif
+
+ /* oidKeyWrapType */
+ #ifdef WOLFSSL_AES_128
+ { AES128_WRAP, AES128_WRAP, oidKeyWrapType, "AES-128 wrap", "aes128-wrap"},
+ #endif
+ #ifdef WOLFSSL_AES_192
+ { AES192_WRAP, AES192_WRAP, oidKeyWrapType, "AES-192 wrap", "aes192-wrap"},
+ #endif
+ #ifdef WOLFSSL_AES_256
+ { AES256_WRAP, AES256_WRAP, oidKeyWrapType, "AES-256 wrap", "aes256-wrap"},
+ #endif
+
+ #ifndef NO_PKCS7
+ #ifndef NO_DH
+ /* oidCmsKeyAgreeType */
+ #ifndef NO_SHA
+ { dhSinglePass_stdDH_sha1kdf_scheme, dhSinglePass_stdDH_sha1kdf_scheme,
+ oidCmsKeyAgreeType, "dhSinglePass-stdDH-sha1kdf-scheme", "dhSinglePass-stdDH-sha1kdf-scheme"},
+ #endif
+ #ifdef WOLFSSL_SHA224
+ { dhSinglePass_stdDH_sha224kdf_scheme,
+ dhSinglePass_stdDH_sha224kdf_scheme, oidCmsKeyAgreeType,
+ "dhSinglePass-stdDH-sha224kdf-scheme", "dhSinglePass-stdDH-sha224kdf-scheme"},
+ #endif
+ #ifndef NO_SHA256
+ { dhSinglePass_stdDH_sha256kdf_scheme,
+ dhSinglePass_stdDH_sha256kdf_scheme, oidCmsKeyAgreeType,
+ "dhSinglePass-stdDH-sha256kdf-scheme", "dhSinglePass-stdDH-sha256kdf-scheme"},
+ #endif
+ #ifdef WOLFSSL_SHA384
+ { dhSinglePass_stdDH_sha384kdf_scheme,
+ dhSinglePass_stdDH_sha384kdf_scheme, oidCmsKeyAgreeType,
+ "dhSinglePass-stdDH-sha384kdf-scheme", "dhSinglePass-stdDH-sha384kdf-scheme"},
+ #endif
+ #ifdef WOLFSSL_SHA512
+ { dhSinglePass_stdDH_sha512kdf_scheme,
+ dhSinglePass_stdDH_sha512kdf_scheme, oidCmsKeyAgreeType,
+ "dhSinglePass-stdDH-sha512kdf-scheme", "dhSinglePass-stdDH-sha512kdf-scheme"},
+ #endif
+ #endif
+ #endif
+ #if defined(WOLFSSL_APACHE_HTTPD)
+ /* "1.3.6.1.5.5.7.8.7" */
+ { NID_id_on_dnsSRV, NID_id_on_dnsSRV, oidCertNameType,
+ WOLFSSL_SN_DNS_SRV, WOLFSSL_LN_DNS_SRV },
+
+ /* "1.3.6.1.4.1.311.20.2.3" */
+ { NID_ms_upn, WOLFSSL_MS_UPN_SUM, oidCertExtType, WOLFSSL_SN_MS_UPN,
+ WOLFSSL_LN_MS_UPN },
+
+ /* "1.3.6.1.5.5.7.1.24" */
+ { NID_tlsfeature, WOLFSSL_TLS_FEATURE_SUM, oidTlsExtType,
+ WOLFSSL_SN_TLS_FEATURE, WOLFSSL_LN_TLS_FEATURE },
+ #endif
+#endif /* OPENSSL_EXTRA */
+};
+
+#define WOLFSSL_OBJECT_INFO_SZ \
+ (sizeof(wolfssl_object_info) / sizeof(*wolfssl_object_info))
+const size_t wolfssl_object_info_sz = WOLFSSL_OBJECT_INFO_SZ;
+#endif
+#if defined(OPENSSL_EXTRA) || \
+ (defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA))
+static WC_RNG globalRNG;
+static int initGlobalRNG = 0;
+#endif
+#if defined(OPENSSL_EXTRA) && \
+ !defined(NO_RSA) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG, int *initTmpRng)
{
- WOLFSSL_MSG("wolfSSL_BN_is_odd");
+ WC_RNG* rng = NULL;
- if (bn == NULL || bn->internal == NULL)
- return 0;
+ if (!rsa || !initTmpRng) {
+ return NULL;
+ }
+ *initTmpRng = 0;
- return mp_isodd((mp_int*)bn->internal);
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \
+ !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING)
+ rng = ((RsaKey*)rsa->internal)->rng;
+#endif
+ if (rng == NULL && tmpRNG) {
+ if (!*tmpRNG) {
+#ifdef WOLFSSL_SMALL_STACK
+ *tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (*tmpRNG == NULL)
+ return NULL;
+#else
+ WOLFSSL_MSG("*tmpRNG is null");
+ return NULL;
+#endif
+ }
+
+ if (wc_InitRng(*tmpRNG) == 0) {
+ rng = *tmpRNG;
+ *initTmpRng = 1;
+ }
+ else {
+ WOLFSSL_MSG("Bad RNG Init, trying global");
+ if (initGlobalRNG == 0)
+ WOLFSSL_MSG("Global RNG no Init");
+ else
+ rng = &globalRNG;
+#ifdef WOLFSSL_SMALL_STACK
+ if (*tmpRNG)
+ XFREE(*tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ *tmpRNG = NULL;
+#endif
+ }
+ }
+ return rng;
}
+#endif
+#ifndef WOLFCRYPT_ONLY
+#ifdef OPENSSL_EXTRA
-int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b)
+/* Not thread safe! Can be called multiple times.
+ * Checks if the global RNG has been created. If not then one is created.
+ *
+ * Returns SSL_SUCCESS when no error is encountered.
+ */
+static int wolfSSL_RAND_Init(void)
{
- WOLFSSL_MSG("wolfSSL_BN_cmp");
+ if (initGlobalRNG == 0) {
+ if (wc_InitRng(&globalRNG) < 0) {
+ WOLFSSL_MSG("wolfSSL Init Global RNG failed");
+ return 0;
+ }
+ initGlobalRNG = 1;
+ }
- if (a == NULL || a->internal == NULL || b == NULL || b->internal ==NULL)
- return 0;
+ return SSL_SUCCESS;
+}
+
+
+/* SSL_SUCCESS on ok */
+int wolfSSL_RAND_seed(const void* seed, int len)
+{
+
+ WOLFSSL_MSG("wolfSSL_RAND_seed");
+
+ (void)seed;
+ (void)len;
- return mp_cmp((mp_int*)a->internal, (mp_int*)b->internal);
+ return wolfSSL_RAND_Init();
}
-int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r)
+/* Returns the path for reading seed data from.
+ * Uses the env variable $RANDFILE first if set, if not then used $HOME/.rnd
+ *
+ * Note uses stdlib by default unless XGETENV macro is overwritten
+ *
+ * fname buffer to hold path
+ * len length of fname buffer
+ *
+ * Returns a pointer to fname on success and NULL on failure
+ */
+const char* wolfSSL_RAND_file_name(char* fname, unsigned long len)
{
- WOLFSSL_MSG("wolfSSL_BN_bn2bin");
+#ifndef NO_FILESYSTEM
+ char* rt;
+ char ap[] = "/.rnd";
- if (bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("NULL bn error");
- return SSL_FATAL_ERROR;
+ WOLFSSL_ENTER("wolfSSL_RAND_file_name");
+
+ if (fname == NULL) {
+ return NULL;
}
- if (r == NULL)
- return mp_unsigned_bin_size((mp_int*)bn->internal);
+ XMEMSET(fname, 0, len);
+ /* if access to stdlib.h */
+ if ((rt = XGETENV("RANDFILE")) != NULL) {
+ if (len > XSTRLEN(rt)) {
+ XMEMCPY(fname, rt, XSTRLEN(rt));
+ }
+ else {
+ WOLFSSL_MSG("RANDFILE too large for buffer");
+ rt = NULL;
+ }
+ }
- if (mp_to_unsigned_bin((mp_int*)bn->internal, r) != MP_OKAY) {
- WOLFSSL_MSG("mp_to_unsigned_bin error");
- return SSL_FATAL_ERROR;
+ /* $RANDFILE was not set or is too large, check $HOME */
+ if (rt == NULL) {
+ WOLFSSL_MSG("Environment variable RANDFILE not set");
+ if ((rt = XGETENV("HOME")) == NULL) {
+ WOLFSSL_MSG("Environment variable HOME not set");
+ return NULL;
+ }
+
+ if (len > XSTRLEN(rt) + XSTRLEN(ap)) {
+ fname[0] = '\0';
+ XSTRNCAT(fname, rt, len);
+ XSTRNCAT(fname, ap, len - XSTRLEN(rt));
+ return fname;
+ }
+ else {
+ WOLFSSL_MSG("HOME too large for buffer");
+ return NULL;
+ }
}
- return mp_unsigned_bin_size((mp_int*)bn->internal);
+ return fname;
+#else
+ /* no filesystem defined */
+ WOLFSSL_ENTER("wolfSSL_RAND_file_name");
+ WOLFSSL_MSG("No filesystem feature enabled, not compiled in");
+ (void)fname;
+ (void)len;
+ return NULL;
+#endif
}
-WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len,
- WOLFSSL_BIGNUM* ret)
+/* Writes 1024 bytes from the RNG to the given file name.
+ *
+ * fname name of file to write to
+ *
+ * Returns the number of bytes written
+ */
+int wolfSSL_RAND_write_file(const char* fname)
{
- WOLFSSL_MSG("wolfSSL_BN_bin2bn");
+ int bytes = 0;
- if (ret && ret->internal) {
- if (mp_read_unsigned_bin((mp_int*)ret->internal, str, len) != 0) {
- WOLFSSL_MSG("mp_read_unsigned_bin failure");
- return NULL;
+ WOLFSSL_ENTER("RAND_write_file");
+
+ if (fname == NULL) {
+ return SSL_FAILURE;
+ }
+
+#ifndef NO_FILESYSTEM
+ {
+ #ifndef WOLFSSL_SMALL_STACK
+ unsigned char buf[1024];
+ #else
+ unsigned char* buf = (unsigned char *)XMALLOC(1024, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (buf == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ return SSL_FAILURE;
+ }
+ #endif
+ bytes = 1024; /* default size of buf */
+
+ if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != SSL_SUCCESS) {
+ WOLFSSL_MSG("No RNG to use");
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return 0;
+ }
+
+ if (wc_RNG_GenerateBlock(&globalRNG, buf, bytes) != 0) {
+ WOLFSSL_MSG("Error generating random buffer");
+ bytes = 0;
+ }
+ else {
+ XFILE f;
+
+ f = XFOPEN(fname, "wb");
+ if (f == XBADFILE) {
+ WOLFSSL_MSG("Error opening the file");
+ bytes = 0;
+ }
+ else {
+ XFWRITE(buf, 1, bytes, f);
+ XFCLOSE(f);
+ }
+ }
+ ForceZero(buf, bytes);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ }
+#endif
+
+ return bytes;
+}
+
+#ifndef FREERTOS_TCP
+
+/* These constant values are protocol values made by egd */
+#if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API)
+ #define WOLFSSL_EGD_NBLOCK 0x01
+ #include <sys/un.h>
+#endif
+
+/* This collects entropy from the path nm and seeds the global PRNG with it.
+ * Makes a call to wolfSSL_RAND_Init which is not thread safe.
+ *
+ * nm is the file path to the egd server
+ *
+ * Returns the number of bytes read.
+ */
+int wolfSSL_RAND_egd(const char* nm)
+{
+#if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) && !defined(HAVE_FIPS) && \
+ defined(HAVE_HASHDRBG)
+ struct sockaddr_un rem;
+ int fd;
+ int ret = WOLFSSL_SUCCESS;
+ word32 bytes = 0;
+ word32 idx = 0;
+#ifndef WOLFSSL_SMALL_STACK
+ unsigned char buf[256];
+#else
+ unsigned char* buf;
+ buf = (unsigned char*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (buf == NULL) {
+ WOLFSSL_MSG("Not enough memory");
+ return WOLFSSL_FATAL_ERROR;
+ }
+#endif
+
+ if (nm == NULL) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ WOLFSSL_MSG("Error creating socket");
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return WOLFSSL_FATAL_ERROR;
+ }
+ if (ret == WOLFSSL_SUCCESS) {
+ rem.sun_family = AF_UNIX;
+ XSTRNCPY(rem.sun_path, nm, sizeof(rem.sun_path) - 1);
+ rem.sun_path[sizeof(rem.sun_path)-1] = '\0';
+ }
+
+ /* connect to egd server */
+ if (ret == WOLFSSL_SUCCESS) {
+ if (connect(fd, (struct sockaddr*)&rem, sizeof(struct sockaddr_un))
+ == -1) {
+ WOLFSSL_MSG("error connecting to egd server");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ while (ret == WOLFSSL_SUCCESS && bytes < 255 && idx + 2 < 256) {
+ if (ret == WOLFSSL_SUCCESS) {
+ buf[idx] = WOLFSSL_EGD_NBLOCK;
+ buf[idx + 1] = 255 - bytes; /* request 255 bytes from server */
+ ret = (int)write(fd, buf + idx, 2);
+ if (ret <= 0 || ret != 2) {
+ if (errno == EAGAIN) {
+ ret = WOLFSSL_SUCCESS;
+ continue;
+ }
+ WOLFSSL_MSG("error requesting entropy from egd server");
+ ret = WOLFSSL_FATAL_ERROR;
+ break;
+ }
+ }
+
+ /* attempting to read */
+ buf[idx] = 0;
+ ret = (int)read(fd, buf + idx, 256 - bytes);
+ if (ret == 0) {
+ WOLFSSL_MSG("error reading entropy from egd server");
+ ret = WOLFSSL_FATAL_ERROR;
+ break;
+ }
+ if (ret > 0 && buf[idx] > 0) {
+ bytes += buf[idx]; /* egd stores amount sent in first byte */
+ if (bytes + idx > 255 || buf[idx] > ret) {
+ WOLFSSL_MSG("Buffer error");
+ ret = WOLFSSL_FATAL_ERROR;
+ break;
+ }
+ XMEMMOVE(buf + idx, buf + idx + 1, buf[idx]);
+ idx = bytes;
+ ret = WOLFSSL_SUCCESS;
+ if (bytes >= 255) {
+ break;
+ }
+ }
+ else {
+ if (errno == EAGAIN || errno == EINTR) {
+ WOLFSSL_MSG("EGD would read");
+ ret = WOLFSSL_SUCCESS; /* try again */
+ }
+ else if (buf[idx] == 0) {
+ /* if egd returned 0 then there is no more entropy to be had.
+ Do not try more reads. */
+ ret = WOLFSSL_SUCCESS;
+ break;
+ }
+ else {
+ WOLFSSL_MSG("Error with read");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
}
}
+
+ if (bytes > 0 && ret == WOLFSSL_SUCCESS) {
+ wolfSSL_RAND_Init(); /* call to check global RNG is created */
+ if (wc_RNG_DRBG_Reseed(&globalRNG, (const byte*) buf, bytes)
+ != 0) {
+ WOLFSSL_MSG("Error with reseeding DRBG structure");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ #ifdef SHOW_SECRETS
+ { /* print out entropy found */
+ word32 i;
+ printf("EGD Entropy = ");
+ for (i = 0; i < bytes; i++) {
+ printf("%02X", buf[i]);
+ }
+ printf("\n");
+ }
+ #endif
+ }
+
+ ForceZero(buf, bytes);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ close(fd);
+
+ if (ret == WOLFSSL_SUCCESS) {
+ return bytes;
+ }
else {
- WOLFSSL_MSG("wolfSSL_BN_bin2bn wants return bignum");
+ return ret;
}
+#else
+ WOLFSSL_MSG("Type of socket needed is not available");
+ WOLFSSL_MSG("\tor using mode where DRBG API is not available");
+ (void)nm;
- return ret;
+ return WOLFSSL_FATAL_ERROR;
+#endif /* USE_WOLFSSL_IO && !USE_WINDOWS_API && !HAVE_FIPS && HAVE_HASHDRBG */
}
+#endif /* !FREERTOS_TCP */
-int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n)
+void wolfSSL_RAND_Cleanup(void)
{
- (void)bn;
- (void)n;
- WOLFSSL_MSG("wolfSSL_BN_mask_bits");
+ WOLFSSL_ENTER("wolfSSL_RAND_Cleanup()");
+
+ if (initGlobalRNG != 0) {
+ wc_FreeRng(&globalRNG);
+ initGlobalRNG = 0;
+ }
+}
- return SSL_FATAL_ERROR;
+
+int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num)
+{
+ return wolfSSL_RAND_bytes(buf, num);
}
/* SSL_SUCCESS on ok */
-int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
+int wolfSSL_RAND_bytes(unsigned char* buf, int num)
{
- int ret = 0;
- int len = bits / 8;
- int initTmpRng = 0;
- RNG* rng = NULL;
+ int ret = 0;
+ int initTmpRng = 0;
+ WC_RNG* rng = NULL;
#ifdef WOLFSSL_SMALL_STACK
- RNG* tmpRNG = NULL;
- byte* buff = NULL;
+ WC_RNG* tmpRNG;
#else
- RNG tmpRNG[1];
- byte buff[1024];
+ WC_RNG tmpRNG[1];
#endif
- (void)top;
- (void)bottom;
- WOLFSSL_MSG("wolfSSL_BN_rand");
-
- if (bits % 8)
- len++;
+ WOLFSSL_ENTER("wolfSSL_RAND_bytes");
#ifdef WOLFSSL_SMALL_STACK
- buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- tmpRNG = (RNG*) XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (buff == NULL || tmpRNG == NULL) {
- XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (tmpRNG == NULL)
return ret;
- }
#endif
- if (bn == NULL || bn->internal == NULL)
- WOLFSSL_MSG("Bad function arguments");
- else if (wc_InitRng(tmpRNG) == 0) {
+ if (initGlobalRNG)
+ rng = &globalRNG;
+ else if(wc_InitRng(tmpRNG) == 0) {
rng = tmpRNG;
initTmpRng = 1;
}
- else if (initGlobalRNG)
- rng = &globalRNG;
-
if (rng) {
- if (wc_RNG_GenerateBlock(rng, buff, len) != 0)
+ if (wc_RNG_GenerateBlock(rng, buf, num) != 0)
WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
- else {
- buff[0] |= 0x80 | 0x40;
- buff[len-1] |= 0x01;
-
- if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY)
- WOLFSSL_MSG("mp read bin failed");
- else
- ret = SSL_SUCCESS;
- }
+ else
+ ret = WOLFSSL_SUCCESS;
}
if (initTmpRng)
wc_FreeRng(tmpRNG);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
#endif
return ret;
}
-int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n)
+int wolfSSL_RAND_poll(void)
{
- (void)bn;
- (void)n;
+ byte entropy[16];
+ int ret = 0;
+ word32 entropy_sz = 16;
- WOLFSSL_MSG("wolfSSL_BN_is_bit_set");
+ WOLFSSL_ENTER("wolfSSL_RAND_poll");
+ if (initGlobalRNG == 0){
+ WOLFSSL_MSG("Global RNG no Init");
+ return WOLFSSL_FAILURE;
+ }
+ ret = wc_GenerateSeed(&globalRNG.seed, entropy, entropy_sz);
+ if (ret != 0){
+ WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
+ ret = WOLFSSL_FAILURE;
+ }else
+ ret = WOLFSSL_SUCCESS;
- return 0;
+ return ret;
}
+#endif /* OPENSSL_EXTRA */
-/* SSL_SUCCESS on ok */
-int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str)
+
+#ifdef OPENSSL_EXTRA
+
+WOLFSSL_ASN1_INTEGER* wolfSSL_BN_to_ASN1_INTEGER(const WOLFSSL_BIGNUM *bn, WOLFSSL_ASN1_INTEGER *ai)
{
- int ret = 0;
- word32 decSz = 1024;
-#ifdef WOLFSSL_SMALL_STACK
- byte* decoded = NULL;
-#else
- byte decoded[1024];
-#endif
+ WOLFSSL_ASN1_INTEGER* a;
+ int len;
+ WOLFSSL_ENTER("wolfSSL_BN_to_ASN1_INTEGER");
- WOLFSSL_MSG("wolfSSL_BN_hex2bn");
+ if (ai == NULL) {
+ a = wolfSSL_ASN1_INTEGER_new();
-#ifdef WOLFSSL_SMALL_STACK
- decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (decoded == NULL)
- return ret;
-#endif
+ if (a == NULL)
+ return NULL;
- if (str == NULL)
- WOLFSSL_MSG("Bad function argument");
- else if (Base16_Decode((byte*)str, (int)XSTRLEN(str), decoded, &decSz) < 0)
- WOLFSSL_MSG("Bad Base16_Decode error");
- else if (bn == NULL)
- ret = decSz;
+ a->type = V_ASN1_INTEGER;
+ }
else {
- if (*bn == NULL)
- *bn = wolfSSL_BN_new();
-
- if (*bn == NULL)
- WOLFSSL_MSG("BN new failed");
- else if (wolfSSL_BN_bin2bn(decoded, decSz, *bn) == NULL)
- WOLFSSL_MSG("Bad bin2bn error");
- else
- ret = SSL_SUCCESS;
+ a = ai;
}
+ if (a) {
+ if (wolfSSL_BN_is_negative(bn) && !wolfSSL_BN_is_zero(bn)) {
+ a->type |= V_ASN1_NEG_INTEGER;
+ a->negative = 1;
+ }
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ len = wolfSSL_BN_num_bytes(bn);
+ if (len == 0)
+ len = 1;
+
+ /* allocate buffer */
+ if (len > (int)sizeof(a->intData)) {
+ /* create new data buffer and copy over */
+ a->data = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (a->data == NULL) {
+ if (a != ai)
+ wolfSSL_ASN1_INTEGER_free(a);
+ return NULL;
+ }
+ a->isDynamic = 1;
+ }
+ else {
+ XMEMSET(a->intData, 0, sizeof(a->intData));
+ a->data = a->intData;
+ }
+ a->length = len;
- return ret;
-}
+ /* populate data */
+ if (wolfSSL_BN_is_zero(bn)) {
+ a->data[0] = 0;
+ }
+ else {
+ len = wolfSSL_BN_bn2bin(bn, a->data);
+ }
+ a->length = len;
+ }
+ return a;
+}
-WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn)
+#ifdef OPENSSL_ALL
+void *wolfSSL_ASN1_item_new(const WOLFSSL_ASN1_ITEM *template)
{
- WOLFSSL_BIGNUM* ret;
-
- WOLFSSL_MSG("wolfSSL_BN_dup");
-
- if (bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
+ void *ret = NULL;
+ const WOLFSSL_ASN1_TEMPLATE *member = NULL;
+ size_t i;
+ WOLFSSL_ENTER("wolfSSL_ASN1_item_new");
+ if (!template) {
return NULL;
}
-
- ret = wolfSSL_BN_new();
- if (ret == NULL) {
- WOLFSSL_MSG("bn new error");
+ if (!(ret = XMALLOC(template->size, NULL, DYNAMIC_TYPE_OPENSSL))) {
return NULL;
}
-
- if (mp_copy((mp_int*)bn->internal, (mp_int*)ret->internal) != MP_OKAY) {
- WOLFSSL_MSG("mp_copy error");
- wolfSSL_BN_free(ret);
- return NULL;
+ XMEMSET(ret, 0, template->size);
+ for (member = template->members, i = 0; i < template->mcount;
+ member++, i++) {
+ switch (member->type) {
+ case WOLFSSL_X509_ALGOR_ASN1:
+ {
+ WOLFSSL_X509_ALGOR* algor = wolfSSL_X509_ALGOR_new();
+ if (!algor) {
+ goto error;
+ }
+ *(WOLFSSL_X509_ALGOR**)(((byte*)ret) + member->offset) = algor;
+ break;
+ }
+ case WOLFSSL_ASN1_BIT_STRING_ASN1:
+ {
+ WOLFSSL_ASN1_BIT_STRING* bit_str = wolfSSL_ASN1_BIT_STRING_new();
+ if (!bit_str) {
+ goto error;
+ }
+ *(WOLFSSL_ASN1_BIT_STRING**)(((byte*)ret) + member->offset) = bit_str;
+ break;
+ }
+ default:
+ WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_new");
+ goto error;
+ }
}
-
return ret;
+error:
+ wolfSSL_ASN1_item_free(ret, template);
+ return NULL;
}
-
-WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn)
+void wolfSSL_ASN1_item_free(void *val, const WOLFSSL_ASN1_ITEM *template)
{
- (void)r;
- (void)bn;
-
- WOLFSSL_MSG("wolfSSL_BN_copy");
-
- return NULL;
+ const WOLFSSL_ASN1_TEMPLATE *member = NULL;
+ size_t i;
+ WOLFSSL_ENTER("wolfSSL_ASN1_item_free");
+ if (val) {
+ for (member = template->members, i = 0; i < template->mcount;
+ member++, i++) {
+ switch (member->type) {
+ case WOLFSSL_X509_ALGOR_ASN1:
+ {
+ WOLFSSL_X509_ALGOR* algor = *(WOLFSSL_X509_ALGOR**)
+ (((byte*)val) + member->offset);
+ if (algor) {
+ wolfSSL_X509_ALGOR_free(algor);
+ }
+ break;
+ }
+ case WOLFSSL_ASN1_BIT_STRING_ASN1:
+ {
+ WOLFSSL_ASN1_BIT_STRING* bit_str = *(WOLFSSL_ASN1_BIT_STRING**)
+ (((byte*)val) + member->offset);
+ if (bit_str) {
+ wolfSSL_ASN1_BIT_STRING_free(bit_str);
+ }
+ break;
+ }
+ default:
+ WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_free");
+ }
+ }
+ XFREE(val, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
}
+#define bufLenOrNull(buf, len) (buf ? buf + len : NULL)
-int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, unsigned long w)
+static int i2dProcessMembers(const void *src, byte *buf,
+ const WOLFSSL_ASN1_TEMPLATE *members, size_t mcount)
{
- (void)bn;
- (void)w;
+ const WOLFSSL_ASN1_TEMPLATE *member = NULL;
+ int len = 0, ret;
+ size_t i;
+ WOLFSSL_ENTER("processMembers");
+ for (member = members, i = 0; i < mcount; member++, i++) {
+ switch (member->type) {
+ case WOLFSSL_X509_ALGOR_ASN1:
+ {
+ word32 oid = 0;
+ word32 idx = 0;
+ const WOLFSSL_X509_ALGOR* algor = *(const WOLFSSL_X509_ALGOR**)
+ (((byte*)src) + member->offset);
+ if (!algor->algorithm) {
+ WOLFSSL_LEAVE("processMembers", WOLFSSL_FAILURE);
+ return WOLFSSL_FAILURE;
+ }
- WOLFSSL_MSG("wolfSSL_BN_set_word");
+ if (GetObjectId(algor->algorithm->obj, &idx, &oid,
+ algor->algorithm->grp, algor->algorithm->objSz) < 0) {
+ WOLFSSL_MSG("Issue getting OID of object");
+ return -1;
+ }
- return SSL_FATAL_ERROR;
+ ret = SetAlgoID(oid, bufLenOrNull(buf, len),
+ algor->algorithm->grp, 0);
+ if (!ret) {
+ return WOLFSSL_FAILURE;
+ }
+ len += ret;
+ break;
+ }
+ case WOLFSSL_ASN1_BIT_STRING_ASN1:
+ {
+ const WOLFSSL_ASN1_BIT_STRING* bit_str;
+ bit_str = *(const WOLFSSL_ASN1_BIT_STRING**)
+ (((byte*)src) + member->offset);
+ len += SetBitString(bit_str->length, 0, bufLenOrNull(buf, len));
+ if (buf && bit_str->data) {
+ XMEMCPY(buf + len, bit_str->data, bit_str->length);
+ }
+ len += bit_str->length;
+ break;
+ }
+ default:
+ WOLFSSL_MSG("Type not support in processMembers");
+ WOLFSSL_LEAVE("processMembers", WOLFSSL_FAILURE);
+ return WOLFSSL_FAILURE;
+ }
+ }
+ WOLFSSL_LEAVE("processMembers", len);
+ return len;
}
-
-int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str)
+int wolfSSL_ASN1_item_i2d(const void *src, byte **dest,
+ const WOLFSSL_ASN1_ITEM *template)
{
- (void)bn;
- (void)str;
+ int len = 0;
+ byte *buf = NULL;
- WOLFSSL_MSG("wolfSSL_BN_dec2bn");
+ WOLFSSL_ENTER("wolfSSL_ASN1_item_i2d");
- return SSL_FATAL_ERROR;
-}
+ if (!src || !template) {
+ WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", WOLFSSL_FAILURE);
+ return WOLFSSL_FAILURE;
+ }
+ if (dest && !*dest) {
+ len = wolfSSL_ASN1_item_i2d(src, NULL, template);
+ if (!len) {
+ goto error;
+ }
+ buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_ASN1);
+ if (!buf) {
+ goto error;
+ }
+ len = 0;
+ }
-char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn)
-{
- (void)bn;
+ switch (template->type) {
+ case ASN_SEQUENCE:
+ {
+ int seq_len = i2dProcessMembers(src, NULL, template->members,
+ template->mcount);
+ if (!seq_len) {
+ goto error;
+ }
+ len += SetSequence(seq_len, bufLenOrNull(buf, len));
+ if (buf &&
+ i2dProcessMembers(src, bufLenOrNull(buf, len), template->members,
+ template->mcount) != seq_len) {
+ WOLFSSL_MSG("Inconsistent sequence length");
+ goto error;
+ }
+ len += seq_len;
+ break;
+ }
+ default:
+ WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_i2d");
+ goto error;
+ }
- WOLFSSL_MSG("wolfSSL_BN_bn2dec");
+ if (dest && !*dest) {
+ *dest = buf;
+ }
+ else if (dest && *dest && buf) {
+ /* *dest length is not checked because the user is responsible
+ * for providing a long enough buffer */
+ XMEMCPY(*dest, buf, len);
+ }
- return NULL;
+ WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", len);
+ return len;
+error:
+ if (buf) {
+ XFREE(buf, NULL, DYNAMIC_TYPE_ASN1);
+ }
+ WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", WOLFSSL_FAILURE);
+ return WOLFSSL_FAILURE;
}
-
+#endif /* OPENSSL_ALL */
#ifndef NO_DH
static void InitwolfSSL_DH(WOLFSSL_DH* dh)
{
if (dh) {
- dh->p = NULL;
- dh->g = NULL;
- dh->pub_key = NULL;
- dh->priv_key = NULL;
- dh->internal = NULL;
- dh->inSet = 0;
- dh->exSet = 0;
+ XMEMSET(dh, 0, sizeof(WOLFSSL_DH));
}
}
@@ -11296,7 +28440,12 @@ WOLFSSL_DH* wolfSSL_DH_new(void)
}
InitwolfSSL_DH(external);
- wc_InitDhKey(key);
+ if (wc_InitDhKey(key) != 0) {
+ WOLFSSL_MSG("wolfSSL_DH_new InitDhKey failure");
+ XFREE(key, NULL, DYNAMIC_TYPE_DH);
+ XFREE(external, NULL, DYNAMIC_TYPE_DH);
+ return NULL;
+ }
external->internal = key;
return external;
@@ -11317,24 +28466,36 @@ void wolfSSL_DH_free(WOLFSSL_DH* dh)
wolfSSL_BN_free(dh->pub_key);
wolfSSL_BN_free(dh->g);
wolfSSL_BN_free(dh->p);
+ wolfSSL_BN_free(dh->q);
InitwolfSSL_DH(dh); /* set back to NULLs for safety */
XFREE(dh, NULL, DYNAMIC_TYPE_DH);
}
}
-
-static int SetDhInternal(WOLFSSL_DH* dh)
+int SetDhInternal(WOLFSSL_DH* dh)
{
- int ret = SSL_FATAL_ERROR;
+ int ret = WOLFSSL_FATAL_ERROR;
int pSz = 1024;
int gSz = 1024;
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ 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)
+ 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)
+ unsigned char priv_key[256];
+ unsigned char pub_key[256];
+ #endif
#endif
WOLFSSL_ENTER("SetDhInternal");
@@ -11345,17 +28506,46 @@ static 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)
+ 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
else {
#ifdef WOLFSSL_SMALL_STACK
- p = (unsigned char*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- g = (unsigned char*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ 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
if (p == NULL || g == NULL) {
- XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
return ret;
}
- #endif
+ #endif /* WOLFSSL_SMALL_STACK */
+
+ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ privSz = wolfSSL_BN_bn2bin(dh->priv_key, priv_key);
+ pubSz = wolfSSL_BN_bn2bin(dh->pub_key, pub_key);
+ if (privSz <= 0) {
+ WOLFSSL_MSG("No private key size.");
+ }
+ if (pubSz <= 0) {
+ 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) {
+ WOLFSSL_MSG("Failed setting private or public key.");
+ }
+ }
+ #endif /* WOLFSSL_QT || OPENSSL_ALL */
pSz = wolfSSL_BN_bn2bin(dh->p, p);
gSz = wolfSSL_BN_bn2bin(dh->g, g);
@@ -11366,12 +28556,16 @@ static int SetDhInternal(WOLFSSL_DH* dh)
WOLFSSL_MSG("Bad DH SetKey");
else {
dh->inSet = 1;
- ret = 0;
+ ret = WOLFSSL_SUCCESS;
}
#ifdef WOLFSSL_SMALL_STACK
- XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ XFREE(priv_key, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
+ XFREE(pub_key, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ #endif
#endif
}
@@ -11379,54 +28573,478 @@ static int SetDhInternal(WOLFSSL_DH* dh)
return ret;
}
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH))
+/* Set the members of DhKey into WOLFSSL_DH
+ * DhKey was populated from wc_DhKeyDecode
+ */
+int SetDhExternal(WOLFSSL_DH *dh)
+{
+ DhKey *key;
+ WOLFSSL_MSG("Entering SetDhExternal");
+
+ if (dh == NULL || dh->internal == NULL) {
+ WOLFSSL_MSG("dh key NULL error");
+ }
+
+ key = (DhKey*)dh->internal;
+
+ if (SetIndividualExternal(&dh->p, &key->p) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("dh param p error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (SetIndividualExternal(&dh->g, &key->g) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("dh param g error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (SetIndividualExternal(&dh->priv_key, &key->priv) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("No DH Private Key");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (SetIndividualExternal(&dh->pub_key, &key->pub) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("No DH Public Key");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ dh->exSet = 1;
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
+/* return code compliant with OpenSSL :
+ * DH prime size in bytes if success, 0 if error
+ */
int wolfSSL_DH_size(WOLFSSL_DH* dh)
{
WOLFSSL_MSG("wolfSSL_DH_size");
if (dh == NULL)
- return 0;
+ return WOLFSSL_FATAL_ERROR;
return wolfSSL_BN_num_bytes(dh->p);
}
+/* This sets a big number with the 768-bit prime from RFC 2409.
+ *
+ * bn if not NULL then the big number structure is used. If NULL then a new
+ * big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_768_prime(WOLFSSL_BIGNUM* bn)
+{
+ const char prm[] = {
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+ "C4C6628B80DC1CD129024E088A67CC74"
+ "020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F1437"
+ "4FE1356D6D51C245E485B576625E7EC6"
+ "F44C42E9A63A3620FFFFFFFFFFFFFFFF"
+ };
+
+ WOLFSSL_ENTER("wolfSSL_DH_768_prime");
+
+ if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Error converting DH 768 prime to big number");
+ return NULL;
+ }
+
+ return bn;
+}
+
+/* This sets a big number with the 1024-bit prime from RFC 2409.
+ *
+ * bn if not NULL then the big number structure is used. If NULL then a new
+ * big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_1024_prime(WOLFSSL_BIGNUM* bn)
+{
+ const char prm[] = {
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+ "C4C6628B80DC1CD129024E088A67CC74"
+ "020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F1437"
+ "4FE1356D6D51C245E485B576625E7EC6"
+ "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE6"
+ "49286651ECE65381FFFFFFFFFFFFFFFF"
+ };
+
+ WOLFSSL_ENTER("wolfSSL_DH_1024_prime");
+
+ if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Error converting DH 1024 prime to big number");
+ return NULL;
+ }
-/* return SSL_SUCCESS on ok, else 0 */
+ return bn;
+}
+
+/* This sets a big number with the 1536-bit prime from RFC 3526.
+ *
+ * bn if not NULL then the big number structure is used. If NULL then a new
+ * big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_1536_prime(WOLFSSL_BIGNUM* bn)
+{
+ const char prm[] = {
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+ "C4C6628B80DC1CD129024E088A67CC74"
+ "020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F1437"
+ "4FE1356D6D51C245E485B576625E7EC6"
+ "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE6"
+ "49286651ECE45B3DC2007CB8A163BF05"
+ "98DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB"
+ "9ED529077096966D670C354E4ABC9804"
+ "F1746C08CA237327FFFFFFFFFFFFFFFF"
+ };
+
+ WOLFSSL_ENTER("wolfSSL_DH_1536_prime");
+
+ if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Error converting DH 1536 prime to big number");
+ return NULL;
+ }
+
+ return bn;
+}
+
+/* This sets a big number with the 2048-bit prime from RFC 3526.
+ *
+ * bn if not NULL then the big number structure is used. If NULL then a new
+ * big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_2048_prime(WOLFSSL_BIGNUM* bn)
+{
+ const char prm[] = {
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+ "C4C6628B80DC1CD129024E088A67CC74"
+ "020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F1437"
+ "4FE1356D6D51C245E485B576625E7EC6"
+ "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE6"
+ "49286651ECE45B3DC2007CB8A163BF05"
+ "98DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB"
+ "9ED529077096966D670C354E4ABC9804"
+ "F1746C08CA18217C32905E462E36CE3B"
+ "E39E772C180E86039B2783A2EC07A28F"
+ "B5C55DF06F4C52C9DE2BCBF695581718"
+ "3995497CEA956AE515D2261898FA0510"
+ "15728E5A8AACAA68FFFFFFFFFFFFFFFF"
+ };
+
+ WOLFSSL_ENTER("wolfSSL_DH_2048_prime");
+
+ if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Error converting DH 2048 prime to big number");
+ return NULL;
+ }
+
+ return bn;
+}
+
+/* This sets a big number with the 3072-bit prime from RFC 3526.
+ *
+ * bn if not NULL then the big number structure is used. If NULL then a new
+ * big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_3072_prime(WOLFSSL_BIGNUM* bn)
+{
+ const char prm[] = {
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+ "C4C6628B80DC1CD129024E088A67CC74"
+ "020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F1437"
+ "4FE1356D6D51C245E485B576625E7EC6"
+ "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE6"
+ "49286651ECE45B3DC2007CB8A163BF05"
+ "98DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB"
+ "9ED529077096966D670C354E4ABC9804"
+ "F1746C08CA18217C32905E462E36CE3B"
+ "E39E772C180E86039B2783A2EC07A28F"
+ "B5C55DF06F4C52C9DE2BCBF695581718"
+ "3995497CEA956AE515D2261898FA0510"
+ "15728E5A8AAAC42DAD33170D04507A33"
+ "A85521ABDF1CBA64ECFB850458DBEF0A"
+ "8AEA71575D060C7DB3970F85A6E1E4C7"
+ "ABF5AE8CDB0933D71E8C94E04A25619D"
+ "CEE3D2261AD2EE6BF12FFA06D98A0864"
+ "D87602733EC86A64521F2B18177B200C"
+ "BBE117577A615D6C770988C0BAD946E2"
+ "08E24FA074E5AB3143DB5BFCE0FD108E"
+ "4B82D120A93AD2CAFFFFFFFFFFFFFFFF"
+ };
+
+ WOLFSSL_ENTER("wolfSSL_DH_3072_prime");
+
+ if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Error converting DH 3072 prime to big number");
+ return NULL;
+ }
+
+ return bn;
+}
+
+/* This sets a big number with the 4096-bit prime from RFC 3526.
+ *
+ * bn if not NULL then the big number structure is used. If NULL then a new
+ * big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_4096_prime(WOLFSSL_BIGNUM* bn)
+{
+ const char prm[] = {
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+ "C4C6628B80DC1CD129024E088A67CC74"
+ "020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F1437"
+ "4FE1356D6D51C245E485B576625E7EC6"
+ "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE6"
+ "49286651ECE45B3DC2007CB8A163BF05"
+ "98DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB"
+ "9ED529077096966D670C354E4ABC9804"
+ "F1746C08CA18217C32905E462E36CE3B"
+ "E39E772C180E86039B2783A2EC07A28F"
+ "B5C55DF06F4C52C9DE2BCBF695581718"
+ "3995497CEA956AE515D2261898FA0510"
+ "15728E5A8AAAC42DAD33170D04507A33"
+ "A85521ABDF1CBA64ECFB850458DBEF0A"
+ "8AEA71575D060C7DB3970F85A6E1E4C7"
+ "ABF5AE8CDB0933D71E8C94E04A25619D"
+ "CEE3D2261AD2EE6BF12FFA06D98A0864"
+ "D87602733EC86A64521F2B18177B200C"
+ "BBE117577A615D6C770988C0BAD946E2"
+ "08E24FA074E5AB3143DB5BFCE0FD108E"
+ "4B82D120A92108011A723C12A787E6D7"
+ "88719A10BDBA5B2699C327186AF4E23C"
+ "1A946834B6150BDA2583E9CA2AD44CE8"
+ "DBBBC2DB04DE8EF92E8EFC141FBECAA6"
+ "287C59474E6BC05D99B2964FA090C3A2"
+ "233BA186515BE7ED1F612970CEE2D7AF"
+ "B81BDD762170481CD0069127D5B05AA9"
+ "93B4EA988D8FDDC186FFB7DC90A6C08F"
+ "4DF435C934063199FFFFFFFFFFFFFFFF"
+ };
+
+ WOLFSSL_ENTER("wolfSSL_DH_4096_prime");
+
+ if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Error converting DH 4096 prime to big number");
+ return NULL;
+ }
+
+ return bn;
+}
+
+/* This sets a big number with the 6144-bit prime from RFC 3526.
+ *
+ * bn if not NULL then the big number structure is used. If NULL then a new
+ * big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_6144_prime(WOLFSSL_BIGNUM* bn)
+{
+ const char prm[] = {
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+ "C4C6628B80DC1CD129024E088A67CC74"
+ "020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F1437"
+ "4FE1356D6D51C245E485B576625E7EC6"
+ "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE6"
+ "49286651ECE45B3DC2007CB8A163BF05"
+ "98DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB"
+ "9ED529077096966D670C354E4ABC9804"
+ "F1746C08CA18217C32905E462E36CE3B"
+ "E39E772C180E86039B2783A2EC07A28F"
+ "B5C55DF06F4C52C9DE2BCBF695581718"
+ "3995497CEA956AE515D2261898FA0510"
+ "15728E5A8AAAC42DAD33170D04507A33"
+ "A85521ABDF1CBA64ECFB850458DBEF0A"
+ "8AEA71575D060C7DB3970F85A6E1E4C7"
+ "ABF5AE8CDB0933D71E8C94E04A25619D"
+ "CEE3D2261AD2EE6BF12FFA06D98A0864"
+ "D87602733EC86A64521F2B18177B200C"
+ "BBE117577A615D6C770988C0BAD946E2"
+ "08E24FA074E5AB3143DB5BFCE0FD108E"
+ "4B82D120A92108011A723C12A787E6D7"
+ "88719A10BDBA5B2699C327186AF4E23C"
+ "1A946834B6150BDA2583E9CA2AD44CE8"
+ "DBBBC2DB04DE8EF92E8EFC141FBECAA6"
+ "287C59474E6BC05D99B2964FA090C3A2"
+ "233BA186515BE7ED1F612970CEE2D7AF"
+ "B81BDD762170481CD0069127D5B05AA9"
+ "93B4EA988D8FDDC186FFB7DC90A6C08F"
+ "4DF435C93402849236C3FAB4D27C7026"
+ "C1D4DCB2602646DEC9751E763DBA37BD"
+ "F8FF9406AD9E530EE5DB382F413001AE"
+ "B06A53ED9027D831179727B0865A8918"
+ "DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
+ "DB7F1447E6CC254B332051512BD7AF42"
+ "6FB8F401378CD2BF5983CA01C64B92EC"
+ "F032EA15D1721D03F482D7CE6E74FEF6"
+ "D55E702F46980C82B5A84031900B1C9E"
+ "59E7C97FBEC7E8F323A97A7E36CC88BE"
+ "0F1D45B7FF585AC54BD407B22B4154AA"
+ "CC8F6D7EBF48E1D814CC5ED20F8037E0"
+ "A79715EEF29BE32806A1D58BB7C5DA76"
+ "F550AA3D8A1FBFF0EB19CCB1A313D55C"
+ "DA56C9EC2EF29632387FE8D76E3C0468"
+ "043E8F663F4860EE12BF2D5B0B7474D6"
+ "E694F91E6DCC4024FFFFFFFFFFFFFFFF"
+ };
+
+ WOLFSSL_ENTER("wolfSSL_DH_6144_prime");
+
+ if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Error converting DH 6144 prime to big number");
+ return NULL;
+ }
+
+ return bn;
+}
+
+
+/* This sets a big number with the 8192-bit prime from RFC 3526.
+ *
+ * bn if not NULL then the big number structure is used. If NULL then a new
+ * big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_8192_prime(WOLFSSL_BIGNUM* bn)
+{
+ const char prm[] = {
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+ "C4C6628B80DC1CD129024E088A67CC74"
+ "020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F1437"
+ "4FE1356D6D51C245E485B576625E7EC6"
+ "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE6"
+ "49286651ECE45B3DC2007CB8A163BF05"
+ "98DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB"
+ "9ED529077096966D670C354E4ABC9804"
+ "F1746C08CA18217C32905E462E36CE3B"
+ "E39E772C180E86039B2783A2EC07A28F"
+ "B5C55DF06F4C52C9DE2BCBF695581718"
+ "3995497CEA956AE515D2261898FA0510"
+ "15728E5A8AAAC42DAD33170D04507A33"
+ "A85521ABDF1CBA64ECFB850458DBEF0A"
+ "8AEA71575D060C7DB3970F85A6E1E4C7"
+ "ABF5AE8CDB0933D71E8C94E04A25619D"
+ "CEE3D2261AD2EE6BF12FFA06D98A0864"
+ "D87602733EC86A64521F2B18177B200C"
+ "BBE117577A615D6C770988C0BAD946E2"
+ "08E24FA074E5AB3143DB5BFCE0FD108E"
+ "4B82D120A92108011A723C12A787E6D7"
+ "88719A10BDBA5B2699C327186AF4E23C"
+ "1A946834B6150BDA2583E9CA2AD44CE8"
+ "DBBBC2DB04DE8EF92E8EFC141FBECAA6"
+ "287C59474E6BC05D99B2964FA090C3A2"
+ "233BA186515BE7ED1F612970CEE2D7AF"
+ "B81BDD762170481CD0069127D5B05AA9"
+ "93B4EA988D8FDDC186FFB7DC90A6C08F"
+ "4DF435C93402849236C3FAB4D27C7026"
+ "C1D4DCB2602646DEC9751E763DBA37BD"
+ "F8FF9406AD9E530EE5DB382F413001AE"
+ "B06A53ED9027D831179727B0865A8918"
+ "DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
+ "DB7F1447E6CC254B332051512BD7AF42"
+ "6FB8F401378CD2BF5983CA01C64B92EC"
+ "F032EA15D1721D03F482D7CE6E74FEF6"
+ "D55E702F46980C82B5A84031900B1C9E"
+ "59E7C97FBEC7E8F323A97A7E36CC88BE"
+ "0F1D45B7FF585AC54BD407B22B4154AA"
+ "CC8F6D7EBF48E1D814CC5ED20F8037E0"
+ "A79715EEF29BE32806A1D58BB7C5DA76"
+ "F550AA3D8A1FBFF0EB19CCB1A313D55C"
+ "DA56C9EC2EF29632387FE8D76E3C0468"
+ "043E8F663F4860EE12BF2D5B0B7474D6"
+ "E694F91E6DBE115974A3926F12FEE5E4"
+ "38777CB6A932DF8CD8BEC4D073B931BA"
+ "3BC832B68D9DD300741FA7BF8AFC47ED"
+ "2576F6936BA424663AAB639C5AE4F568"
+ "3423B4742BF1C978238F16CBE39D652D"
+ "E3FDB8BEFC848AD922222E04A4037C07"
+ "13EB57A81A23F0C73473FC646CEA306B"
+ "4BCBC8862F8385DDFA9D4B7FA2C087E8"
+ "79683303ED5BDD3A062B3CF5B3A278A6"
+ "6D2A13F83F44F82DDF310EE074AB6A36"
+ "4597E899A0255DC164F31CC50846851D"
+ "F9AB48195DED7EA1B1D510BD7EE74D73"
+ "FAF36BC31ECFA268359046F4EB879F92"
+ "4009438B481C6CD7889A002ED5EE382B"
+ "C9190DA6FC026E479558E4475677E9AA"
+ "9E3050E2765694DFC81F56E880B96E71"
+ "60C980DD98EDD3DFFFFFFFFFFFFFFFFF"
+ };
+
+ WOLFSSL_ENTER("wolfSSL_DH_8192_prime");
+
+ if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Error converting DH 8192 prime to big number");
+ return NULL;
+ }
+
+ return bn;
+}
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
int wolfSSL_DH_generate_key(WOLFSSL_DH* dh)
{
- int ret = 0;
- word32 pubSz = 768;
- word32 privSz = 768;
+ int ret = WOLFSSL_FAILURE;
+ word32 pubSz = 0;
+ word32 privSz = 0;
int initTmpRng = 0;
- RNG* rng = NULL;
+ WC_RNG* rng = NULL;
#ifdef WOLFSSL_SMALL_STACK
- unsigned char* pub = NULL;
- unsigned char* priv = NULL;
- RNG* tmpRNG = NULL;
+ WC_RNG* tmpRNG;
#else
- unsigned char pub [768];
- unsigned char priv[768];
- RNG tmpRNG[1];
+ WC_RNG tmpRNG[1];
#endif
+ unsigned char* pub = NULL;
+ unsigned char* priv = NULL;
WOLFSSL_MSG("wolfSSL_DH_generate_key");
#ifdef WOLFSSL_SMALL_STACK
- tmpRNG = (RNG*)XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
- if (tmpRNG == NULL || pub == NULL || priv == NULL) {
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (tmpRNG == NULL) {
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
return ret;
}
#endif
if (dh == NULL || dh->p == NULL || dh->g == NULL)
WOLFSSL_MSG("Bad function arguments");
- else if (dh->inSet == 0 && SetDhInternal(dh) < 0)
+ else if (dh->inSet == 0 && SetDhInternal(dh) != WOLFSSL_SUCCESS)
WOLFSSL_MSG("Bad DH set internal");
else if (wc_InitRng(tmpRNG) == 0) {
rng = tmpRNG;
@@ -11441,13 +29059,24 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh)
}
if (rng) {
- if (wc_DhGenerateKeyPair((DhKey*)dh->internal, rng, priv, &privSz,
+ pubSz = wolfSSL_BN_num_bytes(dh->p);
+ if (dh->length) {
+ privSz = dh->length/8; /* to bytes */
+ } else {
+ privSz = pubSz;
+ }
+ pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
+ if (pub == NULL || priv == NULL) {
+ WOLFSSL_MSG("Unable to malloc memory");
+ }
+ else if (wc_DhGenerateKeyPair((DhKey*)dh->internal, rng, priv, &privSz,
pub, &pubSz) < 0)
WOLFSSL_MSG("Bad wc_DhGenerateKeyPair");
- else {
+ else {
if (dh->pub_key)
wolfSSL_BN_free(dh->pub_key);
-
+
dh->pub_key = wolfSSL_BN_new();
if (dh->pub_key == NULL) {
WOLFSSL_MSG("Bad DH new pub");
@@ -11467,7 +29096,7 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh)
else if (wolfSSL_BN_bin2bn(priv, privSz, dh->priv_key) == NULL)
WOLFSSL_MSG("Bad DH bn2bin error priv");
else
- ret = SSL_SUCCESS;
+ ret = WOLFSSL_SUCCESS;
}
}
}
@@ -11476,25 +29105,27 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh)
wc_FreeRng(tmpRNG);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
#endif
+ XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
return ret;
}
-/* return key size on ok, 0 otherwise */
+/* return code compliant with OpenSSL :
+ * size of shared secret if success, -1 if error
+ */
int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* otherPub,
WOLFSSL_DH* dh)
{
- int ret = 0;
+ int ret = WOLFSSL_FATAL_ERROR;
word32 keySz = 0;
- word32 pubSz = 1024;
- word32 privSz = 1024;
+ int pubSz = 1024;
+ int privSz = 1024;
#ifdef WOLFSSL_SMALL_STACK
- unsigned char* pub = NULL;
+ unsigned char* pub;
unsigned char* priv = NULL;
#else
unsigned char pub [1024];
@@ -11504,14 +29135,14 @@ int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* otherPub,
WOLFSSL_MSG("wolfSSL_DH_compute_key");
#ifdef WOLFSSL_SMALL_STACK
- pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
if (pub == NULL)
return ret;
- priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
if (priv == NULL) {
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return 0;
+ XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ return ret;
}
#endif
@@ -11526,23 +29157,78 @@ int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* otherPub,
else {
privSz = wolfSSL_BN_bn2bin(dh->priv_key, priv);
pubSz = wolfSSL_BN_bn2bin(otherPub, pub);
-
+ if (dh->inSet == 0 && SetDhInternal(dh) != SSL_SUCCESS){
+ WOLFSSL_MSG("Bad DH set internal");
+ }
if (privSz <= 0 || pubSz <= 0)
WOLFSSL_MSG("Bad BN2bin set");
- else if (wc_DhAgree((DhKey*)dh->internal, key, &keySz, priv, privSz, pub,
- pubSz) < 0)
+ else if (wc_DhAgree((DhKey*)dh->internal, key, &keySz,
+ priv, privSz, pub, pubSz) < 0)
WOLFSSL_MSG("wc_DhAgree failed");
else
ret = (int)keySz;
}
#ifdef WOLFSSL_SMALL_STACK
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
#endif
return ret;
}
+
+
+#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
+/* ownership of p,q,and g get taken over by "dh" on success and should be free'd
+ * with a call to wolfSSL_DH_free -- not individually.
+ *
+ * returns WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_DH_set0_pqg(WOLFSSL_DH *dh, WOLFSSL_BIGNUM *p,
+ WOLFSSL_BIGNUM *q, WOLFSSL_BIGNUM *g)
+{
+ int ret;
+ WOLFSSL_ENTER("wolfSSL_DH_set0_pqg");
+
+ /* q can be NULL */
+ if (dh == NULL || p == NULL || g == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* free existing internal DH structure and recreate with new p / g */
+ if (dh->inSet) {
+ ret = wc_FreeDhKey((DhKey*)dh->internal);
+ if (ret != 0) {
+ WOLFSSL_MSG("Unable to free internal DH key");
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ wolfSSL_BN_free(dh->p);
+ wolfSSL_BN_free(dh->q);
+ wolfSSL_BN_free(dh->g);
+ wolfSSL_BN_free(dh->pub_key);
+ wolfSSL_BN_free(dh->priv_key);
+
+ dh->p = p;
+ dh->q = q;
+ dh->g = g;
+
+ ret = SetDhInternal(dh);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Unable to set internal DH key");
+ dh->p = NULL;
+ dh->q = NULL;
+ dh->g = NULL;
+ dh->inSet = 0;
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* v1.1.0 or later */
+
#endif /* NO_DH */
@@ -11584,7 +29270,12 @@ WOLFSSL_DSA* wolfSSL_DSA_new(void)
}
InitwolfSSL_DSA(external);
- InitDsaKey(key);
+ if (wc_InitDsaKey(key) != 0) {
+ WOLFSSL_MSG("wolfSSL_DSA_new InitDsaKey failure");
+ XFREE(key, NULL, DYNAMIC_TYPE_DSA);
+ wolfSSL_DSA_free(external);
+ return NULL;
+ }
external->internal = key;
return external;
@@ -11609,290 +29300,226 @@ void wolfSSL_DSA_free(WOLFSSL_DSA* dsa)
InitwolfSSL_DSA(dsa); /* set back to NULLs for safety */
XFREE(dsa, NULL, DYNAMIC_TYPE_DSA);
- }
-}
-
-
-int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa)
-{
- (void)dsa;
- WOLFSSL_MSG("wolfSSL_DSA_generate_key");
-
- return 0; /* key gen not needed by server */
+ /* dsa = NULL, don't try to access or double free it */
+ }
}
-
-int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits,
- unsigned char* seed, int seedLen, int* counterRet,
- unsigned long* hRet, void* cb)
-{
- (void)dsa;
- (void)bits;
- (void)seed;
- (void)seedLen;
- (void)counterRet;
- (void)hRet;
- (void)cb;
-
- WOLFSSL_MSG("wolfSSL_DSA_generate_parameters_ex");
-
- return 0; /* key gen not needed by server */
-}
#endif /* NO_DSA */
+#endif /* OPENSSL_EXTRA */
-#ifndef NO_RSA
-static void InitwolfSSL_Rsa(WOLFSSL_RSA* rsa)
-{
- if (rsa) {
- rsa->n = NULL;
- rsa->e = NULL;
- rsa->d = NULL;
- rsa->p = NULL;
- rsa->q = NULL;
- rsa->dmp1 = NULL;
- rsa->dmq1 = NULL;
- rsa->iqmp = NULL;
- rsa->internal = NULL;
- rsa->inSet = 0;
- rsa->exSet = 0;
- }
-}
-
+#ifdef OPENSSL_EXTRA
-WOLFSSL_RSA* wolfSSL_RSA_new(void)
+#ifndef NO_DSA
+/* wolfSSL -> OpenSSL */
+int SetDsaExternal(WOLFSSL_DSA* dsa)
{
- WOLFSSL_RSA* external;
- RsaKey* key;
-
- WOLFSSL_MSG("wolfSSL_RSA_new");
+ DsaKey* key;
+ WOLFSSL_MSG("Entering SetDsaExternal");
- key = (RsaKey*) XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
- if (key == NULL) {
- WOLFSSL_MSG("wolfSSL_RSA_new malloc RsaKey failure");
- return NULL;
+ if (dsa == NULL || dsa->internal == NULL) {
+ WOLFSSL_MSG("dsa key NULL error");
+ return WOLFSSL_FATAL_ERROR;
}
- external = (WOLFSSL_RSA*) XMALLOC(sizeof(WOLFSSL_RSA), NULL,
- DYNAMIC_TYPE_RSA);
- if (external == NULL) {
- WOLFSSL_MSG("wolfSSL_RSA_new malloc WOLFSSL_RSA failure");
- XFREE(key, NULL, DYNAMIC_TYPE_RSA);
- return NULL;
- }
+ key = (DsaKey*)dsa->internal;
- InitwolfSSL_Rsa(external);
- if (wc_InitRsaKey(key, NULL) != 0) {
- WOLFSSL_MSG("InitRsaKey WOLFSSL_RSA failure");
- XFREE(external, NULL, DYNAMIC_TYPE_RSA);
- XFREE(key, NULL, DYNAMIC_TYPE_RSA);
- return NULL;
+ if (SetIndividualExternal(&dsa->p, &key->p) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("dsa p key error");
+ return WOLFSSL_FATAL_ERROR;
}
- external->internal = key;
- return external;
-}
-
-
-void wolfSSL_RSA_free(WOLFSSL_RSA* rsa)
-{
- WOLFSSL_MSG("wolfSSL_RSA_free");
-
- if (rsa) {
- if (rsa->internal) {
- wc_FreeRsaKey((RsaKey*)rsa->internal);
- XFREE(rsa->internal, NULL, DYNAMIC_TYPE_RSA);
- rsa->internal = NULL;
- }
- wolfSSL_BN_free(rsa->iqmp);
- wolfSSL_BN_free(rsa->dmq1);
- wolfSSL_BN_free(rsa->dmp1);
- wolfSSL_BN_free(rsa->q);
- wolfSSL_BN_free(rsa->p);
- wolfSSL_BN_free(rsa->d);
- wolfSSL_BN_free(rsa->e);
- wolfSSL_BN_free(rsa->n);
- InitwolfSSL_Rsa(rsa); /* set back to NULLs for safety */
-
- XFREE(rsa, NULL, DYNAMIC_TYPE_RSA);
+ if (SetIndividualExternal(&dsa->q, &key->q) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("dsa q key error");
+ return WOLFSSL_FATAL_ERROR;
}
-}
-#endif /* NO_RSA */
-
-#if !defined(NO_RSA) || !defined(NO_DSA)
-static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi)
-{
- WOLFSSL_MSG("Entering SetIndividualExternal");
-
- if (mpi == NULL) {
- WOLFSSL_MSG("mpi NULL error");
- return SSL_FATAL_ERROR;
+ if (SetIndividualExternal(&dsa->g, &key->g) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("dsa g key error");
+ return WOLFSSL_FATAL_ERROR;
}
- if (*bn == NULL) {
- *bn = wolfSSL_BN_new();
- if (*bn == NULL) {
- WOLFSSL_MSG("SetIndividualExternal alloc failed");
- return SSL_FATAL_ERROR;
- }
+ if (SetIndividualExternal(&dsa->pub_key, &key->y) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("dsa y key error");
+ return WOLFSSL_FATAL_ERROR;
}
- if (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY) {
- WOLFSSL_MSG("mp_copy error");
- return SSL_FATAL_ERROR;
+ if (SetIndividualExternal(&dsa->priv_key, &key->x) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("dsa x key error");
+ return WOLFSSL_FATAL_ERROR;
}
- return 0;
-}
-#endif /* !NO_RSA && !NO_DSA */
+ dsa->exSet = 1;
+ return WOLFSSL_SUCCESS;
+}
-#ifndef NO_DSA
-static int SetDsaExternal(WOLFSSL_DSA* dsa)
+/* Openssl -> WolfSSL */
+int SetDsaInternal(WOLFSSL_DSA* dsa)
{
DsaKey* key;
- WOLFSSL_MSG("Entering SetDsaExternal");
+ WOLFSSL_MSG("Entering SetDsaInternal");
if (dsa == NULL || dsa->internal == NULL) {
WOLFSSL_MSG("dsa key NULL error");
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
key = (DsaKey*)dsa->internal;
- if (SetIndividualExternal(&dsa->p, &key->p) < 0) {
- WOLFSSL_MSG("dsa p key error");
- return SSL_FATAL_ERROR;
+ if (dsa->p != NULL &&
+ SetIndividualInternal(dsa->p, &key->p) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa p key error");
+ return WOLFSSL_FATAL_ERROR;
}
- if (SetIndividualExternal(&dsa->q, &key->q) < 0) {
- WOLFSSL_MSG("dsa q key error");
- return SSL_FATAL_ERROR;
+ if (dsa->q != NULL &&
+ SetIndividualInternal(dsa->q, &key->q) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa q key error");
+ return WOLFSSL_FATAL_ERROR;
}
- if (SetIndividualExternal(&dsa->g, &key->g) < 0) {
- WOLFSSL_MSG("dsa g key error");
- return SSL_FATAL_ERROR;
+ if (dsa->g != NULL &&
+ SetIndividualInternal(dsa->g, &key->g) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa g key error");
+ return WOLFSSL_FATAL_ERROR;
}
- if (SetIndividualExternal(&dsa->pub_key, &key->y) < 0) {
- WOLFSSL_MSG("dsa y key error");
- return SSL_FATAL_ERROR;
+ if (dsa->pub_key != NULL) {
+ if (SetIndividualInternal(dsa->pub_key, &key->y) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa pub_key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* public key */
+ key->type = DSA_PUBLIC;
}
- if (SetIndividualExternal(&dsa->priv_key, &key->x) < 0) {
- WOLFSSL_MSG("dsa x key error");
- return SSL_FATAL_ERROR;
+ if (dsa->priv_key != NULL) {
+ if (SetIndividualInternal(dsa->priv_key, &key->x) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa priv_key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* private key */
+ key->type = DSA_PRIVATE;
}
- dsa->exSet = 1;
+ dsa->inSet = 1;
- return 0;
+ return WOLFSSL_SUCCESS;
}
#endif /* NO_DSA */
+#endif /* OPENSSL_EXTRA */
-#ifndef NO_RSA
-static int SetRsaExternal(WOLFSSL_RSA* rsa)
+#ifdef OPENSSL_EXTRA
+#if !defined(NO_RSA)
+/* Generates a RSA key of length len
+ *
+ * len length of RSA key i.e. 2048
+ * e e to use when generating RSA key
+ * f callback function for generation details
+ * data user callback argument
+ *
+ * Note: Because of wc_MakeRsaKey an RSA key size generated can be slightly
+ * rounded down. For example generating a key of size 2999 with e =
+ * 65537 will make a key of size 374 instead of 375.
+ * Returns a new RSA key on success and NULL on failure
+ */
+WOLFSSL_RSA* wolfSSL_RSA_generate_key(int len, unsigned long e,
+ void(*f)(int, int, void*), void* data)
{
- RsaKey* key;
- WOLFSSL_MSG("Entering SetRsaExternal");
-
- if (rsa == NULL || rsa->internal == NULL) {
- WOLFSSL_MSG("rsa key NULL error");
- return SSL_FATAL_ERROR;
- }
-
- key = (RsaKey*)rsa->internal;
-
- if (SetIndividualExternal(&rsa->n, &key->n) < 0) {
- WOLFSSL_MSG("rsa n key error");
- return SSL_FATAL_ERROR;
- }
+ WOLFSSL_RSA* rsa = NULL;
+ WOLFSSL_BIGNUM* bn = NULL;
- if (SetIndividualExternal(&rsa->e, &key->e) < 0) {
- WOLFSSL_MSG("rsa e key error");
- return SSL_FATAL_ERROR;
- }
+ WOLFSSL_ENTER("wolfSSL_RSA_generate_key");
- if (SetIndividualExternal(&rsa->d, &key->d) < 0) {
- WOLFSSL_MSG("rsa d key error");
- return SSL_FATAL_ERROR;
- }
+ (void)f;
+ (void)data;
- if (SetIndividualExternal(&rsa->p, &key->p) < 0) {
- WOLFSSL_MSG("rsa p key error");
- return SSL_FATAL_ERROR;
+ if (len < 0) {
+ WOLFSSL_MSG("Bad argument: length was less than 0");
+ return NULL;
}
- if (SetIndividualExternal(&rsa->q, &key->q) < 0) {
- WOLFSSL_MSG("rsa q key error");
- return SSL_FATAL_ERROR;
+ bn = wolfSSL_BN_new();
+ if (bn == NULL) {
+ WOLFSSL_MSG("Error creating big number");
+ return NULL;
}
- if (SetIndividualExternal(&rsa->dmp1, &key->dP) < 0) {
- WOLFSSL_MSG("rsa dP key error");
- return SSL_FATAL_ERROR;
+ if (wolfSSL_BN_set_word(bn, (WOLFSSL_BN_ULONG)e) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Error using e value");
+ wolfSSL_BN_free(bn);
+ return NULL;
}
- if (SetIndividualExternal(&rsa->dmq1, &key->dQ) < 0) {
- WOLFSSL_MSG("rsa dQ key error");
- return SSL_FATAL_ERROR;
+ rsa = wolfSSL_RSA_new();
+ if (rsa == NULL) {
+ WOLFSSL_MSG("memory error");
}
-
- if (SetIndividualExternal(&rsa->iqmp, &key->u) < 0) {
- WOLFSSL_MSG("rsa u key error");
- return SSL_FATAL_ERROR;
+ else {
+ if (wolfSSL_RSA_generate_key_ex(rsa, len, bn, NULL) != SSL_SUCCESS){
+ wolfSSL_RSA_free(rsa);
+ rsa = NULL;
+ }
}
+ wolfSSL_BN_free(bn);
- rsa->exSet = 1;
-
- return 0;
+ return rsa;
}
-/* SSL_SUCCESS on ok */
+/* return compliant with OpenSSL
+ * 1 if success, 0 if error
+ */
int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* bn,
- void* cb)
+ void* cb)
{
- int ret = SSL_FATAL_ERROR;
-
- WOLFSSL_MSG("wolfSSL_RSA_generate_key_ex");
+ int ret = WOLFSSL_FAILURE;
- (void)rsa;
- (void)bits;
(void)cb;
(void)bn;
+ (void)bits;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_generate_key_ex");
+
+ if (rsa == NULL || rsa->internal == NULL) {
+ /* bit size checked during make key call */
+ WOLFSSL_MSG("bad arguments");
+ return WOLFSSL_FAILURE;
+ }
#ifdef WOLFSSL_KEY_GEN
{
#ifdef WOLFSSL_SMALL_STACK
- RNG* rng = NULL;
+ WC_RNG* rng;
#else
- RNG rng[1];
+ WC_RNG rng[1];
#endif
#ifdef WOLFSSL_SMALL_STACK
- rng = (RNG*)XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
if (rng == NULL)
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FAILURE;
#endif
if (wc_InitRng(rng) < 0)
WOLFSSL_MSG("RNG init failed");
- else if (wc_MakeRsaKey((RsaKey*)rsa->internal, bits, 65537, rng) < 0)
+ else if (wc_MakeRsaKey((RsaKey*)rsa->internal, bits,
+ wolfSSL_BN_get_word(bn), rng) != MP_OKAY)
WOLFSSL_MSG("wc_MakeRsaKey failed");
- else if (SetRsaExternal(rsa) < 0)
+ else if (SetRsaExternal(rsa) != WOLFSSL_SUCCESS)
WOLFSSL_MSG("SetRsaExternal failed");
else {
rsa->inSet = 1;
- ret = SSL_SUCCESS;
+ ret = WOLFSSL_SUCCESS;
}
wc_FreeRng(rng);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(rng, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
#endif
}
#else
@@ -11900,89 +29527,148 @@ int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* bn,
#endif
return ret;
}
+#endif /* NO_RSA */
-
-/* SSL_SUCCESS on ok */
-int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bn)
+#ifndef NO_DSA
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa)
{
- (void)rsa;
- (void)bn;
+ int ret = WOLFSSL_FAILURE;
- WOLFSSL_MSG("wolfSSL_RSA_blinding_on");
+ WOLFSSL_ENTER("wolfSSL_DSA_generate_key");
- return SSL_SUCCESS; /* on by default */
-}
+ if (dsa == NULL || dsa->internal == NULL) {
+ WOLFSSL_MSG("Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+ if (dsa->inSet == 0) {
+ WOLFSSL_MSG("No DSA internal set, do it");
-int wolfSSL_RSA_public_encrypt(int len, unsigned char* fr,
- unsigned char* to, WOLFSSL_RSA* rsa, int padding)
-{
- (void)len;
- (void)fr;
- (void)to;
- (void)rsa;
- (void)padding;
+ if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetDsaInternal failed");
+ return ret;
+ }
+ }
- WOLFSSL_MSG("wolfSSL_RSA_public_encrypt");
+#ifdef WOLFSSL_KEY_GEN
+ {
+ int initTmpRng = 0;
+ WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG *tmpRNG;
+#else
+ WC_RNG tmpRNG[1];
+#endif
- return SSL_FATAL_ERROR;
+#ifdef WOLFSSL_SMALL_STACK
+ tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (tmpRNG == NULL)
+ return WOLFSSL_FATAL_ERROR;
+#endif
+ if (wc_InitRng(tmpRNG) == 0) {
+ rng = tmpRNG;
+ initTmpRng = 1;
+ }
+ else {
+ WOLFSSL_MSG("Bad RNG Init, trying global");
+ if (initGlobalRNG == 0)
+ WOLFSSL_MSG("Global RNG no Init");
+ else
+ rng = &globalRNG;
+ }
+
+ if (rng) {
+ if (wc_MakeDsaKey(rng, (DsaKey*)dsa->internal) != MP_OKAY)
+ WOLFSSL_MSG("wc_MakeDsaKey failed");
+ else if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS)
+ WOLFSSL_MSG("SetDsaExternal failed");
+ else
+ ret = WOLFSSL_SUCCESS;
+ }
+
+ if (initTmpRng)
+ wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+ }
+#else /* WOLFSSL_KEY_GEN */
+ WOLFSSL_MSG("No Key Gen built in");
+#endif
+ return ret;
}
-int wolfSSL_RSA_private_decrypt(int len, unsigned char* fr,
- unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+/* Returns a pointer to a new WOLFSSL_DSA structure on success and NULL on fail
+ */
+WOLFSSL_DSA* wolfSSL_DSA_generate_parameters(int bits, unsigned char* seed,
+ int seedLen, int* counterRet, unsigned long* hRet,
+ WOLFSSL_BN_CB cb, void* CBArg)
{
- (void)len;
- (void)fr;
- (void)to;
- (void)rsa;
- (void)padding;
+ WOLFSSL_DSA* dsa;
- WOLFSSL_MSG("wolfSSL_RSA_private_decrypt");
+ WOLFSSL_ENTER("wolfSSL_DSA_generate_parameters()");
+
+ (void)cb;
+ (void)CBArg;
+ dsa = wolfSSL_DSA_new();
+ if (dsa == NULL) {
+ return NULL;
+ }
- return SSL_FATAL_ERROR;
+ if (wolfSSL_DSA_generate_parameters_ex(dsa, bits, seed, seedLen,
+ counterRet, hRet, NULL) != SSL_SUCCESS) {
+ wolfSSL_DSA_free(dsa);
+ return NULL;
+ }
+
+ return dsa;
}
-int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa)
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits,
+ unsigned char* seed, int seedLen,
+ int* counterRet,
+ unsigned long* hRet, void* cb)
{
- WOLFSSL_MSG("wolfSSL_RSA_size");
+ int ret = WOLFSSL_FAILURE;
- if (rsa == NULL)
- return 0;
+ (void)bits;
+ (void)seed;
+ (void)seedLen;
+ (void)counterRet;
+ (void)hRet;
+ (void)cb;
- return wolfSSL_BN_num_bytes(rsa->n);
-}
-#endif /* NO_RSA */
+ WOLFSSL_ENTER("wolfSSL_DSA_generate_parameters_ex");
+ if (dsa == NULL || dsa->internal == NULL) {
+ WOLFSSL_MSG("Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
-#ifndef NO_DSA
-/* return SSL_SUCCESS on success, < 0 otherwise */
-int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet,
- WOLFSSL_DSA* dsa)
-{
- int ret = SSL_FATAL_ERROR;
- int initTmpRng = 0;
- RNG* rng = NULL;
+#ifdef WOLFSSL_KEY_GEN
+ {
+ int initTmpRng = 0;
+ WC_RNG *rng = NULL;
#ifdef WOLFSSL_SMALL_STACK
- RNG* tmpRNG = NULL;
+ WC_RNG *tmpRNG;
#else
- RNG tmpRNG[1];
+ WC_RNG tmpRNG[1];
#endif
- WOLFSSL_MSG("wolfSSL_DSA_do_sign");
-
- if (d == NULL || sigRet == NULL || dsa == NULL)
- WOLFSSL_MSG("Bad function arguments");
- else if (dsa->inSet == 0)
- WOLFSSL_MSG("No DSA internal set");
- else {
- #ifdef WOLFSSL_SMALL_STACK
- tmpRNG = (RNG*)XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#ifdef WOLFSSL_SMALL_STACK
+ tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
if (tmpRNG == NULL)
- return SSL_FATAL_ERROR;
- #endif
-
+ return WOLFSSL_FATAL_ERROR;
+#endif
if (wc_InitRng(tmpRNG) == 0) {
rng = tmpRNG;
initTmpRng = 1;
@@ -11996,97 +29682,394 @@ int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet,
}
if (rng) {
- if (DsaSign(d, sigRet, (DsaKey*)dsa->internal, rng) < 0)
- WOLFSSL_MSG("DsaSign failed");
+ if (wc_MakeDsaParameters(rng, bits,
+ (DsaKey*)dsa->internal) != MP_OKAY)
+ WOLFSSL_MSG("wc_MakeDsaParameters failed");
+ else if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS)
+ WOLFSSL_MSG("SetDsaExternal failed");
else
- ret = SSL_SUCCESS;
+ ret = WOLFSSL_SUCCESS;
}
if (initTmpRng)
wc_FreeRng(tmpRNG);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
}
+#else /* WOLFSSL_KEY_GEN */
+ WOLFSSL_MSG("No Key Gen built in");
+#endif
return ret;
}
+
+WOLFSSL_DSA_SIG* wolfSSL_DSA_SIG_new(void)
+{
+ WOLFSSL_DSA_SIG* sig;
+ WOLFSSL_ENTER("wolfSSL_DSA_SIG_new");
+ sig = (WOLFSSL_DSA_SIG*)XMALLOC(sizeof(WOLFSSL_DSA_SIG), NULL, DYNAMIC_TYPE_OPENSSL);
+ if (sig)
+ XMEMSET(sig, 0, sizeof(WOLFSSL_DSA_SIG));
+ return sig;
+}
+
+void wolfSSL_DSA_SIG_free(WOLFSSL_DSA_SIG *sig)
+{
+ WOLFSSL_ENTER("wolfSSL_DSA_SIG_free");
+ if (sig) {
+ if (sig->r) {
+ wolfSSL_BN_free(sig->r);
+ }
+ if (sig->s) {
+ wolfSSL_BN_free(sig->s);
+ }
+ XFREE(sig, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+
+/* return WOLFSSL_SUCCESS on success, < 0 otherwise */
+int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet,
+ WOLFSSL_DSA* dsa)
+{
+ int ret = WOLFSSL_FATAL_ERROR;
+ int initTmpRng = 0;
+ WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG* tmpRNG = NULL;
+#else
+ WC_RNG tmpRNG[1];
+#endif
+
+ WOLFSSL_ENTER("wolfSSL_DSA_do_sign");
+
+ if (d == NULL || sigRet == NULL || dsa == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return ret;
+ }
+
+ if (dsa->inSet == 0)
+ {
+ WOLFSSL_MSG("No DSA internal set, do it");
+
+ if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetDsaInternal failed");
+ return ret;
+ }
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (tmpRNG == NULL)
+ return WOLFSSL_FATAL_ERROR;
+#endif
+
+ if (wc_InitRng(tmpRNG) == 0) {
+ rng = tmpRNG;
+ initTmpRng = 1;
+ }
+ else {
+ WOLFSSL_MSG("Bad RNG Init, trying global");
+ if (initGlobalRNG == 0)
+ WOLFSSL_MSG("Global RNG no Init");
+ else
+ rng = &globalRNG;
+ }
+
+ if (rng) {
+ if (DsaSign(d, sigRet, (DsaKey*)dsa->internal, rng) < 0)
+ WOLFSSL_MSG("DsaSign failed");
+ else
+ ret = WOLFSSL_SUCCESS;
+ }
+
+ if (initTmpRng)
+ wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+ return ret;
+}
+
+#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS)
+WOLFSSL_DSA_SIG* wolfSSL_DSA_do_sign_ex(const unsigned char* digest,
+ int outLen, WOLFSSL_DSA* dsa)
+{
+ WOLFSSL_DSA_SIG* sig = NULL;
+ byte sigBin[DSA_SIG_SIZE];
+
+ WOLFSSL_ENTER("wolfSSL_DSA_do_sign_ex");
+
+ if (!digest || !dsa || outLen != WC_SHA_DIGEST_SIZE) {
+ WOLFSSL_MSG("Bad function arguments");
+ return NULL;
+ }
+
+ if (wolfSSL_DSA_do_sign(digest, sigBin, dsa) != WOLFSSL_SUCCESS) {
+ return NULL;
+ }
+
+ if (!(sig = wolfSSL_DSA_SIG_new())) {
+ goto error;
+ }
+
+ if (!(sig->r = wolfSSL_BN_bin2bn(sigBin, DSA_HALF_SIZE, NULL))) {
+ goto error;
+ }
+
+ if (!(sig->s = wolfSSL_BN_bin2bn(sigBin + DSA_HALF_SIZE, DSA_HALF_SIZE, NULL))) {
+ goto error;
+ }
+
+ return sig;
+error:
+ if (sig) {
+ wolfSSL_DSA_SIG_free(sig);
+ }
+ return NULL;
+}
+#endif /* !HAVE_SELFTEST && !HAVE_FIPS */
+
+int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig,
+ WOLFSSL_DSA* dsa, int *dsacheck)
+{
+ int ret = WOLFSSL_FATAL_ERROR;
+
+ WOLFSSL_ENTER("wolfSSL_DSA_do_verify");
+
+ if (d == NULL || sig == NULL || dsa == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ if (dsa->inSet == 0)
+ {
+ WOLFSSL_MSG("No DSA internal set, do it");
+
+ if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetDsaInternal failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ ret = DsaVerify(d, sig, (DsaKey*)dsa->internal, dsacheck);
+ if (ret != 0 || *dsacheck != 1) {
+ WOLFSSL_MSG("DsaVerify failed");
+ return ret;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS)
+int wolfSSL_DSA_do_verify_ex(const unsigned char* digest, int digest_len,
+ WOLFSSL_DSA_SIG* sig, WOLFSSL_DSA* dsa)
+{
+ int dsacheck, sz;
+ byte sigBin[DSA_SIG_SIZE];
+ byte* sigBinPtr = sigBin;
+
+ WOLFSSL_ENTER("wolfSSL_DSA_do_verify_ex");
+
+ if (!digest || !sig || !dsa || digest_len != WC_SHA_DIGEST_SIZE) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (!sig->r || !sig->s) {
+ WOLFSSL_MSG("No signature found in DSA_SIG");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* front pad with zeros */
+ if (!(sz = wolfSSL_BN_num_bytes(sig->r))) {
+ return WOLFSSL_FAILURE;
+ }
+ while (sz++ < DSA_HALF_SIZE) {
+ *sigBinPtr++ = 0;
+ }
+
+ if (wolfSSL_BN_bn2bin(sig->r, sigBinPtr) == WOLFSSL_FATAL_ERROR) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Move to s */
+ sigBinPtr = sigBin + DSA_HALF_SIZE;
+
+ /* front pad with zeros */
+ if (!(sz = wolfSSL_BN_num_bytes(sig->s))) {
+ return WOLFSSL_FAILURE;
+ }
+ while (sz++ < DSA_HALF_SIZE) {
+ *sigBinPtr++ = 0;
+ }
+
+ if (wolfSSL_BN_bn2bin(sig->s, sigBinPtr) == WOLFSSL_FATAL_ERROR) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_DSA_do_verify(digest, sigBin, dsa, &dsacheck) != WOLFSSL_SUCCESS ||
+ dsacheck != 1) {
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* !HAVE_SELFTEST && !HAVE_FIPS */
#endif /* NO_DSA */
-#ifndef NO_RSA
-/* return SSL_SUCCES on ok, 0 otherwise */
+#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+
+#ifdef DEBUG_SIGN
+static void show(const char *title, const unsigned char *out, unsigned int outlen)
+{
+ const unsigned char *pt;
+ printf("%s[%d] = \n", title, (int)outlen);
+ outlen = outlen>100?100:outlen;
+ for (pt = out; pt < out + outlen;
+ printf("%c", ((*pt)&0x6f)>='A'?((*pt)&0x6f):'.'), pt++);
+ printf("\n");
+}
+#else
+#define show(a,b,c)
+#endif
+
+/* return SSL_SUCCESS on ok, 0 otherwise */
int wolfSSL_RSA_sign(int type, const unsigned char* m,
unsigned int mLen, unsigned char* sigRet,
unsigned int* sigLen, WOLFSSL_RSA* rsa)
{
- word32 outLen;
- word32 signSz;
- int initTmpRng = 0;
- RNG* rng = NULL;
- int ret = 0;
+ return wolfSSL_RSA_sign_ex(type, m, mLen, sigRet, sigLen, rsa, 1);
+}
+
+int wolfSSL_RSA_sign_ex(int type, const unsigned char* m,
+ unsigned int mLen, unsigned char* sigRet,
+ unsigned int* sigLen, WOLFSSL_RSA* rsa, int flag)
+{
+ word32 outLen;
+ word32 signSz;
+ int initTmpRng = 0;
+ WC_RNG* rng = NULL;
+ int ret = 0;
#ifdef WOLFSSL_SMALL_STACK
- RNG* tmpRNG = NULL;
- byte* encodedSig = NULL;
+ WC_RNG* tmpRNG = NULL;
+ byte* encodedSig = NULL;
#else
- RNG tmpRNG[1];
- byte encodedSig[MAX_ENCODED_SIG_SZ];
+ WC_RNG tmpRNG[1];
+ byte encodedSig[MAX_ENCODED_SIG_SZ];
#endif
- WOLFSSL_MSG("wolfSSL_RSA_sign");
+ WOLFSSL_ENTER("wolfSSL_RSA_sign");
- if (m == NULL || sigRet == NULL || sigLen == NULL || rsa == NULL)
+ if (m == NULL || sigRet == NULL || sigLen == NULL || rsa == NULL) {
WOLFSSL_MSG("Bad function arguments");
- else if (rsa->inSet == 0)
- WOLFSSL_MSG("No RSA internal set");
- else if (type != NID_md5 && type != NID_sha1)
- WOLFSSL_MSG("Bad md type");
- else {
- outLen = (word32)wolfSSL_BN_num_bytes(rsa->n);
+ return 0;
+ }
+ show("Message to Sign", m, mLen);
- #ifdef WOLFSSL_SMALL_STACK
- tmpRNG = (RNG*)XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (tmpRNG == NULL)
+ switch (type) {
+ #ifdef WOLFSSL_MD2
+ case NID_md2: type = MD2h; break;
+ #endif
+ #ifndef NO_MD5
+ case NID_md5: type = MD5h; break;
+ #endif
+ #ifndef NO_SHA
+ case NID_sha1: type = SHAh; break;
+ #endif
+ #ifndef NO_SHA256
+ case NID_sha256: type = SHA256h; break;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case NID_sha384: type = SHA384h; break;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case NID_sha512: type = SHA512h; break;
+ #endif
+ #ifndef WOLFSSL_NOSHA3_224
+ case NID_sha3_224: type = SHA3_224h; break;
+ #endif
+ #ifndef WOLFSSL_NOSHA3_256
+ case NID_sha3_256: type = SHA3_256h; break;
+ #endif
+ #ifndef WOLFSSL_NOSHA3_384
+ case NID_sha3_384: type = SHA3_384h; break;
+ #endif
+ #ifndef WOLFSSL_NOSHA3_512
+ case NID_sha3_512: type = SHA3_512h; break;
+ #endif
+ default:
+ WOLFSSL_MSG("This NID (md type) not configured or not implemented");
return 0;
+ }
- encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (encodedSig == NULL) {
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (rsa->inSet == 0)
+ {
+ WOLFSSL_MSG("No RSA internal set, do it");
+
+ if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetRsaInternal failed");
return 0;
}
- #endif
+ }
- if (outLen == 0)
- WOLFSSL_MSG("Bad RSA size");
- else if (wc_InitRng(tmpRNG) == 0) {
- rng = tmpRNG;
- initTmpRng = 1;
- }
- else {
- WOLFSSL_MSG("Bad RNG Init, trying global");
+ outLen = (word32)wolfSSL_BN_num_bytes(rsa->n);
- if (initGlobalRNG == 0)
- WOLFSSL_MSG("Global RNG no Init");
- else
- rng = &globalRNG;
- }
+#ifdef WOLFSSL_SMALL_STACK
+ tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (tmpRNG == NULL)
+ return 0;
+
+ encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
+ DYNAMIC_TYPE_SIGNATURE);
+ if (encodedSig == NULL) {
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+ return 0;
+ }
+#endif
+
+ if (outLen == 0)
+ WOLFSSL_MSG("Bad RSA size");
+ else if (wc_InitRng(tmpRNG) == 0) {
+ rng = tmpRNG;
+ initTmpRng = 1;
+ }
+ else {
+ WOLFSSL_MSG("Bad RNG Init, trying global");
+
+ if (initGlobalRNG == 0)
+ WOLFSSL_MSG("Global RNG no Init");
+ else
+ rng = &globalRNG;
}
if (rng) {
- type = (type == NID_md5) ? MD5h : SHAh;
signSz = wc_EncodeSignature(encodedSig, m, mLen, type);
if (signSz == 0) {
WOLFSSL_MSG("Bad Encode Signature");
}
else {
- *sigLen = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen,
- (RsaKey*)rsa->internal, rng);
- if (*sigLen <= 0)
- WOLFSSL_MSG("Bad Rsa Sign");
- else
+ show("Encoded Message", encodedSig, signSz);
+ if (flag != 0) {
+ ret = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen,
+ (RsaKey*)rsa->internal, rng);
+ if (ret <= 0) {
+ WOLFSSL_MSG("Bad Rsa Sign");
+ ret = 0;
+ }
+ else {
+ *sigLen = (unsigned int)ret;
+ ret = SSL_SUCCESS;
+ show("Signature", sigRet, *sigLen);
+ }
+ } else {
ret = SSL_SUCCESS;
+ XMEMCPY(sigRet, encodedSig, signSz);
+ *sigLen = signSz;
+ }
}
}
@@ -12095,31 +30078,103 @@ int wolfSSL_RSA_sign(int type, const unsigned char* m,
wc_FreeRng(tmpRNG);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+ XFREE(encodedSig, NULL, DYNAMIC_TYPE_SIGNATURE);
#endif
- WOLFSSL_MSG("wolfSSL_RSA_sign success");
+ if (ret == WOLFSSL_SUCCESS)
+ WOLFSSL_MSG("wolfSSL_RSA_sign success");
+ else {
+ WOLFSSL_MSG("wolfSSL_RSA_sign failed");
+ }
return ret;
}
-int wolfSSL_RSA_public_decrypt(int flen, unsigned char* from,
- unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+/* returns WOLFSSL_SUCCESS on successful verify and WOLFSSL_FAILURE on fail */
+int wolfSSL_RSA_verify(int type, const unsigned char* m,
+ unsigned int mLen, const unsigned char* sig,
+ unsigned int sigLen, WOLFSSL_RSA* rsa)
{
- (void)flen;
- (void)from;
- (void)to;
- (void)rsa;
- (void)padding;
-
- WOLFSSL_MSG("wolfSSL_RSA_public_decrypt");
+ int ret;
+ unsigned char *sigRet ;
+ unsigned char *sigDec ;
+ unsigned int len;
- return SSL_FATAL_ERROR;
+ WOLFSSL_ENTER("wolfSSL_RSA_verify");
+ if ((m == NULL) || (sig == NULL)) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ sigRet = (unsigned char *)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (sigRet == NULL) {
+ WOLFSSL_MSG("Memory failure");
+ return WOLFSSL_FAILURE;
+ }
+ sigDec = (unsigned char *)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (sigDec == NULL) {
+ WOLFSSL_MSG("Memory failure");
+ XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+ /* get non-encrypted signature to be compared with decrypted signature */
+ ret = wolfSSL_RSA_sign_ex(type, m, mLen, sigRet, &len, rsa, 0);
+ if (ret <= 0) {
+ WOLFSSL_MSG("Message Digest Error");
+ XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+ show("Encoded Message", sigRet, len);
+ /* decrypt signature */
+ ret = wc_RsaSSL_Verify(sig, sigLen, (unsigned char *)sigDec, sigLen,
+ (RsaKey*)rsa->internal);
+ if (ret <= 0) {
+ WOLFSSL_MSG("RSA Decrypt error");
+ XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+ show("Decrypted Signature", sigDec, ret);
+
+ if ((int)len == ret && XMEMCMP(sigRet, sigDec, ret) == 0) {
+ WOLFSSL_MSG("wolfSSL_RSA_verify success");
+ XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_SUCCESS;
+ }
+ else {
+ WOLFSSL_MSG("wolfSSL_RSA_verify failed");
+ XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
}
+void wolfSSL_RSA_get0_key(const WOLFSSL_RSA *r, const WOLFSSL_BIGNUM **n,
+ const WOLFSSL_BIGNUM **e, const WOLFSSL_BIGNUM **d)
+{
+ WOLFSSL_ENTER("wolfSSL_RSA_get0_key");
-/* generate p-1 and q-1, SSL_SUCCESS on ok */
+ if (r != NULL) {
+ if (n != NULL)
+ *n = r->n;
+ if (e != NULL)
+ *e = r->e;
+ if (d != NULL)
+ *d = r->d;
+ } else {
+ if (n != NULL)
+ *n = NULL;
+ if (e != NULL)
+ *e = NULL;
+ if (d != NULL)
+ *d = NULL;
+ }
+}
+
+/* generate p-1 and q-1, WOLFSSL_SUCCESS on ok */
int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
{
int err;
@@ -12130,12 +30185,12 @@ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
if (rsa == NULL || rsa->p == NULL || rsa->q == NULL || rsa->d == NULL ||
rsa->dmp1 == NULL || rsa->dmq1 == NULL) {
WOLFSSL_MSG("rsa no init error");
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
if (mp_init(&tmp) != MP_OKAY) {
WOLFSSL_MSG("mp_init error");
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
err = mp_sub_d((mp_int*)rsa->p->internal, 1, &tmp);
@@ -12161,456 +30216,5327 @@ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
mp_clear(&tmp);
if (err == MP_OKAY)
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
else
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
+}
+#endif /* !NO_RSA && !HAVE_USER_RSA */
+
+WOLFSSL_HMAC_CTX* wolfSSL_HMAC_CTX_new(void)
+{
+ return (WOLFSSL_HMAC_CTX*)XMALLOC(sizeof(WOLFSSL_HMAC_CTX), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+}
+
+int wolfSSL_HMAC_CTX_Init(WOLFSSL_HMAC_CTX* ctx)
+{
+ WOLFSSL_MSG("wolfSSL_HMAC_CTX_Init");
+
+ if (ctx != NULL) {
+ /* wc_HmacSetKey sets up ctx->hmac */
+ XMEMSET(ctx, 0, sizeof(WOLFSSL_HMAC_CTX));
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key,
+ int keylen, const EVP_MD* type, WOLFSSL_ENGINE* e)
+{
+ WOLFSSL_ENTER("wolfSSL_HMAC_Init_ex");
+
+ /* WOLFSSL_ENGINE not used, call wolfSSL_HMAC_Init */
+ (void)e;
+ return wolfSSL_HMAC_Init(ctx, key, keylen, type);
+}
+
+
+/* helper function for Deep copy of internal wolfSSL hmac structure
+ * returns WOLFSSL_SUCCESS on success */
+int wolfSSL_HmacCopy(Hmac* des, Hmac* src)
+{
+ void* heap;
+
+#ifndef HAVE_FIPS
+ heap = src->heap;
+#else
+ heap = NULL;
+#endif
+ if (wc_HmacInit(des, heap, 0) != 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* requires that hash structures have no dynamic parts to them */
+ switch (src->macType) {
+ #ifndef NO_MD5
+ case WC_MD5:
+ wc_Md5Copy(&src->hash.md5, &des->hash.md5);
+ break;
+ #endif /* !NO_MD5 */
+
+ #ifndef NO_SHA
+ case WC_SHA:
+ wc_ShaCopy(&src->hash.sha, &des->hash.sha);
+ break;
+ #endif /* !NO_SHA */
+
+ #ifdef WOLFSSL_SHA224
+ case WC_SHA224:
+ wc_Sha224Copy(&src->hash.sha224, &des->hash.sha224);
+ break;
+ #endif /* WOLFSSL_SHA224 */
+
+ #ifndef NO_SHA256
+ case WC_SHA256:
+ wc_Sha256Copy(&src->hash.sha256, &des->hash.sha256);
+ break;
+ #endif /* !NO_SHA256 */
+
+ #ifdef WOLFSSL_SHA384
+ case WC_SHA384:
+ wc_Sha384Copy(&src->hash.sha384, &des->hash.sha384);
+ break;
+ #endif /* WOLFSSL_SHA384 */
+ #ifdef WOLFSSL_SHA512
+ case WC_SHA512:
+ wc_Sha512Copy(&src->hash.sha512, &des->hash.sha512);
+ break;
+ #endif /* WOLFSSL_SHA512 */
+
+ default:
+ return WOLFSSL_FAILURE;
+ }
+
+ XMEMCPY((byte*)des->ipad, (byte*)src->ipad, WC_HMAC_BLOCK_SIZE);
+ XMEMCPY((byte*)des->opad, (byte*)src->opad, WC_HMAC_BLOCK_SIZE);
+ XMEMCPY((byte*)des->innerHash, (byte*)src->innerHash, WC_MAX_DIGEST_SIZE);
+#ifndef HAVE_FIPS
+ des->heap = heap;
+#endif
+ des->macType = src->macType;
+ des->innerHashKeyed = src->innerHashKeyed;
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ XMEMCPY(&des->asyncDev, &src->asyncDev, sizeof(WC_ASYNC_DEV));
+ des->keyLen = src->keyLen;
+ #ifdef HAVE_CAVIUM
+ des->data = (byte*)XMALLOC(src->dataLen, des->heap,
+ DYNAMIC_TYPE_HMAC);
+ if (des->data == NULL) {
+ return BUFFER_E;
+ }
+ XMEMCPY(des->data, src->data, src->dataLen);
+ des->dataLen = src->dataLen;
+ #endif /* HAVE_CAVIUM */
+#endif /* WOLFSSL_ASYNC_CRYPT */
+ return WOLFSSL_SUCCESS;
+}
+
+
+/* Deep copy of information from src to des structure
+ *
+ * des destination to copy information to
+ * src structure to get information from
+ *
+ * Returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error
+ */
+int wolfSSL_HMAC_CTX_copy(WOLFSSL_HMAC_CTX* des, WOLFSSL_HMAC_CTX* src)
+{
+ WOLFSSL_ENTER("wolfSSL_HMAC_CTX_copy");
+
+ if (des == NULL || src == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ des->type = src->type;
+ XMEMCPY((byte *)&des->save_ipad, (byte *)&src->hmac.ipad,
+ WC_HMAC_BLOCK_SIZE);
+ XMEMCPY((byte *)&des->save_opad, (byte *)&src->hmac.opad,
+ WC_HMAC_BLOCK_SIZE);
+
+ return wolfSSL_HmacCopy(&des->hmac, &src->hmac);
}
-#endif /* NO_RSA */
-void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen,
+#if defined(HAVE_FIPS) && \
+ (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+
+static int _HMAC_Init(Hmac* hmac, int type, void* heap)
+{
+ int ret = 0;
+
+ switch (type) {
+ #ifndef NO_MD5
+ case WC_MD5:
+ ret = wc_InitMd5(&hmac->hash.md5);
+ break;
+ #endif /* !NO_MD5 */
+
+ #ifndef NO_SHA
+ case WC_SHA:
+ ret = wc_InitSha(&hmac->hash.sha);
+ break;
+ #endif /* !NO_SHA */
+
+ #ifdef WOLFSSL_SHA224
+ case WC_SHA224:
+ ret = wc_InitSha224(&hmac->hash.sha224);
+ break;
+ #endif /* WOLFSSL_SHA224 */
+
+ #ifndef NO_SHA256
+ case WC_SHA256:
+ ret = wc_InitSha256(&hmac->hash.sha256);
+ break;
+ #endif /* !NO_SHA256 */
+
+ #ifdef WOLFSSL_SHA384
+ case WC_SHA384:
+ ret = wc_InitSha384(&hmac->hash.sha384);
+ break;
+ #endif /* WOLFSSL_SHA384 */
+ #ifdef WOLFSSL_SHA512
+ case WC_SHA512:
+ ret = wc_InitSha512(&hmac->hash.sha512);
+ break;
+ #endif /* WOLFSSL_SHA512 */
+
+ #ifdef WOLFSSL_SHA3
+ case WC_SHA3_224:
+ ret = wc_InitSha3_224(&hmac->hash.sha3, heap, INVALID_DEVID);
+ break;
+ case WC_SHA3_256:
+ ret = wc_InitSha3_256(&hmac->hash.sha3, heap, INVALID_DEVID);
+ break;
+ case WC_SHA3_384:
+ ret = wc_InitSha3_384(&hmac->hash.sha3, heap, INVALID_DEVID);
+ break;
+ case WC_SHA3_512:
+ ret = wc_InitSha3_512(&hmac->hash.sha3, heap, INVALID_DEVID);
+ break;
+ #endif
+
+ default:
+ ret = BAD_FUNC_ARG;
+ break;
+ }
+
+ (void)heap;
+
+ return ret;
+}
+
+#else
+ #define _HMAC_Init _InitHmac
+#endif
+
+
+int wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen,
const EVP_MD* type)
{
+ int hmac_error = 0;
+ void* heap = NULL;
+
WOLFSSL_MSG("wolfSSL_HMAC_Init");
if (ctx == NULL) {
WOLFSSL_MSG("no ctx on init");
- return;
+ return WOLFSSL_FAILURE;
}
+#ifndef HAVE_FIPS
+ heap = ctx->hmac.heap;
+#endif
+
if (type) {
WOLFSSL_MSG("init has type");
+#ifndef NO_MD5
if (XSTRNCMP(type, "MD5", 3) == 0) {
WOLFSSL_MSG("md5 hmac");
- ctx->type = MD5;
+ ctx->type = WC_MD5;
}
- else if (XSTRNCMP(type, "SHA256", 6) == 0) {
+ else
+#endif
+#ifdef WOLFSSL_SHA224
+ if (XSTRNCMP(type, "SHA224", 6) == 0) {
+ WOLFSSL_MSG("sha224 hmac");
+ ctx->type = WC_SHA224;
+ }
+ else
+#endif
+#ifndef NO_SHA256
+ if (XSTRNCMP(type, "SHA256", 6) == 0) {
WOLFSSL_MSG("sha256 hmac");
- ctx->type = SHA256;
+ ctx->type = WC_SHA256;
}
+ else
+#endif
+#ifdef WOLFSSL_SHA384
+ if (XSTRNCMP(type, "SHA384", 6) == 0) {
+ WOLFSSL_MSG("sha384 hmac");
+ ctx->type = WC_SHA384;
+ }
+ else
+#endif
+#ifdef WOLFSSL_SHA512
+ if (XSTRNCMP(type, "SHA512", 6) == 0) {
+ WOLFSSL_MSG("sha512 hmac");
+ ctx->type = WC_SHA512;
+ }
+ else
+#endif
+#ifndef NO_SHA
/* has to be last since would pick or 256, 384, or 512 too */
- else if (XSTRNCMP(type, "SHA", 3) == 0) {
+ if (XSTRNCMP(type, "SHA", 3) == 0) {
WOLFSSL_MSG("sha hmac");
- ctx->type = SHA;
+ ctx->type = WC_SHA;
}
- else {
+ else
+#endif
+ {
WOLFSSL_MSG("bad init type");
+ return WOLFSSL_FAILURE;
}
}
if (key && keylen) {
WOLFSSL_MSG("keying hmac");
- wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key, (word32)keylen);
+
+ if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) {
+ hmac_error = wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key,
+ (word32)keylen);
+ if (hmac_error < 0){
+ wc_HmacFree(&ctx->hmac);
+ return WOLFSSL_FAILURE;
+ }
+ XMEMCPY((byte *)&ctx->save_ipad, (byte *)&ctx->hmac.ipad,
+ WC_HMAC_BLOCK_SIZE);
+ XMEMCPY((byte *)&ctx->save_opad, (byte *)&ctx->hmac.opad,
+ WC_HMAC_BLOCK_SIZE);
+ }
/* OpenSSL compat, no error */
+ } else if(ctx->type >= 0) { /* MD5 == 0 */
+ WOLFSSL_MSG("recover hmac");
+ wc_HmacFree(&ctx->hmac);
+ if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) {
+ ctx->hmac.macType = (byte)ctx->type;
+ ctx->hmac.innerHashKeyed = 0;
+ XMEMCPY((byte *)&ctx->hmac.ipad, (byte *)&ctx->save_ipad,
+ WC_HMAC_BLOCK_SIZE);
+ XMEMCPY((byte *)&ctx->hmac.opad, (byte *)&ctx->save_opad,
+ WC_HMAC_BLOCK_SIZE);
+ if ((hmac_error = _HMAC_Init(&ctx->hmac, ctx->hmac.macType, heap))
+ !=0) {
+ return hmac_error;
+ }
+ }
}
+
+ (void)hmac_error;
+
+ return WOLFSSL_SUCCESS;
}
-void wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data,
+int wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data,
int len)
{
+ int hmac_error = 0;
+
WOLFSSL_MSG("wolfSSL_HMAC_Update");
- if (ctx && data) {
+ if (ctx == NULL) {
+ WOLFSSL_MSG("no ctx");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (data) {
WOLFSSL_MSG("updating hmac");
- wc_HmacUpdate(&ctx->hmac, data, (word32)len);
- /* OpenSSL compat, no error */
+ hmac_error = wc_HmacUpdate(&ctx->hmac, data, (word32)len);
+ if (hmac_error < 0){
+ WOLFSSL_MSG("hmac update error");
+ return WOLFSSL_FAILURE;
+ }
}
+
+ return WOLFSSL_SUCCESS;
}
-void wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash,
+int wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash,
unsigned int* len)
{
+ int hmac_error;
+
WOLFSSL_MSG("wolfSSL_HMAC_Final");
- if (ctx && hash) {
- WOLFSSL_MSG("final hmac");
- wc_HmacFinal(&ctx->hmac, hash);
- /* OpenSSL compat, no error */
+ /* "len" parameter is optional. */
+ if (ctx == NULL || hash == NULL) {
+ WOLFSSL_MSG("invalid parameter");
+ return WOLFSSL_FAILURE;
+ }
- if (len) {
- WOLFSSL_MSG("setting output len");
- switch (ctx->type) {
- case MD5:
- *len = MD5_DIGEST_SIZE;
- break;
+ WOLFSSL_MSG("final hmac");
+ hmac_error = wc_HmacFinal(&ctx->hmac, hash);
+ if (hmac_error < 0){
+ WOLFSSL_MSG("final hmac error");
+ return WOLFSSL_FAILURE;
+ }
- case SHA:
- *len = SHA_DIGEST_SIZE;
- break;
+ if (len) {
+ WOLFSSL_MSG("setting output len");
+ switch (ctx->type) {
+ #ifndef NO_MD5
+ case WC_MD5:
+ *len = WC_MD5_DIGEST_SIZE;
+ break;
+ #endif
- case SHA256:
- *len = SHA256_DIGEST_SIZE;
- break;
+ #ifndef NO_SHA
+ case WC_SHA:
+ *len = WC_SHA_DIGEST_SIZE;
+ break;
+ #endif
- default:
- WOLFSSL_MSG("bad hmac type");
+ #ifdef WOLFSSL_SHA224
+ case WC_SHA224:
+ *len = WC_SHA224_DIGEST_SIZE;
+ break;
+ #endif
+
+ #ifndef NO_SHA256
+ case WC_SHA256:
+ *len = WC_SHA256_DIGEST_SIZE;
+ break;
+ #endif
+
+ #ifdef WOLFSSL_SHA384
+ case WC_SHA384:
+ *len = WC_SHA384_DIGEST_SIZE;
+ break;
+ #endif
+
+ #ifdef WOLFSSL_SHA512
+ case WC_SHA512:
+ *len = WC_SHA512_DIGEST_SIZE;
+ break;
+ #endif
+
+ default:
+ WOLFSSL_MSG("bad hmac type");
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx)
+{
+ WOLFSSL_MSG("wolfSSL_HMAC_cleanup");
+
+ if (ctx)
+ wc_HmacFree(&ctx->hmac);
+
+ return SSL_SUCCESS;
+}
+
+
+void wolfSSL_HMAC_CTX_free(WOLFSSL_HMAC_CTX* ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ wolfSSL_HMAC_cleanup(ctx);
+ XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+size_t wolfSSL_HMAC_size(const WOLFSSL_HMAC_CTX *ctx)
+{
+ if (!ctx) {
+ return 0;
+ }
+
+ return (size_t)wc_HashGetDigestSize((enum wc_HashType)ctx->hmac.macType);
+}
+
+#ifndef NO_DES3
+
+void wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset,
+ unsigned char* iv, int len)
+{
+ (void)len;
+
+ WOLFSSL_MSG("wolfSSL_3des_iv");
+
+ if (ctx == NULL || iv == NULL) {
+ WOLFSSL_MSG("Bad function argument");
+ return;
+ }
+
+ if (doset)
+ wc_Des3_SetIV(&ctx->cipher.des3, iv); /* OpenSSL compat, no ret */
+ else
+ XMEMCPY(iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE);
+}
+
+#endif /* NO_DES3 */
+
+
+#ifndef NO_AES
+
+void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset,
+ unsigned char* iv, int len)
+{
+ (void)len;
+
+ WOLFSSL_MSG("wolfSSL_aes_ctr_iv");
+
+ if (ctx == NULL || iv == NULL) {
+ WOLFSSL_MSG("Bad function argument");
+ return;
+ }
+
+ if (doset)
+ (void)wc_AesSetIV(&ctx->cipher.aes, iv); /* OpenSSL compat, no ret */
+ else
+ XMEMCPY(iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
+}
+
+#endif /* NO_AES */
+
+
+/* Free the dynamically allocated data.
+ *
+ * p Pointer to dynamically allocated memory.
+ */
+void wolfSSL_OPENSSL_free(void* p)
+{
+ WOLFSSL_MSG("wolfSSL_OPENSSL_free");
+
+ XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+void *wolfSSL_OPENSSL_malloc(size_t a)
+{
+ return XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+#if defined(WOLFSSL_KEY_GEN) && defined(WOLFSSL_PEM_TO_DER)
+
+static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher,
+ unsigned char* passwd, int passwdSz, byte **cipherInfo)
+{
+ int ret, paddingSz;
+ word32 idx, cipherInfoSz;
+#ifdef WOLFSSL_SMALL_STACK
+ EncryptedInfo* info = NULL;
+#else
+ EncryptedInfo info[1];
+#endif
+
+ WOLFSSL_ENTER("EncryptDerKey");
+
+ if (der == NULL || derSz == NULL || cipher == NULL ||
+ passwd == NULL || cipherInfo == NULL)
+ return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_SMALL_STACK
+ info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
+ DYNAMIC_TYPE_ENCRYPTEDINFO);
+ if (info == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ return WOLFSSL_FAILURE;
+ }
+#endif
+
+ XMEMSET(info, 0, sizeof(EncryptedInfo));
+
+ /* set the cipher name on info */
+ XSTRNCPY(info->name, cipher, NAME_SZ-1);
+ info->name[NAME_SZ-1] = '\0'; /* null term */
+
+ ret = wc_EncryptedInfoGet(info, info->name);
+ if (ret != 0) {
+ WOLFSSL_MSG("unsupported cipher");
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+ #endif
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Generate a random salt */
+ if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("generate iv failed");
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+ return WOLFSSL_FAILURE;
+ }
+
+ /* add the padding before encryption */
+ paddingSz = ((*derSz)/info->ivSz + 1) * info->ivSz - (*derSz);
+ if (paddingSz == 0)
+ paddingSz = info->ivSz;
+ XMEMSET(der+(*derSz), (byte)paddingSz, paddingSz);
+ (*derSz) += paddingSz;
+
+ /* encrypt buffer */
+ if (wc_BufferKeyEncrypt(info, der, *derSz, passwd, passwdSz, WC_MD5) != 0) {
+ WOLFSSL_MSG("encrypt key failed");
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+ return WOLFSSL_FAILURE;
+ }
+
+ /* create cipher info : 'cipher_name,Salt(hex)' */
+ cipherInfoSz = (word32)(2*info->ivSz + XSTRLEN(info->name) + 2);
+ *cipherInfo = (byte*)XMALLOC(cipherInfoSz, NULL,
+ DYNAMIC_TYPE_STRING);
+ if (*cipherInfo == NULL) {
+ WOLFSSL_MSG("malloc failed");
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+ return WOLFSSL_FAILURE;
+ }
+ XSTRNCPY((char*)*cipherInfo, info->name, cipherInfoSz);
+ XSTRNCAT((char*)*cipherInfo, ",", 2);
+
+ idx = (word32)XSTRLEN((char*)*cipherInfo);
+ cipherInfoSz -= idx;
+ ret = Base16_Encode(info->iv, info->ivSz, *cipherInfo+idx, &cipherInfoSz);
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+ if (ret != 0) {
+ WOLFSSL_MSG("Base16_Encode failed");
+ XFREE(*cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_KEY_GEN || WOLFSSL_PEM_TO_DER */
+
+#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+static int wolfSSL_RSA_To_Der(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey)
+{
+ int derSz = 0;
+ int ret;
+ byte* derBuf;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_To_Der");
+
+ if (!rsa || (publicKey != 0 && publicKey != 1)) {
+ WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", BAD_FUNC_ARG);
+ return BAD_FUNC_ARG;
+ }
+
+ if (rsa->inSet == 0) {
+ if ((ret = SetRsaInternal(rsa)) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetRsaInternal() Failed");
+ WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", ret);
+ return ret;
+ }
+ }
+
+ if (publicKey) {
+ if ((derSz = wc_RsaPublicKeyDerSize((RsaKey *)rsa->internal, 1)) < 0) {
+ WOLFSSL_MSG("wc_RsaPublicKeyDerSize failed");
+ WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", derSz);
+ return derSz;
+ }
+ }
+ else {
+ if ((derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, NULL, 0)) < 0) {
+ WOLFSSL_MSG("wc_RsaKeyToDer failed");
+ WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", derSz);
+ return derSz;
+ }
+ }
+
+ if (outBuf) {
+ if (!(derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER))) {
+ WOLFSSL_MSG("malloc failed");
+ WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", MEMORY_ERROR);
+ return MEMORY_ERROR;
+ }
+
+ /* Key to DER */
+ if (publicKey) {
+ derSz = wc_RsaKeyToPublicDer((RsaKey*)rsa->internal, derBuf, derSz);
+ }
+ else {
+ derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, derBuf, derSz);
+ }
+
+ if (derSz < 0) {
+ WOLFSSL_MSG("wc_RsaKeyToPublicDer failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ else {
+ if (*outBuf) {
+ XMEMCPY(*outBuf, derBuf, derSz);
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ else {
+ *outBuf = derBuf;
}
}
}
+
+ WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", derSz);
+ return derSz;
}
+#endif
+#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA)
-void wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx)
+/* Takes a WOLFSSL_RSA key and writes it out to a WOLFSSL_BIO
+ *
+ * bio the WOLFSSL_BIO to write to
+ * key the WOLFSSL_RSA key to write out
+ * cipher cipher used
+ * passwd password string if used
+ * len length of password string
+ * cb password callback to use
+ * arg null terminated string for passphrase
+ */
+int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* key,
+ const WOLFSSL_EVP_CIPHER* cipher,
+ unsigned char* passwd, int len,
+ pem_password_cb* cb, void* arg)
{
- (void)ctx;
+ int ret;
+ WOLFSSL_EVP_PKEY* pkey;
- WOLFSSL_MSG("wolfSSL_HMAC_cleanup");
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSAPrivateKey");
+
+ if (bio == NULL || key == NULL) {
+ WOLFSSL_MSG("Bad Function Arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
+ if (pkey == NULL) {
+ WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ pkey->type = EVP_PKEY_RSA;
+ pkey->rsa = key;
+ pkey->ownRsa = 0;
+#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+ /* similar to how wolfSSL_PEM_write_mem_RSAPrivateKey finds DER of key */
+ {
+ int derSz;
+ byte* derBuf = NULL;
+
+ if ((derSz = wolfSSL_RSA_To_Der(key, &derBuf, 0)) < 0) {
+ WOLFSSL_MSG("wolfSSL_RSA_To_Der failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (pkey->pkey.ptr == NULL) {
+ WOLFSSL_MSG("key malloc failed");
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+ pkey->pkey_sz = derSz;
+ XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+
+ ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len,
+ cb, arg);
+
+ wolfSSL_EVP_PKEY_free(pkey);
+
+ return ret;
+}
+
+#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+/* Takes an RSA public key and writes it out to a WOLFSSL_BIO
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+int wolfSSL_PEM_write_bio_RSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa)
+{
+ int ret = 0, derSz = 0;
+ byte *derBuf = NULL;
+ WOLFSSL_EVP_PKEY* pkey = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSA_PUBKEY");
+
+ if (bio == NULL || rsa == NULL) {
+ WOLFSSL_MSG("Bad Function Arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Initialize pkey structure */
+ pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
+ if (pkey == NULL) {
+ WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ pkey->type = EVP_PKEY_RSA;
+ pkey->rsa = rsa;
+ pkey->ownRsa = 0;
+
+ if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1)) < 0) {
+ WOLFSSL_MSG("wolfSSL_RSA_To_Der failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (pkey->pkey.ptr == NULL) {
+ WOLFSSL_MSG("key malloc failed");
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+ pkey->pkey_sz = derSz;
+ XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ ret = wolfSSL_PEM_write_bio_PUBKEY(bio, pkey);
+ wolfSSL_EVP_PKEY_free(pkey);
+
+ return ret;
+}
+#endif
+
+
+/* Reads an RSA public key from a WOLFSSL_BIO into a WOLFSSL_RSA
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+WOLFSSL_RSA *wolfSSL_PEM_read_bio_RSA_PUBKEY(WOLFSSL_BIO* bio,WOLFSSL_RSA** rsa,
+ pem_password_cb* cb, void *pass)
+{
+ WOLFSSL_EVP_PKEY* pkey;
+ WOLFSSL_RSA* local;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_RSA_PUBKEY");
+
+ pkey = wolfSSL_PEM_read_bio_PUBKEY(bio, NULL, cb, pass);
+ if (pkey == NULL) {
+ return NULL;
+ }
+
+ /* Since the WOLFSSL_RSA structure is being taken from WOLFSSL_EVP_PKEY the
+ * flag indicating that the WOLFSSL_RSA structure is owned should be FALSE
+ * to avoid having it free'd */
+ pkey->ownRsa = 0;
+ local = pkey->rsa;
+ if (rsa != NULL){
+ *rsa = local;
+ }
+
+ wolfSSL_EVP_PKEY_free(pkey);
+ return local;
}
+#endif /* defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) && !defined(NO_RSA) */
-const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int id)
+/* Takes a public key and writes it out to a WOLFSSL_BIO
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+int wolfSSL_PEM_write_bio_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key)
{
- WOLFSSL_MSG("wolfSSL_get_digestbynid");
+ byte* keyDer;
+ int pemSz;
+ int ret;
+ byte* tmp;
- switch(id) {
-#ifndef NO_MD5
- case NID_md5:
- return wolfSSL_EVP_md5();
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PUBKEY");
+
+ if (bio == NULL || key == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ keyDer = (byte*)key->pkey.ptr;
+
+ pemSz = wc_DerToPem(keyDer, key->pkey_sz, NULL, 0, PUBLICKEY_TYPE);
+ if (pemSz < 0) {
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PUBKEY", pemSz);
+ return WOLFSSL_FAILURE;
+ }
+ tmp = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ if (tmp == NULL) {
+ return MEMORY_E;
+ }
+
+ ret = wc_DerToPemEx(keyDer, key->pkey_sz, tmp, pemSz,
+ NULL, PUBLICKEY_TYPE);
+ if (ret < 0) {
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PUBKEY", ret);
+ XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ return WOLFSSL_FAILURE;
+ }
+
+ ret = wolfSSL_BIO_write(bio, tmp, pemSz);
+ XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ if (ret != pemSz) {
+ WOLFSSL_MSG("Unable to write full PEM to BIO");
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* Takes a private key and writes it out to a WOLFSSL_BIO
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key,
+ const WOLFSSL_EVP_CIPHER* cipher,
+ unsigned char* passwd, int len,
+ pem_password_cb* cb, void* arg)
+{
+ byte* keyDer;
+ int pemSz;
+ int type;
+ int ret;
+ byte* tmp;
+
+ (void)cipher;
+ (void)passwd;
+ (void)len;
+ (void)cb;
+ (void)arg;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey");
+
+ if (bio == NULL || key == NULL) {
+ WOLFSSL_MSG("Bad Function Arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ keyDer = (byte*)key->pkey.ptr;
+
+ switch (key->type) {
+#ifndef NO_RSA
+ case EVP_PKEY_RSA:
+ type = PRIVATEKEY_TYPE;
+ break;
#endif
-#ifndef NO_SHA
- case NID_sha1:
- return wolfSSL_EVP_sha1();
+
+#ifndef NO_DSA
+ case EVP_PKEY_DSA:
+ type = DSA_PRIVATEKEY_TYPE;
+ break;
#endif
+
+#ifdef HAVE_ECC
+ case EVP_PKEY_EC:
+ type = ECC_PRIVATEKEY_TYPE;
+ break;
+#endif
+
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+ case EVP_PKEY_DH:
+ type = DH_PRIVATEKEY_TYPE;
+ break;
+#endif
+
default:
- WOLFSSL_MSG("Bad digest id value");
+ WOLFSSL_MSG("Unknown Key type!");
+ type = PRIVATEKEY_TYPE;
+ }
+
+ pemSz = wc_DerToPem(keyDer, key->pkey_sz, NULL, 0, type);
+ if (pemSz < 0) {
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", pemSz);
+ return WOLFSSL_FAILURE;
+ }
+ tmp = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ if (tmp == NULL) {
+ return MEMORY_E;
+ }
+
+ ret = wc_DerToPemEx(keyDer, key->pkey_sz, tmp, pemSz,
+ NULL, type);
+ if (ret < 0) {
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", ret);
+ XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ return WOLFSSL_FAILURE;
+ }
+
+ ret = wolfSSL_BIO_write(bio, tmp, pemSz);
+ XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ if (ret != pemSz) {
+ WOLFSSL_MSG("Unable to write full PEM to BIO");
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) */
+
+#if (defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)) && \
+ (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM))
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher,
+ unsigned char* passwd, int passwdSz,
+ unsigned char **pem, int *plen)
+{
+ byte *derBuf = NULL, *tmp, *cipherInfo = NULL;
+ int derSz = 0;
+ const int type = PRIVATEKEY_TYPE;
+ const char* header = NULL;
+ const char* footer = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_mem_RSAPrivateKey");
+
+ if (pem == NULL || plen == NULL || rsa == NULL || rsa->internal == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wc_PemGetHeaderFooter(type, &header, &footer) != 0)
+ return WOLFSSL_FAILURE;
+
+ if (rsa->inSet == 0) {
+ WOLFSSL_MSG("No RSA internal set, do it");
+
+ if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetRsaInternal failed");
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 0)) < 0) {
+ WOLFSSL_MSG("wolfSSL_RSA_To_Der failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* encrypt DER buffer if required */
+ if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
+ int ret;
+
+ ret = EncryptDerKey(derBuf, &derSz, cipher,
+ passwd, passwdSz, &cipherInfo);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("EncryptDerKey failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ return ret;
+ }
+
+ /* tmp buffer with a max size */
+ *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+ (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE;
+ }
+ else {
+ /* tmp buffer with a max size */
+ *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+ (int)XSTRLEN(footer) + 1;
+ }
+
+ tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM);
+ if (tmp == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ if (cipherInfo != NULL)
+ XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* DER to PEM */
+ *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type);
+ if (*plen <= 0) {
+ WOLFSSL_MSG("wc_DerToPemEx failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+ if (cipherInfo != NULL)
+ XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+ return WOLFSSL_FAILURE;
+ }
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ if (cipherInfo != NULL)
+ XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+
+ *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY);
+ if (*pem == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+ return WOLFSSL_FAILURE;
+ }
+ XMEMSET(*pem, 0, (*plen)+1);
+
+ if (XMEMCPY(*pem, tmp, *plen) == NULL) {
+ WOLFSSL_MSG("XMEMCPY failed");
+ XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+ XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+ return WOLFSSL_FAILURE;
+ }
+ XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_RSAPrivateKey(XFILE fp, WOLFSSL_RSA *rsa,
+ const EVP_CIPHER *enc,
+ unsigned char *kstr, int klen,
+ pem_password_cb *cb, void *u)
+{
+ byte *pem;
+ int plen, ret;
+
+ (void)cb;
+ (void)u;
+
+ WOLFSSL_MSG("wolfSSL_PEM_write_RSAPrivateKey");
+
+ if (fp == XBADFILE || rsa == NULL || rsa->internal == NULL)
+ {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, enc, kstr, klen, &pem, &plen);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ ret = (int)XFWRITE(pem, plen, 1, fp);
+ if (ret != 1) {
+ WOLFSSL_MSG("RSA private key file write failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+ return WOLFSSL_SUCCESS;
+}
+#endif /* NO_FILESYSTEM */
+#endif /* WOLFSSL_KEY_GEN && !NO_RSA && !HAVE_USER_RSA && WOLFSSL_PEM_TO_DER */
+
+
+#ifdef HAVE_ECC
+
+#ifdef ALT_ECC_SIZE
+static int SetIndividualInternalEcc(WOLFSSL_BIGNUM* bn, mp_int* mpi)
+{
+ WOLFSSL_MSG("Entering SetIndividualInternal");
+
+ if (bn == NULL || bn->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (mpi == NULL) {
+ WOLFSSL_MSG("mpi NULL error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) {
+ WOLFSSL_MSG("mp_copy error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* ALT_ECC_SIZE */
+
+/* EC_POINT Openssl -> WolfSSL */
+static int SetECPointInternal(WOLFSSL_EC_POINT *p)
+{
+ ecc_point* point;
+ WOLFSSL_ENTER("SetECPointInternal");
+
+ if (p == NULL || p->internal == NULL) {
+ WOLFSSL_MSG("ECPoint NULL error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ point = (ecc_point*)p->internal;
+
+#ifndef ALT_ECC_SIZE
+ if (p->X != NULL && SetIndividualInternal(p->X, point->x) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ecc point X error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (p->Y != NULL && SetIndividualInternal(p->Y, point->y) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ecc point Y error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (p->Z != NULL && SetIndividualInternal(p->Z, point->z) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ecc point Z error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+#else
+ if (p->X != NULL && SetIndividualInternalEcc(p->X, point->x) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ecc point X error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (p->Y != NULL && SetIndividualInternalEcc(p->Y, point->y) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ecc point Y error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (p->Z != NULL && SetIndividualInternalEcc(p->Z, point->z) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ecc point Z error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+#endif
+
+ p->inSet = 1;
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* EC_POINT WolfSSL -> OpenSSL */
+static int SetECPointExternal(WOLFSSL_EC_POINT *p)
+{
+ ecc_point* point;
+
+ WOLFSSL_ENTER("SetECPointExternal");
+
+ if (p == NULL || p->internal == NULL) {
+ WOLFSSL_MSG("ECPoint NULL error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ point = (ecc_point*)p->internal;
+
+ if (SetIndividualExternal(&p->X, point->x) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ecc point X error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (SetIndividualExternal(&p->Y, point->y) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ecc point Y error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (SetIndividualExternal(&p->Z, point->z) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ecc point Z error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ p->exSet = 1;
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+/* EC_KEY wolfSSL -> OpenSSL */
+int SetECKeyExternal(WOLFSSL_EC_KEY* eckey)
+{
+ ecc_key* key;
+
+ WOLFSSL_ENTER("SetECKeyExternal");
+
+ if (eckey == NULL || eckey->internal == NULL) {
+ WOLFSSL_MSG("ec key NULL error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ key = (ecc_key*)eckey->internal;
+
+ /* set group (OID, nid and idx) */
+ eckey->group->curve_oid = ecc_sets[key->idx].oidSum;
+ eckey->group->curve_nid = ecc_sets[key->idx].id;
+ eckey->group->curve_idx = key->idx;
+
+ if (eckey->pub_key->internal != NULL) {
+ /* set the internal public key */
+ if (wc_ecc_copy_point(&key->pubkey,
+ (ecc_point*)eckey->pub_key->internal) != MP_OKAY) {
+ WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* set the external pubkey (point) */
+ if (SetECPointExternal(eckey->pub_key) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetECKeyExternal SetECPointExternal failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ /* set the external privkey */
+ if (key->type == ECC_PRIVATEKEY) {
+ if (SetIndividualExternal(&eckey->priv_key, &key->k) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ec priv key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
}
+ eckey->exSet = 1;
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* EC_KEY Openssl -> WolfSSL */
+int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
+{
+ ecc_key* key;
+
+ WOLFSSL_ENTER("SetECKeyInternal");
+
+ if (eckey == NULL || eckey->internal == NULL || eckey->group == NULL) {
+ WOLFSSL_MSG("ec key NULL error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ key = (ecc_key*)eckey->internal;
+
+ /* validate group */
+ if ((eckey->group->curve_idx < 0) ||
+ (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) {
+ WOLFSSL_MSG("invalid curve idx");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* set group (idx of curve and corresponding domain parameters) */
+ key->idx = eckey->group->curve_idx;
+ key->dp = &ecc_sets[key->idx];
+
+ /* set pubkey (point) */
+ if (eckey->pub_key != NULL) {
+ if (SetECPointInternal(eckey->pub_key) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ec key pub error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* copy over the public point to key */
+ if (wc_ecc_copy_point((ecc_point*)eckey->pub_key->internal, &key->pubkey) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_copy_point error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* public key */
+ key->type = ECC_PUBLICKEY;
+ }
+
+ /* set privkey */
+ if (eckey->priv_key != NULL) {
+ if (SetIndividualInternal(eckey->priv_key, &key->k) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ec key priv error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* private key */
+ key->type = ECC_PRIVATEKEY;
+ }
+
+ eckey->inSet = 1;
+
+ return WOLFSSL_SUCCESS;
+}
+
+WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key)
+{
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key");
+
+ if (key == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_get0_public_key Bad arguments");
+ return NULL;
+ }
+
+ return key->pub_key;
+}
+
+const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key)
+{
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group");
+
+ if (key == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments");
+ return NULL;
+ }
+
+ return key->group;
+}
+
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key,
+ const WOLFSSL_BIGNUM *priv_key)
+{
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key");
+
+ if (key == NULL || priv_key == NULL) {
+ WOLFSSL_MSG("Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* free key if previously set */
+ if (key->priv_key != NULL)
+ wolfSSL_BN_free(key->priv_key);
+
+ key->priv_key = wolfSSL_BN_dup(priv_key);
+ if (key->priv_key == NULL) {
+ WOLFSSL_MSG("key ecc priv key NULL");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ wolfSSL_BN_free(key->priv_key);
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key)
+{
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key");
+
+ if (key == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments");
+ return NULL;
+ }
+
+ if (wolfSSL_BN_is_zero(key->priv_key)) {
+ /* return NULL if not set */
+ return NULL;
+ }
+
+ return key->priv_key;
+}
+
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid)
+{
+ WOLFSSL_EC_KEY *key;
+ int x;
+ int eccEnum;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name");
+
+ /* If NID passed in is OpenSSL type, convert it to ecc_curve_id enum */
+ eccEnum = NIDToEccEnum(nid);
+ if (eccEnum == -1)
+ eccEnum = nid;
+
+ key = wolfSSL_EC_KEY_new();
+ if (key == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new failure");
+ return NULL;
+ }
+
+ /* set the nid of the curve */
+ key->group->curve_nid = eccEnum;
+
+ /* search and set the corresponding internal curve idx */
+ for (x = 0; ecc_sets[x].size != 0; x++)
+ if (ecc_sets[x].id == key->group->curve_nid) {
+ key->group->curve_idx = x;
+ key->group->curve_oid = ecc_sets[x].oidSum;
+ break;
+ }
+
+ return key;
+}
+
+const char* wolfSSL_EC_curve_nid2nist(int nid)
+{
+ const WOLF_EC_NIST_NAME* nist_name;
+ for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
+ if (nist_name->nid == nid) {
+ return kNistCurves->name;
+ }
+ }
return NULL;
}
+#ifdef WOLFSSL_TLS13
+static int populate_groups(int* groups, int max_count, char *list)
+{
+ char *end;
+ int len;
+ int count = 0;
+ const WOLF_EC_NIST_NAME* nist_name;
+
+ if (!groups || !list) {
+ return -1;
+ }
+
+ for (end = list; ; list = ++end) {
+ if (count > max_count) {
+ WOLFSSL_MSG("Too many curves in list");
+ return -1;
+ }
+ while (*end != ':' && *end != '\0') end++;
+ len = (int)(end - list); /* end points to char after end
+ * of curve name so no need for -1 */
+ if ((len < kNistCurves_MIN_NAME_LEN) ||
+ (len > kNistCurves_MAX_NAME_LEN)) {
+ WOLFSSL_MSG("Unrecognized curve name in list");
+ return -1;
+ }
+ for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
+ if (len == nist_name->name_len &&
+ XSTRNCMP(list, nist_name->name, nist_name->name_len) == 0) {
+ break;
+ }
+ }
+ if (!nist_name->name) {
+ WOLFSSL_MSG("Unrecognized curve name in list");
+ return -1;
+ }
+ groups[count++] = nist_name->nid;
+ if (*end == '\0') break;
+ }
+
+ return count;
+}
-WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY* key)
+int wolfSSL_CTX_set1_groups_list(WOLFSSL_CTX *ctx, char *list)
{
- (void)key;
- WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_RSA");
+ int groups[WOLFSSL_MAX_GROUP_COUNT];
+ int count;
+ if (!ctx || !list) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if ((count = populate_groups(groups,
+ WOLFSSL_MAX_GROUP_COUNT, list)) == -1) {
+ return WOLFSSL_FAILURE;
+ }
+
+ return wolfSSL_CTX_set_groups(ctx, groups, count) == WOLFSSL_SUCCESS ?
+ WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+}
+
+int wolfSSL_set1_groups_list(WOLFSSL *ssl, char *list)
+{
+ int groups[WOLFSSL_MAX_GROUP_COUNT];
+ int count;
+
+ if (!ssl || !list) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if ((count = populate_groups(groups,
+ WOLFSSL_MAX_GROUP_COUNT, list)) == -1) {
+ return WOLFSSL_FAILURE;
+ }
+
+ return wolfSSL_set_groups(ssl, groups, count) == WOLFSSL_SUCCESS ?
+ WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+}
+#endif /* WOLFSSL_TLS13 */
+
+static void InitwolfSSL_ECKey(WOLFSSL_EC_KEY* key)
+{
+ if (key) {
+ key->group = NULL;
+ key->pub_key = NULL;
+ key->priv_key = NULL;
+ key->internal = NULL;
+ key->inSet = 0;
+ key->exSet = 0;
+ }
+}
+
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void)
+{
+ WOLFSSL_EC_KEY *external;
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_new");
+
+ external = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), NULL,
+ DYNAMIC_TYPE_ECC);
+ if (external == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure");
+ return NULL;
+ }
+ XMEMSET(external, 0, sizeof(WOLFSSL_EC_KEY));
+
+ InitwolfSSL_ECKey(external);
+
+ external->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL,
+ DYNAMIC_TYPE_ECC);
+ if (external->internal == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure");
+ goto error;
+ }
+ XMEMSET(external->internal, 0, sizeof(ecc_key));
+
+ if (wc_ecc_init((ecc_key*)external->internal) != 0) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new init ecc key failure");
+ goto error;
+ }
+
+ /* curve group */
+ external->group = wolfSSL_EC_GROUP_new_by_curve_name(ECC_CURVE_DEF);
+ if (external->group == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure");
+ goto error;
+ }
+
+ /* public key */
+ external->pub_key = wolfSSL_EC_POINT_new(external->group);
+ if (external->pub_key == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_new failure");
+ goto error;
+ }
+
+ /* private key */
+ external->priv_key = wolfSSL_BN_new();
+ if (external->priv_key == NULL) {
+ WOLFSSL_MSG("wolfSSL_BN_new failure");
+ goto error;
+ }
+
+ return external;
+error:
+ wolfSSL_EC_KEY_free(external);
return NULL;
}
+void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key)
+{
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_free");
+
+ if (key != NULL) {
+ if (key->internal != NULL) {
+ wc_ecc_free((ecc_key*)key->internal);
+ XFREE(key->internal, NULL, DYNAMIC_TYPE_ECC);
+ }
+ wolfSSL_BN_free(key->priv_key);
+ wolfSSL_EC_POINT_free(key->pub_key);
+ wolfSSL_EC_GROUP_free(key->group);
+ InitwolfSSL_ECKey(key); /* set back to NULLs for safety */
-WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY* key)
+ XFREE(key, NULL, DYNAMIC_TYPE_ECC);
+ /* key = NULL, don't try to access or double free it */
+ }
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group)
{
(void)key;
- WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_DSA");
+ (void)group;
- return NULL;
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group");
+ WOLFSSL_STUB("EC_KEY_set_group");
+
+ return -1;
}
+#endif
+
+int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key)
+{
+ int initTmpRng = 0;
+ WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG* tmpRNG = NULL;
+#else
+ WC_RNG tmpRNG[1];
+#endif
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key");
+
+ if (key == NULL || key->internal == NULL ||
+ key->group == NULL || key->group->curve_idx < 0) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments");
+ return 0;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (tmpRNG == NULL)
+ return 0;
+#endif
+
+ if (wc_InitRng(tmpRNG) == 0) {
+ rng = tmpRNG;
+ initTmpRng = 1;
+ }
+ else {
+ WOLFSSL_MSG("Bad RNG Init, trying global");
+ if (initGlobalRNG == 0)
+ WOLFSSL_MSG("Global RNG no Init");
+ else
+ rng = &globalRNG;
+ }
+
+ if (rng == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG");
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+ return 0;
+ }
+
+ if (wc_ecc_make_key_ex(rng, 0, (ecc_key*)key->internal,
+ key->group->curve_nid) != MP_OKAY) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed");
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+ return 0;
+ }
+
+ if (initTmpRng)
+ wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+ if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed");
+ return 0;
+ }
-void* wolfSSL_EVP_X_STATE(const WOLFSSL_EVP_CIPHER_CTX* ctx)
+ return 1;
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag)
{
- WOLFSSL_MSG("wolfSSL_EVP_X_STATE");
+ (void)key;
+ (void)asn1_flag;
- if (ctx) {
- switch (ctx->cipherType) {
- case ARC4_TYPE:
- WOLFSSL_MSG("returning arc4 state");
- return (void*)&ctx->cipher.arc4.x;
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag");
+ WOLFSSL_STUB("EC_KEY_set_asn1_flag");
+}
+#endif
- default:
- WOLFSSL_MSG("bad x state type");
- return 0;
+static int setupPoint(const WOLFSSL_EC_POINT *p) {
+ if (!p) {
+ return WOLFSSL_FAILURE;
+ }
+ if (p->inSet == 0) {
+ WOLFSSL_MSG("No ECPoint internal set, do it");
+
+ if (SetECPointInternal((WOLFSSL_EC_POINT *)p) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetECPointInternal SetECPointInternal failed");
+ return WOLFSSL_FAILURE;
}
}
+ return WOLFSSL_SUCCESS;
+}
- return NULL;
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key,
+ const WOLFSSL_EC_POINT *pub)
+{
+ ecc_point *pub_p, *key_p;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key");
+
+ if (key == NULL || key->internal == NULL ||
+ pub == NULL || pub->internal == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (key->inSet == 0) {
+ if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ if (setupPoint(pub) != WOLFSSL_SUCCESS) {
+ return WOLFSSL_FAILURE;
+ }
+
+ pub_p = (ecc_point*)pub->internal;
+ key_p = (ecc_point*)key->pub_key->internal;
+
+ /* create new point if required */
+ if (key_p == NULL)
+ key_p = wc_ecc_new_point();
+
+ if (key_p == NULL) {
+ WOLFSSL_MSG("key ecc point NULL");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY) {
+ WOLFSSL_MSG("ecc_copy_point failure");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (SetECPointExternal(key->pub_key) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ wolfSSL_EC_POINT_dump("pub", pub);
+ wolfSSL_EC_POINT_dump("key->pub_key", key->pub_key);
+
+ return WOLFSSL_SUCCESS;
}
+/* End EC_KEY */
+int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key)
+{
+ const EC_GROUP *group;
+ int bits, bytes;
+ word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */
+
+ if (!key) {
+ return WOLFSSL_FAILURE;
+ }
-int wolfSSL_EVP_X_STATE_LEN(const WOLFSSL_EVP_CIPHER_CTX* ctx)
+ if (!(group = wolfSSL_EC_KEY_get0_group(key))) {
+ return WOLFSSL_FAILURE;
+ }
+ if ((bits = wolfSSL_EC_GROUP_order_bits(group)) == 0) {
+ return WOLFSSL_FAILURE;
+ }
+ bytes = (bits + 7) / 8; /* bytes needed to hold bits */
+ return headerSz +
+ 2 + /* possible leading zeroes in r and s */
+ bytes + bytes + /* r and s */
+ 2;
+}
+
+int wolfSSL_ECDSA_sign(int type, const unsigned char *digest,
+ int digestSz, unsigned char *sig,
+ unsigned int *sigSz, WOLFSSL_EC_KEY *key)
{
- WOLFSSL_MSG("wolfSSL_EVP_X_STATE_LEN");
+ int ret = WOLFSSL_SUCCESS;
+ WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG* tmpRNG = NULL;
+#else
+ WC_RNG tmpRNG[1];
+#endif
+ int initTmpRng = 0;
- if (ctx) {
- switch (ctx->cipherType) {
- case ARC4_TYPE:
- WOLFSSL_MSG("returning arc4 state size");
- return sizeof(Arc4);
+ WOLFSSL_ENTER("wolfSSL_ECDSA_sign");
- default:
- WOLFSSL_MSG("bad x state type");
- return 0;
+ if (!key) {
+ return WOLFSSL_FAILURE;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (tmpRNG == NULL)
+ return WOLFSSL_FAILURE;
+#endif
+
+ if (wc_InitRng(tmpRNG) == 0) {
+ rng = tmpRNG;
+ initTmpRng = 1;
+ }
+ else {
+ WOLFSSL_MSG("Bad RNG Init, trying global");
+ if (initGlobalRNG == 0) {
+ WOLFSSL_MSG("Global RNG no Init");
+ }
+ else {
+ rng = &globalRNG;
}
}
+ if (rng) {
+ if (wc_ecc_sign_hash(digest, digestSz, sig, sigSz, rng, (ecc_key*)key->internal) != MP_OKAY) {
+ ret = WOLFSSL_FAILURE;
+ }
+ if (initTmpRng) {
+ wc_FreeRng(tmpRNG);
+ }
+ } else {
+ ret = WOLFSSL_FAILURE;
+ }
- return 0;
+#ifdef WOLFSSL_SMALL_STACK
+ if (tmpRNG)
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+ (void)type;
+ return ret;
}
+#ifndef HAVE_SELFTEST
+/* ECC point compression types were not included in selftest ecc.h */
-#ifndef NO_DES3
+char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group,
+ const WOLFSSL_EC_POINT* point, int form,
+ WOLFSSL_BN_CTX* ctx)
+{
+ static const char* hexDigit = "0123456789ABCDEF";
+ char* hex = NULL;
+ int id;
+ int i, sz, len;
-void wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset,
- unsigned char* iv, int len)
+ (void)ctx;
+
+ if (group == NULL || point == NULL)
+ return NULL;
+
+ id = wc_ecc_get_curve_id(group->curve_idx);
+
+ if ((sz = wc_ecc_get_curve_size_from_id(id)) < 0)
+ return NULL;
+
+ len = sz + 1;
+ if (form == POINT_CONVERSION_UNCOMPRESSED)
+ len += sz;
+
+ hex = (char*)XMALLOC(2 * len + 1, NULL, DYNAMIC_TYPE_ECC);
+ if (hex == NULL)
+ return NULL;
+ XMEMSET(hex, 0, 2 * len + 1);
+
+ /* Put in x-ordinate after format byte. */
+ i = sz - mp_unsigned_bin_size((mp_int*)point->X->internal) + 1;
+ if (mp_to_unsigned_bin((mp_int*)point->X->internal, (byte*)(hex + i)) < 0) {
+ XFREE(hex, NULL, DYNAMIC_TYPE_ECC);
+ return NULL;
+ }
+
+ if (form == POINT_CONVERSION_COMPRESSED) {
+ hex[0] = mp_isodd((mp_int*)point->Y->internal) ? ECC_POINT_COMP_ODD :
+ ECC_POINT_COMP_EVEN;
+ }
+ else {
+ hex[0] = ECC_POINT_UNCOMP;
+ /* Put in y-ordinate after x-ordinate */
+ i = 1 + 2 * sz - mp_unsigned_bin_size((mp_int*)point->Y->internal);
+ if (mp_to_unsigned_bin((mp_int*)point->Y->internal,
+ (byte*)(hex + i)) < 0) {
+ XFREE(hex, NULL, DYNAMIC_TYPE_ECC);
+ return NULL;
+ }
+ }
+
+ for (i = len-1; i >= 0; i--) {
+ byte b = hex[i];
+ hex[i * 2 + 1] = hexDigit[b & 0xf];
+ hex[i * 2 ] = hexDigit[b >> 4];
+ }
+
+ return hex;
+}
+
+#endif /* HAVE_SELFTEST */
+
+void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p)
{
- (void)len;
+#if defined(DEBUG_WOLFSSL)
+ char *num;
- WOLFSSL_MSG("wolfSSL_3des_iv");
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_dump");
- if (ctx == NULL || iv == NULL) {
- WOLFSSL_MSG("Bad function argument");
+ if (!WOLFSSL_IS_DEBUG_ON() || wolfSSL_GetLoggingCb()) {
return;
}
- if (doset)
- wc_Des3_SetIV(&ctx->cipher.des3, iv); /* OpenSSL compat, no ret */
- else
- memcpy(iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE);
+ if (p == NULL) {
+ printf("%s = NULL", msg);
+ return;
+ }
+
+ printf("%s:\n\tinSet=%d, exSet=%d\n", msg, p->inSet, p->exSet);
+ num = wolfSSL_BN_bn2hex(p->X);
+ printf("\tX = %s\n", num);
+ XFREE(num, NULL, DYNAMIC_TYPE_ECC);
+ num = wolfSSL_BN_bn2hex(p->Y);
+ printf("\tY = %s\n", num);
+ XFREE(num, NULL, DYNAMIC_TYPE_ECC);
+ num = wolfSSL_BN_bn2hex(p->Z);
+ printf("\tZ = %s\n", num);
+ XFREE(num, NULL, DYNAMIC_TYPE_ECC);
+#else
+ (void)msg;
+ (void)p;
+#endif
}
-#endif /* NO_DES3 */
+/* Start EC_GROUP */
+/* return code compliant with OpenSSL :
+ * 0 if equal, 1 if not and -1 in case of error
+ */
+int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b,
+ WOLFSSL_BN_CTX *ctx)
+{
+ (void)ctx;
-#ifndef NO_AES
+ WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp");
-void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset,
- unsigned char* iv, int len)
+ if (a == NULL || b == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* ok */
+ if ((a->curve_idx == b->curve_idx) && (a->curve_nid == b->curve_nid))
+ return 0;
+
+ /* ko */
+ return 1;
+}
+
+#endif /* HAVE_ECC */
+#endif /* OPENSSL_EXTRA */
+
+#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of(
+ const WOLFSSL_EC_GROUP *group)
{
- (void)len;
+ return group;
+}
- WOLFSSL_MSG("wolfSSL_aes_ctr_iv");
+int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth)
+{
+ if (meth) {
+ return NID_X9_62_prime_field;
+ }
+ return WOLFSSL_FAILURE;
+}
- if (ctx == NULL || iv == NULL) {
- WOLFSSL_MSG("Bad function argument");
- return;
+void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group)
+{
+ WOLFSSL_ENTER("wolfSSL_EC_GROUP_free");
+
+ XFREE(group, NULL, DYNAMIC_TYPE_ECC);
+ /* group = NULL, don't try to access or double free it */
+}
+#endif
+
+#ifdef OPENSSL_EXTRA
+#ifdef HAVE_ECC
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag)
+{
+ (void)group;
+ (void)flag;
+
+ WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag");
+ WOLFSSL_STUB("EC_GROUP_set_asn1_flag");
+}
+#endif
+
+WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid)
+{
+ WOLFSSL_EC_GROUP *g;
+ int x;
+ int eccEnum;
+
+ WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name");
+
+ /* If NID passed in is OpenSSL type, convert it to ecc_curve_id enum */
+ eccEnum = NIDToEccEnum(nid);
+ if (eccEnum == -1)
+ eccEnum = nid;
+
+
+ /* curve group */
+ g = (WOLFSSL_EC_GROUP*) XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL,
+ DYNAMIC_TYPE_ECC);
+ if (g == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure");
+ return NULL;
}
+ XMEMSET(g, 0, sizeof(WOLFSSL_EC_GROUP));
- if (doset)
- wc_AesSetIV(&ctx->cipher.aes, iv); /* OpenSSL compat, no ret */
- else
- memcpy(iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
+ /* set the nid of the curve */
+ g->curve_nid = eccEnum;
+
+ if (eccEnum > ECC_CURVE_DEF) {
+ /* search and set the corresponding internal curve idx */
+ for (x = 0; ecc_sets[x].size != 0; x++)
+ if (ecc_sets[x].id == g->curve_nid) {
+ g->curve_idx = x;
+ g->curve_oid = ecc_sets[x].oidSum;
+ break;
+ }
+ }
+
+ return g;
}
-#endif /* NO_AES */
+/* return code compliant with OpenSSL :
+ * the curve nid if success, 0 if error
+ */
+int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group)
+{
+ int nid;
+ WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name");
+ if (group == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* If curve_nid is ECC Enum type, return corresponding OpenSSL nid */
+ if ((nid = EccEnumToNID(group->curve_nid)) != -1)
+ return nid;
+
+ return group->curve_nid;
+}
+
+/* return code compliant with OpenSSL :
+ * the degree of the curve if success, 0 if error
+ */
+int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group)
+{
+ int nid;
+ int tmp;
+
+ WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree");
+
+ if (group == NULL || group->curve_idx < 0) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* If curve_nid passed in is an ecc_curve_id enum, convert it to the
+ corresponding OpenSSL NID */
+ tmp = EccEnumToNID(group->curve_nid);
+ if (tmp != -1){
+ nid = tmp;
+ }
+ else{
+ nid = group->curve_nid;
+ }
+
+ switch(nid) {
+ case NID_secp112r1:
+ case NID_secp112r2:
+ return 112;
+ case NID_secp128r1:
+ case NID_secp128r2:
+ return 128;
+ case NID_secp160k1:
+ case NID_secp160r1:
+ case NID_secp160r2:
+ case NID_brainpoolP160r1:
+ return 160;
+ case NID_secp192k1:
+ case NID_brainpoolP192r1:
+ case NID_X9_62_prime192v1:
+ return 192;
+ case NID_secp224k1:
+ case NID_secp224r1:
+ case NID_brainpoolP224r1:
+ return 224;
+ case NID_secp256k1:
+ case NID_brainpoolP256r1:
+ case NID_X9_62_prime256v1:
+ return 256;
+ case NID_brainpoolP320r1:
+ return 320;
+ case NID_secp384r1:
+ case NID_brainpoolP384r1:
+ return 384;
+ case NID_secp521r1:
+ return 521;
+ case NID_brainpoolP512r1:
+ return 512;
+ default:
+ return WOLFSSL_FAILURE;
+ }
+}
+
+/* Converts OpenSSL NID value of ECC curves to the associated enum values in
+ ecc_curve_id, used by ecc_sets[].*/
+int NIDToEccEnum(int n)
+{
+ WOLFSSL_ENTER("NIDToEccEnum()");
+
+ switch(n) {
+ case NID_X9_62_prime192v1:
+ return ECC_SECP192R1;
+ case NID_X9_62_prime192v2:
+ return ECC_PRIME192V2;
+ case NID_X9_62_prime192v3:
+ return ECC_PRIME192V3;
+ case NID_X9_62_prime239v1:
+ return ECC_PRIME239V1;
+ case NID_X9_62_prime239v2:
+ return ECC_PRIME239V2;
+ case NID_X9_62_prime239v3:
+ return ECC_PRIME239V3;
+ case NID_X9_62_prime256v1:
+ return ECC_SECP256R1;
+ case NID_secp112r1:
+ return ECC_SECP112R1;
+ case NID_secp112r2:
+ return ECC_SECP112R2;
+ case NID_secp128r1:
+ return ECC_SECP128R1;
+ case NID_secp128r2:
+ return ECC_SECP128R2;
+ case NID_secp160r1:
+ return ECC_SECP160R1;
+ case NID_secp160r2:
+ return ECC_SECP160R2;
+ case NID_secp224r1:
+ return ECC_SECP224R1;
+ case NID_secp384r1:
+ return ECC_SECP384R1;
+ case NID_secp521r1:
+ return ECC_SECP521R1;
+ case NID_secp160k1:
+ return ECC_SECP160K1;
+ case NID_secp192k1:
+ return ECC_SECP192K1;
+ case NID_secp224k1:
+ return ECC_SECP224K1;
+ case NID_secp256k1:
+ return ECC_SECP256K1;
+ case NID_brainpoolP160r1:
+ return ECC_BRAINPOOLP160R1;
+ case NID_brainpoolP192r1:
+ return ECC_BRAINPOOLP192R1;
+ case NID_brainpoolP224r1:
+ return ECC_BRAINPOOLP224R1;
+ case NID_brainpoolP256r1:
+ return ECC_BRAINPOOLP256R1;
+ case NID_brainpoolP320r1:
+ return ECC_BRAINPOOLP320R1;
+ case NID_brainpoolP384r1:
+ return ECC_BRAINPOOLP384R1;
+ case NID_brainpoolP512r1:
+ return ECC_BRAINPOOLP512R1;
+ default:
+ WOLFSSL_MSG("NID not found");
+ return -1;
+ }
+}
-const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void)
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group,
+ WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx)
{
- WOLFSSL_MSG("wolfSSL_ripemd160");
+ (void)ctx;
- return NULL;
+ if (group == NULL || order == NULL || order->internal == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (mp_init((mp_int*)order->internal) != MP_OKAY) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (mp_read_radix((mp_int*)order->internal,
+ ecc_sets[group->curve_idx].order, MP_RADIX_HEX) != MP_OKAY) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure");
+ mp_clear((mp_int*)order->internal);
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
}
+int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group)
+{
+ int ret;
+ mp_int order;
+
+ if (group == NULL || group->curve_idx < 0) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_order_bits NULL error");
+ return 0;
+ }
+
+ ret = mp_init(&order);
+ if (ret == 0) {
+ ret = mp_read_radix(&order, ecc_sets[group->curve_idx].order,
+ MP_RADIX_HEX);
+ if (ret == 0)
+ ret = mp_count_bits(&order);
+ mp_clear(&order);
+ }
-int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* type)
+ return ret;
+}
+
+/* End EC_GROUP */
+
+/* Start EC_POINT */
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group,
+ const WOLFSSL_EC_POINT *p,
+ unsigned char *out, unsigned int *len)
{
- WOLFSSL_MSG("wolfSSL_EVP_MD_size");
+ int err;
- if (type == NULL) {
- WOLFSSL_MSG("No md type arg");
- return BAD_FUNC_ARG;
+ WOLFSSL_ENTER("wolfSSL_ECPoint_i2d");
+
+ if (group == NULL || p == NULL || len == NULL) {
+ WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error");
+ return WOLFSSL_FAILURE;
}
- if (XSTRNCMP(type, "SHA256", 6) == 0) {
- return SHA256_DIGEST_SIZE;
+ if (setupPoint(p) != WOLFSSL_SUCCESS) {
+ return WOLFSSL_FAILURE;
}
-#ifndef NO_MD5
- else if (XSTRNCMP(type, "MD5", 3) == 0) {
- return MD5_DIGEST_SIZE;
+
+ if (out != NULL) {
+ wolfSSL_EC_POINT_dump("i2d p", p);
+ }
+
+ err = wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal,
+ out, len);
+ if (err != MP_OKAY && !(out == NULL && err == LENGTH_ONLY_E)) {
+ WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len,
+ const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *p)
+{
+ WOLFSSL_ENTER("wolfSSL_ECPoint_d2i");
+
+ if (group == NULL || p == NULL || p->internal == NULL || in == NULL) {
+ WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+#ifndef HAVE_SELFTEST
+ if (wc_ecc_import_point_der_ex(in, len, group->curve_idx,
+ (ecc_point*)p->internal, 0) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_import_point_der_ex failed");
+ return WOLFSSL_FAILURE;
+ }
+#else
+ /* ECC_POINT_UNCOMP is not defined CAVP self test so use magic number */
+ if (in[0] == 0x04) {
+ if (wc_ecc_import_point_der(in, len, group->curve_idx,
+ (ecc_point*)p->internal) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_import_point_der failed");
+ return WOLFSSL_FAILURE;
+ }
+ }
+ else {
+ WOLFSSL_MSG("Only uncompressed points supported with HAVE_SELFTEST");
+ return WOLFSSL_FAILURE;
}
#endif
-#ifdef WOLFSSL_SHA384
- else if (XSTRNCMP(type, "SHA384", 6) == 0) {
- return SHA384_DIGEST_SIZE;
+
+ /* Set new external point */
+ if (SetECPointExternal(p) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetECPointExternal failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ wolfSSL_EC_POINT_dump("d2i p", p);
+
+ return WOLFSSL_SUCCESS;
+}
+
+size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group,
+ const WOLFSSL_EC_POINT *p,
+ char form,
+ byte *buf, size_t len, WOLFSSL_BN_CTX *ctx)
+{
+ word32 min_len = (word32)len;
+#ifndef HAVE_SELFTEST
+ int compressed = form == POINT_CONVERSION_COMPRESSED ? 1 : 0;
+#endif /* !HAVE_SELFTEST */
+
+ WOLFSSL_ENTER("EC_POINT_point2oct");
+
+ if (!group || !p) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (setupPoint(p) != WOLFSSL_SUCCESS) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_EC_POINT_is_at_infinity(group, p)) {
+ /* encodes to a single 0 octet */
+ if (buf != NULL) {
+ if (len < 1) {
+ ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
+ return WOLFSSL_FAILURE;
+ }
+ buf[0] = 0;
+ }
+ return 1;
+ }
+
+ if (form != POINT_CONVERSION_UNCOMPRESSED
+#ifndef HAVE_SELFTEST
+ && form != POINT_CONVERSION_COMPRESSED
+#endif /* !HAVE_SELFTEST */
+ ) {
+ WOLFSSL_MSG("Unsupported curve form");
+ return WOLFSSL_FAILURE;
+ }
+
+#ifndef HAVE_SELFTEST
+ if (wc_ecc_export_point_der_ex(group->curve_idx, (ecc_point*)p->internal,
+ buf, &min_len, compressed) != (buf ? MP_OKAY : LENGTH_ONLY_E)) {
+ return WOLFSSL_FAILURE;
+ }
+#else
+ if (wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal,
+ buf, &min_len) != (buf ? MP_OKAY : LENGTH_ONLY_E)) {
+ return WOLFSSL_FAILURE;
+ }
+#endif /* !HAVE_SELFTEST */
+
+ (void)ctx;
+
+ return (size_t)min_len;
+}
+
+int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group,
+ WOLFSSL_EC_POINT *p, const unsigned char *buf,
+ size_t len, WOLFSSL_BN_CTX *ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
+
+ if (!group || !p) {
+ return WOLFSSL_FAILURE;
+ }
+
+ (void)ctx;
+
+ return wolfSSL_ECPoint_d2i((unsigned char*)buf, (unsigned int)len, group, p);
+}
+
+int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *in, unsigned char **out)
+{
+ size_t len;
+ unsigned char *tmp = NULL;
+ char form;
+ WOLFSSL_ENTER("wolfSSL_i2o_ECPublicKey");
+
+ if (!in) {
+ WOLFSSL_MSG("wolfSSL_i2o_ECPublicKey Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Default to compressed form if not set */
+ form = in->form == POINT_CONVERSION_UNCOMPRESSED ?
+ POINT_CONVERSION_UNCOMPRESSED:
+ POINT_CONVERSION_COMPRESSED;
+
+ len = wolfSSL_EC_POINT_point2oct(in->group, in->pub_key, form,
+ NULL, 0, NULL);
+
+ if (len != WOLFSSL_FAILURE && out) {
+ if (!*out) {
+ if (!(tmp = (unsigned char*)XMALLOC(len, NULL,
+ DYNAMIC_TYPE_OPENSSL))) {
+ WOLFSSL_MSG("malloc failed");
+ return WOLFSSL_FAILURE;
+ }
+ *out = tmp;
+ }
+
+ if (wolfSSL_EC_POINT_point2oct(in->group, in->pub_key, form, *out,
+ len, NULL) == WOLFSSL_FAILURE) {
+ if (tmp) {
+ XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+ *out = NULL;
+ }
+ return WOLFSSL_FAILURE;
+ }
+
+ if (!tmp) {
+ /* Move buffer forward if it was not alloced in this function */
+ *out += len;
+ }
+ }
+
+ return (int)len;
+}
+
+void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *eckey, char form)
+{
+ if (eckey && (form == POINT_CONVERSION_COMPRESSED ||
+ form == POINT_CONVERSION_UNCOMPRESSED)) {
+ eckey->form = form;
+ }
+}
+
+
+/* wolfSSL_EC_POINT_point2bn should return "in" if not null */
+WOLFSSL_BIGNUM *wolfSSL_EC_POINT_point2bn(const WOLFSSL_EC_GROUP *group,
+ const WOLFSSL_EC_POINT *p,
+ char form,
+ WOLFSSL_BIGNUM *in, WOLFSSL_BN_CTX *ctx)
+{
+ size_t len;
+ byte *buf;
+ WOLFSSL_BIGNUM *ret = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
+
+ if (!group || !p) {
+ return NULL;
+ }
+
+ if ((len = wolfSSL_EC_POINT_point2oct(group, p, form,
+ NULL, 0, ctx)) == WOLFSSL_FAILURE) {
+ return NULL;
+ }
+
+ if (!(buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER))) {
+ WOLFSSL_MSG("malloc failed");
+ return NULL;
+ }
+
+ if (wolfSSL_EC_POINT_point2oct(group, p, form,
+ buf, len, ctx) == len) {
+ ret = wolfSSL_BN_bin2bn(buf, (int)len, in);
+ }
+
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return ret;
+}
+
+WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group)
+{
+ WOLFSSL_EC_POINT *p;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_new");
+
+ if (group == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error");
+ return NULL;
+ }
+
+ p = (WOLFSSL_EC_POINT *)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL,
+ DYNAMIC_TYPE_ECC);
+ if (p == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure");
+ return NULL;
+ }
+ XMEMSET(p, 0, sizeof(WOLFSSL_EC_POINT));
+
+ p->internal = wc_ecc_new_point();
+ if (p->internal == NULL) {
+ WOLFSSL_MSG("ecc_new_point failure");
+ XFREE(p, NULL, DYNAMIC_TYPE_ECC);
+ return NULL;
+ }
+
+ return p;
+}
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group,
+ const WOLFSSL_EC_POINT *point,
+ WOLFSSL_BIGNUM *x,
+ WOLFSSL_BIGNUM *y,
+ WOLFSSL_BN_CTX *ctx)
+{
+ mp_digit mp;
+ mp_int modulus;
+ (void)ctx;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp");
+
+ if (group == NULL || point == NULL || point->internal == NULL ||
+ x == NULL || y == NULL || wolfSSL_EC_POINT_is_at_infinity(group, point)) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error");
+ return WOLFSSL_FAILURE;
}
+
+ if (setupPoint(point) != WOLFSSL_SUCCESS) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (!wolfSSL_BN_is_one(point->Z)) {
+ if (mp_init(&modulus) != MP_OKAY) {
+ WOLFSSL_MSG("mp_init failed");
+ return WOLFSSL_FAILURE;
+ }
+ /* Map the Jacobian point back to affine space */
+ if (mp_read_radix(&modulus, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX) != MP_OKAY) {
+ WOLFSSL_MSG("mp_read_radix failed");
+ mp_clear(&modulus);
+ return WOLFSSL_FAILURE;
+ }
+ if (mp_montgomery_setup(&modulus, &mp) != MP_OKAY) {
+ WOLFSSL_MSG("mp_montgomery_setup failed");
+ mp_clear(&modulus);
+ return WOLFSSL_FAILURE;
+ }
+ if (ecc_map((ecc_point*)point->internal, &modulus, mp) != MP_OKAY) {
+ WOLFSSL_MSG("ecc_map failed");
+ mp_clear(&modulus);
+ return WOLFSSL_FAILURE;
+ }
+ if (SetECPointExternal((WOLFSSL_EC_POINT *)point) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetECPointExternal failed");
+ mp_clear(&modulus);
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ BN_copy(x, point->X);
+ BN_copy(y, point->Y);
+ mp_clear(&modulus);
+
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_EC_POINT_set_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group,
+ WOLFSSL_EC_POINT *point,
+ const WOLFSSL_BIGNUM *x,
+ const WOLFSSL_BIGNUM *y,
+ WOLFSSL_BN_CTX *ctx)
+{
+ (void)ctx;
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_set_affine_coordinates_GFp");
+
+ if (group == NULL || point == NULL || point->internal == NULL ||
+ x == NULL || y == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (!point->X) {
+ point->X = wolfSSL_BN_new();
+ }
+ if (!point->Y) {
+ point->Y = wolfSSL_BN_new();
+ }
+ if (!point->Z) {
+ point->Z = wolfSSL_BN_new();
+ }
+ if (!point->X || !point->Y || !point->Z) {
+ WOLFSSL_MSG("wolfSSL_BN_new failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ BN_copy(point->X, x);
+ BN_copy(point->Y, y);
+ BN_copy(point->Z, wolfSSL_BN_value_one());
+
+ if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetECPointInternal failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+#if !defined(WOLFSSL_ATECC508A) && !defined(HAVE_SELFTEST)
+/* Calculate the value: generator * n + q * m
+ * return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r,
+ const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q,
+ const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
+{
+ mp_int a, prime;
+ int ret = WOLFSSL_FAILURE;
+ ecc_point* result = NULL;
+ ecc_point* tmp = NULL;
+
+ (void)ctx;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_mul");
+
+ if (!group || !r) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (!(result = wc_ecc_new_point())) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_new error");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* read the curve prime and a */
+ if (mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL) != MP_OKAY) {
+ WOLFSSL_MSG("mp_init_multi error");
+ goto cleanup;
+ }
+
+ if (q && setupPoint(q) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("setupPoint error");
+ goto cleanup;
+ }
+
+ if (mp_read_radix(&prime, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX)
+ != MP_OKAY) {
+ WOLFSSL_MSG("mp_read_radix prime error");
+ goto cleanup;
+ }
+
+ if (mp_read_radix(&a, ecc_sets[group->curve_idx].Af, MP_RADIX_HEX)
+ != MP_OKAY) {
+ WOLFSSL_MSG("mp_read_radix a error");
+ goto cleanup;
+ }
+
+ if (n) {
+ /* load generator */
+ if (wc_ecc_get_generator(result, group->curve_idx)
+ != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_get_generator error");
+ goto cleanup;
+ }
+ }
+
+ if (n && q && m) {
+ /* r = generator * n + q * m */
+#ifdef ECC_SHAMIR
+ if (ecc_mul2add(result, (mp_int*)n->internal,
+ (ecc_point*)q->internal, (mp_int*)m->internal,
+ result, &a, &prime, NULL)
+ != MP_OKAY) {
+ WOLFSSL_MSG("ecc_mul2add error");
+ goto cleanup;
+ }
+#else
+ mp_digit mp = 0;
+ if (mp_montgomery_setup(&prime, &mp) != MP_OKAY) {
+ WOLFSSL_MSG("mp_montgomery_setup nqm error");
+ goto cleanup;
+ }
+ if (!(tmp = wc_ecc_new_point())) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_new nqm error");
+ goto cleanup;
+ }
+ /* r = generator * n */
+ if (wc_ecc_mulmod((mp_int*)n->internal, result, result, &a, &prime, 1)
+ != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_mulmod nqm error");
+ goto cleanup;
+ }
+ /* tmp = q * m */
+ if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal,
+ tmp, &a, &prime, 1) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_mulmod nqm error");
+ goto cleanup;
+ }
+ /* result = result + tmp */
+ if (ecc_projective_add_point(tmp, result, result, &a, &prime, mp)
+ != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_mulmod nqm error");
+ goto cleanup;
+ }
+ if (ecc_map(result, &prime, mp) != MP_OKAY) {
+ WOLFSSL_MSG("ecc_map nqm error");
+ goto cleanup;
+ }
#endif
-#ifdef WOLFSSL_SHA512
- else if (XSTRNCMP(type, "SHA512", 6) == 0) {
- return SHA512_DIGEST_SIZE;
}
+ else if (n) {
+ /* r = generator * n */
+ if (wc_ecc_mulmod((mp_int*)n->internal, result, result, &a, &prime, 1)
+ != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_mulmod gn error");
+ goto cleanup;
+ }
+ }
+ else if (q && m) {
+ /* r = q * m */
+ if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal,
+ result, &a, &prime, 1) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_mulmod qm error");
+ goto cleanup;
+ }
+ }
+
+ /* copy to destination */
+ if (wc_ecc_copy_point(result, (ecc_point*)r->internal)) {
+ WOLFSSL_MSG("wc_ecc_copy_point error");
+ goto cleanup;
+ }
+ r->inSet = 1;
+ if (SetECPointExternal(r) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetECPointExternal error");
+ goto cleanup;
+ }
+
+ ret = WOLFSSL_SUCCESS;
+cleanup:
+ mp_clear(&a);
+ mp_clear(&prime);
+ wc_ecc_del_point(result);
+ wc_ecc_del_point(tmp);
+ return ret;
+}
+#endif /* !defined(WOLFSSL_ATECC508A) && defined(ECC_SHAMIR) &&
+ * !defined(HAVE_SELFTEST) */
+
+void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *p)
+{
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free");
+
+ wolfSSL_EC_POINT_free(p);
+}
+
+/* return code compliant with OpenSSL :
+ * 0 if equal, 1 if not and -1 in case of error
+ */
+int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group,
+ const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b,
+ WOLFSSL_BN_CTX *ctx)
+{
+ int ret;
+
+ (void)ctx;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp");
+
+ if (group == NULL || a == NULL || a->internal == NULL || b == NULL ||
+ b->internal == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ ret = wc_ecc_cmp_point((ecc_point*)a->internal, (ecc_point*)b->internal);
+ if (ret == MP_EQ)
+ return 0;
+ else if (ret == MP_LT || ret == MP_GT)
+ return 1;
+
+ return WOLFSSL_FATAL_ERROR;
+}
+
+int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest, const WOLFSSL_EC_POINT *src)
+{
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_copy");
+
+ if (!dest || !src) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (setupPoint(src) != WOLFSSL_SUCCESS) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wc_ecc_copy_point((ecc_point*) dest->internal,
+ (ecc_point*) src->internal) != MP_OKAY) {
+ return WOLFSSL_FAILURE;
+ }
+
+ dest->inSet = 1;
+
+ if (SetECPointExternal(dest) != WOLFSSL_SUCCESS) {
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_ECC */
+#endif /* OPENSSL_EXTRA */
+
+#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *p)
+{
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_free");
+
+ if (p != NULL) {
+ if (p->internal != NULL) {
+ wc_ecc_del_point((ecc_point*)p->internal);
+ p->internal = NULL;
+ }
+
+ wolfSSL_BN_free(p->X);
+ wolfSSL_BN_free(p->Y);
+ wolfSSL_BN_free(p->Z);
+ p->X = NULL;
+ p->Y = NULL;
+ p->Z = NULL;
+ p->inSet = p->exSet = 0;
+
+ XFREE(p, NULL, DYNAMIC_TYPE_ECC);
+ /* p = NULL, don't try to access or double free it */
+ }
+}
#endif
-#ifndef NO_SHA
- /* has to be last since would pick or 256, 384, or 512 too */
- else if (XSTRNCMP(type, "SHA", 3) == 0) {
- return SHA_DIGEST_SIZE;
+
+#ifdef OPENSSL_EXTRA
+#ifdef HAVE_ECC
+/* return code compliant with OpenSSL :
+ * 1 if point at infinity, 0 else
+ */
+int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group,
+ const WOLFSSL_EC_POINT *point)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity");
+
+ if (group == NULL || point == NULL || point->internal == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (setupPoint(point) != WOLFSSL_SUCCESS) {
+ return WOLFSSL_FAILURE;
+ }
+
+ ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal);
+ if (ret < 0) {
+ WOLFSSL_MSG("ecc_point_is_at_infinity failure");
+ return WOLFSSL_FAILURE;
}
+
+ return ret;
+}
+
+/* End EC_POINT */
+
+size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *r, size_t nitems)
+{
+ size_t i, min_nitems;
+#ifdef HAVE_SELFTEST
+ size_t ecc_sets_count;
+ for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++);
+ ecc_sets_count = i;
#endif
- return BAD_FUNC_ARG;
+ if (r == NULL || nitems == 0)
+ return ecc_sets_count;
+
+ min_nitems = nitems < ecc_sets_count ? nitems : ecc_sets_count;
+
+ for (i = 0; i < min_nitems; i++) {
+ r[i].nid = EccEnumToNID(ecc_sets[i].id);
+ r[i].comment = wolfSSL_OBJ_nid2sn(r[i].nid);
+ }
+
+ return ecc_sets_count;
}
+/* Start ECDSA_SIG */
+void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig)
+{
+ WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free");
-int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx)
+ if (sig) {
+ wolfSSL_BN_free(sig->r);
+ wolfSSL_BN_free(sig->s);
+
+ XFREE(sig, NULL, DYNAMIC_TYPE_ECC);
+ }
+}
+
+WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void)
{
- WOLFSSL_MSG("wolfSSL_EVP_CIPHER_CTX_iv_length");
+ WOLFSSL_ECDSA_SIG *sig;
+
+ WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new");
+
+ sig = (WOLFSSL_ECDSA_SIG*) XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL,
+ DYNAMIC_TYPE_ECC);
+ if (sig == NULL) {
+ WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure");
+ return NULL;
+ }
- switch (ctx->cipherType) {
+ sig->s = NULL;
+ sig->r = wolfSSL_BN_new();
+ if (sig->r == NULL) {
+ WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure");
+ wolfSSL_ECDSA_SIG_free(sig);
+ return NULL;
+ }
- case AES_128_CBC_TYPE :
- case AES_192_CBC_TYPE :
- case AES_256_CBC_TYPE :
- WOLFSSL_MSG("AES CBC");
- return AES_BLOCK_SIZE;
+ sig->s = wolfSSL_BN_new();
+ if (sig->s == NULL) {
+ WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure");
+ wolfSSL_ECDSA_SIG_free(sig);
+ return NULL;
+ }
-#ifdef WOLFSSL_AES_COUNTER
- case AES_128_CTR_TYPE :
- case AES_192_CTR_TYPE :
- case AES_256_CTR_TYPE :
- WOLFSSL_MSG("AES CTR");
- return AES_BLOCK_SIZE;
+ return sig;
+}
+
+/* return signature structure on success, NULL otherwise */
+WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *d, int dlen,
+ WOLFSSL_EC_KEY *key)
+{
+ WOLFSSL_ECDSA_SIG *sig = NULL;
+ int initTmpRng = 0;
+ WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG* tmpRNG = NULL;
+#else
+ WC_RNG tmpRNG[1];
#endif
- case DES_CBC_TYPE :
- WOLFSSL_MSG("DES CBC");
- return DES_BLOCK_SIZE;
+ WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign");
- case DES_EDE3_CBC_TYPE :
- WOLFSSL_MSG("DES EDE3 CBC");
- return DES_BLOCK_SIZE;
+ if (d == NULL || key == NULL || key->internal == NULL) {
+ WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments");
+ return NULL;
+ }
- case ARC4_TYPE :
- WOLFSSL_MSG("ARC4");
- return 0;
+ /* set internal key if not done */
+ if (key->inSet == 0)
+ {
+ WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it");
- case NULL_CIPHER_TYPE :
- WOLFSSL_MSG("NULL");
- return 0;
+ if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed");
+ return NULL;
+ }
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (tmpRNG == NULL)
+ return NULL;
+#endif
+
+ if (wc_InitRng(tmpRNG) == 0) {
+ rng = tmpRNG;
+ initTmpRng = 1;
+ }
+ else {
+ WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad RNG Init, trying global");
+ if (initGlobalRNG == 0)
+ WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Global RNG no Init");
+ else
+ rng = &globalRNG;
+ }
- default: {
- WOLFSSL_MSG("bad type");
+ if (rng) {
+ mp_int sig_r, sig_s;
+
+ if (mp_init_multi(&sig_r, &sig_s, NULL, NULL, NULL, NULL) == MP_OKAY) {
+ if (wc_ecc_sign_hash_ex(d, dlen, rng, (ecc_key*)key->internal,
+ &sig_r, &sig_s) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_sign_hash_ex failed");
+ }
+ else {
+ /* put signature blob in ECDSA structure */
+ sig = wolfSSL_ECDSA_SIG_new();
+ if (sig == NULL)
+ WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new failed");
+ else if (SetIndividualExternal(&(sig->r), &sig_r)!=WOLFSSL_SUCCESS){
+ WOLFSSL_MSG("ecdsa r key error");
+ wolfSSL_ECDSA_SIG_free(sig);
+ sig = NULL;
+ }
+ else if (SetIndividualExternal(&(sig->s), &sig_s)!=WOLFSSL_SUCCESS){
+ WOLFSSL_MSG("ecdsa s key error");
+ wolfSSL_ECDSA_SIG_free(sig);
+ sig = NULL;
+ }
+
+ }
+ mp_free(&sig_r);
+ mp_free(&sig_s);
}
}
- return 0;
+
+ if (initTmpRng)
+ wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+ return sig;
}
+/* return code compliant with OpenSSL :
+ * 1 for a valid signature, 0 for an invalid signature and -1 on error
+ */
+int wolfSSL_ECDSA_do_verify(const unsigned char *d, int dlen,
+ const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key)
+{
+ int check_sign = 0;
-void wolfSSL_OPENSSL_free(void* p)
+ WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify");
+
+ if (d == NULL || sig == NULL || key == NULL || key->internal == NULL) {
+ WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* set internal key if not done */
+ if (key->inSet == 0)
+ {
+ WOLFSSL_MSG("No EC key internal set, do it");
+
+ if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal,
+ (mp_int*)sig->s->internal, d, dlen, &check_sign,
+ (ecc_key *)key->internal) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_verify_hash failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ else if (check_sign == 0) {
+ WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+WOLFSSL_ECDSA_SIG *wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG **sig,
+ const unsigned char **pp, long len)
{
- WOLFSSL_MSG("wolfSSL_OPENSSL_free");
+ WOLFSSL_ECDSA_SIG *s = NULL;
- XFREE(p, NULL, 0);
+ if (pp == NULL)
+ return NULL;
+
+ if (sig != NULL)
+ s = *sig;
+ if (s == NULL) {
+ s = wolfSSL_ECDSA_SIG_new();
+ if (s == NULL)
+ return NULL;
+ }
+
+ /* DecodeECC_DSA_Sig calls mp_init, so free these */
+ mp_free((mp_int*)s->r->internal);
+ mp_free((mp_int*)s->s->internal);
+
+ if (DecodeECC_DSA_Sig(*pp, (word32)len, (mp_int*)s->r->internal,
+ (mp_int*)s->s->internal) != MP_OKAY) {
+ if (sig == NULL || *sig == NULL)
+ wolfSSL_ECDSA_SIG_free(s);
+ return NULL;
+ }
+
+ *pp += len;
+ if (sig != NULL)
+ *sig = s;
+ return s;
}
+int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp)
+{
+ word32 len;
+
+ if (sig == NULL)
+ return 0;
-int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, RSA* rsa,
- const EVP_CIPHER* cipher,
- unsigned char* passwd, int len,
- pem_password_cb cb, void* arg)
+ /* ASN.1: SEQ + INT + INT
+ * ASN.1 Integer must be a positive value - prepend zero if number has
+ * top bit set.
+ */
+ len = 2 + mp_leading_bit((mp_int*)sig->r->internal) +
+ mp_unsigned_bin_size((mp_int*)sig->r->internal) +
+ 2 + mp_leading_bit((mp_int*)sig->s->internal) +
+ mp_unsigned_bin_size((mp_int*)sig->s->internal);
+ /* Two bytes required for length if ASN.1 SEQ data greater than 127 bytes
+ * and less than 256 bytes.
+ */
+ len = 1 + ((len > 127) ? 2 : 1) + len;
+ if (pp != NULL && *pp != NULL) {
+ if (StoreECC_DSA_Sig(*pp, &len, (mp_int*)sig->r->internal,
+ (mp_int*)sig->s->internal) != MP_OKAY) {
+ len = 0;
+ }
+ else
+ *pp += len;
+ }
+
+ return (int)len;
+}
+/* End ECDSA_SIG */
+
+/* Start ECDH */
+/* return code compliant with OpenSSL :
+ * length of computed key if success, -1 if error
+ */
+int wolfSSL_ECDH_compute_key(void *out, size_t outlen,
+ const WOLFSSL_EC_POINT *pub_key,
+ WOLFSSL_EC_KEY *ecdh,
+ void *(*KDF) (const void *in, size_t inlen,
+ void *out, size_t *outlen))
{
- (void)bio;
- (void)rsa;
+ word32 len;
+ (void)KDF;
+
+ (void)KDF;
+
+ WOLFSSL_ENTER("wolfSSL_ECDH_compute_key");
+
+ if (out == NULL || pub_key == NULL || pub_key->internal == NULL ||
+ ecdh == NULL || ecdh->internal == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* set internal key if not done */
+ if (ecdh->inSet == 0)
+ {
+ WOLFSSL_MSG("No EC key internal set, do it");
+
+ if (SetECKeyInternal(ecdh) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ len = (word32)outlen;
+
+ if (wc_ecc_shared_secret_ssh((ecc_key*)ecdh->internal,
+ (ecc_point*)pub_key->internal,
+ (byte *)out, &len) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_shared_secret failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ return len;
+}
+/* End ECDH */
+
+#if !defined(NO_FILESYSTEM)
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY *x)
+{
+ (void)fp;
+ (void)x;
+ WOLFSSL_STUB("PEM_write_EC_PUBKEY");
+ WOLFSSL_MSG("wolfSSL_PEM_write_EC_PUBKEY not implemented");
+
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects
+ * the results to be an EC key.
+ *
+ * bio structure to read EC private key from
+ * ec if not null is then set to the result
+ * cb password callback for reading PEM
+ * pass password string
+ *
+ * returns a pointer to a new WOLFSSL_EC_KEY struct on success and NULL on fail
+ */
+
+WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_EC_PUBKEY(WOLFSSL_BIO* bio,
+ WOLFSSL_EC_KEY** ec,
+ pem_password_cb* cb, void *pass)
+{
+ WOLFSSL_EVP_PKEY* pkey;
+ WOLFSSL_EC_KEY* local;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_EC_PUBKEY");
+
+ pkey = wolfSSL_PEM_read_bio_PUBKEY(bio, NULL, cb, pass);
+ if (pkey == NULL) {
+ return NULL;
+ }
+
+ /* Since the WOLFSSL_EC_KEY structure is being taken from WOLFSSL_EVP_PKEY the
+ * flag indicating that the WOLFSSL_EC_KEY structure is owned should be FALSE
+ * to avoid having it free'd */
+ pkey->ownEcc = 0;
+ local = pkey->ecc;
+ if (ec != NULL) {
+ *ec = local;
+ }
+
+ wolfSSL_EVP_PKEY_free(pkey);
+ return local;
+}
+
+/* Reads a private EC key from a WOLFSSL_BIO into a WOLFSSL_EC_KEY.
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_ECPrivateKey(WOLFSSL_BIO* bio,
+ WOLFSSL_EC_KEY** ec,
+ pem_password_cb* cb,
+ void *pass)
+{
+ WOLFSSL_EVP_PKEY* pkey;
+ WOLFSSL_EC_KEY* local;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_ECPrivateKey");
+
+ pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass);
+ if (pkey == NULL) {
+ return NULL;
+ }
+
+ /* Since the WOLFSSL_EC_KEY structure is being taken from WOLFSSL_EVP_PKEY the
+ * flag indicating that the WOLFSSL_EC_KEY structure is owned should be FALSE
+ * to avoid having it free'd */
+ pkey->ownEcc = 0;
+ local = pkey->ecc;
+ if (ec != NULL) {
+ *ec = local;
+ }
+
+ wolfSSL_EVP_PKEY_free(pkey);
+ return local;
+}
+#endif /* NO_FILESYSTEM */
+
+#if defined(WOLFSSL_KEY_GEN)
+/* Takes a public WOLFSSL_EC_KEY and writes it out to WOLFSSL_BIO
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+int wolfSSL_PEM_write_bio_EC_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec)
+{
+ int ret = 0, der_max_len = 0, derSz = 0;
+ byte *derBuf;
+ WOLFSSL_EVP_PKEY* pkey;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_EC_PUBKEY");
+
+ if (bio == NULL || ec == NULL) {
+ WOLFSSL_MSG("Bad Function Arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Initialize pkey structure */
+ pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
+ if (pkey == NULL) {
+ WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Set pkey info */
+ pkey->ecc = ec;
+ pkey->ownEcc = 0; /* pkey does not own ECC */
+ pkey->type = EVP_PKEY_EC;
+
+ /* 4 > size of pub, priv + ASN.1 additional information */
+ der_max_len = 4 * wc_ecc_size((ecc_key*)ec->internal) + AES_BLOCK_SIZE;
+
+ derBuf = (byte*)XMALLOC(der_max_len, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (derBuf == NULL) {
+ WOLFSSL_MSG("Malloc failed");
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* convert key to der format */
+ derSz = wc_EccPublicKeyToDer((ecc_key*)ec->internal, derBuf, der_max_len, 1);
+ if (derSz < 0) {
+ WOLFSSL_MSG("wc_EccPublicKeyToDer failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+
+ pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pkey->pkey.ptr == NULL) {
+ WOLFSSL_MSG("key malloc failed");
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* add der info to the evp key */
+ pkey->pkey_sz = derSz;
+ XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ if((ret = wolfSSL_PEM_write_bio_PUBKEY(bio, pkey)) != WOLFSSL_SUCCESS){
+ WOLFSSL_MSG("wolfSSL_PEM_write_bio_PUBKEY failed");
+ }
+ wolfSSL_EVP_PKEY_free(pkey);
+
+ return ret;
+}
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec,
+ const EVP_CIPHER* cipher,
+ unsigned char* passwd, int len,
+ pem_password_cb* cb, void* arg)
+{
+ int ret = 0, der_max_len = 0, derSz = 0;
+ byte *derBuf;
+ WOLFSSL_EVP_PKEY* pkey;
+ WOLFSSL_ENTER("WOLFSSL_PEM_write_bio_ECPrivateKey");
+
+ if (bio == NULL || ec == NULL) {
+ WOLFSSL_MSG("Bad Function Arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Initialize pkey structure */
+ pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
+ if (pkey == NULL) {
+ WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Set pkey info */
+ pkey->ecc = ec;
+ pkey->ownEcc = 0; /* pkey does not own ECC */
+ pkey->type = EVP_PKEY_EC;
+
+ /* 4 > size of pub, priv + ASN.1 additional informations
+ */
+ der_max_len = 4 * wc_ecc_size((ecc_key*)ec->internal) + AES_BLOCK_SIZE;
+
+ derBuf = (byte*)XMALLOC(der_max_len, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (derBuf == NULL) {
+ WOLFSSL_MSG("Malloc failed");
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* convert key to der format */
+ derSz = wc_EccKeyToDer((ecc_key*)ec->internal, derBuf, der_max_len);
+ if (derSz < 0) {
+ WOLFSSL_MSG("wc_EccKeyToDer failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+
+ pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pkey->pkey.ptr == NULL) {
+ WOLFSSL_MSG("key malloc failed");
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* add der info to the evp key */
+ pkey->pkey_sz = derSz;
+ XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len,
+ cb, arg);
+ wolfSSL_EVP_PKEY_free(pkey);
+
+ return ret;
+}
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc,
+ const EVP_CIPHER* cipher,
+ unsigned char* passwd, int passwdSz,
+ unsigned char **pem, int *plen)
+{
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+ byte *derBuf, *tmp, *cipherInfo = NULL;
+ int der_max_len = 0, derSz = 0;
+ const int type = ECC_PRIVATEKEY_TYPE;
+ const char* header = NULL;
+ const char* footer = NULL;
+
+ WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey");
+
+ if (pem == NULL || plen == NULL || ecc == NULL || ecc->internal == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wc_PemGetHeaderFooter(type, &header, &footer) != 0)
+ return WOLFSSL_FAILURE;
+
+ if (ecc->inSet == 0) {
+ WOLFSSL_MSG("No ECC internal set, do it");
+
+ if (SetECKeyInternal(ecc) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ /* 4 > size of pub, priv + ASN.1 additional information */
+ der_max_len = 4 * wc_ecc_size((ecc_key*)ecc->internal) + AES_BLOCK_SIZE;
+
+ derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER);
+ if (derBuf == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Key to DER */
+ derSz = wc_EccKeyToDer((ecc_key*)ecc->internal, derBuf, der_max_len);
+ if (derSz < 0) {
+ WOLFSSL_MSG("wc_EccKeyToDer failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* encrypt DER buffer if required */
+ if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
+ int ret;
+
+ ret = EncryptDerKey(derBuf, &derSz, cipher,
+ passwd, passwdSz, &cipherInfo);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("EncryptDerKey failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ return ret;
+ }
+
+ /* tmp buffer with a max size */
+ *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+ (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE;
+ }
+ else { /* tmp buffer with a max size */
+ *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+ (int)XSTRLEN(footer) + 1;
+ }
+
+ tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM);
+ if (tmp == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ if (cipherInfo != NULL)
+ XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* DER to PEM */
+ *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type);
+ if (*plen <= 0) {
+ WOLFSSL_MSG("wc_DerToPemEx failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+ if (cipherInfo != NULL)
+ XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+ return WOLFSSL_FAILURE;
+ }
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ if (cipherInfo != NULL)
+ XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+
+ *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY);
+ if (*pem == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+ return WOLFSSL_FAILURE;
+ }
+ XMEMSET(*pem, 0, (*plen)+1);
+
+ if (XMEMCPY(*pem, tmp, *plen) == NULL) {
+ WOLFSSL_MSG("XMEMCPY failed");
+ XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+ XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+ return WOLFSSL_FAILURE;
+ }
+ XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+
+ return WOLFSSL_SUCCESS;
+#else
+ (void)ecc;
(void)cipher;
(void)passwd;
- (void)len;
+ (void)passwdSz;
+ (void)pem;
+ (void)plen;
+ return WOLFSSL_FAILURE;
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+}
+
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *ecc,
+ const EVP_CIPHER *enc,
+ unsigned char *kstr, int klen,
+ pem_password_cb *cb, void *u)
+{
+ byte *pem;
+ int plen, ret;
+
(void)cb;
- (void)arg;
+ (void)u;
+
+ WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey");
- WOLFSSL_MSG("wolfSSL_PEM_write_bio_RSAPrivateKey");
+ if (fp == XBADFILE || ecc == NULL || ecc->internal == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
+ }
- return SSL_FATAL_ERROR;
+ ret = wolfSSL_PEM_write_mem_ECPrivateKey(ecc, enc, kstr, klen, &pem, &plen);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ ret = (int)XFWRITE(pem, plen, 1, fp);
+ if (ret != 1) {
+ WOLFSSL_MSG("ECC private key file write failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+ return WOLFSSL_SUCCESS;
}
+#endif /* NO_FILESYSTEM */
+#endif /* defined(WOLFSSL_KEY_GEN) */
+
+#endif /* HAVE_ECC */
+
+
+#ifndef NO_DSA
+
+#if defined(WOLFSSL_KEY_GEN)
+/* Takes a DSA Privatekey and writes it out to a WOLFSSL_BIO
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa,
+ const EVP_CIPHER* cipher,
+ unsigned char* passwd, int len,
+ pem_password_cb* cb, void* arg)
+{
+ int ret = 0, der_max_len = 0, derSz = 0;
+ byte *derBuf;
+ WOLFSSL_EVP_PKEY* pkey;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_DSAPrivateKey");
+
+ if (bio == NULL || dsa == NULL) {
+ WOLFSSL_MSG("Bad Function Arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
+ if (pkey == NULL) {
+ WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ pkey->type = EVP_PKEY_DSA;
+ pkey->dsa = dsa;
+ pkey->ownDsa = 0;
+
+ /* 4 > size of pub, priv, p, q, g + ASN.1 additional information */
+ der_max_len = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE;
-int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, DSA* rsa,
- const EVP_CIPHER* cipher,
- unsigned char* passwd, int len,
- pem_password_cb cb, void* arg)
+ derBuf = (byte*)XMALLOC(der_max_len, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (derBuf == NULL) {
+ WOLFSSL_MSG("Malloc failed");
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* convert key to der format */
+ derSz = wc_DsaKeyToDer((DsaKey*)dsa->internal, derBuf, der_max_len);
+ if (derSz < 0) {
+ WOLFSSL_MSG("wc_DsaKeyToDer failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+
+ pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pkey->pkey.ptr == NULL) {
+ WOLFSSL_MSG("key malloc failed");
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* add der info to the evp key */
+ pkey->pkey_sz = derSz;
+ XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len,
+ cb, arg);
+ wolfSSL_EVP_PKEY_free(pkey);
+
+ return ret;
+}
+
+#ifndef HAVE_SELFTEST
+/* Takes a DSA public key and writes it out to a WOLFSSL_BIO
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+int wolfSSL_PEM_write_bio_DSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa)
{
- (void)bio;
- (void)rsa;
+ int ret = 0, derMax = 0, derSz = 0;
+ byte *derBuf;
+ WOLFSSL_EVP_PKEY* pkey;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_DSA_PUBKEY");
+
+ if (bio == NULL || dsa == NULL) {
+ WOLFSSL_MSG("Bad function arguements");
+ return WOLFSSL_FAILURE;
+ }
+
+ pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
+ if (pkey == NULL) {
+ WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ pkey->type = EVP_PKEY_DSA;
+ pkey->dsa = dsa;
+ pkey->ownDsa = 0;
+
+ /* 4 > size of pub, priv, p, q, g + ASN.1 additional information */
+ derMax = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE;
+
+ derBuf = (byte*)XMALLOC(derMax, bio->heap, DYNAMIC_TYPE_DER);
+ if (derBuf == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Key to DER */
+ derSz = wc_DsaKeyToPublicDer((DsaKey*)dsa->internal, derBuf, derMax);
+ if (derSz < 0) {
+ WOLFSSL_MSG("wc_DsaKeyToDer failed");
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER);
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+
+ pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_DER);
+
+ if (pkey->pkey.ptr == NULL) {
+ WOLFSSL_MSG("key malloc failed");
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER);
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+ pkey->pkey_sz = derSz;
+ XMEMSET(pkey->pkey.ptr, 0, derSz);
+
+ if (XMEMCPY(pkey->pkey.ptr, derBuf, derSz) == NULL) {
+ WOLFSSL_MSG("XMEMCPY failed");
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER);
+ XFREE(pkey->pkey.ptr, bio->heap, DYNAMIC_TYPE_DER);
+ wolfSSL_EVP_PKEY_free(pkey);
+ return WOLFSSL_FAILURE;
+ }
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER);
+ ret = wolfSSL_PEM_write_bio_PUBKEY(bio, pkey);
+ wolfSSL_EVP_PKEY_free(pkey);
+ return ret;
+}
+#endif /* HAVE_SELFTEST */
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
+ const EVP_CIPHER* cipher,
+ unsigned char* passwd, int passwdSz,
+ unsigned char **pem, int *plen)
+{
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+ byte *derBuf, *tmp, *cipherInfo = NULL;
+ int der_max_len = 0, derSz = 0;
+ const int type = DSA_PRIVATEKEY_TYPE;
+ const char* header = NULL;
+ const char* footer = NULL;
+
+ WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey");
+
+ if (pem == NULL || plen == NULL || dsa == NULL || dsa->internal == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wc_PemGetHeaderFooter(type, &header, &footer) != 0)
+ return WOLFSSL_FAILURE;
+
+ if (dsa->inSet == 0) {
+ WOLFSSL_MSG("No DSA internal set, do it");
+
+ if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetDsaInternal failed");
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ /* 4 > size of pub, priv, p, q, g + ASN.1 additional information */
+ der_max_len = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE;
+
+ derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER);
+ if (derBuf == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Key to DER */
+ derSz = wc_DsaKeyToDer((DsaKey*)dsa->internal, derBuf, der_max_len);
+ if (derSz < 0) {
+ WOLFSSL_MSG("wc_DsaKeyToDer failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* encrypt DER buffer if required */
+ if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
+ int ret;
+
+ ret = EncryptDerKey(derBuf, &derSz, cipher,
+ passwd, passwdSz, &cipherInfo);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("EncryptDerKey failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ return ret;
+ }
+
+ /* tmp buffer with a max size */
+ *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+ (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE;
+ }
+ else { /* tmp buffer with a max size */
+ *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+ (int)XSTRLEN(footer) + 1;
+ }
+
+ tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM);
+ if (tmp == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ if (cipherInfo != NULL)
+ XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* DER to PEM */
+ *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type);
+ if (*plen <= 0) {
+ WOLFSSL_MSG("wc_DerToPemEx failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+ if (cipherInfo != NULL)
+ XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+ return WOLFSSL_FAILURE;
+ }
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ if (cipherInfo != NULL)
+ XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+
+ *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY);
+ if (*pem == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+ return WOLFSSL_FAILURE;
+ }
+ XMEMSET(*pem, 0, (*plen)+1);
+
+ if (XMEMCPY(*pem, tmp, *plen) == NULL) {
+ WOLFSSL_MSG("XMEMCPY failed");
+ XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+ XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+ return WOLFSSL_FAILURE;
+ }
+ XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+
+ return WOLFSSL_SUCCESS;
+#else
+ (void)dsa;
(void)cipher;
(void)passwd;
- (void)len;
+ (void)passwdSz;
+ (void)pem;
+ (void)plen;
+ return WOLFSSL_FAILURE;
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+}
+
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_DSAPrivateKey(XFILE fp, WOLFSSL_DSA *dsa,
+ const EVP_CIPHER *enc,
+ unsigned char *kstr, int klen,
+ pem_password_cb *cb, void *u)
+{
+ byte *pem;
+ int plen, ret;
+
(void)cb;
- (void)arg;
+ (void)u;
+
+ WOLFSSL_MSG("wolfSSL_PEM_write_DSAPrivateKey");
+
+ if (fp == XBADFILE || dsa == NULL || dsa->internal == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ ret = wolfSSL_PEM_write_mem_DSAPrivateKey(dsa, enc, kstr, klen, &pem, &plen);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey failed");
+ return WOLFSSL_FAILURE;
+ }
- WOLFSSL_MSG("wolfSSL_PEM_write_bio_DSAPrivateKey");
+ ret = (int)XFWRITE(pem, plen, 1, fp);
+ if (ret != 1) {
+ WOLFSSL_MSG("DSA private key file write failed");
+ return WOLFSSL_FAILURE;
+ }
- return SSL_FATAL_ERROR;
+ XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+ return WOLFSSL_SUCCESS;
}
+#endif /* NO_FILESYSTEM */
+#endif /* defined(WOLFSSL_KEY_GEN) */
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_PEM_write_DSA_PUBKEY(XFILE fp, WOLFSSL_DSA *x)
+{
+ (void)fp;
+ (void)x;
+ WOLFSSL_STUB("PEM_write_DSA_PUBKEY");
+ WOLFSSL_MSG("wolfSSL_PEM_write_DSA_PUBKEY not implemented");
+
+ return WOLFSSL_FAILURE;
+}
+#endif
+#endif /* NO_FILESYSTEM */
+
+#endif /* #ifndef NO_DSA */
+
+static int pem_read_bio_key(WOLFSSL_BIO* bio, pem_password_cb* cb, void* pass,
+ int keyType, int* eccFlag, DerBuffer** der)
+{
+#ifdef WOLFSSL_SMALL_STACK
+ EncryptedInfo* info = NULL;
+#else
+ EncryptedInfo info[1];
+#endif /* WOLFSSL_SMALL_STACK */
+ pem_password_cb* localCb = NULL;
+ char* mem = NULL;
+ int memSz = 0;
+ int ret;
+
+ if(cb) {
+ localCb = cb;
+ } else {
+ if(pass) {
+ localCb = wolfSSL_PEM_def_callback;
+ }
+ }
+
+ if ((ret = wolfSSL_BIO_pending(bio)) > 0) {
+ memSz = ret;
+ mem = (char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ if (mem == NULL) {
+ WOLFSSL_MSG("Memory error");
+ ret = MEMORY_E;
+ }
+ if (ret >= 0) {
+ if ((ret = wolfSSL_BIO_read(bio, mem, memSz)) <= 0) {
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ mem = NULL;
+ ret = MEMORY_E;
+ }
+ }
+ }
+ else if (bio->type == WOLFSSL_BIO_FILE) {
+ int sz = 100; /* read from file by 100 byte chunks */
+ int idx = 0;
+ char* tmp = (char*)XMALLOC(sz, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ memSz = 0;
+ if (tmp == NULL) {
+ WOLFSSL_MSG("Memory error");
+ ret = MEMORY_E;
+ }
+
+ while (ret >= 0 && (sz = wolfSSL_BIO_read(bio, tmp, sz)) > 0) {
+ char* newMem;
+ if (memSz + sz < 0) {
+ /* sanity check */
+ break;
+ }
+ newMem = (char*)XREALLOC(mem, memSz + sz, bio->heap,
+ DYNAMIC_TYPE_OPENSSL);
+ if (newMem == NULL) {
+ WOLFSSL_MSG("Memory error");
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ mem = NULL;
+ XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ tmp = NULL;
+ ret = MEMORY_E;
+ break;
+ }
+ mem = newMem;
+ XMEMCPY(mem + idx, tmp, sz);
+ memSz += sz;
+ idx += sz;
+ sz = 100; /* read another 100 byte chunk from file */
+ }
+ XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ tmp = NULL;
+ if (memSz <= 0) {
+ WOLFSSL_MSG("No data to read from bio");
+ if (mem != NULL) {
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ mem = NULL;
+ }
+ ret = BUFFER_E;
+ }
+ }
+ else {
+ WOLFSSL_MSG("No data to read from bio");
+ ret = NOT_COMPILED_IN;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ if (ret >= 0) {
+ info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (info == NULL) {
+ WOLFSSL_MSG("Error getting memory for EncryptedInfo structure");
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ mem = NULL;
+ ret = MEMORY_E;
+ }
+ }
+#endif
+
+ if (ret >= 0) {
+ XMEMSET(info, 0, sizeof(EncryptedInfo));
+ info->passwd_cb = localCb;
+ info->passwd_userdata = pass;
+ ret = PemToDer((const unsigned char*)mem, memSz, keyType, der,
+ NULL, info, eccFlag);
+
+ if (ret < 0) {
+ WOLFSSL_MSG("Bad Pem To Der");
+ }
+ else {
+ /* write left over data back to bio */
+ if ((memSz - (int)info->consumed) > 0 &&
+ bio->type != WOLFSSL_BIO_FILE) {
+ if (wolfSSL_BIO_write(bio, mem + (int)info->consumed,
+ memSz - (int)info->consumed) <= 0) {
+ WOLFSSL_MSG("Unable to advance bio read pointer");
+ }
+ }
+ }
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+
+ return ret;
+}
WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio,
- WOLFSSL_EVP_PKEY** key, pem_password_cb cb, void* arg)
+ WOLFSSL_EVP_PKEY** key,
+ pem_password_cb* cb,
+ void* pass)
+{
+ WOLFSSL_EVP_PKEY* pkey = NULL;
+ DerBuffer* der = NULL;
+ int keyFormat = 0;
+ int type = -1;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PrivateKey");
+
+ if (bio == NULL)
+ return pkey;
+
+ if (pem_read_bio_key(bio, cb, pass, PRIVATEKEY_TYPE, &keyFormat,
+ &der) >= 0) {
+ const unsigned char* ptr = der->buffer;
+
+ if (keyFormat) {
+ /* keyFormat is Key_Sum enum */
+ if (keyFormat == RSAk)
+ type = EVP_PKEY_RSA;
+ else if (keyFormat == ECDSAk)
+ type = EVP_PKEY_EC;
+ else if (keyFormat == DSAk)
+ type = EVP_PKEY_DSA;
+ else if (keyFormat == DHk)
+ type = EVP_PKEY_DH;
+ }
+ else {
+ /* Default to RSA if format is not set */
+ type = EVP_PKEY_RSA;
+ }
+
+ /* handle case where reuse is attempted */
+ if (key != NULL && *key != NULL)
+ pkey = *key;
+
+ wolfSSL_d2i_PrivateKey(type, &pkey, &ptr, der->length);
+ if (pkey == NULL) {
+ WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY");
+ }
+ }
+
+ FreeDer(&der);
+
+ if (key != NULL && pkey != NULL)
+ *key = pkey;
+
+ WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PrivateKey", 0);
+
+ return pkey;
+}
+
+WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_bio_PUBKEY(WOLFSSL_BIO* bio,
+ WOLFSSL_EVP_PKEY **key,
+ pem_password_cb *cb, void *pass)
{
- (void)bio;
- (void)key;
+ WOLFSSL_EVP_PKEY* pkey = NULL;
+ DerBuffer* der = NULL;
+ int keyFormat = 0;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PUBKEY");
+
+ if (bio == NULL)
+ return pkey;
+
+ if (pem_read_bio_key(bio, cb, pass, PUBLICKEY_TYPE, &keyFormat, &der) >= 0) {
+ const unsigned char* ptr = der->buffer;
+
+ /* handle case where reuse is attempted */
+ if (key != NULL && *key != NULL)
+ pkey = *key;
+
+ wolfSSL_d2i_PUBKEY(&pkey, &ptr, der->length);
+ if (pkey == NULL) {
+ WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY");
+ }
+ }
+
+ FreeDer(&der);
+
+ if (key != NULL && pkey != NULL)
+ *key = pkey;
+
+ WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PUBKEY", 0);
+
+ return pkey;
+}
+
+
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA)
+/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects
+ * the results to be an RSA key.
+ *
+ * bio structure to read RSA private key from
+ * rsa if not null is then set to the result
+ * cb password callback for reading PEM
+ * pass password string
+ *
+ * returns a pointer to a new WOLFSSL_RSA structure on success and NULL on fail
+ */
+WOLFSSL_RSA* wolfSSL_PEM_read_bio_RSAPrivateKey(WOLFSSL_BIO* bio,
+ WOLFSSL_RSA** rsa, pem_password_cb* cb, void* pass)
+{
+ WOLFSSL_EVP_PKEY* pkey;
+ WOLFSSL_RSA* local;
+
+ WOLFSSL_ENTER("PEM_read_bio_RSAPrivateKey");
+
+ pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass);
+ if (pkey == NULL) {
+ return NULL;
+ }
+
+ /* Since the WOLFSSL_RSA structure is being taken from WOLFSSL_EVP_PEKY the
+ * flag indicating that the WOLFSSL_RSA structure is owned should be FALSE
+ * to avoid having it free'd */
+ pkey->ownRsa = 0;
+ local = pkey->rsa;
+ if (rsa != NULL) {
+ *rsa = local;
+ }
+
+ wolfSSL_EVP_PKEY_free(pkey);
+ return local;
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_ALL || !NO_RSA */
+
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && (!defined(NO_CERTS) && \
+ !defined(NO_FILESYSTEM) && !defined(NO_DSA) && defined(WOLFSSL_KEY_GEN))
+/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects
+ * the results to be an DSA key.
+ *
+ * bio structure to read DSA private key from
+ * dsa if not null is then set to the result
+ * cb password callback for reading PEM
+ * pass password string
+ *
+ * returns a pointer to a new WOLFSSL_DSA structure on success and NULL on fail
+ */
+WOLFSSL_DSA* wolfSSL_PEM_read_bio_DSAPrivateKey(WOLFSSL_BIO* bio,
+ WOLFSSL_DSA** dsa,
+ pem_password_cb* cb,void *pass)
+{
+ WOLFSSL_EVP_PKEY* pkey = NULL;
+ WOLFSSL_DSA* local;
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DSAPrivateKey");
+
+
+ pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass);
+ if (pkey == NULL) {
+ WOLFSSL_MSG("Error in PEM_read_bio_PrivateKey");
+ return NULL;
+ }
+ /* Since the WOLFSSL_DSA structure is being taken from WOLFSSL_EVP_PKEY the
+ * flag indicating that the WOLFSSL_DSA structure is owned should be FALSE
+ * to avoid having it free'd */
+ pkey->ownDsa = 0;
+ local = pkey->dsa;
+ if (dsa != NULL) {
+ *dsa = local;
+ }
+ wolfSSL_EVP_PKEY_free(pkey);
+ return local;
+}
+
+/* Reads an DSA public key from a WOLFSSL_BIO into a WOLFSSL_DSA.
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSA_PUBKEY(WOLFSSL_BIO* bio,WOLFSSL_DSA** dsa,
+ pem_password_cb* cb, void *pass)
+{
+ WOLFSSL_EVP_PKEY* pkey;
+ WOLFSSL_DSA* local;
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DSA_PUBKEY");
+
+ pkey = wolfSSL_PEM_read_bio_PUBKEY(bio, NULL, cb, pass);
+ if (pkey == NULL) {
+ WOLFSSL_MSG("wolfSSL_PEM_read_bio_PUBKEY failed");
+ return NULL;
+ }
+
+ /* Since the WOLFSSL_DSA structure is being taken from WOLFSSL_EVP_PKEY the
+ * flag indicating that the WOLFSSL_DSA structure is owned should be FALSE
+ * to avoid having it free'd */
+ pkey->ownDsa = 0;
+ local = pkey->dsa;
+ if (dsa != NULL) {
+ *dsa = local;
+ }
+
+ wolfSSL_EVP_PKEY_free(pkey);
+ return local;
+}
+#endif
+
+#ifdef HAVE_ECC
+/* returns a new WOLFSSL_EC_GROUP structure on success and NULL on fail */
+WOLFSSL_EC_GROUP* wolfSSL_PEM_read_bio_ECPKParameters(WOLFSSL_BIO* bio,
+ WOLFSSL_EC_GROUP** group, pem_password_cb* cb, void* pass)
+{
+ WOLFSSL_EVP_PKEY* pkey;
+ WOLFSSL_EC_GROUP* ret = NULL;
+
+ /* check on if bio is null is done in wolfSSL_PEM_read_bio_PrivateKey */
+ pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass);
+ if (pkey != NULL) {
+ if (pkey->type != EVP_PKEY_EC) {
+ WOLFSSL_MSG("Unexpected key type");
+ }
+ else {
+ ret = (WOLFSSL_EC_GROUP*)wolfSSL_EC_KEY_get0_group(pkey->ecc);
+
+ /* set ecc group to null so it is not free'd when pkey is free'd */
+ pkey->ecc->group = NULL;
+ }
+ }
+
+ (void)group;
+ wolfSSL_EVP_PKEY_free(pkey);
+ return ret;
+}
+#endif /* HAVE_ECC */
+
+#if !defined(NO_FILESYSTEM)
+WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(XFILE fp, EVP_PKEY **x,
+ pem_password_cb *cb, void *u)
+{
+ (void)fp;
+ (void)x;
(void)cb;
- (void)arg;
+ (void)u;
- WOLFSSL_MSG("wolfSSL_PEM_read_bio_PrivateKey");
+ WOLFSSL_MSG("wolfSSL_PEM_read_PUBKEY not implemented");
return NULL;
}
+#endif /* NO_FILESYSTEM */
+#ifndef NO_RSA
+#if defined(XSNPRINTF) && !defined(HAVE_FAST_RSA)
+/* snprintf() must be available */
-#ifndef NO_RSA
-/* Load RSA from Der, SSL_SUCCESS on success < 0 on error */
-int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* der, int derSz)
+/******************************************************************************
+* wolfSSL_RSA_print - writes the human readable form of RSA to bio
+*
+* RETURNS:
+* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE
+*/
+int wolfSSL_RSA_print(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, int offset)
{
+ char tmp[100] = {0};
+ word32 idx = 0;
+ int sz = 0;
+ byte lbit = 0;
+ int rawLen = 0;
+ byte* rawKey = NULL;
+ RsaKey* iRsa = NULL;
+ int i = 0;
+ mp_int *rsaElem = NULL;
+ char rsaStr[][20] = { "Modulus:",
+ "PublicExponent:",
+ "PrivateExponent:",
+ "Prime1:",
+ "Prime2:",
+ "Exponent1:",
+ "Exponent2:",
+ "Coefficient:"
+ };
+
+ WOLFSSL_ENTER("wolfSSL_RSA_print");
+ (void)offset;
+
+ if (bio == NULL || rsa == NULL) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if ((sz = wolfSSL_RSA_size(rsa)) < 0) {
+ WOLFSSL_MSG("Error getting RSA key size");
+ return WOLFSSL_FAILURE;
+ }
+ iRsa = (RsaKey*)rsa->internal;
+
+ XSNPRINTF(tmp, sizeof(tmp) - 1, "\n%s: (%d bit)",
+ "RSA Private-Key", 8 * sz);
+ tmp[sizeof(tmp) - 1] = '\0';
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ for (i=0; i<RSA_INTS; i++) {
+ switch(i) {
+ case 0:
+ /* Print out modulus */
+ rsaElem = &iRsa->n;
+ break;
+ case 1:
+ rsaElem = &iRsa->e;
+ break;
+ case 2:
+ rsaElem = &iRsa->d;
+ break;
+ case 3:
+ rsaElem = &iRsa->p;
+ break;
+ case 4:
+ rsaElem = &iRsa->q;
+ break;
+ case 5:
+ rsaElem = &iRsa->dP;
+ break;
+ case 6:
+ rsaElem = &iRsa->dQ;
+ break;
+ case 7:
+ rsaElem = &iRsa->u;
+ break;
+ default:
+ WOLFSSL_MSG("Bad index value");
+ }
+
+ if (i == 1) {
+ /* Print out exponent values */
+ rawLen = mp_unsigned_bin_size(rsaElem);
+ if (rawLen < 0) {
+ WOLFSSL_MSG("Error getting exponent size");
+ return WOLFSSL_FAILURE;
+ }
+
+ if ((word32)rawLen < sizeof(word32)) {
+ rawLen = sizeof(word32);
+ }
+ rawKey = (byte*)XMALLOC(rawLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (rawKey == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return WOLFSSL_FAILURE;
+ }
+ XMEMSET(rawKey, 0, rawLen);
+ mp_to_unsigned_bin(rsaElem, rawKey);
+ if ((word32)rawLen <= sizeof(word32)) {
+ idx = *(word32*)rawKey;
+ #ifdef BIG_ENDIAN_ORDER
+ idx = ByteReverseWord32(idx);
+ #endif
+ }
+ XSNPRINTF(tmp, sizeof(tmp) - 1, "\nExponent: %d (0x%x)", idx, idx);
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+ XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+ XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ else {
+ XSNPRINTF(tmp, sizeof(tmp) - 1, "\n%s\n ", rsaStr[i]);
+ tmp[sizeof(tmp) - 1] = '\0';
+ if (mp_leading_bit(rsaElem)) {
+ lbit = 1;
+ XSTRNCAT(tmp, "00", 3);
+ }
+
+ rawLen = mp_unsigned_bin_size(rsaElem);
+ rawKey = (byte*)XMALLOC(rawLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (rawKey == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return WOLFSSL_FAILURE;
+ }
+ mp_to_unsigned_bin(rsaElem, rawKey);
+ for (idx = 0; idx < (word32)rawLen; idx++) {
+ char val[5];
+ int valSz = 5;
+
+ if ((idx == 0) && !lbit) {
+ XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]);
+ }
+ else if ((idx != 0) && (((idx + lbit) % 15) == 0)) {
+ tmp[sizeof(tmp) - 1] = '\0';
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+ XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+ XSNPRINTF(tmp, sizeof(tmp) - 1,
+ ":\n ");
+ XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]);
+ }
+ else {
+ XSNPRINTF(val, valSz - 1, ":%02x", rawKey[idx]);
+ }
+ XSTRNCAT(tmp, val, valSz);
+ }
+ XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ /* print out remaining values */
+ if ((idx > 0) && (((idx - 1 + lbit) % 15) != 0)) {
+ tmp[sizeof(tmp) - 1] = '\0';
+ if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+ lbit = 0;
+ }
+
+ }
+ /* done with print out */
+ if (wolfSSL_BIO_write(bio, "\n\0", (int)XSTRLEN("\n\0")) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+#endif /* XSNPRINTF */
+
+#if !defined(NO_FILESYSTEM)
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_RSA *wolfSSL_PEM_read_RSAPublicKey(XFILE fp, WOLFSSL_RSA **x,
+ pem_password_cb *cb, void *u)
+{
+ (void)fp;
+ (void)x;
+ (void)cb;
+ (void)u;
+ WOLFSSL_STUB("PEM_read_RSAPublicKey");
+ WOLFSSL_MSG("wolfSSL_PEM_read_RSAPublicKey not implemented");
+
+ return NULL;
+}
+#endif
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_PEM_write_RSAPublicKey(XFILE fp, WOLFSSL_RSA *x)
+{
+ (void)fp;
+ (void)x;
+ WOLFSSL_STUB("PEM_write_RSAPublicKey");
+ WOLFSSL_MSG("wolfSSL_PEM_write_RSAPublicKey not implemented");
+
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_PEM_write_RSA_PUBKEY(XFILE fp, WOLFSSL_RSA *x)
+{
+ (void)fp;
+ (void)x;
+ WOLFSSL_STUB("PEM_write_RSA_PUBKEY");
+ WOLFSSL_MSG("wolfSSL_PEM_write_RSA_PUBKEY not implemented");
+
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+#endif /* NO_FILESYSTEM */
+
+WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **r, const unsigned char **pp,
+ long len)
+{
+ WOLFSSL_RSA *rsa = NULL;
+
+ WOLFSSL_ENTER("d2i_RSAPublicKey");
+
+ if (pp == NULL) {
+ WOLFSSL_MSG("Bad argument");
+ return NULL;
+ }
+ if ((rsa = wolfSSL_RSA_new()) == NULL) {
+ WOLFSSL_MSG("RSA_new failed");
+ return NULL;
+ }
+
+ if (wolfSSL_RSA_LoadDer_ex(rsa, *pp, (int)len, WOLFSSL_RSA_LOAD_PUBLIC)
+ != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("RSA_LoadDer failed");
+ wolfSSL_RSA_free(rsa);
+ rsa = NULL;
+ }
+ if (r != NULL)
+ *r = rsa;
+
+ return rsa;
+}
+
+/* Converts an RSA private key from DER format to an RSA structure.
+Returns pointer to the RSA structure on success and NULL if error. */
+WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA **r,
+ const unsigned char **derBuf, long derSz)
+{
+ WOLFSSL_RSA *rsa = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey");
+
+ /* check for bad functions arguments */
+ if (derBuf == NULL) {
+ WOLFSSL_MSG("Bad argument");
+ return NULL;
+ }
+ if ((rsa = wolfSSL_RSA_new()) == NULL) {
+ WOLFSSL_MSG("RSA_new failed");
+ return NULL;
+ }
+
+ if (wolfSSL_RSA_LoadDer_ex(rsa, *derBuf, (int)derSz,
+ WOLFSSL_RSA_LOAD_PRIVATE) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("RSA_LoadDer failed");
+ wolfSSL_RSA_free(rsa);
+ rsa = NULL;
+ }
+ if (r != NULL)
+ *r = rsa;
+
+ return rsa;
+}
+
+#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \
+ !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+/* Converts an internal RSA structure to DER format.
+ * If "pp" is null then buffer size only is returned.
+ * If "*pp" is null then a created buffer is set in *pp and the caller is
+ * responsible for free'ing it.
+ * Returns size of DER on success and WOLFSSL_FAILURE if error
+ */
+int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *rsa, unsigned char **pp)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_i2d_RSAPrivateKey");
+
+ /* check for bad functions arguments */
+ if (rsa == NULL) {
+ WOLFSSL_MSG("Bad Function Arguments");
+ return BAD_FUNC_ARG;
+ }
+
+ if ((ret = wolfSSL_RSA_To_Der(rsa, pp, 0)) < 0) {
+ WOLFSSL_MSG("wolfSSL_RSA_To_Der failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ return ret; /* returns size of DER if successful */
+}
+
+
+int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *rsa, const unsigned char **pp)
+{
+ int ret;
+
+ /* check for bad functions arguments */
+ if (rsa == NULL) {
+ WOLFSSL_MSG("Bad Function Arguments");
+ return BAD_FUNC_ARG;
+ }
+
+ if ((ret = wolfSSL_RSA_To_Der(rsa, (byte**)pp, 1)) < 0) {
+ WOLFSSL_MSG("wolfSSL_RSA_To_Der failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ return ret;
+}
+#endif /* !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \
+ * !defined(NO_RSA) && !defined(HAVE_USER_RSA) */
+
+#endif /* !NO_RSA */
+#endif /* OPENSSL_EXTRA */
+
+#if !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */
+int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf, int derSz)
+{
+ return wolfSSL_RSA_LoadDer_ex(rsa, derBuf, derSz, WOLFSSL_RSA_LOAD_PRIVATE);
+}
+
+
+int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf,
+ int derSz, int opt)
+{
+
word32 idx = 0;
int ret;
WOLFSSL_ENTER("wolfSSL_RSA_LoadDer");
- if (rsa == NULL || rsa->internal == NULL || der == NULL || derSz <= 0) {
+ if (rsa == NULL || rsa->internal == NULL || derBuf == NULL || derSz <= 0) {
WOLFSSL_MSG("Bad function arguments");
- return BAD_FUNC_ARG;
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (opt == WOLFSSL_RSA_LOAD_PRIVATE) {
+ ret = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz);
+ }
+ else {
+ ret = wc_RsaPublicKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz);
}
- ret = wc_RsaPrivateKeyDecode(der, &idx, (RsaKey*)rsa->internal, derSz);
if (ret < 0) {
- WOLFSSL_MSG("RsaPrivateKeyDecode failed");
- return ret;
+ if (opt == WOLFSSL_RSA_LOAD_PRIVATE) {
+ WOLFSSL_MSG("RsaPrivateKeyDecode failed");
+ }
+ else {
+ WOLFSSL_MSG("RsaPublicKeyDecode failed");
+ }
+ return SSL_FATAL_ERROR;
}
- if (SetRsaExternal(rsa) < 0) {
+ if (SetRsaExternal(rsa) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("SetRsaExternal failed");
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
rsa->inSet = 1;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
}
-#endif /* NO_RSA */
+#if defined(WC_RSA_PSS) && (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \
+ defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX))
+static int hash2mgf(enum wc_HashType hType)
+{
+ switch (hType) {
+#ifndef NO_SHA
+ case WC_HASH_TYPE_SHA:
+ return WC_MGF1SHA1;
+#endif
+#ifndef NO_SHA256
+#ifdef WOLFSSL_SHA224
+ case WC_HASH_TYPE_SHA224:
+ return WC_MGF1SHA224;
+#endif
+ case WC_HASH_TYPE_SHA256:
+ return WC_MGF1SHA256;
+#endif
+#ifdef WOLFSSL_SHA384
+ case WC_HASH_TYPE_SHA384:
+ return WC_MGF1SHA384;
+#endif
+#ifdef WOLFSSL_SHA512
+ case WC_HASH_TYPE_SHA512:
+ return WC_MGF1SHA512;
+#endif
+ case WC_HASH_TYPE_NONE:
+ case WC_HASH_TYPE_MD2:
+ case WC_HASH_TYPE_MD4:
+ case WC_HASH_TYPE_MD5:
+ case WC_HASH_TYPE_MD5_SHA:
+ case WC_HASH_TYPE_SHA3_224:
+ case WC_HASH_TYPE_SHA3_256:
+ case WC_HASH_TYPE_SHA3_384:
+ case WC_HASH_TYPE_SHA3_512:
+ case WC_HASH_TYPE_BLAKE2B:
+ case WC_HASH_TYPE_BLAKE2S:
+ default:
+ WOLFSSL_MSG("Unrecognized or unsupported hash function");
+ return WC_MGF1NONE;
+ }
+}
+/*
+ * +-----------+
+ * | M |
+ * +-----------+
+ * |
+ * V
+ * Hash
+ * |
+ * V
+ * +--------+----------+----------+
+ * M' = |Padding1| mHash | salt |
+ * +--------+----------+----------+
+ * |
+ * +--------+----------+ V
+ * DB = |Padding2|maskedseed| Hash
+ * +--------+----------+ |
+ * | |
+ * V | +--+
+ * xor <--- MGF <---| |bc|
+ * | | +--+
+ * | | |
+ * V V V
+ * +-------------------+----------+--+
+ * EM = | maskedDB |maskedseed|bc|
+ * +-------------------+----------+--+
+ * Diagram taken from https://tools.ietf.org/html/rfc3447#section-9.1
+ */
+int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *EM,
+ const unsigned char *mHash,
+ const WOLFSSL_EVP_MD *hashAlg, int saltLen)
+{
+ int hashLen, emLen, mgf;
+ int ret = WOLFSSL_FAILURE;
+ int initTmpRng = 0;
+ WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG* tmpRNG = NULL;
+#else
+ WC_RNG _tmpRNG[1];
+ WC_RNG* tmpRNG = _tmpRNG;
+#endif
+ enum wc_HashType hashType;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_padding_add_PKCS1_PSS");
+
+ if (!rsa || !EM || !mHash || !hashAlg) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (!(rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRNG, &initTmpRng))) {
+ WOLFSSL_MSG("WOLFSSL_RSA_GetRNG error");
+ goto cleanup;
+ }
+
+ if (!rsa->exSet && SetRsaExternal(rsa) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetRsaExternal error");
+ goto cleanup;
+ }
+
+ hashType = wolfSSL_EVP_md2macType(hashAlg);
+ if (hashType < WC_HASH_TYPE_NONE || hashType > WC_HASH_TYPE_MAX) {
+ WOLFSSL_MSG("wolfSSL_EVP_md2macType error");
+ goto cleanup;
+ }
+
+ if ((mgf = hash2mgf(hashType)) == WC_MGF1NONE) {
+ WOLFSSL_MSG("hash2mgf error");
+ goto cleanup;
+ }
+
+ if ((hashLen = wolfSSL_EVP_MD_size(hashAlg)) < 0) {
+ WOLFSSL_MSG("wolfSSL_EVP_MD_size error");
+ goto cleanup;
+ }
+
+ if ((emLen = wolfSSL_RSA_size(rsa)) <= 0) {
+ WOLFSSL_MSG("wolfSSL_RSA_size error");
+ goto cleanup;
+ }
+
+ switch (saltLen) {
+ /* Negative saltLen values are treated differently */
+ case RSA_PSS_SALTLEN_DIGEST:
+ saltLen = hashLen;
+ break;
+ case RSA_PSS_SALTLEN_MAX_SIGN:
+ case RSA_PSS_SALTLEN_MAX:
+ saltLen = emLen - hashLen - 2;
+ break;
+ default:
+ if (saltLen < 0) {
+ /* Not any currently implemented negative value */
+ WOLFSSL_MSG("invalid saltLen");
+ goto cleanup;
+ }
+ }
+
+ if (wc_RsaPad_ex(mHash, wolfSSL_EVP_MD_size(hashAlg), EM, emLen,
+ RSA_BLOCK_TYPE_1, rng, WC_RSA_PSS_PAD,
+ wolfSSL_EVP_md2macType(hashAlg), mgf, NULL, 0, saltLen,
+ wolfSSL_BN_num_bits(rsa->n), NULL) != MP_OKAY) {
+ WOLFSSL_MSG("wc_RsaPad_ex error");
+ goto cleanup;
+ }
+
+ ret = WOLFSSL_SUCCESS;
+cleanup:
+ if (initTmpRng)
+ wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+ if (tmpRNG)
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+ return ret;
+}
+
+/*
+ * Refer to wolfSSL_RSA_padding_add_PKCS1_PSS
+ * for an explanation of the parameters.
+ */
+int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash,
+ const WOLFSSL_EVP_MD *hashAlg,
+ const unsigned char *EM, int saltLen)
+{
+ int hashLen, mgf, emLen, mPrimeLen;
+ enum wc_HashType hashType;
+ byte *mPrime = NULL;
+ byte *buf = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_verify_PKCS1_PSS");
+
+ if (!rsa || !mHash || !hashAlg || !EM) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if ((hashLen = wolfSSL_EVP_MD_size(hashAlg)) < 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if ((emLen = wolfSSL_RSA_size(rsa)) <= 0) {
+ WOLFSSL_MSG("wolfSSL_RSA_size error");
+ return WOLFSSL_FAILURE;
+ }
+
+ switch (saltLen) {
+ /* Negative saltLen values are treated differently */
+ case RSA_PSS_SALTLEN_DIGEST:
+ saltLen = hashLen;
+ break;
+ case RSA_PSS_SALTLEN_MAX_SIGN:
+ case RSA_PSS_SALTLEN_MAX:
+ saltLen = emLen - hashLen - 2;
+ break;
+ default:
+ if (saltLen < 0) {
+ /* Not any currently implemented negative value */
+ WOLFSSL_MSG("invalid saltLen");
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ if (!rsa->exSet && SetRsaExternal(rsa) != WOLFSSL_SUCCESS) {
+ return WOLFSSL_FAILURE;
+ }
+
+ hashType = wolfSSL_EVP_md2macType(hashAlg);
+ if (hashType < WC_HASH_TYPE_NONE || hashType > WC_HASH_TYPE_MAX) {
+ WOLFSSL_MSG("wolfSSL_EVP_md2macType error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if ((mgf = hash2mgf(hashType)) == WC_MGF1NONE) {
+ WOLFSSL_MSG("hash2mgf error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if ((hashLen = wolfSSL_EVP_MD_size(hashAlg)) < 0) {
+ WOLFSSL_MSG("wolfSSL_EVP_MD_size error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (!(buf = (byte*)XMALLOC(emLen, NULL, DYNAMIC_TYPE_TMP_BUFFER))) {
+ WOLFSSL_MSG("malloc error");
+ return WOLFSSL_FAILURE;
+ }
+ XMEMCPY(buf, EM, emLen);
+
+ /* Remove and verify the PSS padding */
+ if ((mPrimeLen = wc_RsaUnPad_ex(buf, emLen, &mPrime,
+ RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, hashType,
+ mgf, NULL, 0, saltLen,
+ wolfSSL_BN_num_bits(rsa->n), NULL)) < 0) {
+ WOLFSSL_MSG("wc_RsaPad_ex error");
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Verify the hash is correct */
+ if (wc_RsaPSS_CheckPadding_ex(mHash, hashLen, mPrime, mPrimeLen, hashType,
+ saltLen, wolfSSL_BN_num_bits(rsa->n))
+ != MP_OKAY) {
+ WOLFSSL_MSG("wc_RsaPSS_CheckPadding_ex error");
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_SUCCESS;
+}
+#endif
+
+#if defined(OPENSSL_EXTRA)
+WOLFSSL_RSA_METHOD *wolfSSL_RSA_meth_new(const char *name, int flags)
+{
+ int name_len;
+ WOLFSSL_RSA_METHOD* meth;
+
+ if (name == NULL) {
+ return NULL;
+ }
+
+ meth = (WOLFSSL_RSA_METHOD*)XMALLOC(sizeof(WOLFSSL_RSA_METHOD), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ name_len = (int)XSTRLEN(name);
+ if (!meth) {
+ return NULL;
+ }
+ meth->flags = flags;
+ meth->name = (char*)XMALLOC(name_len+1, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (!meth->name) {
+ XFREE(meth, NULL, DYNAMIC_TYPE_OPENSSL);
+ return NULL;
+ }
+ XMEMCPY(meth->name, name, name_len+1);
+
+ return meth;
+}
+
+void wolfSSL_RSA_meth_free(WOLFSSL_RSA_METHOD *meth)
+{
+ if (meth) {
+ XFREE(meth->name, NULL, DYNAMIC_TYPE_OPENSSL);
+ XFREE(meth, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_RSA_meth_set(WOLFSSL_RSA_METHOD *rsa, void* p)
+{
+ (void)rsa;
+ (void)p;
+ WOLFSSL_STUB("RSA_METHOD is not implemented.");
+ return 1;
+}
+#endif
+
+int wolfSSL_RSA_set_method(WOLFSSL_RSA *rsa, WOLFSSL_RSA_METHOD *meth)
+{
+ if (rsa)
+ rsa->meth = meth;
+ return 1;
+}
+
+const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_method(const WOLFSSL_RSA *rsa)
+{
+ if (!rsa) {
+ return NULL;
+ }
+ return rsa->meth;
+}
+
+const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_default_method(void)
+{
+ return wolfSSL_RSA_meth_new("wolfSSL RSA", 0);
+}
+
+int wolfSSL_RSA_flags(const WOLFSSL_RSA *r)
+{
+ if (r && r->meth) {
+ return r->meth->flags;
+ } else {
+ return 0;
+ }
+}
+
+void wolfSSL_RSA_set_flags(WOLFSSL_RSA *r, int flags)
+{
+ if (r && r->meth) {
+ r->meth->flags = flags;
+ }
+}
+
+#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+WOLFSSL_RSA* wolfSSL_RSAPublicKey_dup(WOLFSSL_RSA *rsa)
+{
+ int derSz = 0;
+ byte *derBuf = NULL;
+ WOLFSSL_RSA* local;
+
+ WOLFSSL_ENTER("wolfSSL_RSAPublicKey_dup");
+
+ if (!rsa) {
+ return NULL;
+ }
+
+ local = wolfSSL_RSA_new();
+ if (local == NULL) {
+ WOLFSSL_MSG("Error creating a new WOLFSSL_RSA structure");
+ return NULL;
+ }
+
+ if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1)) < 0) {
+ WOLFSSL_MSG("wolfSSL_RSA_To_Der failed");
+ return NULL;
+ }
+
+ if (wolfSSL_RSA_LoadDer_ex(local,
+ derBuf, derSz,
+ WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) {
+ wolfSSL_RSA_free(local);
+ local = NULL;
+ }
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_ASN1);
+ return local;
+}
+#endif
+
+void* wolfSSL_RSA_get_ex_data(const WOLFSSL_RSA *rsa, int idx)
+{
+ WOLFSSL_ENTER("wolfSSL_RSA_get_ex_data");
+#ifdef HAVE_EX_DATA
+ if (rsa) {
+ return wolfSSL_CRYPTO_get_ex_data(&rsa->ex_data, idx);
+ }
+#else
+ (void)rsa;
+ (void)idx;
+#endif
+ return NULL;
+}
+
+int wolfSSL_RSA_set_ex_data(WOLFSSL_RSA *rsa, int idx, void *data)
+{
+ WOLFSSL_ENTER("wolfSSL_RSA_set_ex_data");
+ #ifdef HAVE_EX_DATA
+ if (rsa) {
+ return wolfSSL_CRYPTO_set_ex_data(&rsa->ex_data, idx, data);
+ }
+ #else
+ (void)rsa;
+ (void)idx;
+ (void)data;
+ #endif
+ return WOLFSSL_FAILURE;
+}
+
+int wolfSSL_RSA_set0_key(WOLFSSL_RSA *r, WOLFSSL_BIGNUM *n, WOLFSSL_BIGNUM *e,
+ WOLFSSL_BIGNUM *d)
+{
+ /* If the fields n and e in r are NULL, the corresponding input
+ * parameters MUST be non-NULL for n and e. d may be
+ * left NULL (in case only the public key is used).
+ */
+ if ((!r->n && !n) || (!r->e && !e))
+ return 0;
+
+ if (n) {
+ wolfSSL_BN_free(r->n);
+ r->n = n;
+ }
+ if (e) {
+ wolfSSL_BN_free(r->e);
+ r->e = e;
+ }
+ if (d) {
+ wolfSSL_BN_clear_free(r->d);
+ r->d = d;
+ }
+
+ return 1;
+}
+#endif /* OPENSSL_EXTRA */
+#endif /* NO_RSA */
+
+#ifdef OPENSSL_EXTRA
#ifndef NO_DSA
-/* Load DSA from Der, SSL_SUCCESS on success < 0 on error */
-int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* der, int derSz)
+/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */
+int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* derBuf, int derSz)
{
word32 idx = 0;
int ret;
WOLFSSL_ENTER("wolfSSL_DSA_LoadDer");
- if (dsa == NULL || dsa->internal == NULL || der == NULL || derSz <= 0) {
+ if (dsa == NULL || dsa->internal == NULL || derBuf == NULL || derSz <= 0) {
WOLFSSL_MSG("Bad function arguments");
- return BAD_FUNC_ARG;
+ return WOLFSSL_FATAL_ERROR;
}
- ret = DsaPrivateKeyDecode(der, &idx, (DsaKey*)dsa->internal, derSz);
+ ret = DsaPrivateKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz);
if (ret < 0) {
WOLFSSL_MSG("DsaPrivateKeyDecode failed");
- return ret;
+ return WOLFSSL_FATAL_ERROR;
}
- if (SetDsaExternal(dsa) < 0) {
+ if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("SetDsaExternal failed");
- return SSL_FATAL_ERROR;
+ return WOLFSSL_FATAL_ERROR;
}
dsa->inSet = 1;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
+}
+
+/* Loads DSA key from DER buffer. opt = DSA_LOAD_PRIVATE or DSA_LOAD_PUBLIC.
+ returns 1 on success, or 0 on failure. */
+int wolfSSL_DSA_LoadDer_ex(WOLFSSL_DSA* dsa, const unsigned char* derBuf,
+ int derSz, int opt)
+{
+ word32 idx = 0;
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_DSA_LoadDer");
+
+ if (dsa == NULL || dsa->internal == NULL || derBuf == NULL || derSz <= 0) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (opt == WOLFSSL_DSA_LOAD_PRIVATE) {
+ ret = DsaPrivateKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz);
+ }
+ else {
+ ret = DsaPublicKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz);
+ }
+
+ if (ret < 0 && opt == WOLFSSL_DSA_LOAD_PRIVATE) {
+ WOLFSSL_MSG("DsaPrivateKeyDecode failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ else if (ret < 0 && opt == WOLFSSL_DSA_LOAD_PUBLIC) {
+ WOLFSSL_MSG("DsaPublicKeyDecode failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetDsaExternal failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ dsa->inSet = 1;
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_DSA */
+
+#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,
+ int derSz)
+{
+ return wolfSSL_EC_KEY_LoadDer_ex(key, derBuf, derSz,
+ WOLFSSL_EC_KEY_LOAD_PRIVATE);
}
-#endif /* NO_DSA */
+int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
+ int derSz, int opt)
+{
+ word32 idx = 0;
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer");
+
+ if (key == NULL || key->internal == NULL || derBuf == NULL || derSz <= 0) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) {
+ ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal,
+ derSz);
+ }
+ else {
+ ret = wc_EccPublicKeyDecode(derBuf, &idx, (ecc_key*)key->internal,
+ derSz);
+ }
+ if (ret < 0) {
+ if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) {
+ WOLFSSL_MSG("wc_EccPrivateKeyDecode failed");
+ }
+ else {
+ WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
+ }
+ return WOLFSSL_FATAL_ERROR;
+ }
+ if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetECKeyExternal failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ key->inSet = 1;
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_ECC */
+
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH))
+/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */
+int wolfSSL_DH_LoadDer(WOLFSSL_DH* dh, const unsigned char* derBuf, int derSz)
+{
+ word32 idx = 0;
+ int ret;
+
+ if (dh == NULL || dh->internal == NULL || derBuf == NULL || derSz <= 0) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ ret = wc_DhKeyDecode(derBuf, &idx, (DhKey*)dh->internal, (word32)derSz);
+ if (ret < 0) {
+ WOLFSSL_MSG("wc_DhKeyDecode failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (SetDhExternal(dh) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetDhExternal failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* ! NO_DH && WOLFSSL_QT || OPENSSL_ALL */
#endif /* OPENSSL_EXTRA */
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+
+/* increments ref count of WOLFSSL_RSA. Return 1 on success, 0 on error */
+int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa)
+{
+ if (rsa) {
+ if (wc_LockMutex(&rsa->refMutex) != 0) {
+ WOLFSSL_MSG("Failed to lock x509 mutex");
+ }
+ rsa->refCount++;
+ wc_UnLockMutex(&rsa->refMutex);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/* increments ref count of WOLFSSL_X509. Return 1 on success, 0 on error */
+int wolfSSL_X509_up_ref(WOLFSSL_X509* x509)
+{
+ if (x509) {
+ if (wc_LockMutex(&x509->refMutex) != 0) {
+ WOLFSSL_MSG("Failed to lock x509 mutex");
+ }
+ x509->refCount++;
+ wc_UnLockMutex(&x509->refMutex);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
+
+
+#ifdef WOLFSSL_ALT_CERT_CHAINS
+int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl)
+{
+ int isUsing = 0;
+ if (ssl)
+ isUsing = ssl->options.usingAltCertChain;
+ return isUsing;
+}
+#endif /* WOLFSSL_ALT_CERT_CHAINS */
+
+
#ifdef SESSION_CERTS
+#ifdef WOLFSSL_ALT_CERT_CHAINS
+/* Get peer's alternate certificate chain */
+WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_get_peer_alt_chain");
+ if (ssl)
+ return &ssl->session.altChain;
+
+ return 0;
+}
+#endif /* WOLFSSL_ALT_CERT_CHAINS */
+
/* Get peer's certificate chain */
WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl)
@@ -12634,7 +35560,7 @@ int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain)
}
-/* Get peer's ASN.1 DER ceritifcate at index (idx) length in bytes */
+/* Get peer's ASN.1 DER certificate at index (idx) length in bytes */
int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx)
{
WOLFSSL_ENTER("wolfSSL_get_chain_length");
@@ -12645,7 +35571,7 @@ int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx)
}
-/* Get peer's ASN.1 DER ceritifcate at index (idx) */
+/* Get peer's ASN.1 DER certificate at index (idx) */
byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx)
{
WOLFSSL_ENTER("wolfSSL_get_chain_cert");
@@ -12656,7 +35582,7 @@ byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx)
}
-/* Get peer's wolfSSL X509 ceritifcate at index (idx) */
+/* Get peer's wolfSSL X509 certificate at index (idx) */
WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx)
{
int ret;
@@ -12671,15 +35597,16 @@ WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx)
if (chain != NULL) {
#ifdef WOLFSSL_SMALL_STACK
cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
+ DYNAMIC_TYPE_DCERT);
if (cert != NULL)
#endif
{
InitDecodedCert(cert, chain->certs[idx].buffer,
chain->certs[idx].length, NULL);
- if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) != 0)
+ if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) != 0) {
WOLFSSL_MSG("Failed to parse cert");
+ }
else {
x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
DYNAMIC_TYPE_X509);
@@ -12687,11 +35614,11 @@ WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx)
WOLFSSL_MSG("Failed alloc X509");
}
else {
- InitX509(x509, 1);
+ InitX509(x509, 1, NULL);
if ((ret = CopyDecodedToX509(x509, cert)) != 0) {
WOLFSSL_MSG("Failed to copy decoded");
- XFREE(x509, NULL, DYNAMIC_TYPE_X509);
+ wolfSSL_X509_free(x509);
x509 = NULL;
}
}
@@ -12699,39 +35626,59 @@ WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx)
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
#endif
}
}
+ (void)ret;
return x509;
}
-/* Get peer's PEM ceritifcate at index (idx), output to buffer if inLen big
- enough else return error (-1), output length is in *outLen
- SSL_SUCCESS on ok */
+/* Get peer's PEM certificate at index (idx), output to buffer if inLen big
+ enough else return error (-1). If buffer is NULL only calculate
+ outLen. Output length is in *outLen WOLFSSL_SUCCESS on ok */
int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx,
unsigned char* buf, int inLen, int* outLen)
{
- const char header[] = "-----BEGIN CERTIFICATE-----\n";
- const char footer[] = "-----END CERTIFICATE-----\n";
-
- int headerLen = sizeof(header) - 1;
- int footerLen = sizeof(footer) - 1;
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+ const char* header = NULL;
+ const char* footer = NULL;
+ int headerLen;
+ int footerLen;
int i;
int err;
+ word32 szNeeded = 0;
WOLFSSL_ENTER("wolfSSL_get_chain_cert_pem");
- if (!chain || !outLen || !buf)
+ if (!chain || !outLen || idx < 0 || idx >= wolfSSL_get_chain_count(chain))
return BAD_FUNC_ARG;
+ err = wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer);
+ if (err != 0)
+ return err;
+
+ headerLen = (int)XSTRLEN(header);
+ footerLen = (int)XSTRLEN(footer);
+
+ /* Null output buffer return size needed in outLen */
+ if(!buf) {
+ if(Base64_Encode(chain->certs[idx].buffer, chain->certs[idx].length,
+ NULL, &szNeeded) != LENGTH_ONLY_E)
+ return WOLFSSL_FAILURE;
+ *outLen = szNeeded + headerLen + footerLen;
+ return LENGTH_ONLY_E;
+ }
+
/* don't even try if inLen too short */
if (inLen < headerLen + footerLen + chain->certs[idx].length)
return BAD_FUNC_ARG;
/* header */
- XMEMCPY(buf, header, headerLen);
+ if (XMEMCPY(buf, header, headerLen) == NULL)
+ return WOLFSSL_FATAL_ERROR;
+
i = headerLen;
/* body */
@@ -12744,14 +35691,24 @@ int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx,
/* footer */
if ( (i + footerLen) > inLen)
return BAD_FUNC_ARG;
- XMEMCPY(buf + i, footer, footerLen);
+ if (XMEMCPY(buf + i, footer, footerLen) == NULL)
+ return WOLFSSL_FATAL_ERROR;
*outLen += headerLen + footerLen;
- return SSL_SUCCESS;
+ return WOLFSSL_SUCCESS;
+#else
+ (void)chain;
+ (void)idx;
+ (void)buf;
+ (void)inLen;
+ (void)outLen;
+ return WOLFSSL_FAILURE;
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
}
/* get session ID */
+WOLFSSL_ABI
const byte* wolfSSL_get_sessionID(const WOLFSSL_SESSION* session)
{
WOLFSSL_ENTER("wolfSSL_get_sessionID");
@@ -12778,21 +35735,35 @@ void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx)
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
+void wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX* ctx, CallbackEccKeyGen cb)
+{
+ if (ctx)
+ ctx->EccKeyGenCb = cb;
+}
+void wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->EccKeyGenCtx = ctx;
+}
+void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->EccKeyGenCtx;
+ return NULL;
+}
+
+WOLFSSL_ABI
void wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX* ctx, CallbackEccSign cb)
{
if (ctx)
ctx->EccSignCb = cb;
}
-
-
void wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx)
{
if (ssl)
ssl->EccSignCtx = ctx;
}
-
-
void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl)
{
if (ssl)
@@ -12801,21 +35772,16 @@ void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl)
return NULL;
}
-
void wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX* ctx, CallbackEccVerify cb)
{
if (ctx)
ctx->EccVerifyCb = cb;
}
-
-
void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx)
{
if (ssl)
ssl->EccVerifyCtx = ctx;
}
-
-
void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl)
{
if (ssl)
@@ -12824,24 +35790,197 @@ void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl)
return NULL;
}
+void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX* ctx, CallbackEccSharedSecret cb)
+{
+ if (ctx)
+ ctx->EccSharedSecretCb = cb;
+}
+void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->EccSharedSecretCtx = ctx;
+}
+void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->EccSharedSecretCtx;
+
+ return NULL;
+}
#endif /* HAVE_ECC */
-#ifndef NO_RSA
+#ifdef HAVE_ED25519
+void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX* ctx, CallbackEd25519Sign cb)
+{
+ if (ctx)
+ ctx->Ed25519SignCb = cb;
+}
+void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->Ed25519SignCtx = ctx;
+}
+void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->Ed25519SignCtx;
-void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb)
+ return NULL;
+}
+
+void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb)
{
if (ctx)
- ctx->RsaSignCb = cb;
+ ctx->Ed25519VerifyCb = cb;
+}
+void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->Ed25519VerifyCtx = ctx;
}
+void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->Ed25519VerifyCtx;
+ return NULL;
+}
+#endif /* HAVE_ED25519 */
-void wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx)
+#ifdef HAVE_CURVE25519
+void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX* ctx,
+ CallbackX25519KeyGen cb)
+{
+ if (ctx)
+ ctx->X25519KeyGenCb = cb;
+}
+void wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx)
{
if (ssl)
- ssl->RsaSignCtx = ctx;
+ ssl->X25519KeyGenCtx = ctx;
+}
+void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->X25519KeyGenCtx;
+
+ return NULL;
+}
+
+void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX* ctx,
+ CallbackX25519SharedSecret cb)
+{
+ if (ctx)
+ ctx->X25519SharedSecretCb = cb;
+}
+void wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->X25519SharedSecretCtx = ctx;
}
+void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->X25519SharedSecretCtx;
+ return NULL;
+}
+#endif /* HAVE_CURVE25519 */
+#ifdef HAVE_ED448
+void wolfSSL_CTX_SetEd448SignCb(WOLFSSL_CTX* ctx, CallbackEd448Sign cb)
+{
+ if (ctx)
+ ctx->Ed448SignCb = cb;
+}
+void wolfSSL_SetEd448SignCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->Ed448SignCtx = ctx;
+}
+void* wolfSSL_GetEd448SignCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->Ed448SignCtx;
+
+ return NULL;
+}
+
+void wolfSSL_CTX_SetEd448VerifyCb(WOLFSSL_CTX* ctx, CallbackEd448Verify cb)
+{
+ if (ctx)
+ ctx->Ed448VerifyCb = cb;
+}
+void wolfSSL_SetEd448VerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->Ed448VerifyCtx = ctx;
+}
+void* wolfSSL_GetEd448VerifyCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->Ed448VerifyCtx;
+
+ return NULL;
+}
+#endif /* HAVE_ED448 */
+
+#ifdef HAVE_CURVE448
+void wolfSSL_CTX_SetX448KeyGenCb(WOLFSSL_CTX* ctx,
+ CallbackX448KeyGen cb)
+{
+ if (ctx)
+ ctx->X448KeyGenCb = cb;
+}
+void wolfSSL_SetX448KeyGenCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->X448KeyGenCtx = ctx;
+}
+void* wolfSSL_GetX448KeyGenCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->X448KeyGenCtx;
+
+ return NULL;
+}
+
+void wolfSSL_CTX_SetX448SharedSecretCb(WOLFSSL_CTX* ctx,
+ CallbackX448SharedSecret cb)
+{
+ if (ctx)
+ ctx->X448SharedSecretCb = cb;
+}
+void wolfSSL_SetX448SharedSecretCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->X448SharedSecretCtx = ctx;
+}
+void* wolfSSL_GetX448SharedSecretCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->X448SharedSecretCtx;
+
+ return NULL;
+}
+#endif /* HAVE_CURVE448 */
+
+#ifndef NO_RSA
+void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb)
+{
+ if (ctx)
+ ctx->RsaSignCb = cb;
+}
+void wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
+{
+ if (ctx)
+ ctx->RsaSignCheckCb = cb;
+}
+void wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->RsaSignCtx = ctx;
+}
void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl)
{
if (ssl)
@@ -12856,15 +35995,11 @@ void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
if (ctx)
ctx->RsaVerifyCb = cb;
}
-
-
void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx)
{
if (ssl)
ssl->RsaVerifyCtx = ctx;
}
-
-
void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl)
{
if (ssl)
@@ -12873,20 +36008,59 @@ void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl)
return NULL;
}
-void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb)
+#ifdef WC_RSA_PSS
+void wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX* ctx, CallbackRsaPssSign cb)
{
if (ctx)
- ctx->RsaEncCb = cb;
+ ctx->RsaPssSignCb = cb;
+}
+void wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb)
+{
+ if (ctx)
+ ctx->RsaPssSignCheckCb = cb;
}
+void wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->RsaPssSignCtx = ctx;
+}
+void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->RsaPssSignCtx;
+ return NULL;
+}
-void wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx)
+void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb)
+{
+ if (ctx)
+ ctx->RsaPssVerifyCb = cb;
+}
+void wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx)
{
if (ssl)
- ssl->RsaEncCtx = ctx;
+ ssl->RsaPssVerifyCtx = ctx;
}
+void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->RsaPssVerifyCtx;
+ return NULL;
+}
+#endif /* WC_RSA_PSS */
+void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb)
+{
+ if (ctx)
+ ctx->RsaEncCb = cb;
+}
+void wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->RsaEncCtx = ctx;
+}
void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl)
{
if (ssl)
@@ -12900,15 +36074,11 @@ void wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX* ctx, CallbackRsaDec cb)
if (ctx)
ctx->RsaDecCb = cb;
}
-
-
void wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx)
{
if (ssl)
ssl->RsaDecCtx = ctx;
}
-
-
void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl)
{
if (ssl)
@@ -12916,13 +36086,31 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl)
return NULL;
}
-
-
#endif /* NO_RSA */
#endif /* HAVE_PK_CALLBACKS */
#endif /* NO_CERTS */
+#if defined(HAVE_PK_CALLBACKS) && !defined(NO_DH)
+void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX* ctx, CallbackDhAgree cb)
+{
+ if (ctx)
+ ctx->DhAgreeCb = cb;
+}
+void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->DhAgreeCtx = ctx;
+}
+void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->DhAgreeCtx;
+
+ return NULL;
+}
+#endif /* HAVE_PK_CALLBACKS && !NO_DH */
+
#ifdef WOLFSSL_HAVE_WOLFSCEP
/* Used by autoconf to see if wolfSCEP is available */
@@ -12935,3 +36123,11585 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl)
void wolfSSL_cert_service(void) {}
#endif
+#ifdef OPENSSL_EXTRA
+ #ifndef NO_CERTS
+ void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name)
+ {
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_free");
+ FreeX509Name(name, NULL);
+ XFREE(name, NULL, DYNAMIC_TYPE_X509);
+ }
+
+
+ /* Malloc's a new WOLFSSL_X509_NAME structure
+ *
+ * returns NULL on failure, otherwise returns a new structure.
+ */
+ WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void)
+ {
+ WOLFSSL_X509_NAME* name;
+
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_new");
+
+ name = (WOLFSSL_X509_NAME*)XMALLOC(sizeof(WOLFSSL_X509_NAME), NULL,
+ DYNAMIC_TYPE_X509);
+ if (name != NULL) {
+ InitX509Name(name, 1);
+ }
+ return name;
+ }
+
+ /* Creates a duplicate of a WOLFSSL_X509_NAME structure.
+ Returns a new WOLFSSL_X509_NAME structure or NULL on failure */
+ WOLFSSL_X509_NAME* wolfSSL_X509_NAME_dup(WOLFSSL_X509_NAME *name)
+ {
+ WOLFSSL_X509_NAME* dup = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_dup");
+
+ if (name == NULL) {
+ WOLFSSL_MSG("NULL parameter");
+ return NULL;
+ }
+
+ if (!(dup = wolfSSL_X509_NAME_new())) {
+ return NULL;
+ }
+
+ /* copy contents */
+ XMEMCPY(dup, name, sizeof(WOLFSSL_X509_NAME));
+ InitX509Name(dup, 1);
+ dup->sz = name->sz;
+
+ /* handle dynamic portions */
+ if (name->dynamicName) {
+ if (!(dup->name = (char*)XMALLOC(name->sz, 0,
+ DYNAMIC_TYPE_OPENSSL))) {
+ goto err;
+ }
+ }
+ XMEMCPY(dup->name, name->name, name->sz);
+ #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+ !defined(NO_ASN)
+ if (!(dup->fullName.fullName = (char*)XMALLOC(name->fullName.fullNameLen,
+ 0, DYNAMIC_TYPE_OPENSSL))) {
+ goto err;
+ }
+ XMEMCPY(dup->fullName.fullName, name->fullName.fullName,
+ name->fullName.fullNameLen);
+ #endif
+
+ return dup;
+
+ err:
+ if (dup) {
+ if (dup->dynamicName && dup->name) {
+ XFREE(dup->name, 0, DYNAMIC_TYPE_OPENSSL);
+ dup->name = NULL;
+ }
+ #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+ !defined(NO_ASN)
+ if (dup->fullName.fullName &&
+ dup->fullName.fullName != name->fullName.fullName) {
+ XFREE(dup->fullName.fullName, 0, DYNAMIC_TYPE_OPENSSL);
+ dup->fullName.fullName = NULL;
+ }
+ #endif
+ wolfSSL_X509_NAME_free(dup);
+ }
+ return NULL;
+ }
+
+#if defined(WOLFSSL_CERT_GEN)
+ /* helper function for CopyX509NameToCertName()
+ *
+ * returns WOLFSSL_SUCCESS on success
+ */
+ static int CopyX509NameEntry(char* out, int mx, char* in, int inLen)
+ {
+ if (inLen > mx) {
+ WOLFSSL_MSG("Name too long");
+ XMEMCPY(out, in, mx);
+ }
+ else {
+ XMEMCPY(out, in, inLen);
+ out[inLen] = '\0';
+ }
+
+ /* make sure is null terminated */
+ out[mx-1] = '\0';
+
+ return WOLFSSL_SUCCESS;
+ }
+
+
+ /* Helper function to copy cert name from a WOLFSSL_X509_NAME structure to
+ * a CertName structure.
+ *
+ * returns WOLFSSL_SUCCESS on success and a negative error value on failure
+ */
+ static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName)
+ {
+ DecodedName* dn = NULL;
+
+ if (n == NULL || cName == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ dn = &(n->fullName);
+
+ /* initialize cert name */
+ cName->country[0] = '\0';
+ cName->countryEnc = CTC_PRINTABLE;
+ cName->state[0] = '\0';
+ cName->stateEnc = CTC_UTF8;
+ cName->locality[0] = '\0';
+ cName->localityEnc = CTC_UTF8;
+ cName->sur[0] = '\0';
+ cName->surEnc = CTC_UTF8;
+ cName->org[0] = '\0';
+ cName->orgEnc = CTC_UTF8;
+ cName->unit[0] = '\0';
+ cName->unitEnc = CTC_UTF8;
+ cName->commonName[0] = '\0';
+ cName->commonNameEnc = CTC_UTF8;
+ cName->serialDev[0] = '\0';
+ cName->serialDevEnc = CTC_PRINTABLE;
+ #ifdef WOLFSSL_CERT_EXT
+ cName->busCat[0] = '\0';
+ cName->busCatEnc = CTC_UTF8;
+ cName->joiC[0] = '\0';
+ cName->joiCEnc = CTC_PRINTABLE;
+ cName->joiSt[0] = '\0';
+ cName->joiStEnc = CTC_PRINTABLE;
+ #endif
+ cName->email[0] = '\0';
+
+
+ /* ASN_COUNTRY_NAME */
+ WOLFSSL_MSG("Copy Country Name");
+ if (CopyX509NameEntry(cName->country, CTC_NAME_SIZE, dn->fullName + dn->cIdx,
+ dn->cLen) != SSL_SUCCESS) {
+ return BUFFER_E;
+ }
+
+ /* ASN_ORGUNIT_NAME */
+ WOLFSSL_MSG("Copy Org Unit Name");
+ if (CopyX509NameEntry(cName->unit, CTC_NAME_SIZE, dn->fullName + dn->ouIdx,
+ dn->ouLen) != SSL_SUCCESS) {
+ return BUFFER_E;
+ }
+
+ /* ASN_ORG_NAME */
+ WOLFSSL_MSG("Copy Org Name");
+ if (CopyX509NameEntry(cName->org, CTC_NAME_SIZE, dn->fullName + dn->oIdx,
+ dn->oLen) != SSL_SUCCESS) {
+ return BUFFER_E;
+ }
+
+ /* ASN_STATE_NAME */
+ WOLFSSL_MSG("Copy State Name");
+ if (CopyX509NameEntry(cName->state, CTC_NAME_SIZE, dn->fullName + dn->stIdx,
+ dn->stLen) != SSL_SUCCESS) {
+ return BUFFER_E;
+ }
+
+ /* ASN_LOCALITY_NAME */
+ WOLFSSL_MSG("Copy Locality Name");
+ if (CopyX509NameEntry(cName->locality, CTC_NAME_SIZE,
+ dn->fullName + dn->lIdx, dn->lLen)
+ != SSL_SUCCESS) {
+ return BUFFER_E;
+ }
+
+ /* ASN_SUR_NAME */
+ WOLFSSL_MSG("Copy Sur Name");
+ if (CopyX509NameEntry(cName->sur, CTC_NAME_SIZE, dn->fullName + dn->snIdx,
+ dn->snLen) != SSL_SUCCESS) {
+ return BUFFER_E;
+ }
+
+ /* ASN_COMMON_NAME */
+ WOLFSSL_MSG("Copy Common Name");
+ if (CopyX509NameEntry(cName->commonName, CTC_NAME_SIZE,
+ dn->fullName + dn->cnIdx, dn->cnLen)
+ != SSL_SUCCESS) {
+ return BUFFER_E;
+ }
+
+ /* ASN_SERIAL_NUMBER */
+ WOLFSSL_MSG("Copy Serial Number of Device");
+ if (CopyX509NameEntry(cName->serialDev, CTC_NAME_SIZE,
+ dn->fullName + dn->serialIdx, dn->serialLen)
+ != SSL_SUCCESS) {
+ return BUFFER_E;
+ }
+
+ #ifdef WOLFSSL_CERT_EXT
+ /* ASN_BUS_CAT */
+ WOLFSSL_MSG("Copy Business Category");
+ if (CopyX509NameEntry(cName->busCat, CTC_NAME_SIZE,
+ dn->fullName + dn->bcIdx, dn->bcLen)
+ != SSL_SUCCESS) {
+ return BUFFER_E;
+ }
+
+ /* JoI Country */
+ WOLFSSL_MSG("Copy Jurisdiction of Incorporation Country");
+ if (CopyX509NameEntry(cName->joiC, CTC_NAME_SIZE,
+ dn->fullName + dn->jcIdx, dn->jcLen)
+ != SSL_SUCCESS) {
+ return BUFFER_E;
+ }
+
+ /* JoI State */
+ WOLFSSL_MSG("Copy Jurisdiction of Incorporation State");
+ if (CopyX509NameEntry(cName->joiSt, CTC_NAME_SIZE,
+ dn->fullName + dn->jsIdx, dn->jsLen)
+ != SSL_SUCCESS) {
+ return BUFFER_E;
+ }
+ #endif
+
+ WOLFSSL_MSG("Copy Email");
+ if (CopyX509NameEntry(cName->email, CTC_NAME_SIZE,
+ dn->fullName + dn->emailIdx, dn->emailLen)
+ != SSL_SUCCESS) {
+ return BUFFER_E;
+ }
+
+ return WOLFSSL_SUCCESS;
+ }
+
+#ifdef WOLFSSL_CERT_REQ
+ static int ReqCertFromX509(Cert* cert, WOLFSSL_X509* req)
+ {
+ int ret;
+
+ if (wc_InitCert(cert) != 0)
+ return WOLFSSL_FAILURE;
+
+ ret = CopyX509NameToCertName(&req->subject, &cert->subject);
+ if (ret == WOLFSSL_SUCCESS) {
+ cert->version = req->version;
+ cert->isCA = req->isCa;
+#ifdef WOLFSSL_CERT_EXT
+ if (req->subjKeyIdSz != 0) {
+ XMEMCPY(cert->skid, req->subjKeyId, req->subjKeyIdSz);
+ cert->skidSz = req->subjKeyIdSz;
+ }
+ if (req->keyUsageSet)
+ cert->keyUsage = req->keyUsage;
+ /* Extended Key Usage not supported. */
+#endif
+ }
+
+ return ret;
+ }
+#endif
+
+ /* convert a WOLFSSL_X509 to a Cert structure for writing out */
+ static int CertFromX509(Cert* cert, WOLFSSL_X509* x509)
+ {
+ int ret;
+ #ifdef WOLFSSL_CERT_EXT
+ int i;
+ #endif
+
+ WOLFSSL_ENTER("wolfSSL_X509_to_Cert()");
+
+ if (x509 == NULL || cert == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ wc_InitCert(cert);
+
+ cert->version = (int)wolfSSL_X509_get_version(x509);
+
+ #ifdef WOLFSSL_ALT_NAMES
+ if (x509->notBefore.length > 0) {
+ if ((x509->notBefore.length + 2) < CTC_DATE_SIZE) {
+ cert->beforeDate[0] = x509->notBefore.type;
+ cert->beforeDate[1] = x509->notBefore.length;
+ XMEMCPY(&cert->beforeDate[2], x509->notBefore.data,
+ x509->notBefore.length);
+ cert->beforeDateSz = x509->notBefore.length + 2;
+ }
+ else {
+ WOLFSSL_MSG("Not before date too large");
+ return WOLFSSL_FAILURE;
+ }
+ }
+ else {
+ cert->beforeDateSz = 0;
+ }
+ if (x509->notAfter.length > 0) {
+ if ((x509->notAfter.length + 2) < CTC_DATE_SIZE) {
+ cert->afterDate[0] = x509->notAfter.type;
+ cert->afterDate[1] = x509->notAfter.length;
+ XMEMCPY(&cert->afterDate[2], x509->notAfter.data,
+ x509->notAfter.length);
+ cert->afterDateSz = x509->notAfter.length + 2;
+ }
+ else {
+ WOLFSSL_MSG("Not after date too large");
+ return WOLFSSL_FAILURE;
+ }
+ }
+ else {
+ cert->afterDateSz = 0;
+ }
+
+ cert->altNamesSz = FlattenAltNames(cert->altNames,
+ sizeof(cert->altNames), x509->altNames);
+
+ #endif /* WOLFSSL_ALT_NAMES */
+
+ cert->sigType = wolfSSL_X509_get_signature_type(x509);
+ cert->keyType = x509->pubKeyOID;
+ cert->isCA = wolfSSL_X509_get_isCA(x509);
+
+ #ifdef WOLFSSL_CERT_EXT
+ if (x509->subjKeyIdSz < CTC_MAX_SKID_SIZE) {
+ XMEMCPY(cert->skid, x509->subjKeyId, x509->subjKeyIdSz);
+ cert->skidSz = (int)x509->subjKeyIdSz;
+ }
+ else {
+ WOLFSSL_MSG("Subject Key ID too large");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (x509->authKeyIdSz < CTC_MAX_AKID_SIZE) {
+ XMEMCPY(cert->akid, x509->authKeyId, x509->authKeyIdSz);
+ cert->akidSz = (int)x509->authKeyIdSz;
+ }
+ else {
+ WOLFSSL_MSG("Auth Key ID too large");
+ return WOLFSSL_FAILURE;
+ }
+
+ for (i = 0; i < x509->certPoliciesNb; i++) {
+ /* copy the smaller of MAX macros, by default they are currently equal*/
+ if ((int)CTC_MAX_CERTPOL_SZ <= (int)MAX_CERTPOL_SZ) {
+ XMEMCPY(cert->certPolicies[i], x509->certPolicies[i],
+ CTC_MAX_CERTPOL_SZ);
+ }
+ else {
+ XMEMCPY(cert->certPolicies[i], x509->certPolicies[i],
+ MAX_CERTPOL_SZ);
+ }
+ }
+ cert->certPoliciesNb = (word16)x509->certPoliciesNb;
+
+ cert->keyUsage = x509->keyUsage;
+ #endif /* WOLFSSL_CERT_EXT */
+
+ #ifdef WOLFSSL_CERT_REQ
+ /* copy over challenge password for REQ certs */
+ XMEMCPY(cert->challengePw, x509->challengePw, CTC_NAME_SIZE);
+ #endif
+
+ if (x509->serialSz <= CTC_SERIAL_SIZE) {
+ XMEMCPY(cert->serial, x509->serial, x509->serialSz);
+ }
+ else {
+ WOLFSSL_MSG("Serial size error");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* copy over Name structures */
+ if (x509->issuerSet)
+ cert->selfSigned = 0;
+ if ((ret = CopyX509NameToCertName(&(x509->issuer), &(cert->issuer)))
+ != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error copying over issuer names");
+ WOLFSSL_LEAVE("wolfSSL_X509_to_Cert()", ret);
+ return WOLFSSL_FAILURE;
+ }
+ if ((ret = CopyX509NameToCertName(&(x509->subject), &(cert->subject)))
+ != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error copying over subject names");
+ WOLFSSL_LEAVE("wolfSSL_X509_to_Cert()", ret);
+ return WOLFSSL_FAILURE;
+ }
+
+ cert->heap = x509->heap;
+
+ return WOLFSSL_SUCCESS;
+ }
+
+
+ /* returns the sig type to use on success i.e CTC_SHAwRSA and WOLFSSL_FALURE
+ * on fail case */
+ static int wolfSSL_sigTypeFromPKEY(WOLFSSL_EVP_MD* md,
+ WOLFSSL_EVP_PKEY* pkey)
+ {
+ int hashType;
+ int sigType = WOLFSSL_FAILURE;
+
+ /* Convert key type and hash algorithm to a signature algorithm */
+ if (wolfSSL_EVP_get_hashinfo(md, &hashType, NULL) == WOLFSSL_FAILURE)
+ return WOLFSSL_FAILURE;
+
+
+ if (pkey->type == EVP_PKEY_RSA) {
+ switch (hashType) {
+ case WC_HASH_TYPE_SHA:
+ sigType = CTC_SHAwRSA;
+ break;
+ case WC_HASH_TYPE_SHA224:
+ sigType = CTC_SHA224wRSA;
+ break;
+ case WC_HASH_TYPE_SHA256:
+ sigType = CTC_SHA256wRSA;
+ break;
+ case WC_HASH_TYPE_SHA384:
+ sigType = CTC_SHA384wRSA;
+ break;
+ case WC_HASH_TYPE_SHA512:
+ sigType = CTC_SHA512wRSA;
+ break;
+ default:
+ return WOLFSSL_FAILURE;
+ }
+ }
+ else if (pkey->type == EVP_PKEY_EC) {
+ switch (hashType) {
+ case WC_HASH_TYPE_SHA:
+ sigType = CTC_SHAwECDSA;
+ break;
+ case WC_HASH_TYPE_SHA224:
+ sigType = CTC_SHA224wECDSA;
+ break;
+ case WC_HASH_TYPE_SHA256:
+ sigType = CTC_SHA256wECDSA;
+ break;
+ case WC_HASH_TYPE_SHA384:
+ sigType = CTC_SHA384wECDSA;
+ break;
+ case WC_HASH_TYPE_SHA512:
+ sigType = CTC_SHA512wECDSA;
+ break;
+ default:
+ return WOLFSSL_FAILURE;
+ }
+ }
+ else
+ return WOLFSSL_FAILURE;
+ return sigType;
+ }
+
+
+ /* generates DER buffer from WOLFSSL_X509
+ * If req == 1 then creates a request DER buffer
+ *
+ * updates derSz with certificate body size on success
+ * return WOLFSSL_SUCCESS on success
+ */
+ static int wolfSSL_X509_make_der(WOLFSSL_X509* x509, int req,
+ unsigned char* der, int* derSz)
+ {
+ int ret;
+ Cert cert;
+ void* key = NULL;
+ int type = -1;
+ #ifndef NO_RSA
+ RsaKey rsa;
+ #endif
+ #ifdef HAVE_ECC
+ ecc_key ecc;
+ #endif
+ WC_RNG rng;
+ word32 idx = 0;
+
+ if (x509 == NULL || der == NULL || derSz == NULL)
+ return BAD_FUNC_ARG;
+
+ #ifndef WOLFSSL_CERT_REQ
+ if (req) {
+ WOLFSSL_MSG("WOLFSSL_CERT_REQ needed for certificate request");
+ return WOLFSSL_FAILURE;
+ }
+ #endif
+
+ #ifdef WOLFSSL_CERT_REQ
+ if (req) {
+ if (ReqCertFromX509(&cert, x509) != WOLFSSL_SUCCESS)
+ return WOLFSSL_FAILURE;
+ }
+ else
+ #endif
+ {
+ /* Create a Cert that has the certificate fields. */
+ if (CertFromX509(&cert, x509) != WOLFSSL_SUCCESS)
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Create a public key object from requests public key. */
+ #ifndef NO_RSA
+ if (x509->pubKeyOID == RSAk) {
+ type = RSA_TYPE;
+ ret = wc_InitRsaKey(&rsa, x509->heap);
+ if (ret != 0)
+ return ret;
+ ret = wc_RsaPublicKeyDecode(x509->pubKey.buffer, &idx, &rsa,
+ x509->pubKey.length);
+ if (ret != 0) {
+ wc_FreeRsaKey(&rsa);
+ return ret;
+ }
+ key = (void*)&rsa;
+ }
+ #endif
+ #ifdef HAVE_ECC
+ if (x509->pubKeyOID == ECDSAk) {
+ type = ECC_TYPE;
+ ret = wc_ecc_init(&ecc);
+ if (ret != 0)
+ return ret;
+ ret = wc_EccPublicKeyDecode(x509->pubKey.buffer, &idx, &ecc,
+ x509->pubKey.length);
+ if (ret != 0) {
+ wc_ecc_free(&ecc);
+ return ret;
+ }
+ key = (void*)&ecc;
+ }
+ #endif
+ if (key == NULL)
+ return WOLFSSL_FAILURE;
+
+ /* Make the body of the certificate request. */
+ #ifdef WOLFSSL_CERT_REQ
+ if (req) {
+ ret = wc_MakeCertReq_ex(&cert, der, *derSz, type, key);
+ }
+ else
+ #endif
+ {
+ ret = wc_InitRng(&rng);
+ if (ret != 0)
+ return WOLFSSL_FAILURE;
+
+ ret = wc_MakeCert_ex(&cert, der, *derSz, type, key, &rng);
+ wc_FreeRng(&rng);
+ }
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* Dispose of the public key object. */
+ #ifndef NO_RSA
+ if (x509->pubKeyOID == RSAk)
+ wc_FreeRsaKey(&rsa);
+ #endif
+ #ifdef HAVE_ECC
+ if (x509->pubKeyOID == ECDSAk)
+ wc_ecc_free(&ecc);
+ #endif
+ *derSz = ret;
+
+ return WOLFSSL_SUCCESS;
+ }
+
+
+ /* signs a der buffer for the WOLFSSL_X509 structure using the PKEY and MD
+ * hash passed in
+ *
+ * WARNING: this free's and replaces the existing DER buffer in the
+ * WOLFSSL_X509 with the newly signed buffer.
+ * returns size of signed buffer on success and negative values on fail
+ */
+ static int wolfSSL_X509_resign_cert(WOLFSSL_X509* x509, int req,
+ unsigned char* der, int derSz, int certBodySz, WOLFSSL_EVP_MD* md,
+ WOLFSSL_EVP_PKEY* pkey)
+ {
+ int ret;
+ void* key = NULL;
+ int type = -1;
+ int sigType;
+ WC_RNG rng;
+
+ sigType = wolfSSL_sigTypeFromPKEY(md, pkey);
+ if (sigType == WOLFSSL_FAILURE)
+ return WOLFSSL_FATAL_ERROR;
+
+
+ /* Get the private key object and type from pkey. */
+ #ifndef NO_RSA
+ if (pkey->type == EVP_PKEY_RSA) {
+ type = RSA_TYPE;
+ key = pkey->rsa->internal;
+ }
+ #endif
+ #ifdef HAVE_ECC
+ if (pkey->type == EVP_PKEY_EC) {
+ type = ECC_TYPE;
+ key = pkey->ecc->internal;
+ }
+ #endif
+
+ /* Sign the certificate request body. */
+ ret = wc_InitRng(&rng);
+ if (ret != 0)
+ return ret;
+ ret = wc_SignCert_ex(certBodySz, sigType, der, derSz, type, key, &rng);
+ wc_FreeRng(&rng);
+ if (ret < 0)
+ return ret;
+
+ /* Put in the new certificate encoding into the x509 object. */
+ FreeDer(&x509->derCert);
+ type = CERT_TYPE;
+ #ifdef WOLFSSL_REQ_CERT
+ if (req) {
+ type = CERTREQ_TYPE;
+ }
+ #endif
+
+ if (AllocDer(&x509->derCert, ret, type, NULL) != 0)
+ return WOLFSSL_FATAL_ERROR;
+ XMEMCPY(x509->derCert->buffer, der, ret);
+ x509->derCert->length = ret;
+
+ (void)req;
+ return ret;
+ }
+
+
+ /* returns the size of signature on success */
+ int wolfSSL_X509_sign(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey,
+ const WOLFSSL_EVP_MD* md)
+ {
+ int ret;
+ byte der[4096]; /* @TODO dynamic set based on expected cert size */
+ int derSz = sizeof(der);
+
+ WOLFSSL_ENTER("wolfSSL_X509_sign");
+
+ if (x509 == NULL || pkey == NULL || md == NULL)
+ return WOLFSSL_FAILURE;
+
+ x509->sigOID = wolfSSL_sigTypeFromPKEY((WOLFSSL_EVP_MD*)md, pkey);
+ if ((ret = wolfSSL_X509_make_der(x509, 0, der, &derSz)) !=
+ WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Unable to make DER for X509");
+ WOLFSSL_LEAVE("wolfSSL_X509_sign", ret);
+ return WOLFSSL_FAILURE;
+ }
+
+ ret = wolfSSL_X509_resign_cert(x509, 0, der, sizeof(der), derSz,
+ (WOLFSSL_EVP_MD*)md, pkey);
+ if (ret <= 0) {
+ WOLFSSL_LEAVE("wolfSSL_X509_sign", ret);
+ return WOLFSSL_FAILURE;
+ }
+
+ return ret;
+ }
+
+
+ /* Converts the x509 name structure into DER format.
+ *
+ * out pointer to either a pre setup buffer or a pointer to null for
+ * creating a dynamic buffer. In the case that a pre-existing buffer is
+ * used out will be incremented the size of the DER buffer on success.
+ *
+ * returns the size of the buffer on success, or negative value with failure
+ */
+ int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out)
+ {
+ CertName cName;
+ unsigned char buf[256]; /* ASN_MAX_NAME */
+ int sz;
+ WOLFSSL_ENTER("wolfSSL_i2d_X509_NAME");
+
+ if (out == NULL || name == NULL) {
+ return BAD_FUNC_ARG;
+ }
+ XMEMSET(&cName, 0, sizeof(CertName));
+
+ if (CopyX509NameToCertName(name, &cName) != SSL_SUCCESS) {
+ WOLFSSL_MSG("Error converting x509 name to internal CertName");
+ return SSL_FATAL_ERROR;
+ }
+
+ sz = SetName(buf, sizeof(buf), &cName);
+ if (sz < 0) {
+ return sz;
+ }
+
+ /* using buffer passed in */
+ if (*out != NULL) {
+ XMEMCPY(*out, buf, sz);
+ *out += sz;
+ }
+ else {
+ *out = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (*out == NULL) {
+ return MEMORY_E;
+ }
+ XMEMCPY(*out, buf, sz);
+ }
+
+ return sz;
+ }
+#endif /* WOLFSSL_CERT_GEN */
+
+
+ /* Compares the two X509 names. If the size of x is larger then y then a
+ * positive value is returned if x is smaller a negative value is returned.
+ * In the case that the sizes are equal a the value of strcmp between the
+ * two names is returned.
+ *
+ * x First name for comparison
+ * y Second name to compare with x
+ */
+ int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x,
+ const WOLFSSL_X509_NAME* y)
+ {
+ const char* _x;
+ const char* _y;
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_cmp");
+
+ if (x == NULL || y == NULL) {
+ WOLFSSL_MSG("Bad argument passed in");
+ return -2;
+ }
+
+ if (x == y) {
+ return 0; /* match */
+ }
+
+ if (x->sz != y->sz) {
+ return x->sz - y->sz;
+ }
+
+ /*
+ * If the name member is not set or is immediately null terminated then
+ * compare the staticName member
+ */
+ _x = (x->name && *x->name) ? x->name : x->staticName;
+ _y = (y->name && *y->name) ? y->name : y->staticName;
+
+ return XSTRNCMP(_x, _y, x->sz); /* y sz is the same */
+ }
+
+
+ WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x,
+ pem_password_cb *cb, void *u)
+ {
+ WOLFSSL_X509* x509 = NULL;
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+ unsigned char* pem = NULL;
+ int pemSz;
+ long i = 0, l;
+ const char* footer = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509");
+
+ if (bp == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", BAD_FUNC_ARG);
+ return NULL;
+ }
+
+ if ((l = wolfSSL_BIO_get_len(bp)) <= 0) {
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+ /* No certificate in buffer */
+ WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
+ #endif
+ return NULL;
+ }
+
+ pem = (unsigned char*)XMALLOC(l, 0, DYNAMIC_TYPE_PEM);
+ if (pem == NULL)
+ return NULL;
+
+ i = 0;
+ if (wc_PemGetHeaderFooter(CERT_TYPE, NULL, &footer) != 0) {
+ XFREE(pem, 0, DYNAMIC_TYPE_PEM);
+ return NULL;
+ }
+
+ /* TODO: Inefficient
+ * reading in one byte at a time until see "END CERTIFICATE"
+ */
+ while ((l = wolfSSL_BIO_read(bp, (char *)&pem[i], 1)) == 1) {
+ i++;
+ if (i > 26 && XMEMCMP((char *)&pem[i-26], footer, 25) == 0) {
+ if (pem[i-1] == '\r') {
+ /* found \r , Windows line ending is \r\n so try to read one
+ * more byte for \n, ignoring return value */
+ (void)wolfSSL_BIO_read(bp, (char *)&pem[i++], 1);
+ }
+ break;
+ }
+ }
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+ if (l == 0)
+ WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
+ #endif
+ pemSz = (int)i;
+ x509 = wolfSSL_X509_load_certificate_buffer(pem, pemSz,
+ WOLFSSL_FILETYPE_PEM);
+
+ if (x != NULL) {
+ *x = x509;
+ }
+
+ XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
+
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+ (void)bp;
+ (void)x;
+ (void)cb;
+ (void)u;
+
+ return x509;
+ }
+
+ WOLFSSL_X509_CRL *wolfSSL_PEM_read_bio_X509_CRL(WOLFSSL_BIO *bp,
+ WOLFSSL_X509_CRL **x, pem_password_cb *cb, void *u)
+ {
+#if defined(WOLFSSL_PEM_TO_DER) && defined(HAVE_CRL)
+ unsigned char* pem = NULL;
+ int pemSz;
+ int derSz;
+ DerBuffer* der = NULL;
+ WOLFSSL_X509_CRL* crl = NULL;
+
+ if ((pemSz = wolfSSL_BIO_get_len(bp)) <= 0) {
+ goto err;
+ }
+
+ pem = (unsigned char*)XMALLOC(pemSz, 0, DYNAMIC_TYPE_PEM);
+ if (pem == NULL) {
+ goto err;
+ }
+
+ if (wolfSSL_BIO_read(bp, pem, pemSz) != pemSz) {
+ goto err;
+ }
+
+ if((PemToDer(pem, pemSz, CRL_TYPE, &der, NULL, NULL, NULL)) < 0) {
+ goto err;
+ }
+ derSz = der->length;
+ if((crl = wolfSSL_d2i_X509_CRL(x, der->buffer, derSz)) == NULL) {
+ goto err;
+ }
+
+err:
+ if(pem != NULL) {
+ XFREE(pem, 0, DYNAMIC_TYPE_PEM);
+ }
+ if(der != NULL) {
+ FreeDer(&der);
+ }
+
+ (void)cb;
+ (void)u;
+
+ return crl;
+#else
+ (void)bp;
+ (void)x;
+ (void)cb;
+ (void)u;
+
+ return NULL;
+#endif
+ }
+
+#if !defined(NO_FILESYSTEM)
+ static void* wolfSSL_PEM_read_X509_ex(XFILE fp, void **x,
+ pem_password_cb *cb, void *u, int type)
+ {
+ unsigned char* pem = NULL;
+ int pemSz;
+ long i = 0, l;
+ void *newx509;
+ int derSz;
+ DerBuffer* der = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_X509");
+
+ if (fp == XBADFILE) {
+ WOLFSSL_LEAVE("wolfSSL_PEM_read_X509", BAD_FUNC_ARG);
+ return NULL;
+ }
+ /* Read cert from file */
+ i = XFTELL(fp);
+ if (i < 0) {
+ WOLFSSL_LEAVE("wolfSSL_PEM_read_X509", BAD_FUNC_ARG);
+ return NULL;
+ }
+
+ if (XFSEEK(fp, 0, XSEEK_END) != 0)
+ return NULL;
+ l = XFTELL(fp);
+ if (l < 0)
+ return NULL;
+ if (XFSEEK(fp, i, SEEK_SET) != 0)
+ return NULL;
+ pemSz = (int)(l - i);
+
+ /* check calculated length */
+ if (pemSz > MAX_WOLFSSL_FILE_SIZE || pemSz < 0) {
+ WOLFSSL_MSG("PEM_read_X509_ex file size error");
+ return NULL;
+ }
+
+ /* allocate pem buffer */
+ pem = (unsigned char*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_PEM);
+ if (pem == NULL)
+ return NULL;
+
+ if ((int)XFREAD((char *)pem, 1, pemSz, fp) != pemSz)
+ goto err_exit;
+
+ switch (type) {
+ case CERT_TYPE:
+ newx509 = (void *)wolfSSL_X509_load_certificate_buffer(pem,
+ pemSz, WOLFSSL_FILETYPE_PEM);
+ break;
+
+ #ifdef HAVE_CRL
+ case CRL_TYPE:
+ if ((PemToDer(pem, pemSz, CRL_TYPE, &der, NULL, NULL, NULL)) < 0)
+ goto err_exit;
+ derSz = der->length;
+ newx509 = (void*)wolfSSL_d2i_X509_CRL((WOLFSSL_X509_CRL **)x,
+ (const unsigned char *)der->buffer, derSz);
+ if (newx509 == NULL)
+ goto err_exit;
+ FreeDer(&der);
+ break;
+ #endif
+
+ default:
+ goto err_exit;
+ }
+ if (x != NULL) {
+ *x = newx509;
+ }
+ XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
+ return newx509;
+
+ err_exit:
+ if (pem != NULL)
+ XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
+ if (der != NULL)
+ FreeDer(&der);
+
+ /* unused */
+ (void)cb;
+ (void)u;
+ (void)derSz;
+
+ return NULL;
+ }
+
+ WOLFSSL_API WOLFSSL_X509* wolfSSL_PEM_read_X509(XFILE fp, WOLFSSL_X509 **x,
+ pem_password_cb *cb, void *u)
+ {
+ return (WOLFSSL_X509* )wolfSSL_PEM_read_X509_ex(fp, (void **)x, cb, u, CERT_TYPE);
+ }
+
+#if defined(HAVE_CRL)
+ WOLFSSL_API WOLFSSL_X509_CRL* wolfSSL_PEM_read_X509_CRL(XFILE fp, WOLFSSL_X509_CRL **crl,
+ pem_password_cb *cb, void *u)
+ {
+ return (WOLFSSL_X509_CRL* )wolfSSL_PEM_read_X509_ex(fp, (void **)crl, cb, u, CRL_TYPE);
+ }
+#endif
+
+ int wolfSSL_PEM_write_X509(XFILE fp, WOLFSSL_X509* x)
+ {
+ int ret;
+ WOLFSSL_BIO* bio;
+
+ if (x == NULL)
+ return 0;
+
+ bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
+ if (bio == NULL)
+ return 0;
+
+ if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) {
+ wolfSSL_BIO_free(bio);
+ bio = NULL;
+ }
+
+ ret = wolfSSL_PEM_write_bio_X509(bio, x);
+
+ if (bio != NULL)
+ wolfSSL_BIO_free(bio);
+
+ return ret;
+ }
+#endif /* !NO_FILESYSTEM */
+
+ #define PEM_BEGIN "-----BEGIN "
+ #define PEM_BEGIN_SZ 11
+ #define PEM_END "-----END "
+ #define PEM_END_SZ 9
+ #define PEM_HDR_FIN "-----"
+ #define PEM_HDR_FIN_SZ 5
+ #define PEM_HDR_FIN_EOL_NEWLINE "-----\n"
+ #define PEM_HDR_FIN_EOL_NULL_TERM "-----\0"
+ #define PEM_HDR_FIN_EOL_SZ 6
+
+ int wolfSSL_PEM_read_bio(WOLFSSL_BIO* bio, char **name, char **header,
+ unsigned char **data, long *len)
+ {
+ int ret = WOLFSSL_SUCCESS;
+ char pem[256];
+ int pemLen;
+ char* p;
+ char* nameStr = NULL;
+ int nameLen = 0;
+ char* headerStr = NULL;
+ int headerLen;
+ int headerFound = 0;
+ unsigned char* der = NULL;
+ word32 derLen = 0;
+
+ if (bio == NULL || name == NULL || header == NULL || data == NULL ||
+ len == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Find header line. */
+ pem[sizeof(pem) - 1] = '\0';
+ while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) {
+ if (XSTRNCMP(pem, PEM_BEGIN, PEM_BEGIN_SZ) == 0)
+ break;
+ }
+ if (pemLen <= 0)
+ ret = WOLFSSL_FAILURE;
+ /* Have a header line. */
+ if (ret == WOLFSSL_SUCCESS) {
+ while (pem[pemLen - 1] == '\r' || pem[pemLen - 1] == '\n')
+ pemLen--;
+ pem[pemLen] = '\0';
+ if (XSTRNCMP(pem + pemLen - PEM_HDR_FIN_SZ, PEM_HDR_FIN,
+ PEM_HDR_FIN_SZ) != 0) {
+ ret = WOLFSSL_FAILURE;
+ }
+ }
+
+ /* Get out name. */
+ if (ret == WOLFSSL_SUCCESS) {
+ nameLen = pemLen - PEM_BEGIN_SZ - PEM_HDR_FIN_SZ;
+ nameStr = (char*)XMALLOC(nameLen + 1, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (nameStr == NULL)
+ ret = WOLFSSL_FAILURE;
+ }
+ if (ret == WOLFSSL_SUCCESS) {
+ XSTRNCPY(nameStr, pem + PEM_BEGIN_SZ, nameLen);
+ nameStr[nameLen] = '\0';
+
+ /* Get header of PEM - encryption header. */
+ headerLen = 0;
+ while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) {
+ while (pemLen > 0 && (pem[pemLen - 1] == '\r' ||
+ pem[pemLen - 1] == '\n')) {
+ pemLen--;
+ }
+ pem[pemLen++] = '\n';
+ pem[pemLen] = '\0';
+
+ /* Header separator is a blank line. */
+ if (pem[0] == '\n') {
+ headerFound = 1;
+ break;
+ }
+
+ /* Didn't find a blank line - no header. */
+ if (XSTRNCMP(pem, PEM_END, PEM_END_SZ) == 0) {
+ der = (unsigned char*)headerStr;
+ derLen = headerLen;
+ /* Empty header - empty string. */
+ headerStr = (char*)XMALLOC(1, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (headerStr == NULL)
+ ret = WOLFSSL_FAILURE;
+ else
+ headerStr[0] = '\0';
+ break;
+ }
+
+ p = (char*)XREALLOC(headerStr, headerLen + pemLen + 1, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (p == NULL) {
+ ret = WOLFSSL_FAILURE;
+ break;
+ }
+
+ headerStr = p;
+ XMEMCPY(headerStr + headerLen, pem, pemLen + 1);
+ headerLen += pemLen;
+ }
+ if (pemLen <= 0)
+ ret = WOLFSSL_FAILURE;
+ }
+
+ /* Get body of PEM - if there was a header */
+ if (ret == WOLFSSL_SUCCESS && headerFound) {
+ derLen = 0;
+ while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) {
+ while (pemLen > 0 && (pem[pemLen - 1] == '\r' ||
+ pem[pemLen - 1] == '\n')) {
+ pemLen--;
+ }
+ pem[pemLen++] = '\n';
+ pem[pemLen] = '\0';
+
+ if (XSTRNCMP(pem, PEM_END, PEM_END_SZ) == 0)
+ break;
+
+ p = (char*)XREALLOC(der, derLen + pemLen + 1, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (p == NULL) {
+ ret = WOLFSSL_FAILURE;
+ break;
+ }
+
+ der = (unsigned char*)p;
+ XMEMCPY(der + derLen, pem, pemLen + 1);
+ derLen += pemLen;
+ }
+ if (pemLen <= 0)
+ ret = WOLFSSL_FAILURE;
+ }
+
+ /* Check trailer. */
+ if (ret == WOLFSSL_SUCCESS) {
+ if (XSTRNCMP(pem + PEM_END_SZ, nameStr, nameLen) != 0)
+ ret = WOLFSSL_FAILURE;
+ }
+ if (ret == WOLFSSL_SUCCESS) {
+ if (XSTRNCMP(pem + PEM_END_SZ + nameLen,
+ PEM_HDR_FIN_EOL_NEWLINE,
+ PEM_HDR_FIN_EOL_SZ) != 0 &&
+ XSTRNCMP(pem + PEM_END_SZ + nameLen,
+ PEM_HDR_FIN_EOL_NULL_TERM,
+ PEM_HDR_FIN_EOL_SZ) != 0) {
+ ret = WOLFSSL_FAILURE;
+ }
+ }
+
+ /* Base64 decode body. */
+ if (ret == WOLFSSL_SUCCESS) {
+ if (Base64_Decode(der, derLen, der, &derLen) != 0)
+ ret = WOLFSSL_FAILURE;
+ }
+
+ if (ret == WOLFSSL_SUCCESS) {
+ *name = nameStr;
+ *header = headerStr;
+ *data = der;
+ *len = derLen;
+ nameStr = NULL;
+ headerStr = NULL;
+ der = NULL;
+ }
+
+ if (nameStr != NULL)
+ XFREE(nameStr, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (headerStr != NULL)
+ XFREE(headerStr, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (der != NULL)
+ XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return ret;
+ }
+
+ int wolfSSL_PEM_write_bio(WOLFSSL_BIO* bio, const char *name,
+ const char *header, const unsigned char *data,
+ long len)
+ {
+ int err = 0;
+ int outSz = 0;
+ int nameLen;
+ int headerLen;
+ byte* pem = NULL;
+ word32 pemLen;
+ word32 derLen = (word32)len;
+
+ if (bio == NULL || name == NULL || header == NULL || data == NULL)
+ return 0;
+
+ nameLen = (int)XSTRLEN(name);
+ headerLen = (int)XSTRLEN(header);
+
+ pemLen = (derLen + 2) / 3 * 4;
+ pemLen += (pemLen + 63) / 64;
+
+ pem = (byte*)XMALLOC(pemLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ err = pem == NULL;
+ if (!err)
+ err = Base64_Encode(data, derLen, pem, &pemLen) != 0;
+
+ if (!err) {
+ err = wolfSSL_BIO_write(bio, PEM_BEGIN, PEM_BEGIN_SZ) !=
+ (int)PEM_BEGIN_SZ;
+ }
+ if (!err)
+ err = wolfSSL_BIO_write(bio, name, nameLen) != nameLen;
+ if (!err) {
+ err = wolfSSL_BIO_write(bio, PEM_HDR_FIN_EOL_NEWLINE,
+ PEM_HDR_FIN_EOL_SZ) != (int)PEM_HDR_FIN_EOL_SZ;
+ }
+ if (!err && headerLen > 0) {
+ err = wolfSSL_BIO_write(bio, header, headerLen) != headerLen;
+ /* Blank line after a header and before body. */
+ if (!err)
+ err = wolfSSL_BIO_write(bio, "\n", 1) != 1;
+ headerLen++;
+ }
+ if (!err)
+ err = wolfSSL_BIO_write(bio, pem, pemLen) != (int)pemLen;
+ if (!err)
+ err = wolfSSL_BIO_write(bio, PEM_END, PEM_END_SZ) !=
+ (int)PEM_END_SZ;
+ if (!err)
+ err = wolfSSL_BIO_write(bio, name, nameLen) != nameLen;
+ if (!err) {
+ err = wolfSSL_BIO_write(bio, PEM_HDR_FIN_EOL_NEWLINE,
+ PEM_HDR_FIN_EOL_SZ) != (int)PEM_HDR_FIN_EOL_SZ;
+ }
+
+ if (!err) {
+ outSz = PEM_BEGIN_SZ + nameLen + PEM_HDR_FIN_EOL_SZ + headerLen +
+ pemLen + PEM_END_SZ + nameLen + PEM_HDR_FIN_EOL_SZ;
+ }
+
+ if (pem != NULL)
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return outSz;
+ }
+
+#if !defined(NO_FILESYSTEM)
+ int wolfSSL_PEM_read(XFILE fp, char **name, char **header,
+ unsigned char **data, long *len)
+ {
+ int ret;
+ WOLFSSL_BIO* bio;
+
+ if (name == NULL || header == NULL || data == NULL || len == NULL)
+ return WOLFSSL_FAILURE;
+
+ bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
+ if (bio == NULL)
+ return 0;
+
+ if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) {
+ wolfSSL_BIO_free(bio);
+ bio = NULL;
+ }
+
+ ret = wolfSSL_PEM_read_bio(bio, name, header, data, len);
+
+ if (bio != NULL)
+ wolfSSL_BIO_free(bio);
+
+ return ret;
+ }
+
+ int wolfSSL_PEM_write(XFILE fp, const char *name, const char *header,
+ const unsigned char *data, long len)
+ {
+ int ret;
+ WOLFSSL_BIO* bio;
+
+ if (name == NULL || header == NULL || data == NULL)
+ return 0;
+
+ bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
+ if (bio == NULL)
+ return 0;
+
+ if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) {
+ wolfSSL_BIO_free(bio);
+ bio = NULL;
+ }
+
+ ret = wolfSSL_PEM_write_bio(bio, name, header, data, len);
+
+ if (bio != NULL)
+ wolfSSL_BIO_free(bio);
+
+ return ret;
+ }
+#endif
+
+ int wolfSSL_PEM_get_EVP_CIPHER_INFO(char* header, EncryptedInfo* cipher)
+ {
+ if (header == NULL || cipher == NULL)
+ return WOLFSSL_FAILURE;
+
+ XMEMSET(cipher, 0, sizeof(*cipher));
+
+ if (wc_EncryptedInfoParse(cipher, &header, XSTRLEN(header)) != 0)
+ return WOLFSSL_FAILURE;
+
+ return WOLFSSL_SUCCESS;
+ }
+
+ int wolfSSL_PEM_do_header(EncryptedInfo* cipher, unsigned char* data,
+ long* len, pem_password_cb* callback, void* ctx)
+ {
+ int ret = WOLFSSL_SUCCESS;
+ char password[NAME_SZ];
+ int passwordSz;
+
+ if (cipher == NULL || data == NULL || len == NULL || callback == NULL)
+ return WOLFSSL_FAILURE;
+
+ passwordSz = callback(password, sizeof(password), PEM_PASS_READ, ctx);
+ if (passwordSz < 0)
+ ret = WOLFSSL_FAILURE;
+
+ if (ret == WOLFSSL_SUCCESS) {
+ if (wc_BufferKeyDecrypt(cipher, data, (word32)*len, (byte*)password,
+ passwordSz, WC_MD5) != 0) {
+ ret = WOLFSSL_FAILURE;
+ }
+ }
+
+ if (passwordSz > 0)
+ XMEMSET(password, 0, passwordSz);
+
+ return ret;
+ }
+
+ /*
+ * bp : bio to read X509 from
+ * x : x509 to write to
+ * cb : password call back for reading PEM
+ * u : password
+ * _AUX is for working with a trusted X509 certificate
+ */
+ WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX(WOLFSSL_BIO *bp,
+ WOLFSSL_X509 **x, pem_password_cb *cb, void *u) {
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509");
+
+ /* AUX info is; trusted/rejected uses, friendly name, private key id,
+ * and potentially a stack of "other" info. wolfSSL does not store
+ * friendly name or private key id yet in WOLFSSL_X509 for human
+ * readability and does not support extra trusted/rejected uses for
+ * root CA. */
+ return wolfSSL_PEM_read_bio_X509(bp, x, cb, u);
+ }
+
+
+#ifdef OPENSSL_ALL
+ /* create and return a new WOLFSSL_X509_PKEY structure or NULL on failure */
+ static WOLFSSL_X509_PKEY* wolfSSL_X509_PKEY_new(void* heap)
+ {
+ WOLFSSL_X509_PKEY* ret;
+
+ ret = (WOLFSSL_X509_PKEY*)XMALLOC(sizeof(WOLFSSL_X509_PKEY), heap,
+ DYNAMIC_TYPE_KEY);
+ if (ret != NULL) {
+ XMEMSET(ret, 0, sizeof(WOLFSSL_X509_PKEY));
+ ret->heap = heap;
+ }
+ return ret;
+ }
+
+
+ /* sets the values of X509_PKEY based on certificate passed in
+ * return WOLFSSL_SUCCESS on success */
+ static int wolfSSL_X509_PKEY_set(WOLFSSL_X509_PKEY* xPkey,
+ WOLFSSL_X509* x509)
+ {
+ if (xPkey == NULL || x509 == NULL) {
+ return BAD_FUNC_ARG;
+ }
+ wolfSSL_EVP_PKEY_free(xPkey->dec_pkey);
+ xPkey->dec_pkey = wolfSSL_X509_get_pubkey(x509);
+ if (xPkey->dec_pkey == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+ return WOLFSSL_SUCCESS;
+ }
+
+
+ /* free up all memory used by "xPkey" passed in */
+ static void wolfSSL_X509_PKEY_free(WOLFSSL_X509_PKEY* xPkey)
+ {
+ if (xPkey != NULL) {
+ wolfSSL_EVP_PKEY_free(xPkey->dec_pkey);
+ }
+ XFREE(xPkey, xPkey->heap, DYNAMIC_TYPE_KEY);
+ }
+
+
+ /* Takes control of x509 on success
+ * helper function to break out code needed to set WOLFSSL_X509_INFO up
+ * free's "info" passed in if is not defaults
+ *
+ * returns WOLFSSL_SUCCESS on success
+ */
+ static int wolfSSL_X509_INFO_set(WOLFSSL_X509_INFO* info,
+ WOLFSSL_X509* x509)
+ {
+ if (info == NULL || x509 == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* check is fresh "info" passed in, if not free it */
+ if (info->x509 != NULL || info->x_pkey != NULL) {
+ WOLFSSL_X509_INFO* tmp;
+
+ tmp = wolfSSL_X509_INFO_new();
+ if (tmp == NULL) {
+ WOLFSSL_MSG("Unable to create new structure");
+ return MEMORY_E;
+ }
+ wolfSSL_X509_INFO_free(info);
+ info = tmp;
+ }
+
+ info->x509 = x509;
+
+ //@TODO info->num
+ //@TODO info->enc_cipher
+ //@TODO info->enc_len
+ //@TODO info->enc_data
+ //@TODO info->crl
+
+ info->x_pkey = wolfSSL_X509_PKEY_new(x509->heap);
+ return wolfSSL_X509_PKEY_set(info->x_pkey, x509);
+ }
+
+
+ /*
+ * bio WOLFSSL_BIO to read certificates from
+ * sk possible stack to push more X509_INFO structs to. Can be NULL
+ * cb callback password for encrypted PEM certificates
+ * u user input such as password
+ *
+ * returns stack on success and NULL or default stack passed in on fail
+ */
+ WOLF_STACK_OF(WOLFSSL_X509_INFO)* wolfSSL_PEM_X509_INFO_read_bio(
+ WOLFSSL_BIO* bio, WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk,
+ pem_password_cb* cb, void* u)
+ {
+ WOLF_STACK_OF(WOLFSSL_X509_INFO)* localSk;
+ WOLFSSL_X509* x509 = NULL;
+ int ret = WOLFSSL_SUCCESS;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_X509_INFO_read_bio");
+
+ /* attempt to used passed in stack or create a new one */
+ if (sk != NULL) {
+ localSk = sk;
+ }
+ else {
+ localSk = wolfSSL_sk_X509_INFO_new_null();
+ }
+ if (localSk == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_PEM_X509_INFO_read_bio", MEMORY_E);
+ return NULL;
+ }
+
+ /* parse through BIO and push new info's found onto stack */
+ do {
+ x509 = wolfSSL_PEM_read_bio_X509(bio, NULL, cb, u);
+ if (x509 != NULL) {
+ WOLFSSL_X509_INFO* current;
+
+ current = wolfSSL_X509_INFO_new();
+ if (current == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_PEM_X509_INFO_read_bio", MEMORY_E);
+ return NULL;
+ }
+ ret = wolfSSL_X509_INFO_set(current, x509);
+ if (ret != WOLFSSL_SUCCESS) {
+ wolfSSL_X509_free(x509);
+ }
+ else {
+ wolfSSL_sk_X509_INFO_push(localSk, current);
+ }
+ }
+ } while (x509 != NULL && ret == WOLFSSL_SUCCESS);
+ WOLFSSL_LEAVE("wolfSSL_PEM_X509_INFO_read_bio", ret);
+ return localSk;
+ }
+#endif /* OPENSSL_ALL */
+
+ void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne)
+ {
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_free");
+ if (ne != NULL) {
+ if (ne->value != NULL && ne->value != &(ne->data)) {
+ wolfSSL_ASN1_STRING_free(ne->value);
+ }
+ XFREE(ne, NULL, DYNAMIC_TYPE_NAME_ENTRY);
+ }
+ }
+
+
+ WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void)
+ {
+ WOLFSSL_X509_NAME_ENTRY* ne;
+
+ ne = (WOLFSSL_X509_NAME_ENTRY*)XMALLOC(sizeof(WOLFSSL_X509_NAME_ENTRY),
+ NULL, DYNAMIC_TYPE_NAME_ENTRY);
+ if (ne != NULL) {
+ XMEMSET(ne, 0, sizeof(WOLFSSL_X509_NAME_ENTRY));
+ ne->value = &(ne->data);
+ }
+
+ return ne;
+ }
+
+
+ /* Create a new WOLFSSL_X509_NAME_ENTRY structure based on the text passed
+ * in. Returns NULL on failure */
+ WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_txt(
+ WOLFSSL_X509_NAME_ENTRY **neIn, const char *txt, int type,
+ const unsigned char *data, int dataSz)
+ {
+ int nid = -1;
+ WOLFSSL_X509_NAME_ENTRY* ne = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_create_by_txt()");
+
+ if (txt == NULL) {
+ return NULL;
+ }
+
+ if (neIn != NULL) {
+ ne = *neIn;
+ }
+
+ nid = wolfSSL_OBJ_txt2nid(txt);
+ if (nid == NID_undef) {
+ WOLFSSL_MSG("Unable to find text");
+ ne = NULL;
+ }
+ else {
+ if (ne == NULL) {
+ ne = wolfSSL_X509_NAME_ENTRY_new();
+ if (ne == NULL) {
+ return NULL;
+ }
+ }
+ ne->nid = nid;
+ ne->value = wolfSSL_ASN1_STRING_type_new(type);
+ if (ne->value != NULL) {
+ wolfSSL_ASN1_STRING_set(ne->value, (const void*)data, dataSz);
+ ne->set = 1;
+ }
+ }
+
+ return ne;
+ }
+
+
+ WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_NID(
+ WOLFSSL_X509_NAME_ENTRY** out, int nid, int type,
+ const unsigned char* data, int dataSz)
+ {
+ WOLFSSL_X509_NAME_ENTRY* ne;
+
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_create_by_NID()");
+
+ ne = wolfSSL_X509_NAME_ENTRY_new();
+ if (ne == NULL) {
+ return NULL;
+ }
+
+ ne->nid = nid;
+ ne->value = wolfSSL_ASN1_STRING_type_new(type);
+ wolfSSL_ASN1_STRING_set(ne->value, (const void*)data, dataSz);
+ ne->set = 1;
+
+ if (out != NULL) {
+ *out = ne;
+ }
+
+ return ne;
+ }
+
+ static int RebuildFullNameAdd(DecodedName* dName, char* data)
+ {
+ int totalLen = 0;
+ int i;
+ char* fullName;
+ int idx;
+
+ if (dName->cnLen != 0)
+ totalLen += dName->cnLen + 4;
+ if (dName->snLen != 0)
+ totalLen += dName->snLen + 4;
+ if (dName->cLen != 0)
+ totalLen += dName->cLen + 3;
+ if (dName->lLen != 0)
+ totalLen += dName->lLen + 3;
+ if (dName->stLen != 0)
+ totalLen += dName->stLen + 4;
+ if (dName->oLen != 0)
+ totalLen += dName->oLen + 3;
+ if (dName->ouLen != 0)
+ totalLen += dName->ouLen + 4;
+ if (dName->emailLen != 0)
+ totalLen += dName->emailLen + 14;
+ if (dName->uidLen != 0)
+ totalLen += dName->uidLen + 5;
+ if (dName->serialLen != 0)
+ totalLen += dName->serialLen + 14;
+ if (dName->dcNum != 0) {
+ for (i = 0; i < dName->dcNum; i++)
+ totalLen += dName->dcLen[i] + 4;
+ }
+
+ fullName = (char*)XMALLOC(totalLen + 1, NULL, DYNAMIC_TYPE_X509);
+ if (fullName == NULL)
+ return MEMORY_E;
+
+ idx = 0;
+ dName->entryCount = 0;
+ if (dName->cnLen != 0) {
+ dName->entryCount++;
+ XMEMCPY(fullName + idx, WOLFSSL_COMMON_NAME, 4);
+ idx += 4;
+ if (dName->cnIdx == -1)
+ XMEMCPY(fullName + idx, data, dName->cnLen);
+ else {
+ XMEMCPY(fullName + idx, dName->fullName + dName->cnIdx,
+ dName->cnLen);
+ }
+ dName->cnIdx = idx;
+ idx += dName->cnLen;
+ }
+ if (dName->snLen != 0) {
+ dName->entryCount++;
+ XMEMCPY(fullName + idx, WOLFSSL_SUR_NAME, 4);
+ idx += 4;
+ if (dName->snIdx == -1)
+ XMEMCPY(fullName + idx, data, dName->snLen);
+ else {
+ XMEMCPY(fullName + idx, dName->fullName + dName->snIdx,
+ dName->snLen);
+ }
+ dName->snIdx = idx;
+ idx += dName->snLen;
+ }
+ if (dName->cLen != 0) {
+ dName->entryCount++;
+ XMEMCPY(fullName + idx, WOLFSSL_COUNTRY_NAME, 3);
+ idx += 3;
+ if (dName->cIdx == -1)
+ XMEMCPY(fullName + idx, data, dName->cLen);
+ else {
+ XMEMCPY(fullName + idx, dName->fullName + dName->cIdx,
+ dName->cLen);
+ }
+ dName->cIdx = idx;
+ idx += dName->cLen;
+ }
+ if (dName->lLen != 0) {
+ dName->entryCount++;
+ XMEMCPY(fullName + idx, WOLFSSL_LOCALITY_NAME, 3);
+ idx += 3;
+ if (dName->lIdx == -1)
+ XMEMCPY(fullName + idx, data, dName->lLen);
+ else {
+ XMEMCPY(fullName + idx, dName->fullName + dName->lIdx,
+ dName->lLen);
+ }
+ dName->lIdx = idx;
+ idx += dName->lLen;
+ }
+ if (dName->stLen != 0) {
+ dName->entryCount++;
+ XMEMCPY(fullName + idx, WOLFSSL_STATE_NAME, 4);
+ idx += 4;
+ if (dName->stIdx == -1)
+ XMEMCPY(fullName + idx, data, dName->stLen);
+ else {
+ XMEMCPY(fullName + idx, dName->fullName + dName->stIdx,
+ dName->stLen);
+ }
+ dName->stIdx = idx;
+ idx += dName->stLen;
+ }
+ if (dName->oLen != 0) {
+ dName->entryCount++;
+ XMEMCPY(fullName + idx, WOLFSSL_ORG_NAME, 3);
+ idx += 3;
+ if (dName->oIdx == -1)
+ XMEMCPY(fullName + idx, data, dName->oLen);
+ else {
+ XMEMCPY(fullName + idx, dName->fullName + dName->oIdx,
+ dName->oLen);
+ }
+ dName->oIdx = idx;
+ idx += dName->oLen;
+ }
+ if (dName->ouLen != 0) {
+ dName->entryCount++;
+ XMEMCPY(fullName + idx, WOLFSSL_ORGUNIT_NAME, 4);
+ idx += 4;
+ if (dName->ouIdx == -1)
+ XMEMCPY(fullName + idx, data, dName->ouLen);
+ else {
+ XMEMCPY(fullName + idx, dName->fullName + dName->ouIdx,
+ dName->ouLen);
+ }
+ dName->ouIdx = idx;
+ idx += dName->ouLen;
+ }
+ if (dName->emailLen != 0) {
+ dName->entryCount++;
+ XMEMCPY(fullName + idx, "/emailAddress=", 14);
+ idx += 14;
+ if (dName->emailIdx == -1)
+ XMEMCPY(fullName + idx, data, dName->emailLen);
+ else {
+ XMEMCPY(fullName + idx, dName->fullName + dName->emailIdx,
+ dName->emailLen);
+ }
+ dName->emailIdx = idx;
+ idx += dName->emailLen;
+ }
+ if (dName->dcNum != 0) {
+ for (i = 0; i < dName->dcNum; i++) {
+ dName->entryCount++;
+ XMEMCPY(fullName + idx, WOLFSSL_DOMAIN_COMPONENT, 4);
+ idx += 4;
+ XMEMCPY(fullName + idx, dName->fullName + dName->dcIdx[i],
+ dName->dcLen[i]);
+ dName->dcIdx[i] = idx;
+ idx += dName->dcLen[i];
+ }
+ }
+ if (dName->uidLen != 0) {
+ dName->entryCount++;
+ XMEMCPY(fullName + idx, "/UID=", 5);
+ idx += 5;
+ if (dName->uidIdx == -1)
+ XMEMCPY(fullName + idx, data, dName->uidLen);
+ else {
+ XMEMCPY(fullName + idx, dName->fullName + dName->uidIdx,
+ dName->uidLen);
+ }
+ dName->uidIdx = idx;
+ idx += dName->uidLen;
+ }
+ if (dName->serialLen != 0) {
+ dName->entryCount++;
+ XMEMCPY(fullName + idx, WOLFSSL_SERIAL_NUMBER, 14);
+ idx += 14;
+ if (dName->serialIdx == -1)
+ XMEMCPY(fullName + idx, data, dName->serialLen);
+ else {
+ XMEMCPY(fullName + idx, dName->fullName + dName->serialIdx,
+ dName->serialLen);
+ }
+ dName->serialIdx = idx;
+ idx += dName->serialLen;
+ }
+
+ if (dName->fullName != NULL)
+ XFREE(dName->fullName, NULL, DYNAMIC_TYPE_X509);
+ dName->fullName = fullName;
+ dName->fullNameLen = idx + 1;
+
+ return 0;
+ }
+
+ /* Copies entry into name. With it being copied freeing entry becomes the
+ * callers responsibility.
+ * returns 1 for success and 0 for error */
+ int wolfSSL_X509_NAME_add_entry(WOLFSSL_X509_NAME* name,
+ WOLFSSL_X509_NAME_ENTRY* entry, int idx, int set)
+ {
+ int i;
+ int fullName = 1;
+
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_add_entry()");
+
+ switch (entry->nid) {
+ case ASN_COMMON_NAME:
+ name->fullName.cnIdx = -1;
+ name->fullName.cnLen = entry->value->length;
+ name->fullName.cnNid = entry->nid;
+ break;
+ case ASN_SUR_NAME:
+ name->fullName.snIdx = -1;
+ name->fullName.snLen = entry->value->length;
+ name->fullName.snNid = entry->nid;
+ break;
+ case ASN_SERIAL_NUMBER:
+ name->fullName.serialIdx = -1;
+ name->fullName.serialLen = entry->value->length;
+ name->fullName.serialNid = entry->nid;
+ break;
+ case ASN_COUNTRY_NAME:
+ name->fullName.cIdx = -1;
+ name->fullName.cLen = entry->value->length;
+ name->fullName.cNid = entry->nid;
+ break;
+ case ASN_LOCALITY_NAME:
+ name->fullName.lIdx = -1;
+ name->fullName.lLen = entry->value->length;
+ name->fullName.lNid = entry->nid;
+ break;
+ case ASN_STATE_NAME:
+ name->fullName.stIdx = -1;
+ name->fullName.stLen = entry->value->length;
+ name->fullName.stNid = entry->nid;
+ break;
+ case ASN_ORG_NAME:
+ name->fullName.oIdx = -1;
+ name->fullName.oLen = entry->value->length;
+ name->fullName.oNid = entry->nid;
+ break;
+ case ASN_ORGUNIT_NAME:
+ name->fullName.ouIdx = -1;
+ name->fullName.ouLen = entry->value->length;
+ name->fullName.ouNid = entry->nid;
+ break;
+ case NID_emailAddress:
+ name->fullName.emailIdx = -1;
+ name->fullName.emailLen = entry->value->length;
+ name->fullName.emailNid = entry->nid;
+ break;
+ case ASN_USER_ID:
+ name->fullName.uidIdx = -1;
+ name->fullName.uidLen = entry->value->length;
+ name->fullName.uidNid = entry->nid;
+ break;
+ case ASN_DOMAIN_COMPONENT:
+ name->fullName.dcIdx[0] = -1;
+ name->fullName.dcLen[0] = entry->value->length;
+ break;
+ default:
+ fullName = 0;
+ break;
+ }
+
+ if (fullName) {
+ int nid = entry->nid;
+
+ if (nid == NID_emailAddress) {
+ nid = (int)ASN_EMAIL_NAME;
+ }
+
+ if (idx >= DN_NAMES_MAX + DOMAIN_COMPONENT_MAX) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (idx >= 0) {
+ name->fullName.loc[idx] = nid;
+ if (idx == name->fullName.locSz) {
+ name->fullName.locSz += 1;
+ }
+ }
+
+ /* place at end */
+ if (idx < 0 && name->fullName.locSz + 1
+ < DN_NAMES_MAX + DOMAIN_COMPONENT_MAX) {
+ name->fullName.loc[name->fullName.locSz] = nid;
+ name->fullName.locSz += 1;
+ }
+
+ if (RebuildFullNameAdd(&name->fullName, entry->value->data) != 0)
+ return WOLFSSL_FAILURE;
+ }
+ else {
+ for (i = 0; i < MAX_NAME_ENTRIES; i++) {
+ if (name->extra[i].set != 1) { /* not set so overwritten */
+ WOLFSSL_X509_NAME_ENTRY* current = &(name->extra[i]);
+ WOLFSSL_ASN1_STRING* str;
+
+ WOLFSSL_MSG("Found place for name entry");
+
+ XMEMCPY(current, entry, sizeof(WOLFSSL_X509_NAME_ENTRY));
+ str = entry->value;
+ XMEMCPY(&(current->data), str, sizeof(WOLFSSL_ASN1_STRING));
+ current->value = &(current->data);
+ current->data.data = (char*)XMALLOC(str->length,
+ name->x509->heap, DYNAMIC_TYPE_OPENSSL);
+
+ if (current->data.data == NULL) {
+ return SSL_FAILURE;
+ }
+ XMEMCPY(current->data.data, str->data, str->length);
+
+ /* make sure is null terminated */
+ current->data.data[str->length - 1] = '\0';
+
+ current->set = 1; /* make sure now listed as set */
+ break;
+ }
+ }
+
+ if (i == MAX_NAME_ENTRIES) {
+ WOLFSSL_MSG("No spot found for name entry");
+ return SSL_FAILURE;
+ }
+ }
+
+ (void)idx;
+ (void)set;
+ return SSL_SUCCESS;
+ }
+
+ int wolfSSL_X509_NAME_add_entry_by_txt(WOLFSSL_X509_NAME *name,
+ const char *field, int type,
+ const unsigned char *bytes, int len,
+ int loc, int set)
+ {
+ int ret = WOLFSSL_FAILURE;
+ int nid;
+ WOLFSSL_X509_NAME_ENTRY* entry;
+
+ (void)type;
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_add_entry_by_txt");
+
+ if (name == NULL || field == NULL)
+ return WOLFSSL_FAILURE;
+
+ if ((nid = wolfSSL_OBJ_txt2nid(field)) == NID_undef)
+ return WOLFSSL_FAILURE;
+
+ entry = wolfSSL_X509_NAME_ENTRY_create_by_NID(NULL,
+ nid, type, (unsigned char*)bytes, len);
+ if (entry == NULL)
+ return WOLFSSL_FAILURE;
+
+ ret = wolfSSL_X509_NAME_add_entry(name, entry, loc, set);
+ wolfSSL_X509_NAME_ENTRY_free(entry);
+
+ return ret;
+ }
+
+ int wolfSSL_X509_NAME_add_entry_by_NID(WOLFSSL_X509_NAME *name, int nid,
+ int type, const unsigned char *bytes,
+ int len, int loc, int set)
+ {
+ int ret;
+ WOLFSSL_X509_NAME_ENTRY* entry;
+ entry = wolfSSL_X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
+ if (entry == NULL)
+ return WOLFSSL_FAILURE;
+ ret = wolfSSL_X509_NAME_add_entry(name, entry, loc, set);
+ wolfSSL_X509_NAME_ENTRY_free(entry);
+ return ret;
+ }
+ #endif /* !NO_CERTS */
+
+
+ /* NID variables are dependent on compatibility header files currently
+ *
+ * returns a pointer to a new WOLFSSL_ASN1_OBJECT struct on success and NULL
+ * on fail
+ */
+
+ WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int id)
+ {
+ return wolfSSL_OBJ_nid2obj_ex(id, NULL);
+ }
+
+
+ WOLFSSL_LOCAL WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj_ex(int id,
+ WOLFSSL_ASN1_OBJECT* arg_obj)
+ {
+ word32 oidSz = 0;
+ const byte* oid;
+ word32 type = 0;
+ WOLFSSL_ASN1_OBJECT* obj = arg_obj;
+ byte objBuf[MAX_OID_SZ + MAX_LENGTH_SZ + 1]; /* +1 for object tag */
+ word32 objSz = 0;
+ const char* sName = NULL;
+ int i;
+
+ WOLFSSL_ENTER("wolfSSL_OBJ_nid2obj()");
+
+ for (i = 0; i < (int)WOLFSSL_OBJECT_INFO_SZ; i++) {
+ if (wolfssl_object_info[i].nid == id) {
+ id = wolfssl_object_info[i].id;
+ sName = wolfssl_object_info[i].sName;
+ type = wolfssl_object_info[i].type;
+ break;
+ }
+ }
+ if (i == (int)WOLFSSL_OBJECT_INFO_SZ) {
+ WOLFSSL_MSG("NID not in table");
+ #ifdef WOLFSSL_QT
+ sName = NULL;
+ type = id;
+ #else
+ return NULL;
+ #endif
+ }
+
+ #ifdef HAVE_ECC
+ if (type == 0 && wc_ecc_get_oid(id, &oid, &oidSz) > 0) {
+ type = oidCurveType;
+ }
+ #endif /* HAVE_ECC */
+
+ if (sName != NULL) {
+ if (XSTRLEN(sName) > WOLFSSL_MAX_SNAME - 1) {
+ WOLFSSL_MSG("Attempted short name is too large");
+ return NULL;
+ }
+ }
+
+ oid = OidFromId(id, type, &oidSz);
+
+ /* set object ID to buffer */
+ if (obj == NULL){
+ obj = wolfSSL_ASN1_OBJECT_new();
+ if (obj == NULL) {
+ WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+ return NULL;
+ }
+ obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+ } else {
+ obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC;
+ }
+ obj->type = id;
+ obj->grp = type;
+
+ obj->sName[0] = '\0';
+ if (sName != NULL) {
+ XMEMCPY(obj->sName, (char*)sName, XSTRLEN((char*)sName));
+ }
+
+ objBuf[0] = ASN_OBJECT_ID; objSz++;
+ objSz += SetLength(oidSz, objBuf + 1);
+ XMEMCPY(objBuf + objSz, oid, oidSz);
+ objSz += oidSz;
+ obj->objSz = objSz;
+ if(((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) ||
+ (obj->obj == NULL)) {
+ obj->obj = (byte*)XREALLOC((byte*)obj->obj, obj->objSz, NULL,
+ DYNAMIC_TYPE_ASN1);
+ if (obj->obj == NULL) {
+ wolfSSL_ASN1_OBJECT_free(obj);
+ return NULL;
+ }
+ obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA ;
+ } else {
+ obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA ;
+ }
+ XMEMCPY((byte*)obj->obj, objBuf, obj->objSz);
+
+ (void)type;
+
+ return obj;
+ }
+
+ static const char* oid_translate_num_to_str(const char* oid)
+ {
+ const struct oid_dict {
+ const char* num;
+ const char* desc;
+ } oid_dict[] = {
+ { "2.5.29.37.0", "Any Extended Key Usage" },
+ { "1.3.6.1.5.5.7.3.1", "TLS Web Server Authentication" },
+ { "1.3.6.1.5.5.7.3.2", "TLS Web Client Authentication" },
+ { "1.3.6.1.5.5.7.3.3", "Code Signing" },
+ { "1.3.6.1.5.5.7.3.4", "E-mail Protection" },
+ { "1.3.6.1.5.5.7.3.8", "Time Stamping" },
+ { "1.3.6.1.5.5.7.3.9", "OCSP Signing" },
+ { NULL, NULL }
+ };
+ const struct oid_dict* idx;
+
+ for (idx = oid_dict; idx->num != NULL; idx++) {
+ if (!XSTRNCMP(oid, idx->num, XSTRLEN(idx->num))) {
+ return idx->desc;
+ }
+ }
+ return NULL;
+ }
+
+ /* if no_name is one than use numerical form otherwise can be short name.
+ *
+ * returns the buffer size on success
+ */
+ int wolfSSL_OBJ_obj2txt(char *buf, int bufLen, WOLFSSL_ASN1_OBJECT *a, int no_name)
+ {
+ int bufSz;
+ const char* desc;
+
+ WOLFSSL_ENTER("wolfSSL_OBJ_obj2txt()");
+
+ if (buf == NULL || bufLen <= 1 || a == NULL) {
+ WOLFSSL_MSG("Bad input argument");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (no_name == 1) {
+ int length;
+ word32 idx = 0;
+ byte tag;
+
+ if (GetASNTag(a->obj, &idx, &tag, a->objSz) != 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (tag != ASN_OBJECT_ID) {
+ WOLFSSL_MSG("Bad ASN1 Object");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (GetLength((const byte*)a->obj, &idx, &length,
+ a->objSz) < 0 || length < 0) {
+ return ASN_PARSE_E;
+ }
+
+ if (bufLen < MAX_OID_STRING_SZ) {
+ bufSz = bufLen - 1;
+ }
+ else {
+ bufSz = MAX_OID_STRING_SZ;
+ }
+
+ if ((bufSz = DecodePolicyOID(buf, (word32)bufSz, a->obj + idx,
+ (word32)length)) <= 0) {
+ WOLFSSL_MSG("Error decoding OID");
+ return WOLFSSL_FAILURE;
+ }
+
+ }
+ else { /* return short name */
+ if (XSTRLEN(a->sName) + 1 < (word32)bufLen - 1) {
+ bufSz = (int)XSTRLEN(a->sName);
+ }
+ else {
+ bufSz = bufLen - 1;
+ }
+ if (bufSz) {
+ XMEMCPY(buf, a->sName, bufSz);
+ }
+ else if (wolfSSL_OBJ_obj2txt(buf, bufLen, a, 1)) {
+ if ((desc = oid_translate_num_to_str(buf))) {
+ bufSz = (int)XSTRLEN(desc);
+ XMEMCPY(buf, desc, min(bufSz, bufLen));
+ }
+ }
+ else if (a->type == GEN_DNS || a->type == GEN_EMAIL || a->type == GEN_URI) {
+ bufSz = (int)XSTRLEN((const char*)a->obj);
+ XMEMCPY(buf, a->obj, min(bufSz, bufLen));
+ }
+ }
+
+ buf[bufSz] = '\0';
+ #ifdef WOLFSSL_QT
+ /* For unknown extension types, QT expects the short name to be the
+ text representation of the oid */
+ if (XSTRLEN(a->sName) == 0) {
+ XMEMCPY(a->sName, buf, bufSz);
+ }
+ #endif
+ return bufSz;
+ }
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_ASN)
+ /* DN_Tags to strings */
+ static const struct DN_Tag_Strings {
+ enum DN_Tags tag;
+ const char* str;
+ } dn_tag_strings[] = {
+ { ASN_COMMON_NAME, "CN" },
+ { ASN_SUR_NAME, "SN" },
+ { ASN_SERIAL_NUMBER, "serialNumber" },
+ { ASN_COUNTRY_NAME, "C" },
+ { ASN_LOCALITY_NAME, "L" },
+ { ASN_STATE_NAME, "ST" },
+ { ASN_ORG_NAME, "O"},
+ { ASN_ORGUNIT_NAME, "OU"},
+ { ASN_BUS_CAT, "businessCategory"},
+ { ASN_EMAIL_NAME, "emailAddress"},
+ { ASN_USER_ID, "UID"},
+ { ASN_DOMAIN_COMPONENT, "DC"},
+ { ASN_DN_NULL, NULL }
+ };
+
+ int wolfSSL_X509_NAME_get_index_by_OBJ(WOLFSSL_X509_NAME *name,
+ const WOLFSSL_ASN1_OBJECT *obj,
+ int idx) {
+ const struct DN_Tag_Strings* dn;
+ enum DN_Tags tag = ASN_DN_NULL;
+
+ if (!name || idx >= name->fullName.locSz ||
+ !obj || !obj->obj) {
+ return -1;
+ }
+
+ if (idx < 0) {
+ idx = 0;
+ }
+ for (dn = dn_tag_strings; dn->str != NULL; dn++) {
+ /* Find the DN_Tags number for the name */
+ if (XSTRNCMP((const char*) obj->sName, dn->str, obj->objSz - 1) == 0) {
+ tag = dn->tag;
+ break;
+ }
+ }
+ if (!tag) {
+ /* Unable to identify desired name */
+ return -1;
+ }
+ for (idx++; idx < name->fullName.locSz; idx++) {
+ /* Find index of desired name */
+ if ((enum DN_Tags)name->fullName.loc[idx] == tag) {
+ return idx;
+ }
+ }
+ return -1;
+ }
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
+ defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
+ defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
+ defined(WOLFSSL_HAPROXY)
+
+#ifndef NO_SHA
+ /* One shot SHA1 hash of message.
+ *
+ * d message to hash
+ * n size of d buffer
+ * md buffer to hold digest. Should be SHA_DIGEST_SIZE.
+ *
+ * Note: if md is null then a static buffer of SHA_DIGEST_SIZE is used.
+ * When the static buffer is used this function is not thread safe.
+ *
+ * Returns a pointer to the message digest on success and NULL on failure.
+ */
+ unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n,
+ unsigned char *md)
+ {
+ static byte dig[WC_SHA_DIGEST_SIZE];
+ wc_Sha sha;
+
+ WOLFSSL_ENTER("wolfSSL_SHA1");
+
+ if (wc_InitSha_ex(&sha, NULL, 0) != 0) {
+ WOLFSSL_MSG("SHA1 Init failed");
+ return NULL;
+ }
+
+ if (wc_ShaUpdate(&sha, (const byte*)d, (word32)n) != 0) {
+ WOLFSSL_MSG("SHA1 Update failed");
+ return NULL;
+ }
+
+ if (wc_ShaFinal(&sha, dig) != 0) {
+ WOLFSSL_MSG("SHA1 Final failed");
+ return NULL;
+ }
+
+ wc_ShaFree(&sha);
+
+ if (md != NULL) {
+ XMEMCPY(md, dig, WC_SHA_DIGEST_SIZE);
+ return md;
+ }
+ else {
+ return (unsigned char*)dig;
+ }
+ }
+#endif /* ! NO_SHA */
+
+#ifndef NO_SHA256
+ /* One shot SHA256 hash of message.
+ *
+ * d message to hash
+ * n size of d buffer
+ * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
+ *
+ * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
+ * When the static buffer is used this function is not thread safe.
+ *
+ * Returns a pointer to the message digest on success and NULL on failure.
+ */
+ unsigned char *wolfSSL_SHA256(const unsigned char *d, size_t n,
+ unsigned char *md)
+ {
+ static byte dig[WC_SHA256_DIGEST_SIZE];
+ wc_Sha256 sha;
+
+ WOLFSSL_ENTER("wolfSSL_SHA256");
+
+ if (wc_InitSha256_ex(&sha, NULL, 0) != 0) {
+ WOLFSSL_MSG("SHA256 Init failed");
+ return NULL;
+ }
+
+ if (wc_Sha256Update(&sha, (const byte*)d, (word32)n) != 0) {
+ WOLFSSL_MSG("SHA256 Update failed");
+ return NULL;
+ }
+
+ if (wc_Sha256Final(&sha, dig) != 0) {
+ WOLFSSL_MSG("SHA256 Final failed");
+ return NULL;
+ }
+
+ wc_Sha256Free(&sha);
+
+ if (md != NULL) {
+ XMEMCPY(md, dig, WC_SHA256_DIGEST_SIZE);
+ return md;
+ }
+ else {
+ return (unsigned char*)dig;
+ }
+ }
+#endif /* ! NO_SHA256 */
+
+#ifdef WOLFSSL_SHA384
+ /* One shot SHA384 hash of message.
+ *
+ * d message to hash
+ * n size of d buffer
+ * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
+ *
+ * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
+ * When the static buffer is used this function is not thread safe.
+ *
+ * Returns a pointer to the message digest on success and NULL on failure.
+ */
+ unsigned char *wolfSSL_SHA384(const unsigned char *d, size_t n,
+ unsigned char *md)
+ {
+ static byte dig[WC_SHA384_DIGEST_SIZE];
+ wc_Sha384 sha;
+
+ WOLFSSL_ENTER("wolfSSL_SHA384");
+
+ if (wc_InitSha384_ex(&sha, NULL, 0) != 0) {
+ WOLFSSL_MSG("SHA384 Init failed");
+ return NULL;
+ }
+
+ if (wc_Sha384Update(&sha, (const byte*)d, (word32)n) != 0) {
+ WOLFSSL_MSG("SHA384 Update failed");
+ return NULL;
+ }
+
+ if (wc_Sha384Final(&sha, dig) != 0) {
+ WOLFSSL_MSG("SHA384 Final failed");
+ return NULL;
+ }
+
+ wc_Sha384Free(&sha);
+
+ if (md != NULL) {
+ XMEMCPY(md, dig, WC_SHA384_DIGEST_SIZE);
+ return md;
+ }
+ else {
+ return (unsigned char*)dig;
+ }
+ }
+#endif /* WOLFSSL_SHA384 */
+
+
+#if defined(WOLFSSL_SHA512)
+ /* One shot SHA512 hash of message.
+ *
+ * d message to hash
+ * n size of d buffer
+ * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
+ *
+ * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
+ * When the static buffer is used this function is not thread safe.
+ *
+ * Returns a pointer to the message digest on success and NULL on failure.
+ */
+ unsigned char *wolfSSL_SHA512(const unsigned char *d, size_t n,
+ unsigned char *md)
+ {
+ static byte dig[WC_SHA512_DIGEST_SIZE];
+ wc_Sha512 sha;
+
+ WOLFSSL_ENTER("wolfSSL_SHA512");
+
+ if (wc_InitSha512_ex(&sha, NULL, 0) != 0) {
+ WOLFSSL_MSG("SHA512 Init failed");
+ return NULL;
+ }
+
+ if (wc_Sha512Update(&sha, (const byte*)d, (word32)n) != 0) {
+ WOLFSSL_MSG("SHA512 Update failed");
+ return NULL;
+ }
+
+ if (wc_Sha512Final(&sha, dig) != 0) {
+ WOLFSSL_MSG("SHA512 Final failed");
+ return NULL;
+ }
+
+ wc_Sha512Free(&sha);
+
+ if (md != NULL) {
+ XMEMCPY(md, dig, WC_SHA512_DIGEST_SIZE);
+ return md;
+ }
+ else {
+ return (unsigned char*)dig;
+ }
+ }
+#endif /* defined(WOLFSSL_SHA512) */
+#endif /* OPENSSL_EXTRA */
+
+#ifndef WOLFCRYPT_ONLY
+#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
+ defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
+ defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
+ defined(WOLFSSL_HAPROXY)
+
+ char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x)
+ {
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_use_certificate");
+
+ FreeDer(&ctx->certificate); /* Make sure previous is free'd */
+ ret = AllocDer(&ctx->certificate, x->derCert->length, CERT_TYPE,
+ ctx->heap);
+ if (ret != 0)
+ return 0;
+
+ XMEMCPY(ctx->certificate->buffer, x->derCert->buffer,
+ x->derCert->length);
+#ifdef KEEP_OUR_CERT
+ if (ctx->ourCert != NULL && ctx->ownOurCert) {
+ FreeX509(ctx->ourCert);
+ XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509);
+ }
+ #ifndef WOLFSSL_X509_STORE_CERTS
+ ctx->ourCert = x;
+ #else
+ ctx->ourCert = wolfSSL_X509_d2i(NULL, x->derCert->buffer,x->derCert->length);
+ if(ctx->ourCert == NULL){
+ return 0;
+ }
+ #endif
+
+ ctx->ownOurCert = 0;
+#endif
+
+ /* Update the available options with public keys. */
+ switch (x->pubKeyOID) {
+ case RSAk:
+ ctx->haveRSA = 1;
+ break;
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ #endif
+ #ifdef HAVE_ED448
+ case ED448k:
+ #endif
+ case ECDSAk:
+ ctx->haveECC = 1;
+ #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+ ctx->pkCurveOID = x->pkCurveOID;
+ #endif
+ break;
+ }
+
+ return WOLFSSL_SUCCESS;
+ }
+
+ int wolfSSL_CTX_add1_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
+ {
+ int ret;
+ if (ctx == NULL || x509 == NULL || x509->derCert == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ ret = wolfSSL_CTX_load_verify_buffer(ctx, x509->derCert->buffer,
+ x509->derCert->length, WOLFSSL_FILETYPE_ASN1);
+
+ return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+ }
+
+ int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name) {
+ #ifndef NO_FILESYSTEM
+ XFILE fp;
+
+ WOLFSSL_ENTER("wolfSSL_BIO_new_file");
+
+ if ((wolfSSL_BIO_get_fp(b, &fp) == WOLFSSL_SUCCESS) && (fp != XBADFILE))
+ {
+ XFCLOSE(fp);
+ }
+
+ fp = XFOPEN(name, "r");
+ if (fp == XBADFILE)
+ return WOLFSSL_BAD_FILE;
+
+ if (wolfSSL_BIO_set_fp(b, fp, BIO_CLOSE) != WOLFSSL_SUCCESS) {
+ XFCLOSE(fp);
+ return WOLFSSL_BAD_FILE;
+ }
+
+ /* file is closed when bio is free'd */
+ return WOLFSSL_SUCCESS;
+ #else
+ (void)name;
+ (void)b;
+ return WOLFSSL_NOT_IMPLEMENTED;
+ #endif
+ }
+
+ /* Return the corresponding short name for the nid <n>.
+ * or NULL if short name can't be found.
+ */
+ const char * wolfSSL_OBJ_nid2sn(int n) {
+ const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info;
+ size_t i;
+ WOLFSSL_ENTER("wolfSSL_OBJ_nid2sn");
+ for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) {
+ if (obj_info->nid == n) {
+ return obj_info->sName;
+ }
+ }
+ WOLFSSL_MSG("SN not found");
+ return NULL;
+ }
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ int wolfSSL_OBJ_sn2nid(const char *sn) {
+ WOLFSSL_ENTER("wolfSSL_OBJ_sn2nid");
+ if (sn == NULL)
+ return NID_undef;
+ return wc_OBJ_sn2nid(sn);
+ }
+#endif
+
+
+ /* Gets the NID value that corresponds with the ASN1 object.
+ *
+ * o ASN1 object to get NID of
+ *
+ * Return NID on success and a negative value on failure
+ */
+ int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o)
+ {
+ word32 oid = 0;
+ word32 idx = 0;
+
+ WOLFSSL_ENTER("wolfSSL_OBJ_obj2nid");
+
+ if (o == NULL) {
+ return -1;
+ }
+
+ #ifdef WOLFSSL_QT
+ if (o->grp == oidCertExtType) {
+ /* If nid is an unknown extension, return NID_undef */
+ if (wolfSSL_OBJ_nid2sn(o->nid) == NULL)
+ return NID_undef;
+ }
+ #endif
+
+ if (o->nid > 0)
+ return o->nid;
+ if (GetObjectId(o->obj, &idx, &oid, o->grp, o->objSz) < 0) {
+ WOLFSSL_MSG("Issue getting OID of object");
+ return -1;
+ }
+
+ return oid2nid(oid, o->grp);
+ }
+
+ /* Returns the long name that corresponds with an ASN1_OBJECT nid value.
+ * n : NID value of ASN1_OBJECT to search */
+ const char* wolfSSL_OBJ_nid2ln(int n)
+ {
+ const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info;
+ size_t i;
+ WOLFSSL_ENTER("wolfSSL_OBJ_nid2ln");
+ for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) {
+ if (obj_info->nid == n) {
+ return obj_info->lName;
+ }
+ }
+ WOLFSSL_MSG("NID not found in table");
+ return NULL;
+ }
+
+ /* Return the corresponding NID for the long name <ln>
+ * or NID_undef if NID can't be found.
+ */
+ int wolfSSL_OBJ_ln2nid(const char *ln)
+ {
+ const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info;
+ size_t i, lnlen;
+ WOLFSSL_ENTER("wolfSSL_OBJ_ln2nid");
+ if (ln && (lnlen = XSTRLEN(ln)) > 0) {
+ /* Accept input like "/commonName=" */
+ if (ln[0] == '/') {
+ ln++;
+ lnlen--;
+ }
+ if (lnlen) {
+ if (ln[lnlen-1] == '=') {
+ lnlen--;
+ }
+ for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) {
+ if (lnlen == XSTRLEN(obj_info->lName) &&
+ XSTRNCMP(ln, obj_info->lName, lnlen) == 0) {
+ return obj_info->nid;
+ }
+ }
+ }
+ }
+ return NID_undef;
+ }
+
+ /* compares two objects, return 0 if equal */
+ int wolfSSL_OBJ_cmp(const WOLFSSL_ASN1_OBJECT* a,
+ const WOLFSSL_ASN1_OBJECT* b)
+ {
+ WOLFSSL_ENTER("wolfSSL_OBJ_cmp");
+
+ if (a != NULL && b != NULL &&
+ a->obj != NULL && b->obj != NULL &&
+ a->objSz == b->objSz) {
+ return XMEMCMP(a->obj, b->obj, a->objSz);
+ }
+
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Gets the NID value that is related to the OID string passed in. Example
+ * string would be "2.5.29.14" for subject key ID.
+ *
+ * returns NID value on success and NID_undef on error
+ */
+ int wolfSSL_OBJ_txt2nid(const char* s)
+ {
+ unsigned int i;
+ #ifdef WOLFSSL_CERT_EXT
+ int ret;
+ unsigned int sum = 0;
+ unsigned int outSz = MAX_OID_SZ;
+ unsigned char out[MAX_OID_SZ];
+ #endif
+
+ WOLFSSL_ENTER("OBJ_txt2nid");
+
+ if (s == NULL) {
+ return NID_undef;
+ }
+
+ #ifdef WOLFSSL_CERT_EXT
+ ret = EncodePolicyOID(out, &outSz, s, NULL);
+ if (ret == 0) {
+ /* sum OID */
+ for (i = 0; i < outSz; i++) {
+ sum += out[i];
+ }
+ }
+ #endif /* WOLFSSL_CERT_EXT */
+
+ /* get the group that the OID's sum is in
+ * @TODO possible conflict with multiples */
+ for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++) {
+ int len;
+ #ifdef WOLFSSL_CERT_EXT
+ if (ret == 0) {
+ if (wolfssl_object_info[i].id == (int)sum) {
+ return wolfssl_object_info[i].nid;
+ }
+ }
+ #endif
+
+ /* try as a short name */
+ len = (int)XSTRLEN(s);
+ if (XSTRNCMP(wolfssl_object_info[i].sName, s, len) == 0) {
+ return wolfssl_object_info[i].nid;
+ }
+
+ /* try as a long name */
+ if (XSTRNCMP(wolfssl_object_info[i].lName, s, len) == 0) {
+ return wolfssl_object_info[i].nid;
+ }
+ }
+
+ return NID_undef;
+ }
+
+ /* Creates new ASN1_OBJECT from short name, long name, or text
+ * representation of oid. If no_name is 0, then short name, long name, and
+ * numerical value of oid are interpreted. If no_name is 1, then only the
+ * numerical value of the oid is interpreted.
+ *
+ * Returns pointer to ASN1_OBJECT on success, or NULL on error.
+ */
+#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN)
+ WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_txt2obj(const char* s, int no_name)
+ {
+ int len, i, ret;
+ int nid = NID_undef;
+ unsigned int outSz = MAX_OID_SZ;
+ unsigned char out[MAX_OID_SZ];
+ unsigned int sum = 0;
+
+ WOLFSSL_ENTER("wolfSSL_OBJ_txt2obj");
+
+ if (s == NULL)
+ return NULL;
+
+ /* If s is numerical value, try to sum oid */
+ ret = EncodePolicyOID(out, &outSz, s, NULL);
+ if (ret == 0) {
+ for (i = 0; i < (int)outSz; i++) {
+ sum += out[i];
+ }
+ }
+
+ len = (int)XSTRLEN(s);
+
+ /* TODO: update short names in wolfssl_object_info and check OID sums
+ are correct */
+ for (i = 0; i < (int)WOLFSSL_OBJECT_INFO_SZ; i++) {
+ /* Short name, long name, and numerical value are interpreted */
+ if (no_name == 0 && ((XSTRNCMP(s, wolfssl_object_info[i].sName, len) == 0) ||
+ (XSTRNCMP(s, wolfssl_object_info[i].lName, len) == 0) ||
+ (wolfssl_object_info[i].id == (int)sum)))
+ nid = wolfssl_object_info[i].nid;
+ /* Only numerical value is interpreted */
+ else if (no_name == 1 && wolfssl_object_info[i].id == (int)sum)
+ nid = wolfssl_object_info[i].nid;
+ }
+
+ if (nid != NID_undef)
+ return wolfSSL_OBJ_nid2obj(nid);
+
+ return NULL;
+ }
+#endif
+
+ /* compatibility function. Its intended use is to remove OID's from an
+ * internal table that have been added with OBJ_create. wolfSSL manages its
+ * own internal OID values and does not currently support OBJ_create. */
+ void wolfSSL_OBJ_cleanup(void)
+ {
+ WOLFSSL_ENTER("wolfSSL_OBJ_cleanup()");
+ }
+
+ #ifndef NO_WOLFSSL_STUB
+ int wolfSSL_OBJ_create(const char *oid, const char *sn, const char *ln)
+ {
+ (void)oid;
+ (void)sn;
+ (void)ln;
+ WOLFSSL_STUB("wolfSSL_OBJ_create");
+ return WOLFSSL_FAILURE;
+ }
+ #endif
+
+ void wolfSSL_set_verify_depth(WOLFSSL *ssl, int depth)
+ {
+ #if !defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_STUB)
+ (void)ssl;
+ (void)depth;
+ WOLFSSL_STUB("wolfSSL_set_verify_depth");
+ #else
+ WOLFSSL_ENTER("wolfSSL_set_verify_depth");
+ ssl->options.verifyDepth = (byte)depth;
+ #endif
+ }
+
+
+ WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne) {
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_object");
+ if (ne == NULL) return NULL;
+ if (wolfSSL_OBJ_nid2obj_ex(ne->nid, &ne->object) != NULL) {
+ ne->object.nid = ne->nid;
+ return &ne->object;
+ }
+ return NULL;
+ }
+
+
+ /* looks up the DN given the location "loc". "loc" is the number indicating
+ * the order that the DN was parsed as, 0 is first DN parsed.
+ *
+ * returns the setup WOLFSSL_X509_NAME pointer on success and NULL on fail
+ */
+ static WOLFSSL_X509_NAME* wolfSSL_nameByLoc(WOLFSSL_X509_NAME *name, int loc)
+ {
+ char* pt = NULL;
+ int sz = 0;
+
+ switch (name->fullName.loc[loc])
+ {
+ case ASN_COMMON_NAME:
+ sz = name->fullName.cnLen;
+ pt = &name->fullName.fullName[name->fullName.cnIdx];
+ name->cnEntry.nid = name->fullName.cnNid;
+ break;
+ case ASN_COUNTRY_NAME:
+ sz = name->fullName.cLen;
+ pt = &name->fullName.fullName[name->fullName.cIdx];
+ name->cnEntry.nid = name->fullName.cNid;
+ break;
+ case ASN_LOCALITY_NAME:
+ sz = name->fullName.lLen;
+ pt = &name->fullName.fullName[name->fullName.lIdx];
+ name->cnEntry.nid = name->fullName.lNid;
+ break;
+ case ASN_STATE_NAME:
+ sz = name->fullName.stLen;
+ pt = &name->fullName.fullName[name->fullName.stIdx];
+ name->cnEntry.nid = name->fullName.stNid;
+ break;
+ case ASN_ORG_NAME:
+ sz = name->fullName.oLen;
+ pt = &name->fullName.fullName[name->fullName.oIdx];
+ name->cnEntry.nid = name->fullName.oNid;
+ break;
+ case ASN_ORGUNIT_NAME:
+ sz = name->fullName.ouLen;
+ pt = &name->fullName.fullName[name->fullName.ouIdx];
+ name->cnEntry.nid = name->fullName.ouNid;
+ break;
+ case ASN_EMAIL_NAME:
+ sz = name->fullName.emailLen;
+ pt = &name->fullName.fullName[name->fullName.emailIdx];
+ name->cnEntry.nid = name->fullName.emailNid;
+ break;
+ case ASN_SUR_NAME:
+ sz = name->fullName.snLen;
+ pt = &name->fullName.fullName[name->fullName.snIdx];
+ name->cnEntry.nid = name->fullName.snNid;
+ break;
+ case ASN_USER_ID:
+ sz = name->fullName.uidLen;
+ pt = &name->fullName.fullName[name->fullName.uidIdx];
+ name->cnEntry.nid = name->fullName.uidNid;
+ break;
+ case ASN_SERIAL_NUMBER:
+ sz = name->fullName.serialLen;
+ pt = &name->fullName.fullName[name->fullName.serialIdx];
+ name->cnEntry.nid = name->fullName.serialNid;
+ break;
+#ifdef WOLFSSL_CERT_EXT
+ case ASN_BUS_CAT:
+ sz = name->fullName.bcLen;
+ pt = &name->fullName.fullName[name->fullName.bcIdx];
+ break;
+#endif
+
+ case ASN_DOMAIN_COMPONENT:
+ /* get index of DC i.e. first or second or ... case */
+ {
+ int idx = 0, i;
+ for (i = 0; i < loc; i++) {
+ if (name->fullName.loc[i] == ASN_DOMAIN_COMPONENT) {
+ idx++;
+ }
+ }
+
+ /* check that index is not larger than max buffer size or larger
+ * than the number of domain components parsed */
+ if (idx >= DOMAIN_COMPONENT_MAX || idx > name->fullName.dcNum) {
+ WOLFSSL_MSG("Index was larger then domain buffer");
+ return NULL;
+ }
+ pt = &name->fullName.fullName[name->fullName.dcIdx[idx]],
+ sz = name->fullName.dcLen[idx];
+ name->cnEntry.nid = ASN_DOMAIN_COMPONENT;
+ name->cnEntry.data.type = CTC_UTF8;
+ }
+ break;
+
+ default:
+ return NULL;
+ }
+
+ /* -1 to leave room for trailing terminator 0 */
+ if (sz == 0 || sz >= CTC_NAME_SIZE - 1)
+ return NULL;
+ if (wolfSSL_ASN1_STRING_set(name->cnEntry.value, pt, sz) !=
+ WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error setting local ASN1 string data");
+ return NULL;
+ }
+ name->cnEntry.value->type = CTC_UTF8;
+ name->cnEntry.set = 1;
+ return name;
+ }
+
+
+ WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(
+ WOLFSSL_X509_NAME *name, int loc)
+ {
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_get_entry");
+
+ if (name == NULL) {
+ return NULL;
+ }
+
+ if (loc < 0) {
+ WOLFSSL_MSG("Bad argument");
+ return NULL;
+ }
+
+ if (loc <= DN_NAMES_MAX + name->fullName.dcNum) {
+ if (wolfSSL_nameByLoc(name, loc) != NULL)
+ return &name->cnEntry;
+ }
+ /* DC component */
+ if (name->fullName.dcMode) {
+ if (name->fullName.fullName != NULL){
+ if (loc == name->fullName.dcNum){
+ name->cnEntry.data.data
+ = &name->fullName.fullName[name->fullName.cIdx];
+ name->cnEntry.data.length = name->fullName.cLen;
+ name->cnEntry.nid = ASN_COUNTRY_NAME;
+ } else {
+ name->cnEntry.data.data
+ = &name->fullName.fullName[name->fullName.dcIdx[loc]];
+ name->cnEntry.data.length = name->fullName.dcLen[loc];
+ name->cnEntry.nid = ASN_DOMAIN_COMPONENT;
+ }
+ }
+ name->cnEntry.data.type = CTC_UTF8;
+ /* common name index case */
+ } else if (loc == name->fullName.cnIdx && name->x509 != NULL) {
+ /* get CN shortcut from x509 since it has null terminator */
+ name->cnEntry.data.data = name->x509->subjectCN;
+ name->cnEntry.data.length = name->fullName.cnLen;
+ name->cnEntry.data.type = CTC_UTF8;
+ name->cnEntry.nid = ASN_COMMON_NAME;
+ name->cnEntry.set = 1;
+ } else {
+ WOLFSSL_MSG("loc passed in is not in range of parsed DN's");
+ return NULL;
+ }
+ return &name->cnEntry;
+ }
+
+ #ifndef NO_WOLFSSL_STUB
+ int wolfSSL_X509_check_private_key(WOLFSSL_X509 *x509, WOLFSSL_EVP_PKEY *key)
+ {
+ (void) x509;
+ (void) key;
+ WOLFSSL_ENTER("wolfSSL_X509_check_private_key");
+ WOLFSSL_STUB("X509_check_private_key");
+
+ return WOLFSSL_SUCCESS;
+ }
+
+ WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list(
+ WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk)
+ {
+ (void) sk;
+ WOLFSSL_ENTER("wolfSSL_dup_CA_list");
+ WOLFSSL_STUB("SSL_dup_CA_list");
+
+ return NULL;
+ }
+
+ #endif
+
+#endif /* OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE ||
+ HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */
+#endif /* OPENSSL_EXTRA */
+
+#ifndef WOLFCRYPT_ONLY
+
+#ifdef OPENSSL_EXTRA
+
+/* wolfSSL uses negative values for error states. This function returns an
+ * unsigned type so the value returned is the absolute value of the error.
+ */
+unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line)
+{
+ WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error");
+
+ (void)line;
+ (void)file;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(DEBUG_WOLFSSL) || \
+ defined(WOLFSSL_HAPROXY)
+ {
+ int ret;
+
+ if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) {
+ WOLFSSL_MSG("Issue peeking at error node in queue");
+ return 0;
+ }
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+ if (ret == -ASN_NO_PEM_HEADER)
+ return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
+ #endif
+ return (unsigned long)ret;
+ }
+#else
+ return (unsigned long)(0 - NOT_COMPILED_IN);
+#endif
+}
+
+
+#ifndef NO_CERTS
+int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey");
+
+ if (ctx == NULL || pkey == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (pkey->pkey.ptr != NULL) {
+ /* ptr for WOLFSSL_EVP_PKEY struct is expected to be DER format */
+ return wolfSSL_CTX_use_PrivateKey_buffer(ctx,
+ (const unsigned char*)pkey->pkey.ptr,
+ pkey->pkey_sz, SSL_FILETYPE_ASN1);
+ }
+
+ WOLFSSL_MSG("wolfSSL private key not set");
+ return BAD_FUNC_ARG;
+}
+#endif /* !NO_CERTS */
+
+
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data");
+ #ifdef HAVE_EX_DATA
+ if(ctx != NULL) {
+ return wolfSSL_CRYPTO_get_ex_data(&ctx->ex_data, idx);
+ }
+ #else
+ (void)ctx;
+ (void)idx;
+ #endif
+ return NULL;
+}
+
+int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b,
+ void* c)
+{
+ static int ctx_idx = 0;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index");
+ (void)idx;
+ (void)arg;
+ (void)a;
+ (void)b;
+ (void)c;
+
+ return ctx_idx++;
+}
+
+/* Return the index that can be used for the WOLFSSL structure to store
+ * application data.
+ *
+ */
+int wolfSSL_get_ex_new_index(long argValue, void* arg,
+ WOLFSSL_CRYPTO_EX_new* cb1, WOLFSSL_CRYPTO_EX_dup* cb2,
+ WOLFSSL_CRYPTO_EX_free* cb3)
+{
+ static int ssl_idx = 0;
+
+ WOLFSSL_ENTER("wolfSSL_get_ex_new_index");
+
+ (void)argValue;
+ (void)arg;
+ (void)cb1;
+ (void)cb2;
+ (void)cb3;
+
+ return ssl_idx++;
+}
+
+
+int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data");
+ #ifdef HAVE_EX_DATA
+ if (ctx != NULL)
+ {
+ return wolfSSL_CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
+ }
+ #else
+ (void)ctx;
+ (void)idx;
+ (void)data;
+ #endif
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+
+/* Returns char* to app data stored in ex[0].
+ *
+ * ssl WOLFSSL structure to get app data from
+ */
+void* wolfSSL_get_app_data(const WOLFSSL *ssl)
+{
+ /* checkout exdata stuff... */
+ WOLFSSL_ENTER("wolfSSL_get_app_data");
+
+ return wolfSSL_get_ex_data(ssl, 0);
+}
+
+
+/* Set ex array 0 to have app data
+ *
+ * ssl WOLFSSL struct to set app data in
+ * arg data to be stored
+ *
+ * Returns SSL_SUCCESS on success and SSL_FAILURE on failure
+ */
+int wolfSSL_set_app_data(WOLFSSL *ssl, void* arg) {
+ WOLFSSL_ENTER("wolfSSL_set_app_data");
+
+ return wolfSSL_set_ex_data(ssl, 0, arg);
+}
+
+
+int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data)
+{
+ WOLFSSL_ENTER("wolfSSL_set_ex_data");
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+ if (ssl != NULL)
+ {
+ return wolfSSL_CRYPTO_set_ex_data(&ssl->ex_data, idx, data);
+ }
+#else
+ WOLFSSL_MSG("HAVE_EX_DATA macro is not defined");
+ (void)ssl;
+ (void)idx;
+ (void)data;
+#endif
+ return WOLFSSL_FAILURE;
+}
+
+
+
+void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx)
+{
+ WOLFSSL_ENTER("wolfSSL_get_ex_data");
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+ if (ssl != NULL) {
+ return wolfSSL_CRYPTO_get_ex_data(&ssl->ex_data, idx);
+ }
+#else
+ WOLFSSL_MSG("HAVE_EX_DATA macro is not defined");
+ (void)ssl;
+ (void)idx;
+#endif
+ return 0;
+}
+
+#ifndef NO_DSA
+WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, WOLFSSL_DSA **x,
+ pem_password_cb *cb, void *u)
+{
+ WOLFSSL_DSA* dsa;
+ DsaKey* key;
+ int length;
+ unsigned char* buf;
+ word32 bufSz;
+ int ret;
+ word32 idx = 0;
+ DerBuffer* pDer;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DSAparams");
+
+ ret = wolfSSL_BIO_get_mem_data(bp, &buf);
+ if (ret <= 0) {
+ WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret);
+ return NULL;
+ }
+
+ bufSz = (word32)ret;
+
+ if (cb != NULL || u != NULL) {
+ /*
+ * cb is for a call back when encountering encrypted PEM files
+ * if cb == NULL and u != NULL then u = null terminated password string
+ */
+ WOLFSSL_MSG("Not yet supporting call back or password for encrypted PEM");
+ }
+
+ if ((ret = PemToDer(buf, (long)bufSz, DSA_PARAM_TYPE, &pDer, NULL, NULL,
+ NULL)) < 0 ) {
+ WOLFSSL_MSG("Issue converting from PEM to DER");
+ return NULL;
+ }
+
+ if ((ret = GetSequence(pDer->buffer, &idx, &length, pDer->length)) < 0) {
+ WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret);
+ FreeDer(&pDer);
+ return NULL;
+ }
+
+ dsa = wolfSSL_DSA_new();
+ if (dsa == NULL) {
+ FreeDer(&pDer);
+ WOLFSSL_MSG("Error creating DSA struct");
+ return NULL;
+ }
+
+ key = (DsaKey*)dsa->internal;
+ if (key == NULL) {
+ FreeDer(&pDer);
+ wolfSSL_DSA_free(dsa);
+ WOLFSSL_MSG("Error finding DSA key struct");
+ return NULL;
+ }
+
+ if (GetInt(&key->p, pDer->buffer, &idx, pDer->length) < 0 ||
+ GetInt(&key->q, pDer->buffer, &idx, pDer->length) < 0 ||
+ GetInt(&key->g, pDer->buffer, &idx, pDer->length) < 0 ) {
+ WOLFSSL_MSG("dsa key error");
+ FreeDer(&pDer);
+ wolfSSL_DSA_free(dsa);
+ return NULL;
+ }
+
+ if (SetIndividualExternal(&dsa->p, &key->p) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("dsa p key error");
+ FreeDer(&pDer);
+ wolfSSL_DSA_free(dsa);
+ return NULL;
+ }
+
+ if (SetIndividualExternal(&dsa->q, &key->q) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("dsa q key error");
+ FreeDer(&pDer);
+ wolfSSL_DSA_free(dsa);
+ return NULL;
+ }
+
+ if (SetIndividualExternal(&dsa->g, &key->g) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("dsa g key error");
+ FreeDer(&pDer);
+ wolfSSL_DSA_free(dsa);
+ return NULL;
+ }
+
+ if (x != NULL) {
+ *x = dsa;
+ }
+
+ FreeDer(&pDer);
+ return dsa;
+}
+#endif /* NO_DSA */
+#endif /* OPENSSL_EXTRA */
+#endif /* WOLFCRYPT_ONLY */
+
+#if defined(OPENSSL_EXTRA)
+
+/* Begin functions for openssl/buffer.h */
+WOLFSSL_BUF_MEM* wolfSSL_BUF_MEM_new(void)
+{
+ WOLFSSL_BUF_MEM* buf;
+ buf = (WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (buf) {
+ XMEMSET(buf, 0, sizeof(WOLFSSL_BUF_MEM));
+ }
+ return buf;
+}
+
+
+/* returns length of buffer on success */
+int wolfSSL_BUF_MEM_grow(WOLFSSL_BUF_MEM* buf, size_t len)
+{
+ int len_int = (int)len;
+ int mx;
+
+ /* verify provided arguments */
+ if (buf == NULL || len_int < 0) {
+ return 0; /* BAD_FUNC_ARG; */
+ }
+
+ /* check to see if fits in existing length */
+ if (buf->length > len) {
+ buf->length = len;
+ return len_int;
+ }
+
+ /* check to see if fits in max buffer */
+ if (buf->max >= len) {
+ if (buf->data != NULL) {
+ XMEMSET(&buf->data[buf->length], 0, len - buf->length);
+ }
+ buf->length = len;
+ return len_int;
+ }
+
+ /* expand size, to handle growth */
+ mx = (len_int + 3) / 3 * 4;
+
+ /* use realloc */
+ buf->data = (char*)XREALLOC(buf->data, mx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (buf->data == NULL) {
+ return 0; /* ERR_R_MALLOC_FAILURE; */
+ }
+
+ buf->max = mx;
+ XMEMSET(&buf->data[buf->length], 0, len - buf->length);
+ buf->length = len;
+
+ return len_int;
+}
+
+void wolfSSL_BUF_MEM_free(WOLFSSL_BUF_MEM* buf)
+{
+ if (buf) {
+ if (buf->data) {
+ XFREE(buf->data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ buf->data = NULL;
+ }
+ buf->max = 0;
+ buf->length = 0;
+ XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+/* End Functions for openssl/buffer.h */
+
+#endif /* OPENSSL_EXTRA */
+
+
+#if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \
+ || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA)
+
+WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode)
+{
+#ifndef NO_FILESYSTEM
+ WOLFSSL_BIO* bio;
+ XFILE fp;
+
+ WOLFSSL_ENTER("wolfSSL_BIO_new_file");
+
+ fp = XFOPEN(filename, mode);
+ if (fp == XBADFILE)
+ return NULL;
+
+ bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
+ if (bio == NULL) {
+ XFCLOSE(fp);
+ return bio;
+ }
+
+ if (wolfSSL_BIO_set_fp(bio, fp, BIO_CLOSE) != WOLFSSL_SUCCESS) {
+ XFCLOSE(fp);
+ wolfSSL_BIO_free(bio);
+ bio = NULL;
+ }
+
+ /* file is closed when BIO is free'd */
+ return bio;
+#else
+ (void)filename;
+ (void)mode;
+ return NULL;
+#endif /* NO_FILESYSTEM */
+}
+
+#ifndef NO_FILESYSTEM
+WOLFSSL_BIO* wolfSSL_BIO_new_fp(XFILE fp, int close_flag)
+{
+ WOLFSSL_BIO* bio;
+
+ WOLFSSL_ENTER("wolfSSL_BIO_new_fp");
+
+ bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
+ if (bio == NULL) {
+ return bio;
+ }
+
+ if (wolfSSL_BIO_set_fp(bio, fp, close_flag) != WOLFSSL_SUCCESS) {
+ wolfSSL_BIO_free(bio);
+ bio = NULL;
+ }
+
+ /* file is closed when BIO is free'd or by user depending on flag */
+ return bio;
+}
+#endif
+
+
+#ifndef NO_DH
+WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bio, WOLFSSL_DH **x,
+ pem_password_cb *cb, void *u)
+{
+#ifndef NO_FILESYSTEM
+ WOLFSSL_DH* localDh = NULL;
+ unsigned char* mem = NULL;
+ word32 size;
+ long sz;
+ int ret;
+ DerBuffer *der = NULL;
+ byte* p = NULL;
+ byte* g = NULL;
+ word32 pSz = MAX_DH_SIZE;
+ word32 gSz = MAX_DH_SIZE;
+ int memAlloced = 0;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DHparams");
+ (void)cb;
+ (void)u;
+
+ if (bio == NULL) {
+ WOLFSSL_MSG("Bad Function Argument bio is NULL");
+ return NULL;
+ }
+
+ if (bio->type == WOLFSSL_BIO_MEMORY) {
+ /* Use the buffer directly. */
+ ret = wolfSSL_BIO_get_mem_data(bio, &mem);
+ if (mem == NULL || ret <= 0) {
+ WOLFSSL_MSG("Failed to get data from bio struct");
+ goto end;
+ }
+ size = ret;
+ }
+ else if (bio->type == WOLFSSL_BIO_FILE) {
+ /* Read whole file into a new buffer. */
+ if (XFSEEK((XFILE)bio->ptr, 0, SEEK_END) != 0)
+ goto end;
+ sz = XFTELL((XFILE)bio->ptr);
+ if (XFSEEK((XFILE)bio->ptr, 0, SEEK_SET) != 0)
+ goto end;
+ if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0L) {
+ WOLFSSL_MSG("PEM_read_bio_DHparams file size error");
+ goto end;
+ }
+ mem = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_PEM);
+ if (mem == NULL)
+ goto end;
+ memAlloced = 1;
+
+ if (wolfSSL_BIO_read(bio, (char *)mem, (int)sz) <= 0)
+ goto end;
+ size = (word32)sz;
+ }
+ else {
+ WOLFSSL_MSG("BIO type not supported for reading DH parameters");
+ goto end;
+ }
+
+ ret = PemToDer(mem, size, DH_PARAM_TYPE, &der, NULL, NULL, NULL);
+ if (ret != 0)
+ goto end;
+
+ /* Use the object passed in, otherwise allocate a new object */
+ if (x != NULL)
+ localDh = *x;
+ if (localDh == NULL) {
+ localDh = wolfSSL_DH_new();
+ if (localDh == NULL)
+ goto end;
+ }
+
+ /* Load data in manually */
+ p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ if (p == NULL || g == NULL)
+ goto end;
+
+ /* Extract the p and g as data from the DER encoded DH parameters. */
+ ret = wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz);
+ if (ret != 0) {
+ if (x != NULL && localDh != *x)
+ XFREE(localDh, NULL, DYNAMIC_TYPE_OPENSSL);
+ localDh = NULL;
+ goto end;
+ }
+
+ if (x != NULL)
+ *x = localDh;
+
+ /* Put p and g in as big numbers. */
+ if (localDh->p != NULL) {
+ wolfSSL_BN_free(localDh->p);
+ localDh->p = NULL;
+ }
+ if (localDh->g != NULL) {
+ wolfSSL_BN_free(localDh->g);
+ localDh->g = NULL;
+ }
+ localDh->p = wolfSSL_BN_bin2bn(p, pSz, NULL);
+ localDh->g = wolfSSL_BN_bin2bn(g, gSz, NULL);
+ if (localDh->p == NULL || localDh->g == NULL) {
+ if (x != NULL && localDh != *x)
+ wolfSSL_DH_free(localDh);
+ localDh = NULL;
+ }
+
+ if (localDh != NULL && localDh->inSet == 0) {
+ if (SetDhInternal(localDh) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Unable to set internal DH structure");
+ wolfSSL_DH_free(localDh);
+ localDh = NULL;
+ }
+ }
+
+end:
+ if (memAlloced) XFREE(mem, NULL, DYNAMIC_TYPE_PEM);
+ if (der != NULL) FreeDer(&der);
+ XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ return localDh;
+#else
+ (void)bio;
+ (void)x;
+ (void)cb;
+ (void)u;
+ return NULL;
+#endif
+}
+
+#ifndef NO_FILESYSTEM
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)
+/* Convert DH key parameters to DER format, write to output (outSz)
+ * If output is NULL then max expected size is set to outSz and LENGTH_ONLY_E is
+ * returned.
+ *
+ * Note : static function due to redefinition complications with DhKey and FIPS
+ * version 2 build.
+ *
+ * return bytes written on success */
+int wc_DhParamsToDer(DhKey* key, byte* out, word32* outSz)
+{
+ word32 sz = 0, idx = 0;
+ int pSz = 0, gSz = 0, ret;
+ byte scratch[MAX_LENGTH_SZ];
+
+ if (key == NULL || outSz == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ pSz = mp_unsigned_bin_size(&key->p);
+ if (pSz < 0) {
+ return pSz;
+ }
+ if (mp_leading_bit(&key->p)) {
+ pSz++;
+ }
+
+ gSz = mp_unsigned_bin_size(&key->g);
+ if (gSz < 0) {
+ return gSz;
+ }
+ if (mp_leading_bit(&key->g)) {
+ gSz++;
+ }
+
+ sz = ASN_TAG_SZ; /* Integer */
+ sz += SetLength(pSz, scratch);
+ sz += ASN_TAG_SZ; /* Integer */
+ sz += SetLength(gSz, scratch);
+ sz += gSz + pSz;
+
+ if (out == NULL) {
+ byte seqScratch[MAX_SEQ_SZ];
+
+ *outSz = sz + SetSequence(sz, seqScratch);
+ return LENGTH_ONLY_E;
+ }
+
+ if (*outSz < MAX_SEQ_SZ || *outSz < sz) {
+ return BUFFER_E;
+ }
+
+ idx += SetSequence(sz, out);
+ if (*outSz < idx + sz) {
+ return BUFFER_E;
+ }
+
+ out[idx++] = ASN_INTEGER;
+ idx += SetLength(pSz, out + idx);
+ if (mp_leading_bit(&key->p)) {
+ out[idx++] = 0x00;
+ pSz -= 1; /* subtract 1 from size to account for leading 0 */
+ }
+ ret = mp_to_unsigned_bin(&key->p, out + idx);
+ if (ret != MP_OKAY) {
+ return BUFFER_E;
+ }
+ idx += pSz;
+
+ out[idx++] = ASN_INTEGER;
+ idx += SetLength(gSz, out + idx);
+ if (mp_leading_bit(&key->g)) {
+ out[idx++] = 0x00;
+ gSz -= 1; /* subtract 1 from size to account for leading 0 */
+ }
+ ret = mp_to_unsigned_bin(&key->g, out + idx);
+ if (ret != MP_OKAY) {
+ return BUFFER_E;
+ }
+ idx += gSz;
+ return idx;
+}
+
+int wc_DhPubKeyToDer(DhKey* key, byte* out, word32* outSz)
+{
+ word32 sz = 0;
+ word32 paramSz = 0;
+ int ret;
+ int pubSz = 0;
+ int idx = 0;
+ byte scratch[MAX_ALGO_SZ];
+
+ /* Get size of entire key */
+
+ /* SEQUENCE <--| SetAlgoId
+ * OBJECT IDENTIFIER <--|
+ * SEQUENCE <--
+ * INTEGER | wc_DhParamsToDer
+ * INTEGER <--
+ */
+ ret = wc_DhParamsToDer(key, NULL, &paramSz);
+ if (ret != LENGTH_ONLY_E)
+ return ASN_PARSE_E;
+ sz += paramSz;
+ sz += SetAlgoID(DHk, scratch, oidKeyType, paramSz);
+
+ /* BIT STRING
+ * INTEGER
+ */
+ pubSz = mp_unsigned_bin_size(&key->pub);
+ if (pubSz < 0)
+ return pubSz;
+
+ if (mp_leading_bit(&key->pub))
+ pubSz++;
+
+ sz += ASN_TAG_SZ; /* Integer */
+ sz += SetLength(pubSz, scratch);
+ sz += pubSz;
+
+ sz += SetBitString(pubSz, 0, scratch);
+
+ if (out == NULL) {
+ /* Uppermost SEQUENCE */
+ *outSz = sz + SetSequence(sz, scratch);
+ return LENGTH_ONLY_E;
+ }
+ /* end get size of entire key */
+
+ /* Check for indexing errors */
+ if (*outSz < MAX_SEQ_SZ || *outSz < sz) {
+ return BUFFER_E;
+ }
+
+ /* Build Up Entire Key */
+
+ idx += SetSequence(sz, out);
+
+ idx += SetAlgoID(DHk, out+idx, oidKeyType, paramSz);
+ ret = wc_DhParamsToDer(key, out+idx, &paramSz);
+ if (ret < 0)
+ return ret;
+ idx += ret;
+
+ /* BIT STRING
+ * INTEGER
+ */
+ idx += SetBitString(pubSz, 0, out+idx);
+
+ out[idx++] = ASN_INTEGER;
+ idx += SetLength(pubSz, out + idx);
+ if (mp_leading_bit(&key->pub)) {
+ out[idx++] = 0x00;
+ pubSz -= 1; /* subtract 1 from size to account for leading 0 */
+ }
+ ret = mp_to_unsigned_bin(&key->pub, out + idx);
+ if (ret != MP_OKAY) {
+ return BUFFER_E;
+ }
+ idx += pubSz;
+
+ return idx;
+}
+
+int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz)
+{
+ word32 sz = 0;
+ word32 paramSz = 0;
+ int ret;
+ int privSz = 0;
+ int idx = 0;
+ byte scratch[MAX_ALGO_SZ];
+
+ /* Get size of entire key */
+
+ /* INTEGER 0 */
+ sz += ASN_TAG_SZ; /* Integer */
+ sz += SetLength(1, scratch);
+ sz += 1;
+
+ /* SEQUENCE <--| SetAlgoId
+ * OBJECT IDENTIFIER <--|
+ * SEQUENCE <--
+ * INTEGER | wc_DhParamsToDer
+ * INTEGER <--
+ */
+ ret = wc_DhParamsToDer(key, NULL, &paramSz);
+ if (ret != LENGTH_ONLY_E)
+ return ASN_PARSE_E;
+ sz += paramSz;
+ sz += SetAlgoID(DHk, scratch, oidKeyType, paramSz);
+
+ /* OCTET STRING
+ * INTEGER
+ */
+ privSz = mp_unsigned_bin_size(&key->priv);
+ if (privSz < 0)
+ return privSz;
+ else if (privSz > 256) /* Key is larger than 2048 */
+ return ASN_VERSION_E;
+
+ if (mp_leading_bit(&key->priv))
+ privSz++;
+
+ sz += ASN_TAG_SZ; /* Integer */
+ sz += SetLength(privSz, scratch);
+ sz += privSz;
+
+ sz += SetOctetString(privSz + ASN_OCTET_STRING, scratch);
+
+ if (out == NULL) {
+ /* Uppermost SEQUENCE */
+ *outSz = sz + SetSequence(sz, scratch);
+ return LENGTH_ONLY_E;
+ }
+ /* end get size of entire key */
+
+ /* Check for indexing errors */
+ if (*outSz < MAX_SEQ_SZ || *outSz < sz) {
+ return BUFFER_E;
+ }
+
+ /* Build Up Entire Key */
+
+ idx += SetSequence(sz, out);
+
+ /* INTEGER 0 */
+ out[idx++] = ASN_INTEGER;
+ idx += SetLength(1, out+idx);
+ out[idx++] = 0;
+
+ idx += SetAlgoID(DHk, out+idx, oidKeyType, paramSz);
+ ret = wc_DhParamsToDer(key, out+idx, &paramSz);
+ if (ret < 0)
+ return ret;
+ idx += ret;
+
+ /* OCTET STRING
+ * INTEGER
+ */
+ if (privSz == 256) {
+ idx += SetOctetString(privSz + ASN_OCTET_STRING, out+idx);
+ } else if (privSz == 128) {
+ idx += SetOctetString(privSz + ASN_OCTET_STRING-1, out+idx);
+ } else if (privSz == 64) {
+ idx += SetOctetString(privSz + ASN_OCTET_STRING-2, out+idx);
+ } else {
+ WOLFSSL_MSG("Unsupported key size");
+ return ASN_VERSION_E;
+ }
+
+ out[idx++] = ASN_INTEGER;
+ idx += SetLength(privSz, out + idx);
+ if (mp_leading_bit(&key->priv)) {
+ out[idx++] = 0x00;
+ privSz -= 1; /* subtract 1 from size to account for leading 0 */
+ }
+ ret = mp_to_unsigned_bin(&key->priv, out + idx);
+ if (ret != MP_OKAY) {
+ return BUFFER_E;
+ }
+ idx += privSz;
+
+ return idx;
+}
+
+/* Writes the DH parameters in PEM format from "dh" out to the file pointer
+ * passed in.
+ *
+ * returns WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh)
+{
+ int ret;
+ word32 derSz = 0, pemSz = 0;
+ byte *der, *pem;
+ DhKey* key;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_DHparams");
+
+ if (dh == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", BAD_FUNC_ARG);
+ return WOLFSSL_FAILURE;
+ }
+
+ if (dh->inSet == 0) {
+ if (SetDhInternal(dh) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Unable to set internal DH structure");
+ return WOLFSSL_FAILURE;
+ }
+ }
+ key = (DhKey*)dh->internal;
+ ret = wc_DhParamsToDer(key, NULL, &derSz);
+ if (ret != LENGTH_ONLY_E) {
+ WOLFSSL_MSG("Failed to get size of DH params");
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret);
+ return WOLFSSL_FAILURE;
+ }
+
+ der = (byte*)XMALLOC(derSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (der == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", MEMORY_E);
+ return WOLFSSL_FAILURE;
+ }
+ ret = wc_DhParamsToDer(key, der, &derSz);
+ if (ret <= 0) {
+ WOLFSSL_MSG("Failed to export DH params");
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret);
+ XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* convert to PEM */
+ ret = wc_DerToPem(der, derSz, NULL, 0, DH_PARAM_TYPE);
+ if (ret < 0) {
+ WOLFSSL_MSG("Failed to convert DH params to PEM");
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret);
+ XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+ pemSz = (word32)ret;
+
+ pem = (byte*)XMALLOC(pemSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pem == NULL) {
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", MEMORY_E);
+ XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+ ret = wc_DerToPem(der, derSz, pem, pemSz, DH_PARAM_TYPE);
+ XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (ret < 0) {
+ WOLFSSL_MSG("Failed to convert DH params to PEM");
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret);
+ XFREE(pem, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+
+ ret = (int)XFWRITE(pem, 1, pemSz, fp);
+ XFREE(pem, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (ret <= 0) {
+ WOLFSSL_MSG("Failed to write to file");
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret);
+ return WOLFSSL_FAILURE;
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", WOLFSSL_SUCCESS);
+ return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
+#endif /* !NO_FILESYSTEM */
+#endif /* !NO_DH */
+
+#ifdef WOLFSSL_CERT_GEN
+
+#ifdef WOLFSSL_CERT_REQ
+/* writes the x509 from x to the WOLFSSL_BIO bp
+ *
+ * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail
+ */
+int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 *x)
+{
+ byte* pem;
+ int pemSz = 0;
+ const unsigned char* der;
+ int derSz;
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_REQ()");
+
+ if (x == NULL || bp == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ der = wolfSSL_X509_get_der(x, &derSz);
+ if (der == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* get PEM size */
+ pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERTREQ_TYPE);
+ if (pemSz < 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* create PEM buffer and convert from DER */
+ pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pem == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+ if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERTREQ_TYPE) < 0) {
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* write the PEM to BIO */
+ ret = wolfSSL_BIO_write(bp, pem, pemSz);
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ if (ret <= 0) return WOLFSSL_FAILURE;
+ return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_CERT_REQ */
+
+
+/* writes the x509 from x to the WOLFSSL_BIO bp
+ *
+ * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail
+ */
+int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp, WOLFSSL_X509 *x)
+{
+ byte* pem;
+ int pemSz = 0;
+ const unsigned char* der;
+ int derSz;
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_AUX()");
+
+ if (bp == NULL || x == NULL) {
+ WOLFSSL_MSG("NULL argument passed in");
+ return WOLFSSL_FAILURE;
+ }
+
+ der = wolfSSL_X509_get_der(x, &derSz);
+ if (der == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* get PEM size */
+ pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERT_TYPE);
+ if (pemSz < 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* create PEM buffer and convert from DER */
+ pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pem == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+ if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERT_TYPE) < 0) {
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* write the PEM to BIO */
+ ret = wolfSSL_BIO_write(bp, pem, pemSz);
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ if (ret <= 0) return WOLFSSL_FAILURE;
+ return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_CERT_GEN */
+
+int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert)
+{
+ byte* pem;
+ int pemSz = 0;
+ const unsigned char* der;
+ int derSz;
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_AUX()");
+
+ if (bio == NULL || cert == NULL) {
+ WOLFSSL_MSG("NULL argument passed in");
+ return WOLFSSL_FAILURE;
+ }
+
+ der = wolfSSL_X509_get_der(cert, &derSz);
+ if (der == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* get PEM size */
+ pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERT_TYPE);
+ if (pemSz < 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* create PEM buffer and convert from DER */
+ pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pem == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+ if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERT_TYPE) < 0) {
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+
+ /* write the PEM to BIO */
+ ret = wolfSSL_BIO_write(bio, pem, pemSz);
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ if (ret <= 0) return WOLFSSL_FAILURE;
+ return WOLFSSL_SUCCESS;
+}
+
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_DH)
+/* Initialize ctx->dh with dh's params. Return WOLFSSL_SUCCESS on ok */
+long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh)
+{
+ int pSz, gSz;
+ byte *p, *g;
+ int ret=0;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_set_tmp_dh");
+
+ if(!ctx || !dh)
+ return BAD_FUNC_ARG;
+
+ /* Get needed size for p and g */
+ pSz = wolfSSL_BN_bn2bin(dh->p, NULL);
+ gSz = wolfSSL_BN_bn2bin(dh->g, NULL);
+
+ if(pSz <= 0 || gSz <= 0)
+ return WOLFSSL_FATAL_ERROR;
+
+ p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ if(!p)
+ return MEMORY_E;
+
+ g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ if(!g) {
+ XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ return MEMORY_E;
+ }
+
+ pSz = wolfSSL_BN_bn2bin(dh->p, p);
+ gSz = wolfSSL_BN_bn2bin(dh->g, g);
+
+ if(pSz >= 0 && gSz >= 0) /* Conversion successful */
+ ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz);
+
+ XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE(g, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+
+ return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR;
+}
+#endif /* OPENSSL_EXTRA && !NO_DH */
+
+
+/* returns the enum value associated with handshake state
+ *
+ * ssl the WOLFSSL structure to get state of
+ */
+int wolfSSL_get_state(const WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_get_state");
+
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Null argument passed in");
+ return SSL_FAILURE;
+ }
+
+ return ssl->options.handShakeState;
+}
+#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \
+ || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT)
+
+long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt)
+{
+ WOLFSSL_ENTER("wolfSSL_ctrl");
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ switch (cmd) {
+ #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ case SSL_CTRL_SET_TLSEXT_HOSTNAME:
+ WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TLSEXT_HOSTNAME.");
+ #ifdef HAVE_SNI
+ if (pt == NULL) {
+ WOLFSSL_MSG("Passed in NULL Host Name.");
+ break;
+ }
+ return wolfSSL_set_tlsext_host_name(ssl, (const char*) pt);
+ #else
+ WOLFSSL_MSG("SNI not enabled.");
+ break;
+ #endif /* HAVE_SNI */
+ #endif /* WOLFSSL_NGINX || WOLFSSL_QT || OPENSSL_ALL */
+ default:
+ WOLFSSL_MSG("Case not implemented.");
+ }
+ (void)opt;
+ (void)pt;
+ return WOLFSSL_FAILURE;
+}
+
+long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt)
+{
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+ long ctrl_opt;
+#endif
+ long ret = WOLFSSL_SUCCESS;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_ctrl");
+ if (ctx == NULL)
+ return WOLFSSL_FAILURE;
+
+ switch (cmd) {
+ case SSL_CTRL_CHAIN:
+#ifdef SESSION_CERTS
+ {
+ /*
+ * We don't care about opt here because a copy of the certificate is
+ * stored anyway so increasing the reference counter is not necessary.
+ * Just check to make sure that it is set to one of the correct values.
+ */
+ WOLF_STACK_OF(WOLFSSL_X509)* sk = (WOLF_STACK_OF(WOLFSSL_X509)*) pt;
+ WOLFSSL_X509* x509;
+ int i;
+ if (opt != 0 && opt != 1) {
+ ret = WOLFSSL_FAILURE;
+ break;
+ }
+ /* Clear certificate chain */
+ FreeDer(&ctx->certChain);
+ if (sk) {
+ for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) {
+ x509 = wolfSSL_sk_X509_value(sk, i);
+ /* Prevent wolfSSL_CTX_add_extra_chain_cert from freeing cert */
+ if (wolfSSL_X509_up_ref(x509) != 1) {
+ WOLFSSL_MSG("Error increasing reference count");
+ continue;
+ }
+ if (wolfSSL_CTX_add_extra_chain_cert(ctx, x509) !=
+ WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error adding certificate to context");
+ /* Decrease reference count on failure */
+ wolfSSL_X509_free(x509);
+ }
+ }
+ }
+ /* Free previous chain */
+ wolfSSL_sk_X509_free(ctx->x509Chain);
+ ctx->x509Chain = sk;
+ if (sk) {
+ for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) {
+ x509 = wolfSSL_sk_X509_value(sk, i);
+ /* On successful setting of new chain up all refs */
+ if (wolfSSL_X509_up_ref(x509) != 1) {
+ WOLFSSL_MSG("Error increasing reference count");
+ continue;
+ }
+ }
+ }
+ }
+#else
+ WOLFSSL_MSG("Session certificates not compiled in");
+ ret = WOLFSSL_FAILURE;
+#endif
+ break;
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+ case SSL_CTRL_OPTIONS:
+ WOLFSSL_MSG("Entering Case: SSL_CTRL_OPTIONS.");
+ ctrl_opt = wolfSSL_CTX_set_options(ctx, opt);
+
+ #ifdef WOLFSSL_QT
+ /* Set whether to use client or server cipher preference */
+ if ((ctrl_opt & SSL_OP_CIPHER_SERVER_PREFERENCE)
+ == SSL_OP_CIPHER_SERVER_PREFERENCE) {
+ WOLFSSL_MSG("Using Server's Cipher Preference.");
+ ctx->useClientOrder = FALSE;
+ } else {
+ WOLFSSL_MSG("Using Client's Cipher Preference.");
+ ctx->useClientOrder = TRUE;
+ }
+ #endif /* WOLFSSL_QT */
+
+ return ctrl_opt;
+#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
+ case SSL_CTRL_EXTRA_CHAIN_CERT:
+ WOLFSSL_MSG("Entering Case: SSL_CTRL_EXTRA_CHAIN_CERT.");
+ if (pt == NULL) {
+ WOLFSSL_MSG("Passed in x509 pointer NULL.");
+ ret = WOLFSSL_FAILURE;
+ break;
+ }
+ return wolfSSL_CTX_add_extra_chain_cert(ctx, (WOLFSSL_X509*)pt);
+
+#ifndef NO_DH
+ case SSL_CTRL_SET_TMP_DH:
+ WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TMP_DH.");
+ if (pt == NULL) {
+ WOLFSSL_MSG("Passed in DH pointer NULL.");
+ ret = WOLFSSL_FAILURE;
+ break;
+ }
+ return wolfSSL_CTX_set_tmp_dh(ctx, (WOLFSSL_DH*)pt);
+#endif
+
+#ifdef HAVE_ECC
+ case SSL_CTRL_SET_TMP_ECDH:
+ WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TMP_ECDH.");
+ if (pt == NULL) {
+ WOLFSSL_MSG("Passed in ECDH pointer NULL.");
+ ret = WOLFSSL_FAILURE;
+ break;
+ }
+ return wolfSSL_SSL_CTX_set_tmp_ecdh(ctx, (WOLFSSL_EC_KEY*)pt);
+#endif
+ case SSL_CTRL_MODE:
+ wolfSSL_CTX_set_mode(ctx,opt);
+ break;
+
+ default:
+ WOLFSSL_MSG("CTX_ctrl cmd not implemented");
+ ret = WOLFSSL_FAILURE;
+ break;
+ }
+
+ (void)ctx;
+ (void)cmd;
+ (void)opt;
+ (void)pt;
+ WOLFSSL_LEAVE("wolfSSL_CTX_ctrl", (int)ret);
+ return ret;
+}
+
+#ifndef WOLFSSL_NO_STUB
+long wolfSSL_CTX_callback_ctrl(WOLFSSL_CTX* ctx, int cmd, void (*fp)(void))
+{
+ (void) ctx;
+ (void) cmd;
+ (void) fp;
+ WOLFSSL_STUB("wolfSSL_CTX_callback_ctrl");
+ return WOLFSSL_FAILURE;
+
+}
+#endif /* WOLFSSL_NO_STUB */
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_clear_extra_chain_certs(WOLFSSL_CTX* ctx)
+{
+ return wolfSSL_CTX_ctrl(ctx, SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS, 0l, NULL);
+}
+#endif
+
+/* Returns the verifyCallback from the ssl structure if successful.
+Returns NULL otherwise. */
+VerifyCallback wolfSSL_get_verify_callback(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_get_verify_callback()");
+ if (ssl) {
+ return ssl->verifyCallback;
+ }
+ return NULL;
+}
+
+/* Creates a new bio pair.
+Returns WOLFSSL_SUCCESS if no error, WOLFSSL_FAILURE otherwise.*/
+int wolfSSL_BIO_new_bio_pair(WOLFSSL_BIO **bio1_p, size_t writebuf1,
+ WOLFSSL_BIO **bio2_p, size_t writebuf2)
+{
+ WOLFSSL_BIO *bio1 = NULL, *bio2 = NULL;
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_BIO_new_bio_pair()");
+
+ if (bio1_p == NULL || bio2_p == NULL) {
+ WOLFSSL_MSG("Bad Function Argument");
+ return BAD_FUNC_ARG;
+ }
+
+ /* set up the new bio structures and write buf sizes */
+ if ((bio1 = wolfSSL_BIO_new(wolfSSL_BIO_s_bio())) == NULL) {
+ WOLFSSL_MSG("Bio allocation failed");
+ ret = WOLFSSL_FAILURE;
+ }
+ if (ret) {
+ if ((bio2 = wolfSSL_BIO_new(wolfSSL_BIO_s_bio())) == NULL) {
+ WOLFSSL_MSG("Bio allocation failed");
+ ret = WOLFSSL_FAILURE;
+ }
+ }
+ if (ret && writebuf1) {
+ if (!(ret = wolfSSL_BIO_set_write_buf_size(bio1, writebuf1))) {
+ WOLFSSL_MSG("wolfSSL_BIO_set_write_buf() failure");
+ }
+ }
+ if (ret && writebuf2) {
+ if (!(ret = wolfSSL_BIO_set_write_buf_size(bio2, writebuf2))) {
+ WOLFSSL_MSG("wolfSSL_BIO_set_write_buf() failure");
+ }
+ }
+
+ if (ret) {
+ if ((ret = wolfSSL_BIO_make_bio_pair(bio1, bio2))) {
+ *bio1_p = bio1;
+ *bio2_p = bio2;
+ }
+ }
+ if (!ret) {
+ wolfSSL_BIO_free(bio1);
+ bio1 = NULL;
+ wolfSSL_BIO_free(bio2);
+ bio2 = NULL;
+ }
+ return ret;
+}
+
+
+#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \
+ !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+/* Converts an rsa key from a bio buffer into an internal rsa structure.
+Returns a pointer to the new WOLFSSL_RSA structure. */
+WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out)
+{
+ const unsigned char* bioMem = NULL;
+ int bioMemSz = 0;
+ WOLFSSL_RSA* key = NULL;
+ unsigned char maxKeyBuf[4096];
+ unsigned char* bufPtr = NULL;
+ unsigned char* extraBioMem = NULL;
+ int extraBioMemSz = 0;
+ int derLength = 0;
+ int j = 0, i = 0;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey_bio()");
+
+ if (bio == NULL) {
+ WOLFSSL_MSG("Bad Function Argument");
+ return NULL;
+ }
+ (void)out;
+
+ bioMemSz = wolfSSL_BIO_pending(bio);
+ if (bioMemSz <= 0) {
+ WOLFSSL_MSG("wolfSSL_BIO_pending() failure");
+ return NULL;
+ }
+
+ bioMem = (unsigned char*)XMALLOC(bioMemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (bioMem == NULL) {
+ WOLFSSL_MSG("Malloc failure");
+ return NULL;
+ }
+
+ bufPtr = maxKeyBuf;
+ if (wolfSSL_BIO_read(bio, (unsigned char*)bioMem, (int)bioMemSz) == bioMemSz) {
+ const byte* bioMemPt = bioMem; /* leave bioMem pointer unaltered */
+ if ((key = wolfSSL_d2i_RSAPrivateKey(NULL, &bioMemPt, bioMemSz)) == NULL) {
+ XFREE((unsigned char*)bioMem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return NULL;
+ }
+
+ /* This function is used to get the total length of the rsa key. */
+ derLength = wolfSSL_i2d_RSAPrivateKey(key, &bufPtr);
+
+ /* Write extra data back into bio object if necessary. */
+ extraBioMemSz = (bioMemSz - derLength);
+ if (extraBioMemSz > 0) {
+ extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (extraBioMem == NULL) {
+ WOLFSSL_MSG("Malloc failure");
+ XFREE((unsigned char*)extraBioMem, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE((unsigned char*)bioMem, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ return NULL;
+ }
+
+ for (i = derLength; i < bioMemSz; i++) {
+ *(extraBioMem + j) = *(bioMem + i);
+ j++;
+ }
+
+ wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz);
+ if (wolfSSL_BIO_pending(bio) <= 0) {
+ WOLFSSL_MSG("Failed to write memory to bio");
+ XFREE((unsigned char*)extraBioMem, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE((unsigned char*)bioMem, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ return NULL;
+ }
+ XFREE((unsigned char*)extraBioMem, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ }
+
+ if (out != NULL && key != NULL) {
+ *out = key;
+ }
+ }
+ XFREE((unsigned char*)bioMem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return key;
+}
+#endif
+
+
+/* Adds the ASN1 certificate to the user ctx.
+Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/
+int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX *ctx, int derSz,
+ const unsigned char *der)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_ASN1()");
+ if (der != NULL && ctx != NULL) {
+ if (wolfSSL_CTX_use_certificate_buffer(ctx, der, derSz,
+ WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS) {
+ return WOLFSSL_SUCCESS;
+ }
+
+ }
+ return WOLFSSL_FAILURE;
+}
+
+
+#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \
+ !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+/* Adds the rsa private key to the user ctx.
+Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/
+int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL_RSA* rsa)
+{
+ int ret;
+ int derSize;
+ unsigned char maxDerBuf[4096];
+ unsigned char* key = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey()");
+
+ if (ctx == NULL || rsa == NULL) {
+ WOLFSSL_MSG("one or more inputs were NULL");
+ return BAD_FUNC_ARG;
+ }
+ key = maxDerBuf;
+ /* convert RSA struct to der encoded buffer and get the size */
+ if ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, &key)) <= 0) {
+ WOLFSSL_MSG("wolfSSL_i2d_RSAPrivateKey() failure");
+ return WOLFSSL_FAILURE;
+ }
+ ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, (const unsigned char*)maxDerBuf,
+ derSize, SSL_FILETYPE_ASN1);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("wolfSSL_CTX_USE_PrivateKey_buffer() failure");
+ return WOLFSSL_FAILURE;
+ }
+ return ret;
+}
+#endif /* NO_RSA && !HAVE_FAST_RSA */
+
+
+/* Converts EVP_PKEY data from a bio buffer to a WOLFSSL_EVP_PKEY structure.
+Returns pointer to private EVP_PKEY struct upon success, NULL if there
+is a failure.*/
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO* bio,
+ WOLFSSL_EVP_PKEY** out)
+{
+ unsigned char* mem = NULL;
+ int memSz = 0;
+ WOLFSSL_EVP_PKEY* key = NULL;
+ int i = 0, j = 0;
+ unsigned char* extraBioMem = NULL;
+ int extraBioMemSz = 0;
+ int derLength = 0;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_bio()");
+
+ if (bio == NULL) {
+ return NULL;
+ }
+ (void)out;
+
+ memSz = wolfSSL_BIO_pending(bio);
+ if (memSz <= 0) {
+ WOLFSSL_MSG("wolfSSL_BIO_pending() failure");
+ return NULL;
+ }
+
+ mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (mem == NULL) {
+ WOLFSSL_MSG("Malloc failure");
+ return NULL;
+ }
+
+ if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) {
+ /* Determines key type and returns the new private EVP_PKEY object */
+ if ((key = wolfSSL_d2i_PrivateKey_EVP(NULL, &mem, (long)memSz)) == NULL) {
+ WOLFSSL_MSG("wolfSSL_d2i_PrivateKey_EVP() failure");
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return NULL;
+ }
+
+ /* Write extra data back into bio object if necessary. */
+ derLength = key->pkey_sz;
+ extraBioMemSz = (memSz - derLength);
+ if (extraBioMemSz > 0) {
+ extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (extraBioMem == NULL) {
+ WOLFSSL_MSG("Malloc failure");
+ XFREE((unsigned char*)extraBioMem, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return NULL;
+ }
+
+ for (i = derLength; i < memSz; i++) {
+ *(extraBioMem + j) = *(mem + i);
+ j++;
+ }
+
+ wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz);
+ if (wolfSSL_BIO_pending(bio) <= 0) {
+ WOLFSSL_MSG("Failed to write memory to bio");
+ XFREE((unsigned char*)extraBioMem, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return NULL;
+ }
+ XFREE((unsigned char*)extraBioMem, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ }
+
+ if (out != NULL) {
+ *out = key;
+ }
+ }
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return key;
+}
+
+
+/* Converts a DER encoded private key to a WOLFSSL_EVP_PKEY structure.
+ * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL
+ * on fail */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out,
+ unsigned char** in, long inSz)
+{
+ WOLFSSL_EVP_PKEY* pkey = NULL;
+ const unsigned char* mem;
+ long memSz = inSz;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_EVP()");
+
+ if (in == NULL || *in == NULL || inSz < 0) {
+ WOLFSSL_MSG("Bad argument");
+ return NULL;
+ }
+ mem = *in;
+
+ #if !defined(NO_RSA)
+ {
+ RsaKey rsa;
+ word32 keyIdx = 0;
+
+ /* test if RSA key */
+ if (wc_InitRsaKey(&rsa, NULL) == 0 &&
+ wc_RsaPrivateKeyDecode(mem, &keyIdx, &rsa, (word32)memSz) == 0) {
+ wc_FreeRsaKey(&rsa);
+ pkey = wolfSSL_EVP_PKEY_new();
+ if (pkey != NULL) {
+ pkey->pkey_sz = keyIdx;
+ pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
+ DYNAMIC_TYPE_PRIVATE_KEY);
+ if (pkey->pkey.ptr == NULL) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+ XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+ pkey->type = EVP_PKEY_RSA;
+ if (out != NULL) {
+ *out = pkey;
+ }
+
+ pkey->ownRsa = 1;
+ pkey->rsa = wolfSSL_RSA_new();
+ if (pkey->rsa == NULL) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+
+ if (wolfSSL_RSA_LoadDer_ex(pkey->rsa,
+ (const unsigned char*)pkey->pkey.ptr,
+ pkey->pkey_sz, WOLFSSL_RSA_LOAD_PRIVATE) != 1) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+
+ return pkey;
+ }
+ }
+ wc_FreeRsaKey(&rsa);
+ }
+ #endif /* NO_RSA */
+
+ #ifdef HAVE_ECC
+ {
+ word32 keyIdx = 0;
+ ecc_key ecc;
+
+ /* test if ecc key */
+ if (wc_ecc_init(&ecc) == 0 &&
+ wc_EccPrivateKeyDecode(mem, &keyIdx, &ecc, (word32)memSz) == 0) {
+ wc_ecc_free(&ecc);
+ pkey = wolfSSL_EVP_PKEY_new();
+ if (pkey != NULL) {
+ pkey->pkey_sz = keyIdx;
+ pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL,
+ DYNAMIC_TYPE_PRIVATE_KEY);
+ if (pkey->pkey.ptr == NULL) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ return NULL;
+ }
+ XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+ pkey->type = EVP_PKEY_EC;
+ if (out != NULL) {
+ *out = pkey;
+ }
+ return pkey;
+ }
+ }
+ wc_ecc_free(&ecc);
+ }
+ #endif /* HAVE_ECC */
+ return pkey;
+}
+#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT */
+
+
+/* stunnel compatibility functions*/
+#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \
+ defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \
+ defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH)))
+void wolfSSL_ERR_remove_thread_state(void* pid)
+{
+ (void) pid;
+ return;
+}
+
+#ifndef NO_FILESYSTEM
+/***TBD ***/
+void wolfSSL_print_all_errors_fp(XFILE fp)
+{
+ (void)fp;
+}
+#endif
+
+int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data)
+{
+ WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data");
+#ifdef HAVE_EX_DATA
+ if(session != NULL) {
+ return wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx, data);
+ }
+#else
+ (void)session;
+ (void)idx;
+ (void)data;
+#endif
+ return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1,
+ void* cb2, CRYPTO_free_func* cb3)
+{
+ WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_new_index");
+ (void)idx;
+ (void)cb1;
+ (void)cb2;
+ (void)cb3;
+ if (XSTRNCMP((const char*)data, "redirect index", 14) == 0) {
+ return 0;
+ }
+ else if (XSTRNCMP((const char*)data, "addr index", 10) == 0) {
+ return 1;
+ }
+ return WOLFSSL_FAILURE;
+}
+
+
+void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx)
+{
+ WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data");
+#ifdef HAVE_EX_DATA
+ if (session != NULL) {
+ return wolfSSL_CRYPTO_get_ex_data(&session->ex_data, idx);
+ }
+#else
+ (void)session;
+ (void)idx;
+#endif
+ return NULL;
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int),
+ void *(*r) (void *, size_t, const char *,
+ int), void (*f) (void *))
+{
+ (void) m;
+ (void) r;
+ (void) f;
+ WOLFSSL_ENTER("wolfSSL_CRYPTO_set_mem_ex_functions");
+ WOLFSSL_STUB("CRYPTO_set_mem_ex_functions");
+
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+
+void wolfSSL_CRYPTO_cleanup_all_ex_data(void){
+ WOLFSSL_ENTER("CRYPTO_cleanup_all_ex_data");
+}
+
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_DH *wolfSSL_DH_generate_parameters(int prime_len, int generator,
+ void (*callback) (int, int, void *), void *cb_arg)
+{
+ (void)prime_len;
+ (void)generator;
+ (void)callback;
+ (void)cb_arg;
+ WOLFSSL_ENTER("wolfSSL_DH_generate_parameters");
+ WOLFSSL_STUB("DH_generate_parameters");
+
+ return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH* dh, int prime_len, int generator,
+ void (*callback) (int, int, void *))
+{
+ (void)prime_len;
+ (void)generator;
+ (void)callback;
+ (void)dh;
+ WOLFSSL_ENTER("wolfSSL_DH_generate_parameters_ex");
+ WOLFSSL_STUB("DH_generate_parameters_ex");
+
+ return -1;
+}
+#endif
+
+void wolfSSL_ERR_load_crypto_strings(void)
+{
+ WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings");
+ /* Do nothing */
+ return;
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_FIPS_mode(void)
+{
+ WOLFSSL_ENTER("wolfSSL_FIPS_mode");
+ WOLFSSL_STUB("FIPS_mode");
+
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_FIPS_mode_set(int r)
+{
+ (void)r;
+ WOLFSSL_ENTER("wolfSSL_FIPS_mode_set");
+ WOLFSSL_STUB("FIPS_mode_set");
+
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_RAND_set_rand_method(const void *meth)
+{
+ (void) meth;
+ WOLFSSL_ENTER("wolfSSL_RAND_set_rand_method");
+ WOLFSSL_STUB("RAND_set_rand_method");
+
+ /* if implemented RAND_bytes and RAND_pseudo_bytes need updated
+ * those two functions will call the respective functions from meth */
+ return SSL_FAILURE;
+}
+#endif
+
+int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits)
+{
+ int ret = WOLFSSL_FAILURE;
+ WOLFSSL_ENTER("wolfSSL_CIPHER_get_bits");
+
+ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ (void)alg_bits;
+ if (c!= NULL)
+ ret = c->bits;
+ #else
+ if (c != NULL && c->ssl != NULL) {
+ ret = 8 * c->ssl->specs.key_size;
+ if (alg_bits != NULL) {
+ *alg_bits = ret;
+ }
+ }
+ #endif
+ return ret;
+}
+
+#if defined(OPENSSL_ALL)
+WOLFSSL_X509_INFO* wolfSSL_X509_INFO_new(void)
+{
+ WOLFSSL_X509_INFO* info;
+ info = (WOLFSSL_X509_INFO*)XMALLOC(sizeof(WOLFSSL_X509_INFO), NULL,
+ DYNAMIC_TYPE_X509);
+ if (info) {
+ XMEMSET(info, 0, sizeof(*info));
+ }
+ return info;
+}
+
+void wolfSSL_X509_INFO_free(WOLFSSL_X509_INFO* info)
+{
+ if (info == NULL)
+ return;
+
+ if (info->x509) {
+ wolfSSL_X509_free(info->x509);
+ info->x509 = NULL;
+ }
+#ifdef HAVE_CRL
+ if (info->crl) {
+ wolfSSL_X509_CRL_free(info->crl);
+ info->crl = NULL;
+ }
+#endif
+ wolfSSL_X509_PKEY_free(info->x_pkey);
+ info->x_pkey = NULL;
+
+ XFREE(info, NULL, DYNAMIC_TYPE_X509);
+}
+#endif
+
+WOLFSSL_STACK* wolfSSL_sk_X509_INFO_new_null(void)
+{
+ WOLFSSL_STACK* sk = wolfSSL_sk_new_node(NULL);
+ if (sk) {
+ sk->type = STACK_TYPE_X509_INFO;
+ }
+ return sk;
+}
+
+
+/* returns value less than 0 on fail to match
+ * On a successful match the priority level found is returned
+ */
+int wolfSSL_sk_SSL_CIPHER_find(
+ WOLF_STACK_OF(WOLFSSL_CIPHER)* sk, const WOLFSSL_CIPHER* toFind)
+{
+ WOLFSSL_STACK* next;
+ int i, sz;
+
+ if (sk == NULL || toFind == NULL) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ sz = wolfSSL_sk_SSL_CIPHER_num(sk);
+ next = sk;
+ for (i = 0; i < sz && next != NULL; i++) {
+ if (next->data.cipher.cipherSuite0 == toFind->cipherSuite0 &&
+ next->data.cipher.cipherSuite == toFind->cipherSuite) {
+ return sz - i; /* reverse because stack pushed highest on first */
+ }
+ next = next->next;
+ }
+ return WOLFSSL_FATAL_ERROR;
+}
+
+
+/* copies over data of "in" to "out" */
+static void wolfSSL_CIPHER_copy(WOLFSSL_CIPHER* in, WOLFSSL_CIPHER* out)
+{
+ if (in == NULL || out == NULL)
+ return;
+
+ out->cipherSuite = in->cipherSuite;
+ out->cipherSuite0 = in->cipherSuite0;
+}
+
+
+/* create duplicate of stack and return the new stack
+ * returns null on failure */
+WOLF_STACK_OF(WOLFSSL_CIPHER)* wolfSSL_sk_SSL_CIPHER_dup(
+ WOLF_STACK_OF(WOLFSSL_CIPHER)* in)
+{
+ WOLFSSL_STACK* current;
+ WOLF_STACK_OF(WOLFSSL_CIPHER)* ret = NULL;
+ int i, sz;
+
+ sz = wolfSSL_sk_SSL_CIPHER_num(in);
+ current = in;
+ for (i = 0; i < sz && current != NULL; i++) {
+ WOLFSSL_STACK* add = wolfSSL_sk_new_node(in->heap);
+ if (add != NULL) {
+ add->type = STACK_TYPE_CIPHER;
+ wolfSSL_CIPHER_copy(&(current->data.cipher), &(add->data.cipher));
+ add->num = i+1;
+ add->next = ret;
+ ret = add;
+ current = current->next;
+ }
+ }
+ return ret;
+}
+
+/* nothing to do yet */
+static void wolfSSL_CIPHER_free(WOLFSSL_CIPHER* in)
+{
+ (void)in;
+}
+
+
+/* free's all nodes in the stack and there data */
+void wolfSSL_sk_SSL_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
+{
+ WOLFSSL_STACK* current = sk;
+
+ while (current != NULL) {
+ WOLFSSL_STACK* toFree = current;
+ current = current->next;
+
+ wolfSSL_CIPHER_free(&(toFree->data.cipher));
+ wolfSSL_sk_free_node(toFree);
+ }
+}
+
+
+int wolfSSL_sk_X509_INFO_num(const WOLF_STACK_OF(WOLFSSL_X509_INFO) *sk)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_X509_INFO_num");
+
+ if (sk == NULL)
+ return -1;
+ return (int)sk->num;
+}
+
+WOLFSSL_X509_INFO* wolfSSL_sk_X509_INFO_value(const WOLF_STACK_OF(WOLFSSL_X509_INFO) *sk, int i)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_X509_INFO_value");
+
+ for (; sk != NULL && i > 0; i--)
+ sk = sk->next;
+
+ if (i != 0 || sk == NULL)
+ return NULL;
+ return sk->data.info;
+}
+
+WOLFSSL_X509_INFO* wolfSSL_sk_X509_INFO_pop(WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk)
+{
+ WOLFSSL_STACK* node;
+ WOLFSSL_X509_INFO* info;
+
+ if (sk == NULL) {
+ return NULL;
+ }
+
+ node = sk->next;
+ info = sk->data.info;
+
+ if (node != NULL) { /* update sk and remove node from stack */
+ sk->data.info = node->data.info;
+ sk->next = node->next;
+ XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+ else { /* last x509 in stack */
+ sk->data.info = NULL;
+ }
+
+ if (sk->num > 0) {
+ sk->num -= 1;
+ }
+
+ return info;
+}
+
+#if defined(OPENSSL_ALL)
+void wolfSSL_sk_X509_INFO_pop_free(WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk,
+ void (*f) (WOLFSSL_X509_INFO*))
+{
+ WOLFSSL_STACK* node;
+
+ WOLFSSL_ENTER("wolfSSL_sk_X509_INFO_pop_free");
+
+ if (sk == NULL) {
+ return;
+ }
+
+ /* parse through stack freeing each node */
+ node = sk->next;
+ while (node && sk->num > 1) {
+ WOLFSSL_STACK* tmp = node;
+ node = node->next;
+
+ if (f)
+ f(tmp->data.info);
+ else
+ wolfSSL_X509_INFO_free(tmp->data.info);
+ tmp->data.info = NULL;
+ XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+ sk->num -= 1;
+ }
+
+ /* free head of stack */
+ if (sk->num == 1) {
+ if (f)
+ f(sk->data.info);
+ else
+ wolfSSL_X509_INFO_free(sk->data.info);
+ sk->data.info = NULL;
+ }
+ XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+void wolfSSL_sk_X509_INFO_free(WOLF_STACK_OF(WOLFSSL_X509_INFO) *sk)
+{
+ wolfSSL_sk_X509_INFO_pop_free(sk, NULL);
+}
+
+
+/* Adds the WOLFSSL_X509_INFO to the stack "sk". "sk" takes control of "in" and
+ * tries to free it when the stack is free'd.
+ *
+ * return 1 on success 0 on fail
+ */
+int wolfSSL_sk_X509_INFO_push(WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk,
+ WOLFSSL_X509_INFO* in)
+{
+ WOLFSSL_STACK* node;
+
+ if (sk == NULL || in == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* no previous values in stack */
+ if (sk->data.info == NULL) {
+ sk->data.info = in;
+ sk->num += 1;
+ return WOLFSSL_SUCCESS;
+ }
+
+ /* stack already has value(s) create a new node and add more */
+ node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+ DYNAMIC_TYPE_X509);
+ if (node == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return WOLFSSL_FAILURE;
+ }
+ XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+ /* push new obj onto head of stack */
+ node->data.info = sk->data.info;
+ node->next = sk->next;
+ node->type = sk->type;
+ sk->next = node;
+ sk->data.info = in;
+ sk->num += 1;
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_sk_X509_NAME_new(wolf_sk_compare_cb cb)
+{
+ WOLFSSL_STACK* sk;
+
+ WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_new");
+
+ sk = wolfSSL_sk_new_node(NULL);
+ if (sk != NULL) {
+ sk->type = STACK_TYPE_X509_NAME;
+ sk->comp = cb;
+ }
+
+ return sk;
+}
+
+int wolfSSL_sk_X509_NAME_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk,
+ WOLFSSL_X509_NAME* name)
+{
+ WOLFSSL_STACK* node;
+
+ WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_push");
+
+ if (sk == NULL || name == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* no previous values in stack */
+ if (sk->data.name == NULL) {
+ sk->data.name = name;
+ sk->num += 1;
+ return 0;
+ }
+
+ /* stack already has value(s) create a new node and add more */
+ node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (node == NULL) {
+ WOLFSSL_MSG("Memory error");
+ return MEMORY_E;
+ }
+ XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+ /* push new obj onto head of stack */
+ node->data.name = sk->data.name;
+ node->next = sk->next;
+ sk->type = STACK_TYPE_X509_NAME;
+ sk->next = node;
+ sk->data.name = name;
+ sk->num += 1;
+
+ return 0;
+}
+
+/* return index of found, or negative to indicate not found */
+int wolfSSL_sk_X509_NAME_find(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk,
+ WOLFSSL_X509_NAME *name)
+{
+ int i;
+
+ WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_find");
+
+ if (sk == NULL)
+ return BAD_FUNC_ARG;
+
+ for (i = 0; sk; i++, sk = sk->next) {
+ if (wolfSSL_X509_NAME_cmp(sk->data.name, name) == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int wolfSSL_sk_X509_OBJECT_num(const WOLF_STACK_OF(WOLFSSL_X509_OBJECT) *s)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_X509_OBJECT_num");
+ if (s) {
+ return (int)s->num;
+ } else {
+ return 0;
+ }
+}
+
+
+int wolfSSL_sk_X509_NAME_set_cmp_func(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk,
+ wolf_sk_compare_cb cb)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_set_cmp_func");
+
+ if (sk == NULL)
+ return BAD_FUNC_ARG;
+
+ sk->comp = cb;
+ return 0;
+}
+#endif /* OPENSSL_ALL */
+
+int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num");
+
+ if (sk == NULL)
+ return BAD_FUNC_ARG;
+
+ return (int)sk->num;
+}
+
+/* Getter function for WOLFSSL_X509_NAME pointer
+ *
+ * sk is the stack to retrieve pointer from
+ * i is the index value in stack
+ *
+ * returns a pointer to a WOLFSSL_X509_NAME structure on success and NULL on
+ * fail
+ */
+WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_value(const STACK_OF(WOLFSSL_X509_NAME)* sk,
+ int i)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value");
+
+ for (; sk != NULL && i > 0; i--) {
+ sk = sk->next;
+ }
+
+ if (i != 0 || sk == NULL)
+ return NULL;
+
+ return sk->data.name;
+}
+
+WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk)
+{
+ WOLFSSL_STACK* node;
+ WOLFSSL_X509_NAME* name;
+
+ if (sk == NULL) {
+ return NULL;
+ }
+
+ node = sk->next;
+ name = sk->data.name;
+
+ if (node != NULL) { /* update sk and remove node from stack */
+ sk->data.name = node->data.name;
+ sk->next = node->next;
+ XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+ else { /* last x509 in stack */
+ sk->data.name = NULL;
+ }
+
+ if (sk->num > 0) {
+ sk->num -= 1;
+ }
+
+ return name;
+}
+
+void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk,
+ void (*f) (WOLFSSL_X509_NAME*))
+{
+ WOLFSSL_STACK* node;
+ WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_pop_free");
+
+ if (sk == NULL)
+ return;
+
+ node = sk->next;
+ while (node && sk->num > 1) {
+ WOLFSSL_STACK* tmp = node;
+ node = node->next;
+ if (f)
+ f(tmp->data.name);
+ else
+ wolfSSL_X509_NAME_free(tmp->data.name);
+ tmp->data.name = NULL;
+ XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+ sk->num -= 1;
+ }
+
+ /* free head of stack */
+ if (sk->num == 1) {
+ if (f)
+ f(sk->data.name);
+ else
+ wolfSSL_X509_NAME_free(sk->data.name);
+ sk->data.name = NULL;
+ }
+
+ XFREE(sk, sk->heap, DYNAMIC_TYPE_OPENSSL);
+}
+
+/* Free only the sk structure, NOT X509_NAME members */
+void wolfSSL_sk_X509_NAME_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk)
+{
+ WOLFSSL_STACK* node;
+ WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_free");
+
+ if (sk == NULL)
+ return;
+
+ node = sk->next;
+ while (sk->num > 1) {
+ WOLFSSL_STACK* tmp = node;
+ node = node->next;
+ XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+ sk->num -= 1;
+ }
+
+ XFREE(sk, sk->heap, DYNAMIC_TYPE_OPENSSL);
+}
+
+#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+/* Helper function for X509_NAME_print_ex. Sets *buf to string for domain
+ name attribute based on NID. Returns size of buf */
+static int get_dn_attr_by_nid(int n, const char** buf)
+{
+ int len = 0;
+ const char *str;
+
+ switch(n)
+ {
+ case NID_commonName :
+ str = "CN";
+ len = 2;
+ break;
+ case NID_countryName:
+ str = "C";
+ len = 1;
+ break;
+ case NID_localityName:
+ str = "L";
+ len = 1;
+ break;
+ case NID_stateOrProvinceName:
+ str = "ST";
+ len = 2;
+ break;
+ case NID_organizationName:
+ str = "O";
+ len = 1;
+ break;
+ case NID_organizationalUnitName:
+ str = "OU";
+ len = 2;
+ break;
+ case NID_emailAddress:
+ str = "emailAddress";
+ len = 12;
+ break;
+ default:
+ WOLFSSL_MSG("Attribute type not found");
+ str = NULL;
+
+ }
+ if (buf != NULL)
+ *buf = str;
+ return len;
+}
+#endif
+
+/*
+ * The BIO output of wolfSSL_X509_NAME_print_ex does NOT include the null terminator
+ */
+int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name,
+ int indent, unsigned long flags)
+{
+#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+ int count = 0, len = 0, totalSz = 0, tmpSz = 0;
+ char tmp[ASN_NAME_MAX];
+ char fullName[ASN_NAME_MAX];
+ const char *buf = NULL;
+ WOLFSSL_X509_NAME_ENTRY* ne;
+ WOLFSSL_ASN1_STRING* str;
+#endif
+ int i;
+ (void)flags;
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_print_ex");
+
+ for (i = 0; i < indent; i++) {
+ if (wolfSSL_BIO_write(bio, " ", 1) != 1)
+ return WOLFSSL_FAILURE;
+ }
+
+#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+ /* If XN_FLAG_DN_REV is present, print X509_NAME in reverse order */
+ if (flags == (XN_FLAG_RFC2253 & ~XN_FLAG_DN_REV)) {
+ fullName[0] = '\0';
+ count = wolfSSL_X509_NAME_entry_count(name);
+ for (i = 0; i < count; i++) {
+ ne = wolfSSL_X509_NAME_get_entry(name, count - i - 1);
+ if (ne == NULL)
+ return WOLFSSL_FAILURE;
+
+ str = wolfSSL_X509_NAME_ENTRY_get_data(ne);
+ if (str == NULL)
+ return WOLFSSL_FAILURE;
+
+ len = get_dn_attr_by_nid(ne->nid, &buf);
+ if (len == 0 || buf == NULL)
+ return WOLFSSL_FAILURE;
+
+ tmpSz = str->length + len + 2; /* + 2 for '=' and comma */
+ if (tmpSz > ASN_NAME_MAX) {
+ WOLFSSL_MSG("Size greater than ASN_NAME_MAX");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (i < count - 1) {
+ /* tmpSz+1 for last null char */
+ XSNPRINTF(tmp, tmpSz+1, "%s=%s,", buf, str->data);
+ XSTRNCAT(fullName, tmp, tmpSz);
+ }
+ else {
+ XSNPRINTF(tmp, tmpSz, "%s=%s", buf, str->data);
+ XSTRNCAT(fullName, tmp, tmpSz-1);
+ tmpSz--; /* Don't include null char in tmpSz */
+ }
+ totalSz += tmpSz;
+ }
+ if (wolfSSL_BIO_write(bio, fullName, totalSz) != totalSz)
+ return WOLFSSL_FAILURE;
+ return WOLFSSL_SUCCESS;
+ }
+#else
+ if (flags == XN_FLAG_RFC2253) {
+ if (wolfSSL_BIO_write(bio, name->name + 1, name->sz - 2)
+ != name->sz - 2)
+ return WOLFSSL_FAILURE;
+ }
+#endif /* WOLFSSL_APACHE_HTTPD || OPENSSL_ALL || WOLFSSL_NGINX */
+ else if (wolfSSL_BIO_write(bio, name->name, name->sz - 1) != name->sz - 1)
+ return WOLFSSL_FAILURE;
+
+ return WOLFSSL_SUCCESS;
+}
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(const WOLFSSL_X509* x)
+{
+ (void)x;
+ WOLFSSL_ENTER("wolfSSL_X509_get0_pubkey_bitstr");
+ WOLFSSL_STUB("X509_get0_pubkey_bitstr");
+
+ return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session)
+{
+ (void)ctx;
+ (void)session;
+ WOLFSSL_ENTER("wolfSSL_CTX_add_session");
+ WOLFSSL_STUB("SSL_CTX_add_session");
+
+ return WOLFSSL_SUCCESS;
+}
+#endif
+
+
+int wolfSSL_version(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_version");
+ if (ssl->version.major == SSLv3_MAJOR) {
+ switch (ssl->version.minor) {
+ case SSLv3_MINOR :
+ return SSL3_VERSION;
+ case TLSv1_MINOR :
+ return TLS1_VERSION;
+ case TLSv1_1_MINOR :
+ return TLS1_1_VERSION;
+ case TLSv1_2_MINOR :
+ return TLS1_2_VERSION;
+ case TLSv1_3_MINOR :
+ return TLS1_3_VERSION;
+ default:
+ return WOLFSSL_FAILURE;
+ }
+ }
+ else if (ssl->version.major == DTLS_MAJOR) {
+ switch (ssl->version.minor) {
+ case DTLS_MINOR :
+ return DTLS1_VERSION;
+ case DTLSv1_2_MINOR :
+ return DTLS1_2_VERSION;
+ default:
+ return WOLFSSL_FAILURE;
+ }
+ }
+ return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME* name)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_get_sz");
+ if(!name)
+ return -1;
+ return name->sz;
+}
+
+#ifdef HAVE_SNI
+int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name)
+{
+ int ret;
+ WOLFSSL_ENTER("wolfSSL_set_tlsext_host_name");
+ ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME,
+ host_name, (word16)XSTRLEN(host_name));
+ WOLFSSL_LEAVE("wolfSSL_set_tlsext_host_name", ret);
+ return ret;
+}
+
+
+#ifndef NO_WOLFSSL_SERVER
+const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type)
+{
+ void * serverName = NULL;
+ if (ssl == NULL)
+ return NULL;
+ TLSX_SNI_GetRequest(ssl->extensions, type, &serverName);
+ return (const char *)serverName;
+}
+#endif /* NO_WOLFSSL_SERVER */
+#endif /* HAVE_SNI */
+
+WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
+{
+ if (ssl && ctx && SetSSL_CTX(ssl, ctx, 0) == WOLFSSL_SUCCESS)
+ return ssl->ctx;
+ return NULL;
+}
+
+
+VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_get_verify_callback");
+ if(ctx)
+ return ctx->verifyCallback;
+ return NULL;
+}
+
+
+void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback");
+ if (ctx)
+ ctx->sniRecvCb = cb;
+}
+
+int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx,
+ CallbackSniRecv cb)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_tlsext_servername_callback");
+ if (ctx) {
+ ctx->sniRecvCb = cb;
+ return WOLFSSL_SUCCESS;
+ }
+ return WOLFSSL_FAILURE;
+}
+
+int wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg");
+ if (ctx) {
+ ctx->sniRecvCbArg = arg;
+ return WOLFSSL_SUCCESS;
+ }
+ return WOLFSSL_FAILURE;
+}
+
+void wolfSSL_ERR_load_BIO_strings(void) {
+ WOLFSSL_ENTER("ERR_load_BIO_strings");
+ /* do nothing */
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_THREADID_set_callback(void(*threadid_func)(void*))
+{
+ WOLFSSL_ENTER("wolfSSL_THREADID_set_callback");
+ WOLFSSL_STUB("CRYPTO_THREADID_set_callback");
+ (void)threadid_func;
+ return;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_THREADID_set_numeric(void* id, unsigned long val)
+{
+ WOLFSSL_ENTER("wolfSSL_THREADID_set_numeric");
+ WOLFSSL_STUB("CRYPTO_THREADID_set_numeric");
+ (void)id;
+ (void)val;
+ return;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(
+ WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_NAME* name)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_get1_certs");
+ WOLFSSL_STUB("X509_STORE_get1_certs");
+ (void)ctx;
+ (void)name;
+ return NULL;
+}
+
+WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects(
+ WOLFSSL_X509_STORE* store)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_STORE_get0_objects");
+ WOLFSSL_STUB("wolfSSL_X509_STORE_get0_objects");
+ (void)store;
+ return NULL;
+}
+
+WOLFSSL_X509_OBJECT* wolfSSL_sk_X509_OBJECT_delete(
+ WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* sk, int i)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_X509_OBJECT_delete");
+ WOLFSSL_STUB("wolfSSL_sk_X509_OBJECT_delete");
+ (void)sk;
+ (void)i;
+ return NULL;
+}
+
+void wolfSSL_X509_OBJECT_free(WOLFSSL_X509_OBJECT *a)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_OBJECT_free");
+ WOLFSSL_STUB("wolfSSL_X509_OBJECT_free");
+ (void)a;
+}
+
+#endif
+
+
+#endif /* OPENSSL_ALL || (OPENSSL_EXTRA && (HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_LIGHTY)) */
+
+
+#if defined(OPENSSL_EXTRA)
+
+int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_X509_num");
+
+ if (s == NULL)
+ return -1;
+ return (int)s->num;
+}
+
+unsigned long wolfSSL_ERR_peek_last_error(void)
+{
+ WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error");
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_NGINX)
+ {
+ int ret;
+
+ if ((ret = wc_PeekErrorNode(-1, NULL, NULL, NULL)) < 0) {
+ WOLFSSL_MSG("Issue peeking at error node in queue");
+ return 0;
+ }
+ if (ret == -ASN_NO_PEM_HEADER)
+ return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
+ return (unsigned long)ret;
+ }
+#else
+ return (unsigned long)(0 - NOT_COMPILED_IN);
+#endif
+}
+
+#endif /* OPENSSL_EXTRA */
+
+WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_get_SSL_CTX");
+ return ssl->ctx;
+}
+
+#if defined(OPENSSL_ALL) || \
+ defined(OPENSSL_EXTRA) || defined(HAVE_STUNNEL) || \
+ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+
+const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen)
+{
+ WOLFSSL_ENTER("wolfSSL_SESSION_get_id");
+ if(!sess || !idLen) {
+ WOLFSSL_MSG("Bad func args. Please provide idLen");
+ return NULL;
+ }
+ *idLen = sess->sessionIDSz;
+ return sess->sessionID;
+}
+
+#if (defined(HAVE_SESSION_TICKET) || defined(SESSION_CERTS)) && \
+ !defined(NO_FILESYSTEM)
+
+#if defined(SESSION_CERTS) || \
+ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+/* returns a pointer to the protocol used by the session */
+static const char* wolfSSL_SESSION_get_protocol(const WOLFSSL_SESSION* in)
+{
+ return wolfSSL_internal_get_version((ProtocolVersion*)&in->version);
+}
+#endif
+
+/* returns true (non 0) if the session has EMS (extended master secret) */
+static int wolfSSL_SESSION_haveEMS(const WOLFSSL_SESSION* in)
+{
+ if (in == NULL)
+ return 0;
+ return in->haveEMS;
+}
+
+#if defined(HAVE_SESSION_TICKET)
+/* prints out the ticket to bio passed in
+ * return WOLFSSL_SUCCESS on success
+ */
+static int wolfSSL_SESSION_print_ticket(WOLFSSL_BIO* bio,
+ const WOLFSSL_SESSION* in, const char* tab)
+{
+ unsigned short i, j, z, sz;
+ short tag = 0;
+ byte* pt;
+
+
+ if (in == NULL || bio == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ sz = in->ticketLen;
+ pt = in->ticket;
+
+ if (wolfSSL_BIO_printf(bio, "%s\n", (sz == 0)? " NONE": "") <= 0)
+ return WOLFSSL_FAILURE;
+
+ for (i = 0; i < sz;) {
+ char asc[16];
+
+ if (sz - i < 16) {
+ if (wolfSSL_BIO_printf(bio, "%s%04X -", tab, tag + (sz - i)) <= 0)
+ return WOLFSSL_FAILURE;
+ }
+ else {
+ if (wolfSSL_BIO_printf(bio, "%s%04X -", tab, tag) <= 0)
+ return WOLFSSL_FAILURE;
+ }
+ for (j = 0; i < sz && j < 8; j++,i++) {
+ asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.';
+ if (wolfSSL_BIO_printf(bio, " %02X", pt[i]) <= 0)
+ return WOLFSSL_FAILURE;
+ }
+
+ if (i < sz) {
+ asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.';
+ if (wolfSSL_BIO_printf(bio, "-%02X", pt[i]) <= 0)
+ return WOLFSSL_FAILURE;
+ j++;
+ i++;
+ }
+
+ for (; i < sz && j < 16; j++,i++) {
+ asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.';
+ if (wolfSSL_BIO_printf(bio, " %02X", pt[i]) <= 0)
+ return WOLFSSL_FAILURE;
+ }
+
+ /* pad out spacing */
+ for (z = j; z < 17; z++) {
+ if (wolfSSL_BIO_printf(bio, " ") <= 0)
+ return WOLFSSL_FAILURE;
+ }
+
+ for (z = 0; z < j; z++) {
+ if (wolfSSL_BIO_printf(bio, "%c", asc[z]) <= 0)
+ return WOLFSSL_FAILURE;
+ }
+ if (wolfSSL_BIO_printf(bio, "\n") <= 0)
+ return WOLFSSL_FAILURE;
+
+ tag += 16;
+ }
+ return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_SESSION_TICKET */
+
+
+/* prints out the session information in human readable form
+ * return WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_SESSION_print(WOLFSSL_BIO *bp, const WOLFSSL_SESSION *x)
+{
+ const unsigned char* pt;
+ unsigned char buf[SECRET_LEN];
+ unsigned int sz = 0, i;
+ int ret;
+ WOLFSSL_SESSION* session = (WOLFSSL_SESSION*)x;
+
+ if (session == NULL) {
+ WOLFSSL_MSG("Bad NULL argument");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_BIO_printf(bp, "%s\n", "SSL-Session:") <= 0)
+ return WOLFSSL_FAILURE;
+
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+ defined(HAVE_SESSION_TICKET))
+ if (wolfSSL_BIO_printf(bp, " Protocol : %s\n",
+ wolfSSL_SESSION_get_protocol(session)) <= 0)
+ return WOLFSSL_FAILURE;
+#endif
+
+ if (wolfSSL_BIO_printf(bp, " Cipher : %s\n",
+ wolfSSL_SESSION_CIPHER_get_name(session)) <= 0)
+ return WOLFSSL_FAILURE;
+
+ pt = wolfSSL_SESSION_get_id(session, &sz);
+ if (wolfSSL_BIO_printf(bp, " Session-ID: ") <= 0)
+ return WOLFSSL_FAILURE;
+
+ for (i = 0; i < sz; i++) {
+ if (wolfSSL_BIO_printf(bp, "%02X", pt[i]) <= 0)
+ return WOLFSSL_FAILURE;
+ }
+ if (wolfSSL_BIO_printf(bp, "\n") <= 0)
+ return WOLFSSL_FAILURE;
+
+ if (wolfSSL_BIO_printf(bp, " Session-ID-ctx: \n") <= 0)
+ return WOLFSSL_FAILURE;
+
+ ret = wolfSSL_SESSION_get_master_key(x, buf, sizeof(buf));
+ if (wolfSSL_BIO_printf(bp, " Master-Key: ") <= 0)
+ return WOLFSSL_FAILURE;
+
+ if (ret > 0) {
+ sz = (unsigned int)ret;
+ for (i = 0; i < sz; i++) {
+ if (wolfSSL_BIO_printf(bp, "%02X", buf[i]) <= 0)
+ return WOLFSSL_FAILURE;
+ }
+ }
+ if (wolfSSL_BIO_printf(bp, "\n") <= 0)
+ return WOLFSSL_FAILURE;
+
+ /* @TODO PSK identity hint and SRP */
+
+ if (wolfSSL_BIO_printf(bp, " TLS session ticket:") <= 0)
+ return WOLFSSL_FAILURE;
+
+#ifdef HAVE_SESSION_TICKET
+ if (wolfSSL_SESSION_print_ticket(bp, x, " ") != WOLFSSL_SUCCESS)
+ return WOLFSSL_FAILURE;
+#endif
+
+ if (wolfSSL_BIO_printf(bp, " Start Time: %ld\n",
+ wolfSSL_SESSION_get_time(x)) <= 0)
+ return WOLFSSL_FAILURE;
+
+ if (wolfSSL_BIO_printf(bp, " Timeout : %ld (sec)\n",
+ wolfSSL_SESSION_get_timeout(x)) <= 0)
+ return WOLFSSL_FAILURE;
+
+ /* @TODO verify return code print */
+
+ if (wolfSSL_BIO_printf(bp, " Extended master secret: %s\n",
+ (wolfSSL_SESSION_haveEMS(session) == 0)? "no" : "yes") <= 0)
+ return WOLFSSL_FAILURE;
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* (HAVE_SESSION_TICKET || SESSION_CERTS) && !NO_FILESYSTEM */
+
+#endif /* OPENSSL_ALL || OPENSSL_EXTRA || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \
+ || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX)
+
+int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx)
+{
+ int mode = 0;
+ WOLFSSL_ENTER("wolfSSL_CTX_get_verify_mode");
+
+ if(!ctx)
+ return WOLFSSL_FATAL_ERROR;
+
+ if (ctx->verifyPeer)
+ mode |= WOLFSSL_VERIFY_PEER;
+ else if (ctx->verifyNone)
+ mode |= WOLFSSL_VERIFY_NONE;
+
+ if (ctx->failNoCert)
+ mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+
+ if (ctx->failNoCertxPSK)
+ mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK;
+
+ WOLFSSL_LEAVE("wolfSSL_CTX_get_verify_mode", mode);
+ return mode;
+}
+
+#endif
+#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE25519)
+/* return 1 if success, 0 if error
+ * output keys are little endian format
+ */
+int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz,
+ unsigned char *pub, unsigned int *pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+ WOLFSSL_MSG("No Key Gen built in");
+ (void) priv;
+ (void) privSz;
+ (void) pub;
+ (void) pubSz;
+ return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+ int ret = WOLFSSL_FAILURE;
+ int initTmpRng = 0;
+ WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG *tmpRNG = NULL;
+#else
+ WC_RNG tmpRNG[1];
+#endif
+
+ WOLFSSL_ENTER("wolfSSL_EC25519_generate_key");
+
+ if (priv == NULL || privSz == NULL || *privSz < CURVE25519_KEYSIZE ||
+ pub == NULL || pubSz == NULL || *pubSz < CURVE25519_KEYSIZE) {
+ WOLFSSL_MSG("Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (tmpRNG == NULL)
+ return WOLFSSL_FAILURE;
+#endif
+ if (wc_InitRng(tmpRNG) == 0) {
+ rng = tmpRNG;
+ initTmpRng = 1;
+ }
+ else {
+ WOLFSSL_MSG("Bad RNG Init, trying global");
+ if (initGlobalRNG == 0)
+ WOLFSSL_MSG("Global RNG no Init");
+ else
+ rng = &globalRNG;
+ }
+
+ if (rng) {
+ curve25519_key key;
+
+ if (wc_curve25519_init(&key) != MP_OKAY)
+ WOLFSSL_MSG("wc_curve25519_init failed");
+ else if (wc_curve25519_make_key(rng, CURVE25519_KEYSIZE, &key)!=MP_OKAY)
+ WOLFSSL_MSG("wc_curve25519_make_key failed");
+ /* export key pair */
+ else if (wc_curve25519_export_key_raw_ex(&key, priv, privSz, pub,
+ pubSz, EC25519_LITTLE_ENDIAN)
+ != MP_OKAY)
+ WOLFSSL_MSG("wc_curve25519_export_key_raw_ex failed");
+ else
+ ret = WOLFSSL_SUCCESS;
+
+ wc_curve25519_free(&key);
+ }
+
+ if (initTmpRng)
+ wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+ return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ */
+int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz,
+ const unsigned char *priv, unsigned int privSz,
+ const unsigned char *pub, unsigned int pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+ WOLFSSL_MSG("No Key Gen built in");
+ (void) shared;
+ (void) sharedSz;
+ (void) priv;
+ (void) privSz;
+ (void) pub;
+ (void) pubSz;
+ return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+ int ret = WOLFSSL_FAILURE;
+ curve25519_key privkey, pubkey;
+
+ WOLFSSL_ENTER("wolfSSL_EC25519_shared_key");
+
+ if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE25519_KEYSIZE ||
+ priv == NULL || privSz < CURVE25519_KEYSIZE ||
+ pub == NULL || pubSz < CURVE25519_KEYSIZE) {
+ WOLFSSL_MSG("Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* import private key */
+ if (wc_curve25519_init(&privkey) != MP_OKAY) {
+ WOLFSSL_MSG("wc_curve25519_init privkey failed");
+ return ret;
+ }
+ if (wc_curve25519_import_private_ex(priv, privSz, &privkey,
+ EC25519_LITTLE_ENDIAN) != MP_OKAY) {
+ WOLFSSL_MSG("wc_curve25519_import_private_ex failed");
+ wc_curve25519_free(&privkey);
+ return ret;
+ }
+
+ /* import public key */
+ if (wc_curve25519_init(&pubkey) != MP_OKAY) {
+ WOLFSSL_MSG("wc_curve25519_init pubkey failed");
+ wc_curve25519_free(&privkey);
+ return ret;
+ }
+ if (wc_curve25519_import_public_ex(pub, pubSz, &pubkey,
+ EC25519_LITTLE_ENDIAN) != MP_OKAY) {
+ WOLFSSL_MSG("wc_curve25519_import_public_ex failed");
+ wc_curve25519_free(&privkey);
+ wc_curve25519_free(&pubkey);
+ return ret;
+ }
+
+ if (wc_curve25519_shared_secret_ex(&privkey, &pubkey,
+ shared, sharedSz,
+ EC25519_LITTLE_ENDIAN) != MP_OKAY)
+ WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed");
+ else
+ ret = WOLFSSL_SUCCESS;
+
+ wc_curve25519_free(&privkey);
+ wc_curve25519_free(&pubkey);
+
+ return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+#endif /* OPENSSL_EXTRA && HAVE_CURVE25519 */
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_ED25519)
+/* return 1 if success, 0 if error
+ * output keys are little endian format
+ */
+int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz,
+ unsigned char *pub, unsigned int *pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+ WOLFSSL_MSG("No Key Gen built in");
+ (void) priv;
+ (void) privSz;
+ (void) pub;
+ (void) pubSz;
+ return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+ int ret = WOLFSSL_FAILURE;
+ int initTmpRng = 0;
+ WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG *tmpRNG = NULL;
+#else
+ WC_RNG tmpRNG[1];
+#endif
+
+ WOLFSSL_ENTER("wolfSSL_ED25519_generate_key");
+
+ if (priv == NULL || privSz == NULL || *privSz < ED25519_PRV_KEY_SIZE ||
+ pub == NULL || pubSz == NULL || *pubSz < ED25519_PUB_KEY_SIZE) {
+ WOLFSSL_MSG("Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (tmpRNG == NULL)
+ return WOLFSSL_FATAL_ERROR;
+#endif
+ if (wc_InitRng(tmpRNG) == 0) {
+ rng = tmpRNG;
+ initTmpRng = 1;
+ }
+ else {
+ WOLFSSL_MSG("Bad RNG Init, trying global");
+ if (initGlobalRNG == 0)
+ WOLFSSL_MSG("Global RNG no Init");
+ else
+ rng = &globalRNG;
+ }
+
+ if (rng) {
+ ed25519_key key;
+
+ if (wc_ed25519_init(&key) != MP_OKAY)
+ WOLFSSL_MSG("wc_ed25519_init failed");
+ else if (wc_ed25519_make_key(rng, ED25519_KEY_SIZE, &key)!=MP_OKAY)
+ WOLFSSL_MSG("wc_ed25519_make_key failed");
+ /* export private key */
+ else if (wc_ed25519_export_key(&key, priv, privSz, pub, pubSz)!=MP_OKAY)
+ WOLFSSL_MSG("wc_ed25519_export_key failed");
+ else
+ ret = WOLFSSL_SUCCESS;
+
+ wc_ed25519_free(&key);
+ }
+
+ if (initTmpRng)
+ wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+ return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ * priv is a buffer containing private and public part of key
+ */
+int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz,
+ const unsigned char *priv, unsigned int privSz,
+ unsigned char *sig, unsigned int *sigSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+ WOLFSSL_MSG("No Key Gen built in");
+ (void) msg;
+ (void) msgSz;
+ (void) priv;
+ (void) privSz;
+ (void) sig;
+ (void) sigSz;
+ return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+ ed25519_key key;
+ int ret = WOLFSSL_FAILURE;
+
+ WOLFSSL_ENTER("wolfSSL_ED25519_sign");
+
+ if (priv == NULL || privSz != ED25519_PRV_KEY_SIZE ||
+ msg == NULL || sig == NULL || *sigSz < ED25519_SIG_SIZE) {
+ WOLFSSL_MSG("Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* import key */
+ if (wc_ed25519_init(&key) != MP_OKAY) {
+ WOLFSSL_MSG("wc_curve25519_init failed");
+ return ret;
+ }
+ if (wc_ed25519_import_private_key(priv, privSz/2,
+ priv+(privSz/2), ED25519_PUB_KEY_SIZE,
+ &key) != MP_OKAY){
+ WOLFSSL_MSG("wc_ed25519_import_private failed");
+ wc_ed25519_free(&key);
+ return ret;
+ }
+
+ if (wc_ed25519_sign_msg(msg, msgSz, sig, sigSz, &key) != MP_OKAY)
+ WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed");
+ else
+ ret = WOLFSSL_SUCCESS;
+
+ wc_ed25519_free(&key);
+
+ return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ * pub is a buffer containing public part of key
+ */
+int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz,
+ const unsigned char *pub, unsigned int pubSz,
+ const unsigned char *sig, unsigned int sigSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+ WOLFSSL_MSG("No Key Gen built in");
+ (void) msg;
+ (void) msgSz;
+ (void) pub;
+ (void) pubSz;
+ (void) sig;
+ (void) sigSz;
+ return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+ ed25519_key key;
+ int ret = WOLFSSL_FAILURE, check = 0;
+
+ WOLFSSL_ENTER("wolfSSL_ED25519_verify");
+
+ if (pub == NULL || pubSz != ED25519_PUB_KEY_SIZE ||
+ msg == NULL || sig == NULL || sigSz != ED25519_SIG_SIZE) {
+ WOLFSSL_MSG("Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* import key */
+ if (wc_ed25519_init(&key) != MP_OKAY) {
+ WOLFSSL_MSG("wc_curve25519_init failed");
+ return ret;
+ }
+ if (wc_ed25519_import_public(pub, pubSz, &key) != MP_OKAY){
+ WOLFSSL_MSG("wc_ed25519_import_public failed");
+ wc_ed25519_free(&key);
+ return ret;
+ }
+
+ if ((ret = wc_ed25519_verify_msg((byte*)sig, sigSz, msg, msgSz,
+ &check, &key)) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ed25519_verify_msg failed");
+ }
+ else if (!check)
+ WOLFSSL_MSG("wc_ed25519_verify_msg failed (signature invalid)");
+ else
+ ret = WOLFSSL_SUCCESS;
+
+ wc_ed25519_free(&key);
+
+ return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+#endif /* OPENSSL_EXTRA && HAVE_ED25519 */
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE448)
+/* return 1 if success, 0 if error
+ * output keys are little endian format
+ */
+int wolfSSL_EC448_generate_key(unsigned char *priv, unsigned int *privSz,
+ unsigned char *pub, unsigned int *pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+ WOLFSSL_MSG("No Key Gen built in");
+ (void) priv;
+ (void) privSz;
+ (void) pub;
+ (void) pubSz;
+ return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+ int ret = WOLFSSL_FAILURE;
+ int initTmpRng = 0;
+ WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG *tmpRNG = NULL;
+#else
+ WC_RNG tmpRNG[1];
+#endif
+
+ WOLFSSL_ENTER("wolfSSL_EC448_generate_key");
+
+ if (priv == NULL || privSz == NULL || *privSz < CURVE448_KEY_SIZE ||
+ pub == NULL || pubSz == NULL || *pubSz < CURVE448_KEY_SIZE) {
+ WOLFSSL_MSG("Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (tmpRNG == NULL)
+ return WOLFSSL_FAILURE;
+#endif
+ if (wc_InitRng(tmpRNG) == 0) {
+ rng = tmpRNG;
+ initTmpRng = 1;
+ }
+ else {
+ WOLFSSL_MSG("Bad RNG Init, trying global");
+ if (initGlobalRNG == 0)
+ WOLFSSL_MSG("Global RNG no Init");
+ else
+ rng = &globalRNG;
+ }
+
+ if (rng) {
+ curve448_key key;
+
+ if (wc_curve448_init(&key) != MP_OKAY)
+ WOLFSSL_MSG("wc_curve448_init failed");
+ else if (wc_curve448_make_key(rng, CURVE448_KEY_SIZE, &key)!=MP_OKAY)
+ WOLFSSL_MSG("wc_curve448_make_key failed");
+ /* export key pair */
+ else if (wc_curve448_export_key_raw_ex(&key, priv, privSz, pub, pubSz,
+ EC448_LITTLE_ENDIAN)
+ != MP_OKAY)
+ WOLFSSL_MSG("wc_curve448_export_key_raw_ex failed");
+ else
+ ret = WOLFSSL_SUCCESS;
+
+ wc_curve448_free(&key);
+ }
+
+ if (initTmpRng)
+ wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+ return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ */
+int wolfSSL_EC448_shared_key(unsigned char *shared, unsigned int *sharedSz,
+ const unsigned char *priv, unsigned int privSz,
+ const unsigned char *pub, unsigned int pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+ WOLFSSL_MSG("No Key Gen built in");
+ (void) shared;
+ (void) sharedSz;
+ (void) priv;
+ (void) privSz;
+ (void) pub;
+ (void) pubSz;
+ return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+ int ret = WOLFSSL_FAILURE;
+ curve448_key privkey, pubkey;
+
+ WOLFSSL_ENTER("wolfSSL_EC448_shared_key");
+
+ if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE448_KEY_SIZE ||
+ priv == NULL || privSz < CURVE448_KEY_SIZE ||
+ pub == NULL || pubSz < CURVE448_KEY_SIZE) {
+ WOLFSSL_MSG("Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* import private key */
+ if (wc_curve448_init(&privkey) != MP_OKAY) {
+ WOLFSSL_MSG("wc_curve448_init privkey failed");
+ return ret;
+ }
+ if (wc_curve448_import_private_ex(priv, privSz, &privkey,
+ EC448_LITTLE_ENDIAN) != MP_OKAY) {
+ WOLFSSL_MSG("wc_curve448_import_private_ex failed");
+ wc_curve448_free(&privkey);
+ return ret;
+ }
+
+ /* import public key */
+ if (wc_curve448_init(&pubkey) != MP_OKAY) {
+ WOLFSSL_MSG("wc_curve448_init pubkey failed");
+ wc_curve448_free(&privkey);
+ return ret;
+ }
+ if (wc_curve448_import_public_ex(pub, pubSz, &pubkey,
+ EC448_LITTLE_ENDIAN) != MP_OKAY) {
+ WOLFSSL_MSG("wc_curve448_import_public_ex failed");
+ wc_curve448_free(&privkey);
+ wc_curve448_free(&pubkey);
+ return ret;
+ }
+
+ if (wc_curve448_shared_secret_ex(&privkey, &pubkey, shared, sharedSz,
+ EC448_LITTLE_ENDIAN) != MP_OKAY)
+ WOLFSSL_MSG("wc_curve448_shared_secret_ex failed");
+ else
+ ret = WOLFSSL_SUCCESS;
+
+ wc_curve448_free(&privkey);
+ wc_curve448_free(&pubkey);
+
+ return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+#endif /* OPENSSL_EXTRA && HAVE_CURVE448 */
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_ED448)
+/* return 1 if success, 0 if error
+ * output keys are little endian format
+ */
+int wolfSSL_ED448_generate_key(unsigned char *priv, unsigned int *privSz,
+ unsigned char *pub, unsigned int *pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+ WOLFSSL_MSG("No Key Gen built in");
+ (void) priv;
+ (void) privSz;
+ (void) pub;
+ (void) pubSz;
+ return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+ int ret = WOLFSSL_FAILURE;
+ int initTmpRng = 0;
+ WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG *tmpRNG = NULL;
+#else
+ WC_RNG tmpRNG[1];
+#endif
+
+ WOLFSSL_ENTER("wolfSSL_ED448_generate_key");
+
+ if (priv == NULL || privSz == NULL || *privSz < ED448_PRV_KEY_SIZE ||
+ pub == NULL || pubSz == NULL || *pubSz < ED448_PUB_KEY_SIZE) {
+ WOLFSSL_MSG("Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (tmpRNG == NULL)
+ return WOLFSSL_FATAL_ERROR;
+#endif
+ if (wc_InitRng(tmpRNG) == 0) {
+ rng = tmpRNG;
+ initTmpRng = 1;
+ }
+ else {
+ WOLFSSL_MSG("Bad RNG Init, trying global");
+ if (initGlobalRNG == 0)
+ WOLFSSL_MSG("Global RNG no Init");
+ else
+ rng = &globalRNG;
+ }
+
+ if (rng) {
+ ed448_key key;
+
+ if (wc_ed448_init(&key) != MP_OKAY)
+ WOLFSSL_MSG("wc_ed448_init failed");
+ else if (wc_ed448_make_key(rng, ED448_KEY_SIZE, &key) != MP_OKAY)
+ WOLFSSL_MSG("wc_ed448_make_key failed");
+ /* export private key */
+ else if (wc_ed448_export_key(&key, priv, privSz, pub, pubSz) != MP_OKAY)
+ WOLFSSL_MSG("wc_ed448_export_key failed");
+ else
+ ret = WOLFSSL_SUCCESS;
+
+ wc_ed448_free(&key);
+ }
+
+ if (initTmpRng)
+ wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+ return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ * priv is a buffer containing private and public part of key
+ */
+int wolfSSL_ED448_sign(const unsigned char *msg, unsigned int msgSz,
+ const unsigned char *priv, unsigned int privSz,
+ unsigned char *sig, unsigned int *sigSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+ WOLFSSL_MSG("No Key Gen built in");
+ (void) msg;
+ (void) msgSz;
+ (void) priv;
+ (void) privSz;
+ (void) sig;
+ (void) sigSz;
+ return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+ ed448_key key;
+ int ret = WOLFSSL_FAILURE;
+
+ WOLFSSL_ENTER("wolfSSL_ED448_sign");
+
+ if (priv == NULL || privSz != ED448_PRV_KEY_SIZE || msg == NULL ||
+ sig == NULL || *sigSz < ED448_SIG_SIZE) {
+ WOLFSSL_MSG("Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* import key */
+ if (wc_ed448_init(&key) != MP_OKAY) {
+ WOLFSSL_MSG("wc_curve448_init failed");
+ return ret;
+ }
+ if (wc_ed448_import_private_key(priv, privSz/2, priv+(privSz/2),
+ ED448_PUB_KEY_SIZE, &key) != MP_OKAY){
+ WOLFSSL_MSG("wc_ed448_import_private failed");
+ wc_ed448_free(&key);
+ return ret;
+ }
+
+ if (wc_ed448_sign_msg(msg, msgSz, sig, sigSz, &key) != MP_OKAY)
+ WOLFSSL_MSG("wc_curve448_shared_secret_ex failed");
+ else
+ ret = WOLFSSL_SUCCESS;
+
+ wc_ed448_free(&key);
+
+ return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ * pub is a buffer containing public part of key
+ */
+int wolfSSL_ED448_verify(const unsigned char *msg, unsigned int msgSz,
+ const unsigned char *pub, unsigned int pubSz,
+ const unsigned char *sig, unsigned int sigSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+ WOLFSSL_MSG("No Key Gen built in");
+ (void) msg;
+ (void) msgSz;
+ (void) pub;
+ (void) pubSz;
+ (void) sig;
+ (void) sigSz;
+ return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+ ed448_key key;
+ int ret = WOLFSSL_FAILURE, check = 0;
+
+ WOLFSSL_ENTER("wolfSSL_ED448_verify");
+
+ if (pub == NULL || pubSz != ED448_PUB_KEY_SIZE || msg == NULL ||
+ sig == NULL || sigSz != ED448_SIG_SIZE) {
+ WOLFSSL_MSG("Bad arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* import key */
+ if (wc_ed448_init(&key) != MP_OKAY) {
+ WOLFSSL_MSG("wc_curve448_init failed");
+ return ret;
+ }
+ if (wc_ed448_import_public(pub, pubSz, &key) != MP_OKAY){
+ WOLFSSL_MSG("wc_ed448_import_public failed");
+ wc_ed448_free(&key);
+ return ret;
+ }
+
+ if ((ret = wc_ed448_verify_msg((byte*)sig, sigSz, msg, msgSz, &check,
+ &key)) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ed448_verify_msg failed");
+ }
+ else if (!check)
+ WOLFSSL_MSG("wc_ed448_verify_msg failed (signature invalid)");
+ else
+ ret = WOLFSSL_SUCCESS;
+
+ wc_ed448_free(&key);
+
+ return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+#endif /* OPENSSL_EXTRA && HAVE_ED448 */
+
+#ifdef WOLFSSL_JNI
+
+int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr)
+{
+ WOLFSSL_ENTER("wolfSSL_set_jobject");
+ if (ssl != NULL)
+ {
+ ssl->jObjectRef = objPtr;
+ return WOLFSSL_SUCCESS;
+ }
+ return WOLFSSL_FAILURE;
+}
+
+void* wolfSSL_get_jobject(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_get_jobject");
+ if (ssl != NULL)
+ return ssl->jObjectRef;
+ return NULL;
+}
+
+#endif /* WOLFSSL_JNI */
+
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents,
+ WOLF_EVENT_FLAG flags, int* eventCount)
+{
+ if (ctx == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ return wolfAsync_EventQueuePoll(&ctx->event_queue, NULL,
+ events, maxEvents, flags, eventCount);
+}
+
+int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags)
+{
+ int ret, eventCount = 0;
+ WOLF_EVENT* events[1];
+
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, ssl,
+ events, sizeof(events)/sizeof(*events), flags, &eventCount);
+ if (ret == 0) {
+ ret = eventCount;
+ }
+
+ return ret;
+}
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+#ifdef OPENSSL_EXTRA
+unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line,
+ const char **data, int *flags)
+{
+ WOLFSSL_ENTER("wolfSSL_ERR_peek_error_line_data");
+
+ (void)line;
+ (void)file;
+
+ /* No data or flags stored - error display only in Nginx. */
+ if (data != NULL) {
+ *data = "";
+ }
+ if (flags != NULL) {
+ *flags = 0;
+ }
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
+ defined(WOLFSSL_OPENSSH) || defined(WOLFSSL_HAPROXY) || \
+ defined(WOLFSSL_MYSQL_COMPATIBLE)
+ {
+ int ret = 0;
+
+ while (1) {
+ if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) {
+ WOLFSSL_MSG("Issue peeking at error node in queue");
+ return 0;
+ }
+ /* OpenSSL uses positive error codes */
+ if (ret < 0) {
+ ret = -ret;
+ }
+
+ if (ret == -ASN_NO_PEM_HEADER)
+ return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
+ if (ret != WANT_READ && ret != WANT_WRITE &&
+ ret != ZERO_RETURN && ret != WOLFSSL_ERROR_ZERO_RETURN &&
+ ret != SOCKET_PEER_CLOSED_E && ret != SOCKET_ERROR_E)
+ break;
+
+ wc_RemoveErrorNode(-1);
+ }
+
+ return (unsigned long)ret;
+ }
+#else
+ return (unsigned long)(0 - NOT_COMPILED_IN);
+#endif
+}
+#endif
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+
+/* returns a pointer to internal cipher suite list. Should not be free'd by
+ * caller.
+ */
+WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl)
+{
+ WOLF_STACK_OF(WOLFSSL_CIPHER)* ret = NULL;
+ Suites* suites;
+
+ WOLFSSL_ENTER("wolfSSL_get_ciphers_compat");
+ if (ssl == NULL || (ssl->suites == NULL && ssl->ctx->suites == NULL)) {
+ return NULL;
+ }
+
+ if (ssl->suites != NULL) {
+ suites = ssl->suites;
+ }
+ else {
+ suites = ssl->ctx->suites;
+ }
+
+ /* check if stack needs populated */
+ if (suites->stack == NULL) {
+ int i;
+ for (i = 0; i < suites->suiteSz; i+=2) {
+ WOLFSSL_STACK* add = wolfSSL_sk_new_node(ssl->heap);
+ if (add != NULL) {
+ add->type = STACK_TYPE_CIPHER;
+ add->data.cipher.cipherSuite0 = suites->suites[i];
+ add->data.cipher.cipherSuite = suites->suites[i+1];
+ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ /* in_stack is checked in wolfSSL_CIPHER_description */
+ add->data.cipher.in_stack = 1;
+ #endif
+
+ add->next = ret;
+ if (ret != NULL) {
+ add->num = ret->num + 1;
+ }
+ else {
+ add->num = 1;
+ }
+ ret = add;
+ }
+ }
+ suites->stack = ret;
+ }
+ return suites->stack;
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_OPENSSL_config(char *config_name)
+{
+ (void)config_name;
+ WOLFSSL_STUB("OPENSSL_config");
+}
+#endif /* !NO_WOLFSSL_STUB */
+#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \
+ || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY)
+int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, void *b, void *c)
+{
+ static int x509_idx = 0;
+
+ WOLFSSL_ENTER("wolfSSL_X509_get_ex_new_index");
+ (void)idx;
+ (void)arg;
+ (void)a;
+ (void)b;
+ (void)c;
+
+ return x509_idx++;
+}
+
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+void* wolfSSL_CRYPTO_get_ex_data(const WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data");
+#ifdef MAX_EX_DATA
+ if(ex_data && idx < MAX_EX_DATA && idx >= 0) {
+ return ex_data->ex_data[idx];
+ }
+#else
+ (void)ex_data;
+ (void)idx;
+#endif
+ return NULL;
+}
+
+int wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx, void *data)
+{
+ WOLFSSL_ENTER("wolfSSL_CRYPTO_set_ex_data");
+#ifdef MAX_EX_DATA
+ if (ex_data && idx < MAX_EX_DATA && idx >= 0) {
+ ex_data->ex_data[idx] = data;
+ return WOLFSSL_SUCCESS;
+ }
+#else
+ (void)ex_data;
+ (void)idx;
+ (void)data;
+#endif
+ return WOLFSSL_FAILURE;
+}
+#endif /* defined(HAVE_EX_DATA) || defined(FORTRESS) */
+
+void *wolfSSL_X509_get_ex_data(X509 *x509, int idx)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_get_ex_data");
+ #ifdef HAVE_EX_DATA
+ if (x509 != NULL) {
+ return wolfSSL_CRYPTO_get_ex_data(&x509->ex_data, idx);
+ }
+ #else
+ (void)x509;
+ (void)idx;
+ #endif
+ return NULL;
+}
+
+int wolfSSL_X509_set_ex_data(X509 *x509, int idx, void *data)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_set_ex_data");
+ #ifdef HAVE_EX_DATA
+ if (x509 != NULL)
+ {
+ return wolfSSL_CRYPTO_set_ex_data(&x509->ex_data, idx, data);
+ }
+ #else
+ (void)x509;
+ (void)idx;
+ (void)data;
+ #endif
+ return WOLFSSL_FAILURE;
+}
+
+int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *name,
+ const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_NAME_digest");
+
+ if (name == NULL || type == NULL)
+ return WOLFSSL_FAILURE;
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_PWDBASED)
+ return wolfSSL_EVP_Digest((unsigned char*)name->fullName.fullName,
+ name->fullName.fullNameLen, md, len, type, NULL);
+#else
+ (void)md;
+ (void)len;
+ return NOT_COMPILED_IN;
+#endif
+}
+
+long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_timeout");
+
+ if (ctx == NULL)
+ return 0;
+
+ return ctx->timeout;
+}
+
+
+/* returns the time in seconds of the current timeout */
+long wolfSSL_get_timeout(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_get_timeout");
+
+ if (ssl == NULL)
+ return 0;
+ return ssl->timeout;
+}
+
+#ifdef HAVE_ECC
+int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, WOLFSSL_EC_KEY *ecdh)
+{
+ WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_tmp_ecdh");
+
+ if (ctx == NULL || ecdh == NULL)
+ return BAD_FUNC_ARG;
+
+ ctx->ecdhCurveOID = ecdh->group->curve_oid;
+
+ return WOLFSSL_SUCCESS;
+}
+#endif
+
+/* Assumes that the session passed in is from the cache. */
+int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s)
+{
+ WOLFSSL_ENTER("wolfSSL_SSL_CTX_remove_session");
+
+ if (ctx == NULL || s == NULL)
+ return BAD_FUNC_ARG;
+
+#ifdef HAVE_EXT_CACHE
+ if (!ctx->internalCacheOff)
+#endif
+ {
+ /* Don't remove session just timeout session. */
+ s->timeout = 0;
+ }
+
+#ifdef HAVE_EXT_CACHE
+ if (ctx->rem_sess_cb != NULL)
+ ctx->rem_sess_cb(ctx, s);
+#endif
+
+ return 0;
+}
+
+BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s)
+{
+ WOLFSSL_ENTER("wolfSSL_SSL_get_rbio");
+ /* Nginx sets the buffer size if the read BIO is different to write BIO.
+ * The setting buffer size doesn't do anything so return NULL for both.
+ */
+ if (s == NULL)
+ return NULL;
+
+ return s->biord;
+}
+BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s)
+{
+ WOLFSSL_ENTER("wolfSSL_SSL_get_wbio");
+ (void)s;
+ /* Nginx sets the buffer size if the read BIO is different to write BIO.
+ * The setting buffer size doesn't do anything so return NULL for both.
+ */
+ if (s == NULL)
+ return NULL;
+
+ return s->biowr;
+}
+
+int wolfSSL_SSL_do_handshake(WOLFSSL *s)
+{
+ WOLFSSL_ENTER("wolfSSL_SSL_do_handshake");
+
+ if (s == NULL)
+ return WOLFSSL_FAILURE;
+
+ if (s->options.side == WOLFSSL_CLIENT_END) {
+ #ifndef NO_WOLFSSL_CLIENT
+ return wolfSSL_connect(s);
+ #else
+ WOLFSSL_MSG("Client not compiled in");
+ return WOLFSSL_FAILURE;
+ #endif
+ }
+
+#ifndef NO_WOLFSSL_SERVER
+ return wolfSSL_accept(s);
+#else
+ WOLFSSL_MSG("Server not compiled in");
+ return WOLFSSL_FAILURE;
+#endif
+}
+
+int wolfSSL_SSL_in_init(WOLFSSL *ssl)
+{
+ WOLFSSL_ENTER("SSL_in_init");
+
+ if (ssl == NULL)
+ return WOLFSSL_FAILURE;
+
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ return ssl->options.connectState < SECOND_REPLY_DONE;
+ }
+ return ssl->options.acceptState < ACCEPT_THIRD_REPLY_DONE;
+}
+
+int wolfSSL_SSL_in_connect_init(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("SSL_connect_init");
+
+ if (ssl == NULL)
+ return WOLFSSL_FAILURE;
+
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ return ssl->options.connectState > CONNECT_BEGIN &&
+ ssl->options.connectState < SECOND_REPLY_DONE;
+ }
+
+ return ssl->options.acceptState > ACCEPT_BEGIN &&
+ ssl->options.acceptState < ACCEPT_THIRD_REPLY_DONE;
+}
+
+#ifndef NO_SESSION_CACHE
+
+WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl)
+{
+ WOLFSSL_SESSION *session;
+
+ WOLFSSL_ENTER("wolfSSL_SSL_get0_session");
+
+ if (ssl == NULL) {
+ return NULL;
+ }
+
+ session = wolfSSL_get_session((WOLFSSL*)ssl);
+
+#ifdef HAVE_EXT_CACHE
+ ((WOLFSSL*)ssl)->extSession = session;
+#endif
+
+ return session;
+}
+
+#endif /* NO_SESSION_CACHE */
+
+int wolfSSL_X509_check_host(X509 *x, const char *chk, size_t chklen,
+ unsigned int flags, char **peername)
+{
+ int ret;
+ DecodedCert dCert;
+
+ WOLFSSL_ENTER("wolfSSL_X509_check_host");
+
+ /* flags and peername not needed for Nginx. */
+ (void)flags;
+ (void)peername;
+
+ if (flags == WOLFSSL_NO_WILDCARDS) {
+ WOLFSSL_MSG("X509_CHECK_FLAG_NO_WILDCARDS not yet implemented");
+ return WOLFSSL_FAILURE;
+ }
+
+ InitDecodedCert(&dCert, x->derCert->buffer, x->derCert->length, NULL);
+ ret = ParseCertRelative(&dCert, CERT_TYPE, 0, NULL);
+ if (ret != 0) {
+ FreeDecodedCert(&dCert);
+ return WOLFSSL_FAILURE;
+ }
+
+ ret = CheckHostName(&dCert, (char *)chk, chklen);
+ FreeDecodedCert(&dCert);
+ if (ret != 0)
+ return WOLFSSL_FAILURE;
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a)
+{
+ static char num[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+ int i;
+ word32 j;
+ word32 len = 0;
+
+ WOLFSSL_ENTER("wolfSSL_i2a_ASN1_INTEGER");
+
+ if (bp == NULL || a == NULL)
+ return WOLFSSL_FAILURE;
+
+ /* Skip ASN.1 INTEGER (type) byte. */
+ i = 1;
+ /* When indefinite length, can't determine length with data available. */
+ if (a->data[i] == 0x80)
+ return 0;
+ /* One length byte if less than 0x80. */
+ if (a->data[i] < 0x80)
+ len = a->data[i++];
+ /* Multiple length byte if greater than 0x80. */
+ else if (a->data[i] > 0x80) {
+ switch (a->data[i++] - 0x80) {
+ case 4:
+ len |= a->data[i++] << 24;
+ FALL_THROUGH;
+ case 3:
+ len |= a->data[i++] << 16;
+ FALL_THROUGH;
+ case 2:
+ len |= a->data[i++] << 8;
+ FALL_THROUGH;
+ case 1:
+ len |= a->data[i++];
+ break;
+ default:
+ /* Not supporting greater than 4 bytes of length. */
+ return 0;
+ }
+ }
+
+ /* Zero length integer is the value zero. */
+ if (len == 0) {
+ wolfSSL_BIO_write(bp, "00", 2);
+ return 2;
+ }
+
+ /* Don't do negative - just write out every byte. */
+ for (j = 0; j < len; i++,j++) {
+ wolfSSL_BIO_write(bp, &num[a->data[i] >> 4], 1);
+ wolfSSL_BIO_write(bp, &num[a->data[i] & 0xf], 1);
+ }
+
+ /* Two nibbles written for each byte. */
+ return len * 2;
+}
+
+
+#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
+/* Expected return values from implementations of OpenSSL ticket key callback.
+ */
+#define TICKET_KEY_CB_RET_FAILURE -1
+#define TICKET_KEY_CB_RET_NOT_FOUND 0
+#define TICKET_KEY_CB_RET_OK 1
+#define TICKET_KEY_CB_RET_RENEW 2
+
+/* The ticket key callback as used in OpenSSL is stored here. */
+static int (*ticketKeyCb)(WOLFSSL *ssl, unsigned char *name, unsigned char *iv,
+ WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc) = NULL;
+
+/* Implementation of session ticket encryption/decryption using OpenSSL
+ * callback to initialize the cipher and HMAC.
+ *
+ * ssl The SSL/TLS object.
+ * keyName The key name - used to identify the key to be used.
+ * iv The IV to use.
+ * mac The MAC of the encrypted data.
+ * enc Encrypt ticket.
+ * encTicket The ticket data.
+ * encTicketLen The length of the ticket data.
+ * encLen The encrypted/decrypted ticket length - output length.
+ * ctx Ignored. Application specific data.
+ * returns WOLFSSL_TICKET_RET_OK to indicate success,
+ * WOLFSSL_TICKET_RET_CREATE if a new ticket is required and
+ * WOLFSSL_TICKET_RET_FATAL on error.
+ */
+static int wolfSSL_TicketKeyCb(WOLFSSL* ssl,
+ unsigned char keyName[WOLFSSL_TICKET_NAME_SZ],
+ unsigned char iv[WOLFSSL_TICKET_IV_SZ],
+ unsigned char mac[WOLFSSL_TICKET_MAC_SZ],
+ int enc, unsigned char* encTicket,
+ int encTicketLen, int* encLen, void* ctx)
+{
+ byte digest[WC_MAX_DIGEST_SIZE];
+ WOLFSSL_EVP_CIPHER_CTX evpCtx;
+ WOLFSSL_HMAC_CTX hmacCtx;
+ unsigned int mdSz = 0;
+ int len = 0;
+ int ret = WOLFSSL_TICKET_RET_FATAL;
+ int res;
+
+ (void)ctx;
+
+ if (ticketKeyCb == NULL)
+ return WOLFSSL_TICKET_RET_FATAL;
+
+ wolfSSL_EVP_CIPHER_CTX_init(&evpCtx);
+ /* Initialize the cipher and HMAC. */
+ res = ticketKeyCb(ssl, keyName, iv, &evpCtx, &hmacCtx, enc);
+ if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW)
+ return WOLFSSL_TICKET_RET_FATAL;
+
+ if (enc)
+ {
+ /* Encrypt in place. */
+ if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len,
+ encTicket, encTicketLen))
+ goto end;
+ encTicketLen = len;
+ if (!wolfSSL_EVP_EncryptFinal(&evpCtx, &encTicket[encTicketLen], &len))
+ goto end;
+ /* Total length of encrypted data. */
+ encTicketLen += len;
+ *encLen = encTicketLen;
+
+ /* HMAC the encrypted data into the parameter 'mac'. */
+ if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen))
+ goto end;
+#ifdef WOLFSSL_SHA512
+ /* Check for SHA512, which would overrun the mac buffer */
+ if (hmacCtx.hmac.macType == WC_SHA512)
+ goto end;
+#endif
+ if (!wolfSSL_HMAC_Final(&hmacCtx, mac, &mdSz))
+ goto end;
+ }
+ else
+ {
+ /* HMAC the encrypted data and compare it to the passed in data. */
+ if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen))
+ goto end;
+ if (!wolfSSL_HMAC_Final(&hmacCtx, digest, &mdSz))
+ goto end;
+ if (XMEMCMP(mac, digest, mdSz) != 0)
+ goto end;
+
+ /* Decrypt the ticket data in place. */
+ if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len,
+ encTicket, encTicketLen))
+ goto end;
+ encTicketLen = len;
+ if (!wolfSSL_EVP_DecryptFinal(&evpCtx, &encTicket[encTicketLen], &len))
+ goto end;
+ /* Total length of decrypted data. */
+ *encLen = encTicketLen + len;
+ }
+
+ ret = (res == TICKET_KEY_CB_RET_RENEW) ? WOLFSSL_TICKET_RET_CREATE :
+ WOLFSSL_TICKET_RET_OK;
+end:
+ return ret;
+}
+
+/* Set the callback to use when encrypting/decrypting tickets.
+ *
+ * ctx The SSL/TLS context object.
+ * cb The OpenSSL session ticket callback.
+ * returns WOLFSSL_SUCCESS to indicate success.
+ */
+int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, int (*cb)(
+ WOLFSSL *ssl, unsigned char *name, unsigned char *iv,
+ WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc))
+{
+ /* Store callback in a global. */
+ ticketKeyCb = cb;
+ /* Set the ticket encryption callback to be a wrapper around OpenSSL
+ * callback.
+ */
+ ctx->ticketEncCb = wolfSSL_TicketKeyCb;
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_SESSION_TICKET */
+
+#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY ||
+ OPENSSL_EXTRA || HAVE_LIGHTY */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+#ifdef HAVE_OCSP
+/* Not an OpenSSL API. */
+int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response)
+{
+ *response = ssl->ocspResp;
+ return ssl->ocspRespSz;
+}
+
+/* Not an OpenSSL API. */
+char* wolfSSL_get_ocsp_url(WOLFSSL* ssl)
+{
+ return ssl->url;
+}
+
+/* Not an OpenSSL API. */
+int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url)
+{
+ if (ssl == NULL)
+ return WOLFSSL_FAILURE;
+
+ ssl->url = url;
+ return WOLFSSL_SUCCESS;
+}
+#endif /* OCSP */
+#endif /* OPENSSL_ALL / WOLFSSL_NGINX / WOLFSSL_HAPROXY */
+
+#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
+ defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, WOLF_STACK_OF(X509)** chain)
+{
+ word32 idx;
+ word32 length;
+ WOLFSSL_STACK* node;
+ WOLFSSL_STACK* last = NULL;
+
+ if (ctx == NULL || chain == NULL) {
+ chain = NULL;
+ return WOLFSSL_FAILURE;
+ }
+ if (ctx->x509Chain != NULL) {
+ *chain = ctx->x509Chain;
+ return WOLFSSL_SUCCESS;
+ }
+
+ /* If there are no chains then success! */
+ *chain = NULL;
+ if (ctx->certChain == NULL || ctx->certChain->length == 0) {
+ return WOLFSSL_SUCCESS;
+ }
+
+ /* Create a new stack of WOLFSSL_X509 object from chain buffer. */
+ for (idx = 0; idx < ctx->certChain->length; ) {
+ node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (node == NULL)
+ return WOLFSSL_FAILURE;
+ node->next = NULL;
+
+ /* 3 byte length | X509 DER data */
+ ato24(ctx->certChain->buffer + idx, &length);
+ idx += 3;
+
+ /* Create a new X509 from DER encoded data. */
+ node->data.x509 = wolfSSL_X509_d2i(NULL, ctx->certChain->buffer + idx,
+ length);
+ if (node->data.x509 == NULL) {
+ XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
+ /* Return as much of the chain as we created. */
+ ctx->x509Chain = *chain;
+ return WOLFSSL_FAILURE;
+ }
+ idx += length;
+
+ /* Add object to the end of the stack. */
+ if (last == NULL) {
+ node->num = 1;
+ *chain = node;
+ }
+ else {
+ (*chain)->num++;
+ last->next = node;
+ }
+
+ last = node;
+ }
+
+ ctx->x509Chain = *chain;
+
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx,
+ int(*cb)(WOLFSSL*, void*))
+{
+ if (ctx == NULL || ctx->cm == NULL)
+ return WOLFSSL_FAILURE;
+
+#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
+ /* Ensure stapling is on for callback to be used. */
+ wolfSSL_CTX_EnableOCSPStapling(ctx);
+
+ if (ctx->cm->ocsp_stapling == NULL)
+ return WOLFSSL_FAILURE;
+
+ ctx->cm->ocsp_stapling->statusCb = cb;
+#else
+ (void)cb;
+#endif
+
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer,
+ WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x)
+{
+ WOLFSSL_STACK* node;
+ Signer* ca = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ DecodedCert* cert = NULL;
+#else
+ DecodedCert cert[1];
+#endif
+
+ if (issuer == NULL || ctx == NULL || x == NULL)
+ return WOLFSSL_FATAL_ERROR;
+
+ if (ctx->chain != NULL) {
+ for (node = ctx->chain; node != NULL; node = node->next) {
+ if (wolfSSL_X509_check_issued(node->data.x509, x) == X509_V_OK) {
+ *issuer = x;
+ return WOLFSSL_SUCCESS;
+ }
+ }
+ }
+
+
+#ifdef WOLFSSL_SMALL_STACK
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
+ if (cert == NULL)
+ return WOLFSSL_FAILURE;
+#endif
+
+ /* Use existing CA retrieval APIs that use DecodedCert. */
+ InitDecodedCert(cert, x->derCert->buffer, x->derCert->length, NULL);
+ if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) {
+ #ifndef NO_SKID
+ if (cert->extAuthKeyIdSet)
+ ca = GetCA(ctx->store->cm, cert->extAuthKeyId);
+ if (ca == NULL)
+ ca = GetCAByName(ctx->store->cm, cert->issuerHash);
+ #else /* NO_SKID */
+ ca = GetCA(ctx->store->cm, cert->issuerHash);
+ #endif /* NO SKID */
+ }
+ FreeDecodedCert(cert);
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+#endif
+
+ if (ca == NULL)
+ return WOLFSSL_FAILURE;
+
+#ifdef WOLFSSL_SIGNER_DER_CERT
+ /* populate issuer with Signer DER */
+ *issuer = wolfSSL_X509_d2i(issuer, ca->derCert->buffer,
+ ca->derCert->length);
+ if (*issuer == NULL)
+ return WOLFSSL_FAILURE;
+#else
+ /* Create an empty certificate as CA doesn't have a certificate. */
+ *issuer = (WOLFSSL_X509 *)XMALLOC(sizeof(WOLFSSL_X509), 0,
+ DYNAMIC_TYPE_OPENSSL);
+ if (*issuer == NULL)
+ return WOLFSSL_FAILURE;
+
+ InitX509((*issuer), 1, NULL);
+#endif
+
+ /* Result is ignored when passed to wolfSSL_OCSP_cert_to_id(). */
+
+ return WOLFSSL_SUCCESS;
+}
+
+void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk)
+{
+ WOLFSSL_STACK *curr;
+
+ while (sk != NULL) {
+ curr = sk;
+ sk = sk->next;
+
+ XFREE(curr, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+
+WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x)
+{
+ WOLFSSL_STACK* list = NULL;
+ char* url;
+
+ if (x->authInfoSz == 0)
+ return NULL;
+
+ list = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK) + x->authInfoSz + 1,
+ NULL, DYNAMIC_TYPE_OPENSSL);
+ if (list == NULL)
+ return NULL;
+
+ url = (char*)list;
+ url += sizeof(WOLFSSL_STACK);
+ XMEMCPY(url, x->authInfo, x->authInfoSz);
+ url[x->authInfoSz] = '\0';
+
+ list->data.string = url;
+ list->next = NULL;
+
+ return list;
+}
+
+int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, WOLFSSL_X509 *subject)
+{
+ WOLFSSL_X509_NAME *issuerName = wolfSSL_X509_get_issuer_name(subject);
+ WOLFSSL_X509_NAME *subjectName = wolfSSL_X509_get_subject_name(issuer);
+
+ if (issuerName == NULL || subjectName == NULL)
+ return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
+
+ /* Literal matching of encoded names and key ids. */
+ if (issuerName->sz != subjectName->sz ||
+ XMEMCMP(issuerName->name, subjectName->name, subjectName->sz) != 0) {
+ return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
+ }
+
+ if (subject->authKeyId != NULL && issuer->subjKeyId != NULL) {
+ if (subject->authKeyIdSz != issuer->subjKeyIdSz ||
+ XMEMCMP(subject->authKeyId, issuer->subjKeyId,
+ issuer->subjKeyIdSz) != 0) {
+ return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
+ }
+ }
+
+ return X509_V_OK;
+}
+
+WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x)
+{
+ return wolfSSL_X509_d2i(NULL, x->derCert->buffer, x->derCert->length);
+}
+
+char* wolfSSL_sk_WOLFSSL_STRING_value(WOLF_STACK_OF(WOLFSSL_STRING)* strings,
+ int idx)
+{
+ for (; idx > 0 && strings != NULL; idx--)
+ strings = strings->next;
+ if (strings == NULL)
+ return NULL;
+ return strings->data.string;
+}
+#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+#ifdef HAVE_ALPN
+void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, const unsigned char **data,
+ unsigned int *len)
+{
+ word16 nameLen;
+
+ if (ssl != NULL && data != NULL && len != NULL) {
+ TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen);
+ *len = nameLen;
+ }
+}
+
+int wolfSSL_select_next_proto(unsigned char **out, unsigned char *outLen,
+ const unsigned char *in, unsigned int inLen,
+ const unsigned char *clientNames,
+ unsigned int clientLen)
+{
+ unsigned int i, j;
+ byte lenIn, lenClient;
+
+ if (out == NULL || outLen == NULL || in == NULL || clientNames == NULL)
+ return OPENSSL_NPN_UNSUPPORTED;
+
+ for (i = 0; i < inLen; i += lenIn) {
+ lenIn = in[i++];
+ for (j = 0; j < clientLen; j += lenClient) {
+ lenClient = clientNames[j++];
+
+ if (lenIn != lenClient)
+ continue;
+
+ if (XMEMCMP(in + i, clientNames + j, lenIn) == 0) {
+ *out = (unsigned char *)(in + i);
+ *outLen = lenIn;
+ return OPENSSL_NPN_NEGOTIATED;
+ }
+ }
+ }
+
+ *out = (unsigned char *)clientNames + 1;
+ *outLen = clientNames[0];
+ return OPENSSL_NPN_NO_OVERLAP;
+}
+
+void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx,
+ int (*cb) (WOLFSSL *ssl,
+ const unsigned char **out,
+ unsigned char *outlen,
+ const unsigned char *in,
+ unsigned int inlen,
+ void *arg), void *arg)
+{
+ if (ctx != NULL) {
+ ctx->alpnSelect = cb;
+ ctx->alpnSelectArg = arg;
+ }
+}
+
+void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s,
+ int (*cb) (WOLFSSL *ssl,
+ const unsigned char
+ **out,
+ unsigned int *outlen,
+ void *arg), void *arg)
+{
+ (void)s;
+ (void)cb;
+ (void)arg;
+ WOLFSSL_STUB("wolfSSL_CTX_set_next_protos_advertised_cb");
+}
+
+void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s,
+ int (*cb) (WOLFSSL *ssl,
+ unsigned char **out,
+ unsigned char *outlen,
+ const unsigned char *in,
+ unsigned int inlen,
+ void *arg), void *arg)
+{
+ (void)s;
+ (void)cb;
+ (void)arg;
+ WOLFSSL_STUB("wolfSSL_CTX_set_next_proto_select_cb");
+}
+
+void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data,
+ unsigned *len)
+{
+ (void)s;
+ (void)data;
+ (void)len;
+ WOLFSSL_STUB("wolfSSL_get0_next_proto_negotiated");
+}
+#endif /* HAVE_ALPN */
+
+#endif /* WOLFSSL_NGINX / WOLFSSL_HAPROXY */
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
+int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, const char* names)
+{
+ int idx, start = 0, len;
+ word16 curve;
+ char name[MAX_CURVE_NAME_SZ];
+
+ /* Disable all curves so that only the ones the user wants are enabled. */
+ ctx->disabledCurves = 0xFFFFFFFFUL;
+ for (idx = 1; names[idx-1] != '\0'; idx++) {
+ if (names[idx] != ':' && names[idx] != '\0')
+ continue;
+
+ len = idx - 1 - start;
+ if (len > MAX_CURVE_NAME_SZ - 1)
+ return WOLFSSL_FAILURE;
+
+ XMEMCPY(name, names + start, len);
+ name[len] = 0;
+
+ if ((XSTRNCMP(name, "prime256v1", len) == 0) ||
+ (XSTRNCMP(name, "secp256r1", len) == 0) ||
+ (XSTRNCMP(name, "P-256", len) == 0)) {
+ curve = WOLFSSL_ECC_SECP256R1;
+ }
+ else if ((XSTRNCMP(name, "secp384r1", len) == 0) ||
+ (XSTRNCMP(name, "P-384", len) == 0)) {
+ curve = WOLFSSL_ECC_SECP384R1;
+ }
+ else if ((XSTRNCMP(name, "secp521r1", len) == 0) ||
+ (XSTRNCMP(name, "P-521", len) == 0)) {
+ curve = WOLFSSL_ECC_SECP521R1;
+ }
+ else if (XSTRNCMP(name, "X25519", len) == 0) {
+ curve = WOLFSSL_ECC_X25519;
+ }
+ else if (XSTRNCMP(name, "X448", len) == 0) {
+ curve = WOLFSSL_ECC_X448;
+ }
+ else {
+ #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+ int ret;
+ const ecc_set_type *eccSet;
+
+ ret = wc_ecc_get_curve_idx_from_name(name);
+ if (ret < 0) {
+ WOLFSSL_MSG("Could not find name in set");
+ return WOLFSSL_FAILURE;
+ }
+
+ eccSet = wc_ecc_get_curve_params(ret);
+ if (eccSet == NULL) {
+ WOLFSSL_MSG("NULL set returned");
+ return WOLFSSL_FAILURE;
+ }
+
+ curve = GetCurveByOID(eccSet->oidSum);
+ #else
+ WOLFSSL_MSG("API not present to search farther using name");
+ return WOLFSSL_FAILURE;
+ #endif
+ }
+
+ if (curve > (sizeof(word32) * WOLFSSL_BIT_SIZE)) {
+ /* shift left more than size of ctx->disabledCurves causes static
+ * analysis report */
+ WOLFSSL_MSG("curve value is too large for upcoming shift");
+ return WOLFSSL_FAILURE;
+ }
+
+ #if defined(HAVE_SUPPORTED_CURVES) && !defined(NO_WOLFSSL_CLIENT)
+ /* set the supported curve so client TLS extension contains only the
+ * desired curves */
+ if (wolfSSL_CTX_UseSupportedCurve(ctx, curve) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Unable to set supported curve");
+ return WOLFSSL_FAILURE;
+ }
+ #endif
+
+ /* Switch the bit to off and therefore is enabled. */
+ ctx->disabledCurves &= ~(1U << curve);
+ start = idx + 1;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_set1_curves_list(WOLFSSL* ssl, const char* names)
+{
+ if (ssl == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+ return wolfSSL_CTX_set1_curves_list(ssl->ctx, names);
+}
+#endif /* OPENSSL_EXTRA && HAVE_ECC */
+
+#ifdef OPENSSL_EXTRA
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb)
+{
+ WOLFSSL_STUB("SSL_CTX_set_msg_callback");
+ (void)ctx;
+ (void)cb;
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+
+/* Sets a callback for when sending and receiving protocol messages.
+ *
+ * ssl WOLFSSL structure to set callback in
+ * cb callback to use
+ *
+ * return SSL_SUCCESS on success and SSL_FAILURE with error case
+ */
+int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb)
+{
+ WOLFSSL_ENTER("wolfSSL_set_msg_callback");
+
+ if (ssl == NULL) {
+ return SSL_FAILURE;
+ }
+
+ if (cb != NULL) {
+ ssl->toInfoOn = 1;
+ }
+
+ ssl->protoMsgCb = cb;
+ return SSL_SUCCESS;
+}
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg)
+{
+ WOLFSSL_STUB("SSL_CTX_set_msg_callback_arg");
+ (void)ctx;
+ (void)arg;
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg)
+{
+ WOLFSSL_ENTER("wolfSSL_set_msg_callback_arg");
+ if (ssl == NULL)
+ return WOLFSSL_FAILURE;
+
+ ssl->protoMsgCtx = arg;
+ return WOLFSSL_SUCCESS;
+}
+
+void *wolfSSL_OPENSSL_memdup(const void *data, size_t siz, const char* file, int line)
+{
+ void *ret;
+ (void)file;
+ (void)line;
+
+ if (data == NULL || siz >= INT_MAX)
+ return NULL;
+
+ ret = OPENSSL_malloc(siz);
+ if (ret == NULL) {
+ return NULL;
+ }
+ return XMEMCPY(ret, data, siz);
+}
+
+int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx, const unsigned char *p,
+ unsigned int p_len)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_alpn_protos");
+ if(ctx == NULL)
+ return BAD_FUNC_ARG;
+ if((void *)ctx->alpn_cli_protos != NULL)
+ wolfSSL_OPENSSL_free((void *)ctx->alpn_cli_protos);
+ ctx->alpn_cli_protos =
+ (const unsigned char *)wolfSSL_OPENSSL_memdup(p, p_len, NULL, 0);
+ if (ctx->alpn_cli_protos == NULL) {
+ return SSL_FAILURE;
+ }
+ ctx->alpn_cli_protos_len = p_len;
+
+ return SSL_SUCCESS;
+}
+
+
+#ifdef HAVE_ALPN
+/* Sets the ALPN extension protos
+ *
+ * example format is
+ * unsigned char p[] = {
+ * 8, 'h', 't', 't', 'p', '/', '1', '.', '1'
+ * };
+ *
+ * returns WOLFSSL_SUCCESS on success */
+int wolfSSL_set_alpn_protos(WOLFSSL* ssl,
+ const unsigned char* p, unsigned int p_len)
+{
+ WOLFSSL_BIO* bio;
+ char* pt;
+
+ unsigned int sz;
+ unsigned int idx = 0;
+ int alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH;
+ WOLFSSL_ENTER("wolfSSL_set_alpn_protos");
+
+ if (ssl == NULL || p_len <= 1) {
+ return WOLFSSL_FAILURE;
+ }
+
+ bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
+ if (bio == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* convert into comma separated list */
+ while (idx < p_len - 1) {
+ unsigned int i;
+
+ sz = p[idx++];
+ if (idx + sz > p_len) {
+ WOLFSSL_MSG("Bad list format");
+ wolfSSL_BIO_free(bio);
+ return WOLFSSL_FAILURE;
+ }
+ if (sz > 0) {
+ for (i = 0; i < sz; i++) {
+ wolfSSL_BIO_write(bio, &p[idx++], 1);
+ }
+ if (idx < p_len - 1)
+ wolfSSL_BIO_write(bio, ",", 1);
+ }
+ }
+ wolfSSL_BIO_write(bio, "\0", 1);
+
+ /* clears out all current ALPN extensions set */
+ TLSX_Remove(&ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL, ssl->heap);
+
+ if ((sz = wolfSSL_BIO_get_mem_data(bio, &pt)) > 0) {
+ wolfSSL_UseALPN(ssl, pt, sz, alpn_opt);
+ }
+ wolfSSL_BIO_free(bio);
+ return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_ALPN */
+#endif
+
+#endif /* WOLFCRYPT_ONLY */
+
+#if defined(OPENSSL_EXTRA)
+
+#define WOLFSSL_BIO_INCLUDED
+#include "src/bio.c"
+
+int oid2nid(word32 oid, int grp)
+{
+ /* get OID type */
+ switch (grp) {
+ /* oidHashType */
+ case oidHashType:
+ switch (oid) {
+ #ifdef WOLFSSL_MD2
+ case MD2h:
+ return NID_md2;
+ #endif
+ #ifndef NO_MD5
+ case MD5h:
+ return NID_md5;
+ #endif
+ #ifndef NO_SHA
+ case SHAh:
+ return NID_sha1;
+ #endif
+ case SHA224h:
+ return NID_sha224;
+ #ifndef NO_SHA256
+ case SHA256h:
+ return NID_sha256;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case SHA384h:
+ return NID_sha384;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case SHA512h:
+ return NID_sha512;
+ #endif
+ }
+ break;
+
+ /* oidSigType */
+ case oidSigType:
+ switch (oid) {
+ #ifndef NO_DSA
+ case CTC_SHAwDSA:
+ return CTC_SHAwDSA;
+ #endif /* NO_DSA */
+ #ifndef NO_RSA
+ case CTC_MD2wRSA:
+ return CTC_MD2wRSA;
+ case CTC_MD5wRSA:
+ return CTC_MD5wRSA;
+ case CTC_SHAwRSA:
+ return CTC_SHAwRSA;
+ case CTC_SHA224wRSA:
+ return CTC_SHA224wRSA;
+ case CTC_SHA256wRSA:
+ return CTC_SHA256wRSA;
+ case CTC_SHA384wRSA:
+ return CTC_SHA384wRSA;
+ case CTC_SHA512wRSA:
+ return CTC_SHA512wRSA;
+ #endif /* NO_RSA */
+ #ifdef HAVE_ECC
+ case CTC_SHAwECDSA:
+ return CTC_SHAwECDSA;
+ case CTC_SHA224wECDSA:
+ return CTC_SHA224wECDSA;
+ case CTC_SHA256wECDSA:
+ return CTC_SHA256wECDSA;
+ case CTC_SHA384wECDSA:
+ return CTC_SHA384wECDSA;
+ case CTC_SHA512wECDSA:
+ return CTC_SHA512wECDSA;
+ #endif /* HAVE_ECC */
+ }
+ break;
+
+ /* oidKeyType */
+ case oidKeyType:
+ switch (oid) {
+ #ifndef NO_DSA
+ case DSAk:
+ return DSAk;
+ #endif /* NO_DSA */
+ #ifndef NO_RSA
+ case RSAk:
+ return RSAk;
+ #endif /* NO_RSA */
+ #ifdef HAVE_NTRU
+ case NTRUk:
+ return NTRUk;
+ #endif /* HAVE_NTRU */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ return ECDSAk;
+ #endif /* HAVE_ECC */
+ }
+ break;
+
+
+ #ifdef HAVE_ECC
+ case oidCurveType:
+ switch (oid) {
+ case ECC_SECP192R1_OID:
+ return NID_X9_62_prime192v1;
+ case ECC_PRIME192V2_OID:
+ return NID_X9_62_prime192v2;
+ case ECC_PRIME192V3_OID:
+ return NID_X9_62_prime192v3;
+ case ECC_PRIME239V1_OID:
+ return NID_X9_62_prime239v1;
+ case ECC_PRIME239V2_OID:
+ return NID_X9_62_prime239v2;
+ case ECC_PRIME239V3_OID:
+ return NID_X9_62_prime239v3;
+ case ECC_SECP256R1_OID:
+ return NID_X9_62_prime256v1;
+ case ECC_SECP112R1_OID:
+ return NID_secp112r1;
+ case ECC_SECP112R2_OID:
+ return NID_secp112r2;
+ case ECC_SECP128R1_OID:
+ return NID_secp128r1;
+ case ECC_SECP128R2_OID:
+ return NID_secp128r2;
+ case ECC_SECP160R1_OID:
+ return NID_secp160r1;
+ case ECC_SECP160R2_OID:
+ return NID_secp160r2;
+ case ECC_SECP224R1_OID:
+ return NID_secp224r1;
+ case ECC_SECP384R1_OID:
+ return NID_secp384r1;
+ case ECC_SECP521R1_OID:
+ return NID_secp521r1;
+ case ECC_SECP160K1_OID:
+ return NID_secp160k1;
+ case ECC_SECP192K1_OID:
+ return NID_secp192k1;
+ case ECC_SECP224K1_OID:
+ return NID_secp224k1;
+ case ECC_SECP256K1_OID:
+ return NID_secp256k1;
+ case ECC_BRAINPOOLP160R1_OID:
+ return NID_brainpoolP160r1;
+ case ECC_BRAINPOOLP192R1_OID:
+ return NID_brainpoolP192r1;
+ case ECC_BRAINPOOLP224R1_OID:
+ return NID_brainpoolP224r1;
+ case ECC_BRAINPOOLP256R1_OID:
+ return NID_brainpoolP256r1;
+ case ECC_BRAINPOOLP320R1_OID:
+ return NID_brainpoolP320r1;
+ case ECC_BRAINPOOLP384R1_OID:
+ return NID_brainpoolP384r1;
+ case ECC_BRAINPOOLP512R1_OID:
+ return NID_brainpoolP512r1;
+ }
+ break;
+ #endif /* HAVE_ECC */
+
+ /* oidBlkType */
+ case oidBlkType:
+ switch (oid) {
+ #ifdef WOLFSSL_AES_128
+ case AES128CBCb:
+ return AES128CBCb;
+ #endif
+ #ifdef WOLFSSL_AES_192
+ case AES192CBCb:
+ return AES192CBCb;
+ #endif
+ #ifdef WOLFSSL_AES_256
+ case AES256CBCb:
+ return AES256CBCb;
+ #endif
+ #ifndef NO_DES3
+ case DESb:
+ return NID_des;
+ case DES3b:
+ return NID_des3;
+ #endif
+ }
+ break;
+
+ #ifdef HAVE_OCSP
+ case oidOcspType:
+ switch (oid) {
+ case OCSP_BASIC_OID:
+ return NID_id_pkix_OCSP_basic;
+ case OCSP_NONCE_OID:
+ return OCSP_NONCE_OID;
+ }
+ break;
+ #endif /* HAVE_OCSP */
+
+ /* oidCertExtType */
+ case oidCertExtType:
+ switch (oid) {
+ case BASIC_CA_OID:
+ return BASIC_CA_OID;
+ case ALT_NAMES_OID:
+ return ALT_NAMES_OID;
+ case CRL_DIST_OID:
+ return CRL_DIST_OID;
+ case AUTH_INFO_OID:
+ return AUTH_INFO_OID;
+ case AUTH_KEY_OID:
+ return AUTH_KEY_OID;
+ case SUBJ_KEY_OID:
+ return SUBJ_KEY_OID;
+ case INHIBIT_ANY_OID:
+ return INHIBIT_ANY_OID;
+ case KEY_USAGE_OID:
+ return NID_key_usage;
+ case NAME_CONS_OID:
+ return NID_name_constraints;
+ case CERT_POLICY_OID:
+ return NID_certificate_policies;
+ }
+ break;
+
+ /* oidCertAuthInfoType */
+ case oidCertAuthInfoType:
+ switch (oid) {
+ case AIA_OCSP_OID:
+ return AIA_OCSP_OID;
+ case AIA_CA_ISSUER_OID:
+ return AIA_CA_ISSUER_OID;
+ }
+ break;
+
+ /* oidCertPolicyType */
+ case oidCertPolicyType:
+ switch (oid) {
+ case CP_ANY_OID:
+ return NID_any_policy;
+ }
+ break;
+
+ /* oidCertAltNameType */
+ case oidCertAltNameType:
+ switch (oid) {
+ case HW_NAME_OID:
+ return NID_hw_name_oid;
+ }
+ break;
+
+ /* oidCertKeyUseType */
+ case oidCertKeyUseType:
+ switch (oid) {
+ case EKU_ANY_OID:
+ return NID_anyExtendedKeyUsage;
+ case EKU_SERVER_AUTH_OID:
+ return EKU_SERVER_AUTH_OID;
+ case EKU_CLIENT_AUTH_OID:
+ return EKU_CLIENT_AUTH_OID;
+ case EKU_OCSP_SIGN_OID:
+ return EKU_OCSP_SIGN_OID;
+ }
+ break;
+
+ /* oidKdfType */
+ case oidKdfType:
+ switch (oid) {
+ case PBKDF2_OID:
+ return PBKDF2_OID;
+ }
+ break;
+
+ /* oidPBEType */
+ case oidPBEType:
+ switch (oid) {
+ case PBE_SHA1_RC4_128:
+ return PBE_SHA1_RC4_128;
+ case PBE_SHA1_DES:
+ return PBE_SHA1_DES;
+ case PBE_SHA1_DES3:
+ return PBE_SHA1_DES3;
+ }
+ break;
+
+ /* oidKeyWrapType */
+ case oidKeyWrapType:
+ switch (oid) {
+ #ifdef WOLFSSL_AES_128
+ case AES128_WRAP:
+ return AES128_WRAP;
+ #endif
+ #ifdef WOLFSSL_AES_192
+ case AES192_WRAP:
+ return AES192_WRAP;
+ #endif
+ #ifdef WOLFSSL_AES_256
+ case AES256_WRAP:
+ return AES256_WRAP;
+ #endif
+ }
+ break;
+
+ /* oidCmsKeyAgreeType */
+ case oidCmsKeyAgreeType:
+ switch (oid) {
+ #ifndef NO_SHA
+ case dhSinglePass_stdDH_sha1kdf_scheme:
+ return dhSinglePass_stdDH_sha1kdf_scheme;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case dhSinglePass_stdDH_sha224kdf_scheme:
+ return dhSinglePass_stdDH_sha224kdf_scheme;
+ #endif
+ #ifndef NO_SHA256
+ case dhSinglePass_stdDH_sha256kdf_scheme:
+ return dhSinglePass_stdDH_sha256kdf_scheme;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case dhSinglePass_stdDH_sha384kdf_scheme:
+ return dhSinglePass_stdDH_sha384kdf_scheme;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case dhSinglePass_stdDH_sha512kdf_scheme:
+ return dhSinglePass_stdDH_sha512kdf_scheme;
+ #endif
+ }
+ break;
+
+ default:
+ WOLFSSL_MSG("NID not in table");
+ return -1;
+ }
+
+ return -1;
+}
+
+
+/* when calling SetIndividualInternal, mpi should be cleared by caller if no
+ * longer used. ie mp_free(mpi). This is to free data when fastmath is
+ * disabled since a copy of mpi is made by this function and placed into bn.
+ */
+int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi)
+{
+ WOLFSSL_MSG("Entering SetIndividualInternal");
+
+ if (bn == NULL || bn->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (mpi == NULL || (mp_init(mpi) != MP_OKAY)) {
+ WOLFSSL_MSG("mpi NULL error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) {
+ WOLFSSL_MSG("mp_copy error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+#ifndef NO_ASN
+WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai,
+ WOLFSSL_BIGNUM *bn)
+{
+ mp_int mpi;
+ word32 idx = 0;
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_to_BN");
+
+ if (ai == NULL) {
+ return NULL;
+ }
+
+ ret = GetInt(&mpi, ai->data, &idx, ai->dataMax);
+ if (ret != 0) {
+ #ifdef WOLFSSL_QT
+ mp_init(&mpi); /* must init mpi */
+ /* Serial number in QT starts at index 0 of data */
+ if (mp_read_unsigned_bin(&mpi, (byte*)ai->data, ai->length) != 0) {
+ mp_clear(&mpi);
+ return NULL;
+ }
+ #else
+ /* expecting ASN1 format for INTEGER */
+ WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_to_BN", ret);
+ return NULL;
+ #endif
+ }
+
+ /* mp_clear needs called because mpi is copied and causes memory leak with
+ * --disable-fastmath */
+ ret = SetIndividualExternal(&bn, &mpi);
+ mp_clear(&mpi);
+
+ if (ret != WOLFSSL_SUCCESS) {
+ return NULL;
+ }
+ return bn;
+}
+#endif /* !NO_ASN */
+
+#if !defined(NO_DSA) && !defined(NO_DH)
+WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *dsa)
+{
+ WOLFSSL_DH* dh;
+ DhKey* key;
+
+ WOLFSSL_ENTER("wolfSSL_DSA_dup_DH");
+
+ if (dsa == NULL) {
+ return NULL;
+ }
+
+ dh = wolfSSL_DH_new();
+ if (dh == NULL) {
+ return NULL;
+ }
+ key = (DhKey*)dh->internal;
+
+ if (dsa->p != NULL &&
+ SetIndividualInternal(((WOLFSSL_DSA*)dsa)->p, &key->p) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa p key error");
+ wolfSSL_DH_free(dh);
+ return NULL;
+ }
+ if (dsa->g != NULL &&
+ SetIndividualInternal(((WOLFSSL_DSA*)dsa)->g, &key->g) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa g key error");
+ wolfSSL_DH_free(dh);
+ return NULL;
+ }
+
+ if (SetIndividualExternal(&dh->p, &key->p) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("dsa p key error");
+ wolfSSL_DH_free(dh);
+ return NULL;
+ }
+ if (SetIndividualExternal(&dh->g, &key->g) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("dsa g key error");
+ wolfSSL_DH_free(dh);
+ return NULL;
+ }
+
+ return dh;
+}
+#endif /* !NO_DSA && !NO_DH */
+
+
+#ifndef NO_RSA
+#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+/* Openssl -> WolfSSL */
+int SetRsaInternal(WOLFSSL_RSA* rsa)
+{
+ RsaKey* key;
+ WOLFSSL_MSG("Entering SetRsaInternal");
+
+ if (rsa == NULL || rsa->internal == NULL) {
+ WOLFSSL_MSG("rsa key NULL error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ key = (RsaKey*)rsa->internal;
+
+ if (SetIndividualInternal(rsa->n, &key->n) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa n key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (SetIndividualInternal(rsa->e, &key->e) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa e key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* public key */
+ key->type = RSA_PUBLIC;
+
+ if (rsa->d != NULL) {
+ if (SetIndividualInternal(rsa->d, &key->d) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa d key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* private key */
+ key->type = RSA_PRIVATE;
+ }
+
+ if (rsa->p != NULL &&
+ SetIndividualInternal(rsa->p, &key->p) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa p key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (rsa->q != NULL &&
+ SetIndividualInternal(rsa->q, &key->q) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa q key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+#ifndef RSA_LOW_MEM
+ if (rsa->dmp1 != NULL &&
+ SetIndividualInternal(rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa dP key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (rsa->dmq1 != NULL &&
+ SetIndividualInternal(rsa->dmq1, &key->dQ) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa dQ key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (rsa->iqmp != NULL &&
+ SetIndividualInternal(rsa->iqmp, &key->u) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa u key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+#endif /* !RSA_LOW_MEM */
+
+ rsa->inSet = 1;
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+/* SSL_SUCCESS on ok */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bn)
+{
+ (void)rsa;
+ (void)bn;
+ WOLFSSL_STUB("RSA_blinding_on");
+ WOLFSSL_MSG("wolfSSL_RSA_blinding_on");
+
+ return WOLFSSL_SUCCESS; /* on by default */
+}
+#endif
+
+/* return compliant with OpenSSL
+ * size of encrypted data if success , -1 if error
+ */
+int wolfSSL_RSA_public_encrypt(int len, const unsigned char* fr,
+ unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+{
+ int initTmpRng = 0;
+ WC_RNG *rng = NULL;
+ int outLen;
+ int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG* tmpRNG = NULL;
+#else
+ WC_RNG _tmpRNG[1];
+ WC_RNG* tmpRNG = _tmpRNG;
+#endif
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+ int mgf = WC_MGF1NONE;
+ enum wc_HashType hash = WC_HASH_TYPE_NONE;
+#endif
+
+ WOLFSSL_MSG("wolfSSL_RSA_public_encrypt");
+
+ /* Check and remap the padding to internal values, if needed. */
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+ if (padding == RSA_PKCS1_PADDING)
+ padding = WC_RSA_PKCSV15_PAD;
+ else if (padding == RSA_PKCS1_OAEP_PADDING) {
+ padding = WC_RSA_OAEP_PAD;
+ hash = WC_HASH_TYPE_SHA;
+ mgf = WC_MGF1SHA1;
+ }
+ else if (padding == RSA_PKCS1_PSS_PADDING) {
+ padding = WC_RSA_PSS_PAD;
+ hash = WC_HASH_TYPE_SHA256;
+ mgf = WC_MGF1SHA256;
+ }
+ else if (padding == RSA_NO_PADDING) {
+ padding = WC_RSA_NO_PAD;
+ }
+#else
+ if (padding == RSA_PKCS1_PADDING)
+ ;
+#endif
+ else {
+ WOLFSSL_MSG("wolfSSL_RSA_public_encrypt unsupported padding");
+ return 0;
+ }
+
+ if (rsa->inSet == 0)
+ {
+ if (SetRsaInternal(rsa) != SSL_SUCCESS) {
+ WOLFSSL_MSG("SetRsaInternal failed");
+ return 0;
+ }
+ }
+
+ outLen = wolfSSL_RSA_size(rsa);
+
+ rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRNG, &initTmpRng);
+
+ if (outLen == 0) {
+ WOLFSSL_MSG("Bad RSA size");
+ }
+
+ if (rng) {
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+ ret = wc_RsaPublicEncrypt_ex(fr, len, to, outLen,
+ (RsaKey*)rsa->internal, rng, padding,
+ hash, mgf, NULL, 0);
+#else
+ ret = wc_RsaPublicEncrypt(fr, len, to, outLen,
+ (RsaKey*)rsa->internal, rng);
+#endif
+ if (ret <= 0) {
+ WOLFSSL_MSG("Bad Rsa Encrypt");
+ }
+ if (len <= 0) {
+ WOLFSSL_MSG("Bad Rsa Encrypt");
+ }
+ }
+
+ if (initTmpRng)
+ wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+ if (tmpRNG)
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+ if (ret >= 0)
+ WOLFSSL_MSG("wolfSSL_RSA_public_encrypt success");
+ else {
+ WOLFSSL_MSG("wolfSSL_RSA_public_encrypt failed");
+ ret = WOLFSSL_FATAL_ERROR; /* return -1 on error case */
+ }
+ return ret;
+}
+
+
+
+
+/* return compliant with OpenSSL
+ * size of plain recovered data if success , -1 if error
+ */
+int wolfSSL_RSA_private_decrypt(int len, const unsigned char* fr,
+ unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+{
+ int outLen;
+ int ret = 0;
+ #if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+ int mgf = WC_MGF1NONE;
+ enum wc_HashType hash = WC_HASH_TYPE_NONE;
+ #endif
+
+ WOLFSSL_MSG("wolfSSL_RSA_private_decrypt");
+
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+ if (padding == RSA_PKCS1_PADDING)
+ padding = WC_RSA_PKCSV15_PAD;
+ else if (padding == RSA_PKCS1_OAEP_PADDING) {
+ padding = WC_RSA_OAEP_PAD;
+ hash = WC_HASH_TYPE_SHA;
+ mgf = WC_MGF1SHA1;
+ }
+ else if (padding == RSA_PKCS1_PSS_PADDING) {
+ padding = WC_RSA_PSS_PAD;
+ hash = WC_HASH_TYPE_SHA256;
+ mgf = WC_MGF1SHA256;
+ }
+ else if (padding == RSA_NO_PADDING) {
+ padding = WC_RSA_NO_PAD;
+ }
+#else
+ if (padding == RSA_PKCS1_PADDING)
+ ;
+#endif
+ else {
+ WOLFSSL_MSG("wolfSSL_RSA_private_decrypt unsupported padding");
+ return 0;
+ }
+
+ if (rsa->inSet == 0)
+ {
+ if (SetRsaInternal(rsa) != SSL_SUCCESS) {
+ WOLFSSL_MSG("SetRsaInternal failed");
+ return 0;
+ }
+ }
+
+ outLen = wolfSSL_RSA_size(rsa);
+ if (outLen == 0) {
+ WOLFSSL_MSG("Bad RSA size");
+ }
+
+ /* size of 'to' buffer must be size of RSA key */
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+ ret = wc_RsaPrivateDecrypt_ex(fr, len, to, outLen,
+ (RsaKey*)rsa->internal, padding,
+ hash, mgf, NULL, 0);
+#else
+ ret = wc_RsaPrivateDecrypt(fr, len, to, outLen,
+ (RsaKey*)rsa->internal);
+#endif
+
+ if (len <= 0) {
+ WOLFSSL_MSG("Bad Rsa Decrypt");
+ }
+
+ if (ret > 0)
+ WOLFSSL_MSG("wolfSSL_RSA_private_decrypt success");
+ else {
+ WOLFSSL_MSG("wolfSSL_RSA_private_decrypt failed");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ return ret;
+}
+
+#if !defined(_WIN32) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from,
+ unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+{
+ int tlen = 0;
+ int pad_type;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_public_decrypt");
+
+ if (rsa == NULL || rsa->internal == NULL || from == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
+ }
+
+ switch (padding) {
+ case RSA_PKCS1_PADDING:
+ pad_type = WC_RSA_PKCSV15_PAD;
+ break;
+ case RSA_PKCS1_OAEP_PADDING:
+ pad_type = WC_RSA_OAEP_PAD;
+ break;
+ case RSA_PKCS1_PSS_PADDING:
+ pad_type = WC_RSA_PSS_PAD;
+ break;
+ case RSA_NO_PADDING:
+ pad_type = WC_RSA_NO_PAD;
+ break;
+ default:
+ WOLFSSL_MSG("wolfSSL_RSA_public_decrypt unsupported padding");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (rsa->inSet == 0)
+ {
+ WOLFSSL_MSG("No RSA internal set, do it");
+
+ if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("SetRsaInternal failed");
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ /* size of 'to' buffer must be size of RSA key */
+ tlen = wc_RsaSSL_Verify_ex(from, flen, to, wolfSSL_RSA_size(rsa),
+ (RsaKey*)rsa->internal, pad_type);
+ if (tlen <= 0)
+ WOLFSSL_MSG("wolfSSL_RSA_public_decrypt failed");
+ else {
+ WOLFSSL_MSG("wolfSSL_RSA_public_decrypt success");
+ }
+ return tlen;
+}
+#endif /* !defined(_WIN32) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) */
+
+/* RSA private encrypt calls wc_RsaSSL_Sign. Similar function set up as RSA
+ * public decrypt.
+ *
+ * len Length of input buffer
+ * in Input buffer to sign
+ * out Output buffer (expected to be greater than or equal to RSA key size)
+ * rsa Key to use for encryption
+ * padding Type of RSA padding to use.
+ */
+int wolfSSL_RSA_private_encrypt(int len, unsigned char* in,
+ unsigned char* out, WOLFSSL_RSA* rsa, int padding)
+{
+ int sz = 0;
+ WC_RNG* rng = NULL;
+#if !defined(WC_RSA_BLINDING) || defined(HAVE_USER_RSA)
+ WC_RNG rng_lcl;
+#endif
+ RsaKey* key;
+
+ WOLFSSL_MSG("wolfSSL_RSA_private_encrypt");
+
+ if (len < 0 || rsa == NULL || rsa->internal == NULL || in == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return 0;
+ }
+
+ if (padding != RSA_PKCS1_PADDING && padding != RSA_PKCS1_PSS_PADDING) {
+ WOLFSSL_MSG("wolfSSL_RSA_private_encrypt unsupported padding");
+ return 0;
+ }
+
+ if (rsa->inSet == 0)
+ {
+ WOLFSSL_MSG("Setting internal RSA structure");
+
+ if (SetRsaInternal(rsa) != SSL_SUCCESS) {
+ WOLFSSL_MSG("SetRsaInternal failed");
+ return 0;
+ }
+ }
+
+ key = (RsaKey*)rsa->internal;
+#if defined(WC_RSA_BLINDING) && !defined(HAVE_USER_RSA)
+ rng = key->rng;
+#else
+ rng = &rng_lcl;
+ #ifndef HAVE_FIPS
+ if (wc_InitRng_ex(rng, key->heap, INVALID_DEVID) != 0)
+ #else
+ if (wc_InitRng(rng) != 0)
+ #endif
+ {
+ WOLFSSL_MSG("Error with random number");
+ return SSL_FATAL_ERROR;
+ }
+#endif
+
+ /* size of output buffer must be size of RSA key */
+ sz = wc_RsaSSL_Sign(in, (word32)len, out, wolfSSL_RSA_size(rsa), key, rng);
+ #if !defined(WC_RSA_BLINDING) || defined(HAVE_USER_RSA)
+ if (wc_FreeRng(rng) != 0) {
+ WOLFSSL_MSG("Error freeing random number generator");
+ return SSL_FATAL_ERROR;
+ }
+ #endif
+ if (sz <= 0) {
+ WOLFSSL_LEAVE("wolfSSL_RSA_private_encrypt", sz);
+ return 0;
+ }
+
+ return sz;
+}
+#endif /* HAVE_USER_RSA */
+#endif
+
+
+/* frees all nodes in the current threads error queue
+ *
+ * id thread id. ERR_remove_state is depreciated and id is ignored. The
+ * current threads queue will be free'd.
+ */
+void wolfSSL_ERR_remove_state(unsigned long id)
+{
+ WOLFSSL_ENTER("wolfSSL_ERR_remove_state");
+ (void)id;
+ if (wc_ERR_remove_state() != 0) {
+ WOLFSSL_MSG("Error with removing the state");
+ }
+}
+
+
+WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void)
+{
+ static int ctx; /* wolfcrypt doesn't now need ctx */
+
+ WOLFSSL_MSG("wolfSSL_BN_CTX_new");
+ return (WOLFSSL_BN_CTX*)&ctx;
+
+}
+
+void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx)
+{
+ (void)ctx;
+ WOLFSSL_MSG("wolfSSL_BN_CTX_init");
+}
+
+
+void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx)
+{
+ (void)ctx;
+ WOLFSSL_MSG("wolfSSL_BN_CTX_free");
+ /* do free since static ctx that does nothing */
+}
+
+/* WOLFSSL_SUCCESS on ok */
+int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
+ const WOLFSSL_BIGNUM* b)
+{
+ WOLFSSL_MSG("wolfSSL_BN_sub");
+
+ if (r == NULL || a == NULL || b == NULL)
+ return 0;
+
+ if (mp_sub((mp_int*)a->internal,(mp_int*)b->internal,
+ (mp_int*)r->internal) == MP_OKAY)
+ return WOLFSSL_SUCCESS;
+
+ WOLFSSL_MSG("wolfSSL_BN_sub mp_sub failed");
+ return 0;
+}
+
+/* WOLFSSL_SUCCESS on ok */
+int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
+ const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c)
+{
+ (void)c;
+ WOLFSSL_MSG("wolfSSL_BN_mod");
+
+ if (r == NULL || a == NULL || b == NULL)
+ return 0;
+
+ if (mp_mod((mp_int*)a->internal,(mp_int*)b->internal,
+ (mp_int*)r->internal) == MP_OKAY)
+ return WOLFSSL_SUCCESS;
+
+ WOLFSSL_MSG("wolfSSL_BN_mod mp_mod failed");
+ return 0;
+}
+
+
+/* r = (a^p) % m */
+int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
+ const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_BN_mod_exp");
+
+ (void) ctx;
+ if (r == NULL || a == NULL || p == NULL || m == NULL) {
+ WOLFSSL_MSG("Bad Argument");
+ return WOLFSSL_FAILURE;
+ }
+
+ if ((ret = mp_exptmod((mp_int*)a->internal,(mp_int*)p->internal,
+ (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) {
+ return WOLFSSL_SUCCESS;
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_BN_mod_exp", ret);
+ (void)ret;
+
+ return WOLFSSL_FAILURE;
+}
+
+/* r = (a * p) % m */
+int wolfSSL_BN_mod_mul(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
+ const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_BN_mod_mul");
+
+ (void) ctx;
+ if (r == NULL || a == NULL || p == NULL || m == NULL) {
+ WOLFSSL_MSG("Bad Argument");
+ return SSL_FAILURE;
+ }
+
+ if ((ret = mp_mulmod((mp_int*)a->internal,(mp_int*)p->internal,
+ (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) {
+ return SSL_SUCCESS;
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_BN_mod_mul", ret);
+ (void)ret;
+
+ return SSL_FAILURE;
+}
+
+#ifdef OPENSSL_EXTRA
+const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void)
+{
+ WOLFSSL_MSG("wolfSSL_BN_value_one");
+
+ if (bn_one == NULL) {
+ bn_one = wolfSSL_BN_new();
+ if (bn_one) {
+ if (mp_set_int((mp_int*)bn_one->internal, 1) != MP_OKAY) {
+ /* handle error by freeing BN and returning NULL */
+ wolfSSL_BN_free(bn_one);
+ bn_one = NULL;
+ }
+ }
+ }
+
+ return bn_one;
+}
+#endif
+
+/* return compliant with OpenSSL
+ * size of BIGNUM in bytes, 0 if error */
+int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn)
+{
+ WOLFSSL_ENTER("wolfSSL_BN_num_bytes");
+
+ if (bn == NULL || bn->internal == NULL)
+ return WOLFSSL_FAILURE;
+
+ return mp_unsigned_bin_size((mp_int*)bn->internal);
+}
+
+/* return compliant with OpenSSL
+ * size of BIGNUM in bits, 0 if error */
+int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn)
+{
+ WOLFSSL_ENTER("wolfSSL_BN_num_bits");
+
+ if (bn == NULL || bn->internal == NULL)
+ return WOLFSSL_FAILURE;
+
+ return mp_count_bits((mp_int*)bn->internal);
+}
+
+int wolfSSL_BN_is_negative(const WOLFSSL_BIGNUM* bn)
+{
+ if (bn == NULL)
+ return WOLFSSL_FAILURE;
+
+ return mp_isneg((mp_int*)bn->internal);
+}
+
+/* return compliant with OpenSSL
+ * 1 if BIGNUM is zero, 0 else */
+int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn)
+{
+ WOLFSSL_MSG("wolfSSL_BN_is_zero");
+
+ if (bn == NULL || bn->internal == NULL)
+ return WOLFSSL_FAILURE;
+
+ if (mp_iszero((mp_int*)bn->internal) == MP_YES)
+ return WOLFSSL_SUCCESS;
+
+ return WOLFSSL_FAILURE;
+}
+
+/* return compliant with OpenSSL
+ * 1 if BIGNUM is one, 0 else */
+int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn)
+{
+ WOLFSSL_MSG("wolfSSL_BN_is_one");
+
+ if (bn == NULL || bn->internal == NULL)
+ return WOLFSSL_FAILURE;
+
+ if (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ)
+ return WOLFSSL_SUCCESS;
+
+ return WOLFSSL_FAILURE;
+}
+
+/* return compliant with OpenSSL
+ * 1 if BIGNUM is odd, 0 else */
+int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn)
+{
+ WOLFSSL_MSG("wolfSSL_BN_is_odd");
+
+ if (bn == NULL || bn->internal == NULL)
+ return WOLFSSL_FAILURE;
+
+ if (mp_isodd((mp_int*)bn->internal) == MP_YES)
+ return WOLFSSL_SUCCESS;
+
+ return WOLFSSL_FAILURE;
+}
+
+/* return compliant with OpenSSL
+ * 1 if BIGNUM is word, 0 else */
+int wolfSSL_BN_is_word(const WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w)
+{
+ WOLFSSL_ENTER("wolfSSL_BN_is_word");
+
+ if (bn == NULL || bn->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (mp_isword((mp_int*)bn->internal, w) == MP_YES) {
+ return WOLFSSL_SUCCESS;
+ }
+
+ return WOLFSSL_FAILURE;
+}
+
+/* return compliant with OpenSSL
+ * -1 if a < b, 0 if a == b and 1 if a > b
+ */
+int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b)
+{
+ int ret;
+
+ WOLFSSL_MSG("wolfSSL_BN_cmp");
+
+ if (a == NULL || a->internal == NULL || b == NULL || b->internal == NULL)
+ return WOLFSSL_FATAL_ERROR;
+
+ ret = mp_cmp((mp_int*)a->internal, (mp_int*)b->internal);
+
+ return (ret == MP_EQ ? 0 : (ret == MP_GT ? 1 : -1));
+}
+
+/* return compliant with OpenSSL
+ * length of BIGNUM in bytes, -1 if error */
+int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r)
+{
+ WOLFSSL_MSG("wolfSSL_BN_bn2bin");
+
+ if (bn == NULL || bn->internal == NULL) {
+ WOLFSSL_MSG("NULL bn error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (r == NULL)
+ return mp_unsigned_bin_size((mp_int*)bn->internal);
+
+ if (mp_to_unsigned_bin((mp_int*)bn->internal, r) != MP_OKAY) {
+ WOLFSSL_MSG("mp_to_unsigned_bin error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ return mp_unsigned_bin_size((mp_int*)bn->internal);
+}
+
+
+WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len,
+ WOLFSSL_BIGNUM* ret)
+{
+ int weOwn = 0;
+
+ WOLFSSL_MSG("wolfSSL_BN_bin2bn");
+
+ /* if ret is null create a BN */
+ if (ret == NULL) {
+ ret = wolfSSL_BN_new();
+ weOwn = 1;
+ if (ret == NULL)
+ return NULL;
+ }
+
+ /* check ret and ret->internal then read in value */
+ if (ret && ret->internal) {
+ if (mp_read_unsigned_bin((mp_int*)ret->internal, str, len) != 0) {
+ WOLFSSL_MSG("mp_read_unsigned_bin failure");
+ if (weOwn)
+ wolfSSL_BN_free(ret);
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+
+ return ret;
+}
+
+/* return compliant with OpenSSL
+ * 1 if success, 0 if error */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n)
+{
+ (void)bn;
+ (void)n;
+ WOLFSSL_ENTER("wolfSSL_BN_mask_bits");
+ WOLFSSL_STUB("BN_mask_bits");
+ return SSL_FAILURE;
+}
+#endif
+
+
+/* WOLFSSL_SUCCESS on ok */
+int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
+{
+ int ret = 0;
+ int len = bits / 8;
+ int initTmpRng = 0;
+ WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG* tmpRNG = NULL;
+ byte* buff = NULL;
+#else
+ WC_RNG tmpRNG[1];
+ byte buff[1024];
+#endif
+
+ (void)top;
+ (void)bottom;
+ WOLFSSL_MSG("wolfSSL_BN_rand");
+
+ if (bits % 8)
+ len++;
+
+#ifdef WOLFSSL_SMALL_STACK
+ buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (buff == NULL || tmpRNG == NULL) {
+ XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+ return ret;
+ }
+#endif
+
+ if (bn == NULL || bn->internal == NULL)
+ WOLFSSL_MSG("Bad function arguments");
+ else if (wc_InitRng(tmpRNG) == 0) {
+ rng = tmpRNG;
+ initTmpRng = 1;
+ }
+ else if (initGlobalRNG)
+ rng = &globalRNG;
+
+ if (rng) {
+ if (wc_RNG_GenerateBlock(rng, buff, len) != 0)
+ WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
+ else {
+ buff[0] |= 0x80 | 0x40;
+ buff[len-1] |= 0x01;
+
+ if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY)
+ WOLFSSL_MSG("mp read bin failed");
+ else
+ ret = WOLFSSL_SUCCESS;
+ }
+ }
+
+ if (initTmpRng)
+ wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+ return ret;
+}
+
+
+/* WOLFSSL_SUCCESS on ok
+ * code is same as wolfSSL_BN_rand except for how top and bottom is handled.
+ * top -1 then leave most sig bit alone
+ * top 0 then most sig is set to 1
+ * top is 1 then first two most sig bits are 1
+ *
+ * bottom is hot then odd number */
+int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
+{
+ int ret = 0;
+ int len = bits / 8;
+ int initTmpRng = 0;
+ WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG* tmpRNG = NULL;
+ byte* buff = NULL;
+#else
+ WC_RNG tmpRNG[1];
+ byte buff[1024];
+#endif
+
+ WOLFSSL_MSG("wolfSSL_BN_rand");
+
+ if (bits % 8)
+ len++;
+
+#ifdef WOLFSSL_SMALL_STACK
+ buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (buff == NULL || tmpRNG == NULL) {
+ XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+#endif
+
+ if (bn == NULL || bn->internal == NULL)
+ WOLFSSL_MSG("Bad function arguments");
+ else if (wc_InitRng(tmpRNG) == 0) {
+ rng = tmpRNG;
+ initTmpRng = 1;
+ }
+ else if (initGlobalRNG)
+ rng = &globalRNG;
+
+ if (rng) {
+ if (wc_RNG_GenerateBlock(rng, buff, len) != 0)
+ WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
+ else {
+ switch (top) {
+ case -1:
+ break;
+
+ case 0:
+ buff[0] |= 0x80;
+ break;
+
+ case 1:
+ buff[0] |= 0x80 | 0x40;
+ break;
+ }
+
+ if (bottom == 1) {
+ buff[len-1] |= 0x01;
+ }
+
+ if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY)
+ WOLFSSL_MSG("mp read bin failed");
+ else
+ ret = WOLFSSL_SUCCESS;
+ }
+ }
+
+ if (initTmpRng)
+ wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+ return ret;
+}
+
+/* return code compliant with OpenSSL :
+ * 1 if bit set, 0 else
+ */
+int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n)
+{
+ if (bn == NULL || bn->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+ return mp_is_bit_set((mp_int*)bn->internal, (mp_digit)n);
+}
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 else
+ */
+int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM* bn, int n)
+{
+ if (bn == NULL || bn->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (mp_set_bit((mp_int*)bn->internal, n) != MP_OKAY) {
+ WOLFSSL_MSG("mp_set_bit error");
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_BN_clear_bit(WOLFSSL_BIGNUM* bn, int n)
+{
+ int ret = WOLFSSL_FAILURE;
+#ifndef WOLFSSL_SMALL_STACK
+ mp_int tmp[1];
+#else
+ mp_int* tmp = NULL;
+#endif
+
+ if (bn == NULL || bn->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ goto cleanup;
+ }
+ if (mp_is_bit_set((mp_int*)bn->internal, n)) {
+#ifdef WOLFSSL_SMALL_STACK
+ tmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+ if (tmp == NULL) {
+ goto cleanup;
+ }
+#endif
+ if (mp_init(tmp) != MP_OKAY) {
+ goto cleanup;
+ }
+ if (mp_set_bit(tmp, n) != MP_OKAY) {
+ goto cleanup;
+ }
+ if (mp_sub((mp_int*)bn->internal, tmp, (mp_int*)bn->internal) != MP_OKAY) {
+ goto cleanup;
+ }
+ }
+
+ ret = WOLFSSL_SUCCESS;
+cleanup:
+ mp_clear(tmp);
+#ifdef WOLFSSL_SMALL_STACK
+ if (tmp)
+ XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
+ return ret;
+}
+
+
+/* WOLFSSL_SUCCESS on ok */
+/* Note on use: this function expects str to be an even length. It is
+ * converting pairs of bytes into 8-bit values. As an example, the RSA
+ * public exponent is commonly 0x010001. To get it to convert, you need
+ * to pass in the string "010001", it will fail if you use "10001". This
+ * is an affect of how Base16_Decode() works.
+ */
+int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str)
+{
+ int ret = 0;
+ word32 decSz = 1024;
+#ifdef WOLFSSL_SMALL_STACK
+ byte* decoded;
+#else
+ byte decoded[1024];
+#endif
+ int weOwn = 0;
+ int strLen;
+
+ WOLFSSL_MSG("wolfSSL_BN_hex2bn");
+
+#ifdef WOLFSSL_SMALL_STACK
+ decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_DER);
+ if (decoded == NULL)
+ return ret;
+#endif
+
+ if (str == NULL || str[0] == '\0') {
+ WOLFSSL_MSG("Bad function argument");
+ ret = WOLFSSL_FAILURE;
+ } else {
+ strLen = (int)XSTRLEN(str);
+ /* ignore trailing new lines */
+ while (str[strLen-1] == '\n' && strLen > 0) strLen--;
+
+ if (Base16_Decode((byte*)str, strLen, decoded, &decSz) < 0)
+ WOLFSSL_MSG("Bad Base16_Decode error");
+ else if (bn == NULL)
+ ret = decSz;
+ else {
+ if (*bn == NULL) {
+ *bn = wolfSSL_BN_new();
+ if (*bn != NULL) {
+ weOwn = 1;
+ }
+ }
+
+ if (*bn == NULL)
+ WOLFSSL_MSG("BN new failed");
+ else if (wolfSSL_BN_bin2bn(decoded, decSz, *bn) == NULL) {
+ WOLFSSL_MSG("Bad bin2bn error");
+ if (weOwn == 1) {
+ wolfSSL_BN_free(*bn); /* Free new BN */
+ }
+ }
+ else
+ ret = WOLFSSL_SUCCESS;
+ }
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(decoded, NULL, DYNAMIC_TYPE_DER);
+#endif
+
+ return ret;
+}
+
+
+WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn)
+{
+ WOLFSSL_BIGNUM* ret;
+
+ WOLFSSL_MSG("wolfSSL_BN_dup");
+
+ if (bn == NULL || bn->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return NULL;
+ }
+
+ ret = wolfSSL_BN_new();
+ if (ret == NULL) {
+ WOLFSSL_MSG("bn new error");
+ return NULL;
+ }
+
+ if (mp_copy((mp_int*)bn->internal, (mp_int*)ret->internal) != MP_OKAY) {
+ WOLFSSL_MSG("mp_copy error");
+ wolfSSL_BN_free(ret);
+ return NULL;
+ }
+
+ ret->neg = bn->neg;
+
+ return ret;
+}
+
+
+WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn)
+{
+ WOLFSSL_MSG("wolfSSL_BN_copy");
+
+ if (r == NULL || bn == NULL) {
+ WOLFSSL_MSG("r or bn NULL error");
+ return NULL;
+ }
+
+ if (mp_copy((mp_int*)bn->internal, (mp_int*)r->internal) != MP_OKAY) {
+ WOLFSSL_MSG("mp_copy error");
+ return NULL;
+ }
+
+ r->neg = bn->neg;
+
+ return r;
+}
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 else
+ */
+int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w)
+{
+ WOLFSSL_MSG("wolfSSL_BN_set_word");
+
+ if (bn == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY) {
+ WOLFSSL_MSG("mp_init_set_int error");
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+/* Returns the big number as an unsigned long if possible.
+ *
+ * bn big number structure to get value from
+ *
+ * Returns value or 0xFFFFFFFFL if bigger than unsigned long.
+ */
+unsigned long wolfSSL_BN_get_word(const WOLFSSL_BIGNUM* bn)
+{
+ mp_int* mp;
+
+ WOLFSSL_MSG("wolfSSL_BN_get_word");
+
+ if (bn == NULL) {
+ WOLFSSL_MSG("Invalid argument");
+ return 0;
+ }
+
+ if (wolfSSL_BN_num_bytes(bn) > (int)sizeof(unsigned long)) {
+ WOLFSSL_MSG("bignum is larger than unsigned long");
+ return 0xFFFFFFFFL;
+ }
+ mp = (mp_int*)bn->internal;
+
+ return (unsigned long)(mp->dp[0]);
+}
+
+/* return code compliant with OpenSSL :
+ * number length in decimal if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str)
+{
+ (void)bn;
+ (void)str;
+
+ WOLFSSL_MSG("wolfSSL_BN_dec2bn");
+ WOLFSSL_STUB("BN_dec2bn");
+ return SSL_FAILURE;
+}
+#endif
+
+#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY)
+char *wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn)
+{
+ int len = 0;
+ char *buf;
+
+ WOLFSSL_MSG("wolfSSL_BN_bn2dec");
+
+ if (bn == NULL || bn->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return NULL;
+ }
+
+ if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_DEC, &len) != MP_OKAY) {
+ WOLFSSL_MSG("mp_radix_size failure");
+ return NULL;
+ }
+
+ buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (buf == NULL) {
+ WOLFSSL_MSG("BN_bn2dec malloc buffer failure");
+ return NULL;
+ }
+
+ if (mp_todecimal((mp_int*)bn->internal, buf) != MP_OKAY) {
+ XFREE(buf, NULL, DYNAMIC_TYPE_ECC);
+ return NULL;
+ }
+
+ return buf;
+}
+#else
+char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn)
+{
+ (void)bn;
+
+ WOLFSSL_MSG("wolfSSL_BN_bn2dec");
+
+ return NULL;
+}
+#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 else
+ */
+int wolfSSL_BN_lshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n)
+{
+ WOLFSSL_MSG("wolfSSL_BN_lshift");
+
+ if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){
+ WOLFSSL_MSG("bn NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (mp_mul_2d((mp_int*)bn->internal, n, (mp_int*)r->internal) != MP_OKAY) {
+ WOLFSSL_MSG("mp_mul_2d error");
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 else
+ */
+int wolfSSL_BN_rshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n)
+{
+ WOLFSSL_MSG("wolfSSL_BN_rshift");
+
+ if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){
+ WOLFSSL_MSG("bn NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (mp_div_2d((mp_int*)bn->internal, n,
+ (mp_int*)r->internal, NULL) != MP_OKAY) {
+ WOLFSSL_MSG("mp_mul_2d error");
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 else
+ */
+int wolfSSL_BN_add_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w)
+{
+ WOLFSSL_MSG("wolfSSL_BN_add_word");
+
+ if (bn == NULL || bn->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (mp_add_d((mp_int*)bn->internal, w, (mp_int*)bn->internal) != MP_OKAY) {
+ WOLFSSL_MSG("mp_add_d error");
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 else
+ */
+int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b)
+{
+ WOLFSSL_MSG("wolfSSL_BN_add");
+
+ if (r == NULL || r->internal == NULL || a == NULL || a->internal == NULL ||
+ b == NULL || b->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (mp_add((mp_int*)a->internal, (mp_int*)b->internal,
+ (mp_int*)r->internal) != MP_OKAY) {
+ WOLFSSL_MSG("mp_add_d error");
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* r = a + b (mod m) */
+int wolfSSL_BN_mod_add(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
+ const WOLFSSL_BIGNUM *b, const WOLFSSL_BIGNUM *m,
+ WOLFSSL_BN_CTX *ctx)
+{
+ (void)ctx;
+ WOLFSSL_MSG("wolfSSL_BN_add");
+
+ if (r == NULL || r->internal == NULL ||
+ a == NULL || a->internal == NULL ||
+ b == NULL || b->internal == NULL ||
+ m == NULL || m->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (mp_addmod((mp_int*)a->internal, (mp_int*)b->internal,
+ (mp_int*)m->internal, (mp_int*)r->internal) != MP_OKAY) {
+ WOLFSSL_MSG("mp_add_d error");
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+#ifdef WOLFSSL_KEY_GEN
+
+/* return code compliant with OpenSSL :
+ * 1 if prime, 0 if not, -1 if error
+ */
+int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks,
+ WOLFSSL_BN_CTX *ctx, WOLFSSL_BN_GENCB *cb)
+{
+ WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG* tmpRNG = NULL;
+#else
+ WC_RNG tmpRNG[1];
+#endif
+ int initTmpRng = 0;
+ int res = MP_NO;
+
+ (void)ctx;
+ (void)cb;
+
+ WOLFSSL_MSG("wolfSSL_BN_is_prime_ex");
+
+ if (bn == NULL || bn->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (tmpRNG == NULL)
+ return WOLFSSL_FAILURE;
+#endif
+ if (wc_InitRng(tmpRNG) == 0) {
+ rng = tmpRNG;
+ initTmpRng = 1;
+ }
+ else {
+ WOLFSSL_MSG("Bad RNG Init, trying global");
+ if (initGlobalRNG == 0) {
+ WOLFSSL_MSG("Global RNG no Init");
+ }
+ else
+ rng = &globalRNG;
+ }
+
+ if (rng) {
+ if (mp_prime_is_prime_ex((mp_int*)bn->internal,
+ nbchecks, &res, rng) != MP_OKAY) {
+ WOLFSSL_MSG("mp_prime_is_prime_ex error");
+ res = MP_NO;
+ }
+ }
+
+ if (initTmpRng)
+ wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+ if (res != MP_YES) {
+ WOLFSSL_MSG("mp_prime_is_prime_ex not prime");
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ * (bn mod w) if success, -1 if error
+ */
+WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM *bn,
+ WOLFSSL_BN_ULONG w)
+{
+ WOLFSSL_BN_ULONG ret = 0;
+
+ WOLFSSL_MSG("wolfSSL_BN_mod_word");
+
+ if (bn == NULL || bn->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR;
+ }
+
+ if (mp_mod_d((mp_int*)bn->internal, w, &ret) != MP_OKAY) {
+ WOLFSSL_MSG("mp_add_d error");
+ return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR;
+ }
+
+ return ret;
+}
+#endif /* #ifdef WOLFSSL_KEY_GEN */
+
+char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn)
+{
+ int len = 0;
+ char *buf;
+
+ WOLFSSL_ENTER("wolfSSL_BN_bn2hex");
+
+ if (bn == NULL || bn->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return NULL;
+ }
+
+ if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_HEX, &len) != MP_OKAY) {
+ WOLFSSL_MSG("mp_radix_size failure");
+ return NULL;
+ }
+ len += 1; /* add one for null terminator */
+
+ buf = (char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (buf == NULL) {
+ WOLFSSL_MSG("BN_bn2hex malloc buffer failure");
+ return NULL;
+ }
+
+ if (mp_tohex((mp_int*)bn->internal, buf) != MP_OKAY) {
+ XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
+ return NULL;
+ }
+
+ return buf;
+}
+
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ * 1 if success, 0 if error
+ */
+int wolfSSL_BN_print_fp(XFILE fp, const WOLFSSL_BIGNUM *bn)
+{
+ char *buf;
+
+ WOLFSSL_ENTER("wolfSSL_BN_print_fp");
+
+ if (fp == XBADFILE || bn == NULL || bn->internal == NULL) {
+ WOLFSSL_MSG("bn NULL error");
+ return WOLFSSL_FAILURE;
+ }
+
+ buf = wolfSSL_BN_bn2hex(bn);
+ if (buf == NULL) {
+ WOLFSSL_MSG("wolfSSL_BN_bn2hex failure");
+ return WOLFSSL_FAILURE;
+ }
+
+ fprintf(fp, "%s", buf);
+ XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_FILESYSTEM */
+
+
+WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx)
+{
+ /* ctx is not used, return new Bignum */
+ (void)ctx;
+
+ WOLFSSL_ENTER("wolfSSL_BN_CTX_get");
+
+ return wolfSSL_BN_new();
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx)
+{
+ (void)ctx;
+
+ WOLFSSL_ENTER("wolfSSL_BN_CTX_start");
+ WOLFSSL_STUB("BN_CTX_start");
+ WOLFSSL_MSG("wolfSSL_BN_CTX_start TBD");
+}
+#endif
+
+
+WOLFSSL_BIGNUM *wolfSSL_BN_mod_inverse(WOLFSSL_BIGNUM *r,
+ WOLFSSL_BIGNUM *a,
+ const WOLFSSL_BIGNUM *n,
+ WOLFSSL_BN_CTX *ctx)
+{
+ int dynamic = 0;
+
+ /* ctx is not used */
+ (void)ctx;
+
+ WOLFSSL_ENTER("wolfSSL_BN_mod_inverse");
+
+ /* check parameter */
+ if (r == NULL) {
+ r = wolfSSL_BN_new();
+ if (r == NULL){
+ WOLFSSL_MSG("WolfSSL_BN_new() failed");
+ return NULL;
+ }
+ dynamic = 1;
+ }
+
+ if (a == NULL) {
+ WOLFSSL_MSG("a NULL error");
+ if (dynamic == 1) {
+ wolfSSL_BN_free(r);
+ }
+ return NULL;
+ }
+
+ if (n == NULL) {
+ WOLFSSL_MSG("n NULL error");
+ if (dynamic == 1) {
+ wolfSSL_BN_free(r);
+ }
+ return NULL;
+ }
+
+ /* Compute inverse of a modulo n and return r */
+ if (mp_invmod((mp_int *)a->internal,(mp_int *)n->internal,
+ (mp_int*)r->internal) == MP_VAL){
+ WOLFSSL_MSG("mp_invmod() error");
+ if (dynamic == 1) {
+ wolfSSL_BN_free(r);
+ }
+ return NULL;
+ }
+
+ return r;
+}
+#endif /* OPENSSL_EXTRA */
+#if (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) && !defined(NO_ASN)
+static int unprintable_char(char c)
+{
+ const unsigned char last_unprintable = 31;
+ const unsigned char LF = 10;
+ const unsigned char CR = 13;
+
+ if (c <= last_unprintable && c != LF && c != CR) {
+ return 1;
+ }
+ return 0;
+}
+
+int wolfSSL_ASN1_STRING_print(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str)
+{
+ int i;
+
+ WOLFSSL_ENTER("wolfSSL_ASN1_STRING_print");
+ if (out == NULL || str == NULL)
+ return WOLFSSL_FAILURE;
+
+ for (i=0; i < str->length; i++) {
+ if (unprintable_char(str->data[i])) {
+ str->data[i] = '.';
+ }
+ }
+
+ if (wolfSSL_BIO_write(out, str->data, str->length) != str->length){
+ return WOLFSSL_FAILURE;
+ }
+
+ return str->length;
+}
+#endif /* (WOLFSSL_QT || OPENSSL_ALL) && !NO_ASN */
+
+#if defined(OPENSSL_EXTRA)
+int wolfSSL_X509_check_ca(WOLFSSL_X509 *x509)
+{
+ WOLFSSL_ENTER("X509_check_ca");
+
+ if (x509 == NULL)
+ return WOLFSSL_FAILURE;
+ if (x509->isCa)
+ return 1;
+ if (x509->extKeyUsageCrit)
+ return 4;
+
+ return 0;
+}
+
+
+const char *wolfSSL_ASN1_tag2str(int tag)
+{
+ static const char *const tag_label[31] = {
+ "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", "NULL",
+ "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", "ENUMERATED",
+ "<ASN1 11>", "UTF8STRING", "<ASN1 13>", "<ASN1 14>", "<ASN1 15>",
+ "SEQUENCE", "SET", "NUMERICSTRING", "PRINTABLESTRING", "T61STRING",
+ "VIDEOTEXTSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME",
+ "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", "UNIVERSALSTRING",
+ "<ASN1 29>", "BMPSTRING"
+ };
+
+ if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
+ tag &= ~0x100;
+ if (tag < 0 || tag > 30)
+ return "(unknown)";
+ return tag_label[tag];
+}
+
+static int check_esc_char(char c, char *esc)
+{
+ char *ptr;
+
+ ptr = esc;
+ while(*ptr != 0){
+ if (c == *ptr)
+ return 1;
+ ptr++;
+ }
+ return 0;
+}
+
+int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str,
+ unsigned long flags)
+{
+ size_t str_len = 0, type_len = 0;
+ unsigned char *typebuf = NULL;
+ const char *hash="#";
+
+ WOLFSSL_ENTER("wolfSSL_ASN1_STRING_PRINT_ex");
+ if (out == NULL || str == NULL)
+ return WOLFSSL_FAILURE;
+
+ /* add ASN1 type tag */
+ if (flags & ASN1_STRFLGS_SHOW_TYPE){
+ const char *tag = wolfSSL_ASN1_tag2str(str->type);
+ /* colon len + tag len + null*/
+ type_len = XSTRLEN(tag) + 2;
+ typebuf = (unsigned char *)XMALLOC(type_len , NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (typebuf == NULL){
+ WOLFSSL_MSG("memory alloc failed.");
+ return WOLFSSL_FAILURE;
+ }
+ XMEMSET(typebuf, 0, type_len);
+ XSNPRINTF((char*)typebuf, (size_t)type_len , "%s:", tag);
+ type_len--;
+ }
+
+ /* dump hex */
+ if (flags & ASN1_STRFLGS_DUMP_ALL){
+ static const char hex_char[] = { '0', '1', '2', '3', '4', '5', '6',
+ '7','8', '9', 'A', 'B', 'C', 'D',
+ 'E', 'F' };
+ char hex_tmp[4];
+ char *str_ptr, *str_end;
+
+ if (type_len > 0){
+ if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){
+ XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+ str_len += type_len;
+ }
+ if (wolfSSL_BIO_write(out, hash, 1) != 1){
+ goto err_exit;
+ }
+ str_len++;
+ if (flags & ASN1_STRFLGS_DUMP_DER){
+ hex_tmp[0] = hex_char[str->type >> 4];
+ hex_tmp[1] = hex_char[str->type & 0xf];
+ hex_tmp[2] = hex_char[str->length >> 4];
+ hex_tmp[3] = hex_char[str->length & 0xf];
+ if (wolfSSL_BIO_write(out, hex_tmp, 4) != 4){
+ goto err_exit;
+ }
+ str_len += 4;
+ XMEMSET(hex_tmp, 0, 4);
+ }
+
+ str_ptr = str->data;
+ str_end = str->data + str->length;
+ while (str_ptr < str_end){
+ hex_tmp[0] = hex_char[*str_ptr >> 4];
+ hex_tmp[1] = hex_char[*str_ptr & 0xf];
+ if (wolfSSL_BIO_write(out, hex_tmp, 2) != 2){
+ goto err_exit;
+ }
+ str_ptr++;
+ str_len += 2;
+ }
+ if (type_len > 0)
+ XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return (int)str_len;
+ }
+
+ if (type_len > 0){
+ if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){
+ XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+ }
+ str_len += type_len;
+ }
+
+ if (flags & ASN1_STRFLGS_ESC_2253){
+ char esc_ch[] = "+;<>\\";
+ char* esc_ptr;
+
+ esc_ptr = str->data;
+ while (*esc_ptr != 0){
+ if (check_esc_char(*esc_ptr, esc_ch)){
+ if (wolfSSL_BIO_write(out,"\\", 1) != 1)
+ goto err_exit;
+ str_len++;
+ }
+ if (wolfSSL_BIO_write(out, esc_ptr, 1) != 1)
+ goto err_exit;
+ str_len++;
+ esc_ptr++;
+ }
+ if (type_len > 0)
+ XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return (int)str_len;
+ }
+
+ if (wolfSSL_BIO_write(out, str->data, str->length) != str->length){
+ goto err_exit;
+ }
+ str_len += str->length;
+ if (type_len > 0)
+ XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return (int)str_len;
+
+err_exit:
+ if (type_len > 0)
+ XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
+}
+
+#if !defined(NO_ASN_TIME) && !defined(USER_TIME) && !defined(TIME_OVERRIDES)
+WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_new(void)
+{
+ WOLFSSL_ASN1_TIME* ret = (WOLFSSL_ASN1_TIME*)
+ XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL, DYNAMIC_TYPE_OPENSSL);
+ if (!ret)
+ return NULL;
+ XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TIME));
+ return ret;
+}
+
+void wolfSSL_ASN1_TIME_free(WOLFSSL_ASN1_TIME* t)
+{
+ if (t) {
+ XFREE(t, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+
+WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME *s, time_t t,
+ int offset_day, long offset_sec)
+{
+ const time_t sec_per_day = 24*60*60;
+ struct tm* ts = NULL;
+ struct tm* tmpTime;
+ time_t t_adj = 0;
+ time_t offset_day_sec = 0;
+#if defined(NEED_TMP_TIME)
+ struct tm tmpTimeStorage;
+
+ tmpTime = &tmpTimeStorage;
+#else
+ tmpTime = NULL;
+#endif
+ (void)tmpTime;
+
+ WOLFSSL_ENTER("wolfSSL_ASN1_TIME_adj");
+
+ if (s == NULL){
+ s = wolfSSL_ASN1_TIME_new();
+ if (s == NULL){
+ return NULL;
+ }
+ }
+
+ /* compute GMT time with offset */
+ offset_day_sec = offset_day * sec_per_day;
+ t_adj = t + offset_day_sec + offset_sec;
+ ts = (struct tm *)XGMTIME(&t_adj, tmpTime);
+ if (ts == NULL){
+ WOLFSSL_MSG("failed to get time data.");
+ XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL);
+ return NULL;
+ }
+
+ /* create ASN1 time notation */
+ /* UTC Time */
+ if (ts->tm_year >= 50 && ts->tm_year < 150){
+ char utc_str[ASN_UTC_TIME_SIZE];
+ int utc_year = 0,utc_mon,utc_day,utc_hour,utc_min,utc_sec;
+
+ s->type = V_ASN1_UTCTIME;
+ s->length = ASN_UTC_TIME_SIZE;
+
+ if (ts->tm_year >= 50 && ts->tm_year < 100){
+ utc_year = ts->tm_year;
+ } else if (ts->tm_year >= 100 && ts->tm_year < 150){
+ utc_year = ts->tm_year - 100;
+ }
+ utc_mon = ts->tm_mon + 1;
+ utc_day = ts->tm_mday;
+ utc_hour = ts->tm_hour;
+ utc_min = ts->tm_min;
+ utc_sec = ts->tm_sec;
+ XSNPRINTF((char *)utc_str, sizeof(utc_str),
+ "%02d%02d%02d%02d%02d%02dZ",
+ utc_year, utc_mon, utc_day, utc_hour, utc_min, utc_sec);
+ XMEMCPY(s->data, (byte *)utc_str, s->length);
+ /* GeneralizedTime */
+ } else {
+ char gt_str[ASN_GENERALIZED_TIME_MAX];
+ int gt_year,gt_mon,gt_day,gt_hour,gt_min,gt_sec;
+
+ s->type = V_ASN1_GENERALIZEDTIME;
+ s->length = ASN_GENERALIZED_TIME_SIZE;
+
+ gt_year = ts->tm_year + 1900;
+ gt_mon = ts->tm_mon + 1;
+ gt_day = ts->tm_mday;
+ gt_hour = ts->tm_hour;
+ gt_min = ts->tm_min;
+ gt_sec = ts->tm_sec;
+ XSNPRINTF((char *)gt_str, sizeof(gt_str),
+ "%4d%02d%02d%02d%02d%02dZ",
+ gt_year, gt_mon, gt_day, gt_hour, gt_min,gt_sec);
+ XMEMCPY(s->data, (byte *)gt_str, s->length);
+ }
+
+ return s;
+}
+#endif /* !NO_ASN_TIME && !USER_TIME && !TIME_OVERRIDES */
+
+#ifndef NO_ASN_TIME
+/* not a compatibility function - length getter for opaque type */
+int wolfSSL_ASN1_TIME_get_length(WOLFSSL_ASN1_TIME *t)
+{
+ WOLFSSL_ENTER("wolfSSL_ASN1_TIME_get_length");
+ if (t == NULL)
+ return WOLFSSL_FAILURE;
+ return t->length;
+}
+/* not a compatibility function - data getter for opaque type */
+unsigned char* wolfSSL_ASN1_TIME_get_data(WOLFSSL_ASN1_TIME *t)
+{
+ WOLFSSL_ENTER("wolfSSL_ASN1_TIME_get_data");
+ if (t == NULL)
+ return NULL;
+ return t->data;
+}
+
+WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t,
+ WOLFSSL_ASN1_TIME **out)
+{
+ int time_type = 0;
+ WOLFSSL_ASN1_TIME *ret = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_generalizedtime");
+ if (t == NULL) {
+ WOLFSSL_MSG("Invalid ASN_TIME value");
+ } else {
+ time_type = t->type;
+ if (time_type != ASN_UTC_TIME && time_type != ASN_GENERALIZED_TIME){
+ WOLFSSL_MSG("Invalid ASN_TIME type.");
+ } else {
+ if (out == NULL || *out == NULL) {
+ ret = wolfSSL_ASN1_TIME_new();
+ if (ret == NULL){
+ WOLFSSL_MSG("memory alloc failed.");
+ }
+ } else {
+ ret = *out;
+ }
+ }
+ }
+
+ if (ret != NULL) {
+ if (time_type == ASN_GENERALIZED_TIME){
+ XMEMCPY(ret->data, t->data, ASN_GENERALIZED_TIME_SIZE);
+ } else { /* ASN_UTC_TIME */
+ /* convert UTC to generalized time */
+ ret->type = ASN_GENERALIZED_TIME;
+ ret->length = ASN_GENERALIZED_TIME_SIZE;
+ if (t->data[0] >= '5') {
+ ret->data[0] = '1'; ret->data[1] = '9';
+ } else {
+ ret->data[0] = '2'; ret->data[1] = '0';
+ }
+ XMEMCPY(&ret->data[2], t->data, ASN_UTC_TIME_SIZE);
+ }
+ }
+
+ return ret;
+}
+#endif /* !NO_ASN_TIME */
+
+#ifndef NO_ASN
+int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp)
+{
+ unsigned char *pptr = NULL;
+ char pad = 0 ;
+ unsigned char pad_val = 0;
+ int ret_size = 0;
+ unsigned char data1 = 0;
+ unsigned char neg = 0;
+ int i = 0;
+
+ WOLFSSL_ENTER("wolfSSL_i2c_ASN1_INTEGER");
+ if (a == NULL)
+ return WOLFSSL_FAILURE;
+
+ ret_size = a->intData[1];
+ if (ret_size == 0)
+ ret_size = 1;
+ else{
+ ret_size = (int)a->intData[1];
+ neg = a->negative;
+ data1 = a->intData[2];
+ if (ret_size == 1 && data1 == 0)
+ neg = 0;
+ /* 0x80 or greater positive number in first byte */
+ if (!neg && (data1 > 127)){
+ pad = 1;
+ pad_val = 0;
+ } else if (neg){
+ /* negative number */
+ if (data1 > 128){
+ pad = 1;
+ pad_val = 0xff;
+ } else if (data1 == 128){
+ for (i = 3; i < a->intData[1] + 2; i++){
+ if (a->intData[i]){
+ pad = 1;
+ pad_val = 0xff;
+ break;
+ }
+ }
+ }
+ }
+ ret_size += (int)pad;
+ }
+ if (pp == NULL)
+ return ret_size;
+
+ pptr = *pp;
+ if (pad)
+ *(pptr++) = pad_val;
+ if (a->intData[1] == 0)
+ *(pptr++) = 0;
+ else if (!neg){
+ /* positive number */
+ for (i=0; i < a->intData[1]; i++){
+ *pptr = a->intData[i+2];
+ pptr++;
+ }
+ } else {
+ /* negative number */
+ int str_len = 0;
+
+ /* 0 padding from end of buffer */
+ str_len = (int)a->intData[1];
+ pptr += a->intData[1] - 1;
+ while (!a->intData[str_len + 2] && str_len > 1){
+ *(pptr--) = 0;
+ str_len--;
+ }
+ /* 2's complement next octet */
+ *(pptr--) = ((a->intData[str_len + 1]) ^ 0xff) + 1;
+ str_len--;
+ /* Complement any octets left */
+ while (str_len > 0){
+ *(pptr--) = a->intData[str_len + 1] ^ 0xff;
+ str_len--;
+ }
+ }
+ *pp += ret_size;
+ return ret_size;
+}
+#endif /* !NO_ASN */
+
+
+#ifndef NO_CERTS
+int wolfSSL_X509_CA_num(WOLFSSL_X509_STORE* store)
+{
+ int i = 0;
+ int cnt_ret = 0;
+ Signer **table;
+
+ WOLFSSL_ENTER("wolfSSL_X509_CA_num");
+ if (store == NULL || store->cm == NULL){
+ WOLFSSL_MSG("invalid parameter");
+ return WOLFSSL_FAILURE;
+ }
+
+ table = store->cm->caTable;
+ if (table){
+ if (wc_LockMutex(&store->cm->caLock) == 0){
+ for (i = 0; i < CA_TABLE_SIZE; i++) {
+ Signer* signer = table[i];
+ while (signer) {
+ Signer* next = signer->next;
+ cnt_ret++;
+ signer = next;
+ }
+ }
+ wc_UnLockMutex(&store->cm->caLock);
+ }
+ }
+
+ return cnt_ret;
+}
+#endif /* !NO_CERTS */
+
+long wolfSSL_X509_get_version(const WOLFSSL_X509 *x509)
+{
+ int version = 0;
+
+ WOLFSSL_ENTER("wolfSSL_X509_get_version");
+
+ if (x509 == NULL){
+ WOLFSSL_MSG("invalid parameter");
+ return 0L;
+ }
+ version = x509->version;
+ if (version != 0)
+ return (long)version - 1L;
+
+ return 0L;
+}
+
+
+int wolfSSL_X509_get_signature_nid(const WOLFSSL_X509 *x)
+{
+ if (x == NULL)
+ return 0;
+
+ return oid2nid(x->sigOID, oidSigType);
+}
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_RSA)
+/* return compliant with OpenSSL
+ * RSA modulus size in bytes, -1 if error
+ */
+int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa)
+{
+ WOLFSSL_ENTER("wolfSSL_RSA_size");
+
+ if (rsa == NULL)
+ return WOLFSSL_FATAL_ERROR;
+ if (rsa->inSet == 0)
+ {
+ if (SetRsaInternal((WOLFSSL_RSA*)rsa) != SSL_SUCCESS) {
+ WOLFSSL_MSG("SetRsaInternal failed");
+ return 0;
+ }
+ }
+ return wc_RsaEncryptSize((RsaKey*)rsa->internal);
+}
+#endif
+
+#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) && \
+ !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+/* WolfSSL -> OpenSSL */
+int SetRsaExternal(WOLFSSL_RSA* rsa)
+{
+ RsaKey* key;
+ WOLFSSL_MSG("Entering SetRsaExternal");
+
+ if (rsa == NULL || rsa->internal == NULL) {
+ WOLFSSL_MSG("rsa key NULL error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ key = (RsaKey*)rsa->internal;
+
+ if (SetIndividualExternal(&rsa->n, &key->n) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa n key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (SetIndividualExternal(&rsa->e, &key->e) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa e key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (key->type == RSA_PRIVATE) {
+ if (SetIndividualExternal(&rsa->d, &key->d) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa d key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (SetIndividualExternal(&rsa->p, &key->p) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa p key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (SetIndividualExternal(&rsa->q, &key->q) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa q key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ #ifndef RSA_LOW_MEM
+ if (SetIndividualExternal(&rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa dP key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (SetIndividualExternal(&rsa->dmq1, &key->dQ) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa dQ key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (SetIndividualExternal(&rsa->iqmp, &key->u) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("rsa u key error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ #endif /* !RSA_LOW_MEM */
+ }
+ rsa->exSet = 1;
+
+ return WOLFSSL_SUCCESS;
+}
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* when calling SetIndividualExternal, mpi should be cleared by caller if no
+ * longer used. ie mp_free(mpi). This is to free data when fastmath is
+ * disabled since a copy of mpi is made by this function and placed into bn.
+ */
+int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi)
+{
+ byte dynamic = 0;
+
+ WOLFSSL_MSG("Entering SetIndividualExternal");
+
+ if (mpi == NULL || bn == NULL) {
+ WOLFSSL_MSG("mpi NULL error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (*bn == NULL) {
+ *bn = wolfSSL_BN_new();
+ if (*bn == NULL) {
+ WOLFSSL_MSG("SetIndividualExternal alloc failed");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ dynamic = 1;
+ }
+
+ if (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY) {
+ WOLFSSL_MSG("mp_copy error");
+ if (dynamic == 1) {
+ wolfSSL_BN_free(*bn);
+ }
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+static void InitwolfSSL_BigNum(WOLFSSL_BIGNUM* bn)
+{
+ if (bn) {
+ XMEMSET(bn, 0, sizeof(WOLFSSL_BIGNUM));
+ bn->neg = 0;
+ bn->internal = NULL;
+ }
+}
+
+
+WOLFSSL_BIGNUM* wolfSSL_BN_new(void)
+{
+ WOLFSSL_BIGNUM* external;
+ mp_int* mpi;
+
+ WOLFSSL_MSG("wolfSSL_BN_new");
+
+#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT)
+ mpi = (mp_int*) XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+ if (mpi == NULL) {
+ WOLFSSL_MSG("wolfSSL_BN_new malloc mpi failure");
+ return NULL;
+ }
+#endif
+
+ external = (WOLFSSL_BIGNUM*) XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL,
+ DYNAMIC_TYPE_BIGINT);
+ if (external == NULL) {
+ WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure");
+#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT)
+ XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
+ return NULL;
+ }
+
+#if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT)
+ mpi = &external->fp;
+#endif
+
+ InitwolfSSL_BigNum(external);
+ if (mp_init(mpi) != MP_OKAY) {
+ wolfSSL_BN_free(external);
+ return NULL;
+ }
+ external->internal = mpi;
+
+ return external;
+}
+
+
+#if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT)
+/* This function works without BN_free only with TFM */
+void wolfSSL_BN_init(WOLFSSL_BIGNUM* bn)
+{
+ if(bn == NULL)return;
+ WOLFSSL_MSG("wolfSSL_BN_init");
+ InitwolfSSL_BigNum(bn);
+ if (mp_init(&bn->fp) != MP_OKAY)
+ return;
+ bn->internal = (void *)&bn->fp;
+}
+#endif
+
+void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn)
+{
+ WOLFSSL_MSG("wolfSSL_BN_free");
+ if (bn) {
+ if (bn->internal) {
+ mp_int* bni = (mp_int*)bn->internal;
+ mp_free(bni);
+#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT)
+ XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
+ bn->internal = NULL;
+ }
+ XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT);
+ /* bn = NULL, don't try to access or double free it */
+ }
+}
+
+void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn)
+{
+ WOLFSSL_MSG("wolfSSL_BN_clear_free");
+ if (bn) {
+ if (bn->internal) {
+ mp_int* bni = (mp_int*)bn->internal;
+ mp_forcezero(bni);
+ }
+ wolfSSL_BN_free(bn);
+ }
+}
+
+void wolfSSL_BN_clear(WOLFSSL_BIGNUM* bn)
+{
+ WOLFSSL_MSG("wolfSSL_BN_clear");
+ if (bn && bn->internal) {
+ mp_forcezero((mp_int*)bn->internal);
+ }
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#if !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+static void InitwolfSSL_Rsa(WOLFSSL_RSA* rsa)
+{
+ if (rsa) {
+ XMEMSET(rsa, 0, sizeof(WOLFSSL_RSA));
+ }
+}
+
+
+void wolfSSL_RSA_free(WOLFSSL_RSA* rsa)
+{
+ WOLFSSL_ENTER("wolfSSL_RSA_free");
+
+ if (rsa) {
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+ int doFree = 0;
+ if (wc_LockMutex(&rsa->refMutex) != 0) {
+ WOLFSSL_MSG("Couldn't lock rsa mutex");
+ }
+
+ /* only free if all references to it are done */
+ rsa->refCount--;
+ if (rsa->refCount == 0) {
+ doFree = 1;
+ }
+ wc_UnLockMutex(&rsa->refMutex);
+
+ if (!doFree) {
+ return;
+ }
+
+ wc_FreeMutex(&rsa->refMutex);
+#endif
+
+ if (rsa->internal) {
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \
+ !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING)
+ WC_RNG* rng;
+
+ /* check if RNG is owned before freeing it */
+ if (rsa->ownRng) {
+ rng = ((RsaKey*)rsa->internal)->rng;
+ if (rng != NULL && rng != &globalRNG) {
+ wc_FreeRng(rng);
+ XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
+ }
+ }
+#endif /* WC_RSA_BLINDING */
+ wc_FreeRsaKey((RsaKey*)rsa->internal);
+ XFREE(rsa->internal, NULL, DYNAMIC_TYPE_RSA);
+ rsa->internal = NULL;
+ }
+ wolfSSL_BN_free(rsa->iqmp);
+ wolfSSL_BN_free(rsa->dmq1);
+ wolfSSL_BN_free(rsa->dmp1);
+ wolfSSL_BN_free(rsa->q);
+ wolfSSL_BN_free(rsa->p);
+ wolfSSL_BN_free(rsa->d);
+ wolfSSL_BN_free(rsa->e);
+ wolfSSL_BN_free(rsa->n);
+
+ #ifdef WC_RSA_BLINDING
+ if (rsa->rng && wc_FreeRng(rsa->rng) != 0) {
+ WOLFSSL_MSG("Issue freeing rng");
+ }
+ XFREE(rsa->rng, NULL, DYNAMIC_TYPE_RNG);
+ #endif
+
+#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
+ if (rsa->meth) {
+ wolfSSL_RSA_meth_free(rsa->meth);
+ }
+#endif
+
+ InitwolfSSL_Rsa(rsa); /* set back to NULLs for safety */
+
+ XFREE(rsa, NULL, DYNAMIC_TYPE_RSA);
+
+ /* rsa = NULL, don't try to access or double free it */
+ }
+}
+
+WOLFSSL_RSA* wolfSSL_RSA_new(void)
+{
+ WOLFSSL_RSA* external;
+ RsaKey* key;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_new");
+
+ key = (RsaKey*) XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
+ if (key == NULL) {
+ WOLFSSL_MSG("wolfSSL_RSA_new malloc RsaKey failure");
+ return NULL;
+ }
+
+ external = (WOLFSSL_RSA*) XMALLOC(sizeof(WOLFSSL_RSA), NULL,
+ DYNAMIC_TYPE_RSA);
+ if (external == NULL) {
+ WOLFSSL_MSG("wolfSSL_RSA_new malloc WOLFSSL_RSA failure");
+ XFREE(key, NULL, DYNAMIC_TYPE_RSA);
+ return NULL;
+ }
+
+ InitwolfSSL_Rsa(external);
+ if (wc_InitRsaKey(key, NULL) != 0) {
+ WOLFSSL_MSG("InitRsaKey WOLFSSL_RSA failure");
+ XFREE(external, NULL, DYNAMIC_TYPE_RSA);
+ XFREE(key, NULL, DYNAMIC_TYPE_RSA);
+ return NULL;
+ }
+
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \
+ !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING)
+ {
+ WC_RNG* rng;
+
+ rng = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (rng != NULL && wc_InitRng(rng) != 0) {
+ WOLFSSL_MSG("InitRng failure, attempting to use global RNG");
+ XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
+ rng = NULL;
+ }
+
+ external->ownRng = 1;
+ if (rng == NULL && initGlobalRNG) {
+ external->ownRng = 0;
+ rng = &globalRNG;
+ }
+
+ if (rng == NULL) {
+ WOLFSSL_MSG("wolfSSL_RSA_new no WC_RNG for blinding");
+ XFREE(external, NULL, DYNAMIC_TYPE_RSA);
+ XFREE(key, NULL, DYNAMIC_TYPE_RSA);
+ return NULL;
+ }
+
+ wc_RsaSetRNG(key, rng);
+ }
+#else
+ XMEMSET(key, 0, sizeof(RsaKey));
+#endif /* WC_RSA_BLINDING */
+
+ external->internal = key;
+ external->inSet = 0;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+ external->refCount = 1;
+ wc_InitMutex(&external->refMutex);
+#endif
+ return external;
+}
+#endif /* !NO_RSA && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */
+
+#if defined(OPENSSL_ALL) && defined(HAVE_PKCS7)
+PKCS7* wolfSSL_PKCS7_new(void)
+{
+ WOLFSSL_PKCS7* pkcs7;
+ int ret = 0;
+
+ pkcs7 = (WOLFSSL_PKCS7*)XMALLOC(sizeof(*pkcs7), NULL, DYNAMIC_TYPE_PKCS7);
+ if (pkcs7 != NULL) {
+ XMEMSET(pkcs7, 0, sizeof(*pkcs7));
+ ret = wc_PKCS7_Init(&pkcs7->pkcs7, NULL, INVALID_DEVID);
+ }
+
+ if (ret != 0 && pkcs7 != NULL)
+ XFREE(pkcs7, NULL, DYNAMIC_TYPE_PKCS7);
+
+ return (PKCS7*)pkcs7;
+}
+/******************************************************************************
+* wolfSSL_PKCS7_SIGNED_new - allocates PKCS7 and initialize it for a signed data
+*
+* RETURNS:
+* returns pointer to the PKCS7 structure on success, otherwise returns NULL
+*/
+PKCS7_SIGNED* wolfSSL_PKCS7_SIGNED_new(void)
+{
+ byte signedData[]= { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02};
+ PKCS7* pkcs7 = NULL;
+
+ if ((pkcs7 = wolfSSL_PKCS7_new()) == NULL)
+ return NULL;
+ pkcs7->contentOID = SIGNED_DATA;
+ if ((wc_PKCS7_SetContentType(pkcs7, signedData, sizeof(signedData))) < 0) {
+ if (pkcs7) {
+ wolfSSL_PKCS7_free(pkcs7);
+ return NULL;
+ }
+ }
+ return pkcs7;
+}
+
+void wolfSSL_PKCS7_free(PKCS7* pkcs7)
+{
+ WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
+
+ if (p7 != NULL) {
+ if (p7->data != NULL)
+ XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7);
+ wc_PKCS7_Free(&p7->pkcs7);
+ XFREE(p7, NULL, DYNAMIC_TYPE_PKCS7);
+ }
+}
+void wolfSSL_PKCS7_SIGNED_free(PKCS7_SIGNED* p7)
+{
+ wolfSSL_PKCS7_free(p7);
+ return;
+}
+PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, int len)
+{
+ WOLFSSL_PKCS7* pkcs7 = NULL;
+ word32 idx = 0;
+
+ if (in == NULL)
+ return NULL;
+
+ if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)
+ return NULL;
+
+ if (GetSequence(*in, &idx, &pkcs7->len, len) < 0) {
+ wolfSSL_PKCS7_free((PKCS7*)pkcs7);
+ return NULL;
+ }
+ pkcs7->len += idx;
+
+ pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7);
+ if (pkcs7->data == NULL) {
+ wolfSSL_PKCS7_free((PKCS7*)pkcs7);
+ return NULL;
+ }
+ XMEMCPY(pkcs7->data, *in, pkcs7->len);
+ *in += pkcs7->len;
+
+ if (p7 != NULL)
+ *p7 = (PKCS7*)pkcs7;
+ return (PKCS7*)pkcs7;
+}
+
+PKCS7* wolfSSL_d2i_PKCS7_bio(WOLFSSL_BIO* bio, PKCS7** p7)
+{
+ WOLFSSL_PKCS7* pkcs7;
+
+ if (bio == NULL)
+ return NULL;
+
+ if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)
+ return NULL;
+
+ pkcs7->len = wolfSSL_BIO_pending(bio);
+ pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7);
+ if (pkcs7->data == NULL) {
+ wolfSSL_PKCS7_free((PKCS7*)pkcs7);
+ return NULL;
+ }
+
+ if (wolfSSL_BIO_read(bio, pkcs7->data, pkcs7->len) != pkcs7->len) {
+ wolfSSL_PKCS7_free((PKCS7*)pkcs7);
+ return NULL;
+ }
+
+ if (p7 != NULL)
+ *p7 = (PKCS7*)pkcs7;
+ return (PKCS7*)pkcs7;
+}
+
+int wolfSSL_PKCS7_verify(PKCS7* pkcs7, WOLFSSL_STACK* certs,
+ WOLFSSL_X509_STORE* store, WOLFSSL_BIO* in,
+ WOLFSSL_BIO* out, int flags)
+{
+ int ret = 0;
+ unsigned char* mem = NULL;
+ int memSz = 0;
+ WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
+
+ if (pkcs7 == NULL)
+ return WOLFSSL_FAILURE;
+
+ if (in != NULL) {
+ if ((memSz = wolfSSL_BIO_get_mem_data(in, &mem)) < 0)
+ return WOLFSSL_FAILURE;
+
+ p7->pkcs7.content = mem;
+ p7->pkcs7.contentSz = memSz;
+ }
+
+ /* certs is the list of certificates to find the cert with issuer/serial. */
+ (void)certs;
+ /* store is the certificate store to use to verify signer certificate
+ * associated with the signers.
+ */
+ (void)store;
+
+ ret = wc_PKCS7_VerifySignedData_ex(&p7->pkcs7, NULL, 0, p7->data, p7->len,
+ NULL, 0);
+ if (ret != 0)
+ return WOLFSSL_FAILURE;
+
+ if ((flags & PKCS7_NOVERIFY) != PKCS7_NOVERIFY) {
+ /* All signer certificates are verified. */
+ return WOLFSSL_FAILURE;
+ }
+
+ if (out != NULL)
+ wolfSSL_BIO_write(out, p7->pkcs7.content, p7->pkcs7.contentSz);
+
+ return WOLFSSL_SUCCESS;
+}
+
+WOLFSSL_STACK* wolfSSL_PKCS7_get0_signers(PKCS7* pkcs7, WOLFSSL_STACK* certs,
+ int flags)
+{
+ WOLFSSL_STACK* signers = NULL;
+ WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
+
+ if (p7 == NULL)
+ return NULL;
+ /* Only PKCS#7 messages with a single cert that is the verifying certificate
+ * is supported.
+ */
+ if ((flags | PKCS7_NOINTERN) == PKCS7_NOINTERN)
+ return NULL;
+
+ signers = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+ DYNAMIC_TYPE_X509);
+ if (signers == NULL)
+ return NULL;
+
+ signers->num = 1;
+ signers->data.x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
+ DYNAMIC_TYPE_X509);
+ if (signers->data.x509 == NULL) {
+ XFREE(signers, NULL, DYNAMIC_TYPE_X509);
+ return NULL;
+ }
+
+ if (DecodeToX509(signers->data.x509, p7->pkcs7.singleCert,
+ p7->pkcs7.singleCertSz) != 0) {
+ XFREE(signers->data.x509, NULL, DYNAMIC_TYPE_X509);
+ XFREE(signers, NULL, DYNAMIC_TYPE_X509);
+ return NULL;
+ }
+
+ (void)certs;
+
+ return signers;
+}
+
+/******************************************************************************
+* wolfSSL_PEM_write_bio_PKCS7 - writes the PKCS7 data to BIO
+*
+* RETURNS:
+* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE
+*/
+
+int wolfSSL_PEM_write_bio_PKCS7(WOLFSSL_BIO* bio, PKCS7* p7)
+{
+#ifdef WOLFSSL_SMALL_STACK
+ byte* outputHead;
+ byte* outputFoot;
+#else
+ byte outputHead[2048];
+ byte outputFoot[2048];
+#endif
+ word32 outputHeadSz = 2048;
+ word32 outputFootSz = 2048;
+ word32 outputSz = 0;
+ byte* output = NULL;
+ byte* pem = NULL;
+ int pemSz = -1;
+ enum wc_HashType hashType;
+ byte hashBuf[WC_MAX_DIGEST_SIZE];
+ word32 hashSz = -1;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PKCS7()");
+
+ if (bio == NULL || p7 == NULL)
+ return WOLFSSL_FAILURE;
+
+#ifdef WOLFSSL_SMALL_STACK
+ outputHead = (byte*)XMALLOC(outputHeadSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (outputHead == NULL)
+ return MEMORY_E;
+
+ outputFoot = (byte*)XMALLOC(outputFootSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (outputFoot == NULL)
+ goto error;
+
+#endif
+
+ XMEMSET(hashBuf, 0, WC_MAX_DIGEST_SIZE);
+ XMEMSET(outputHead, 0, outputHeadSz);
+ XMEMSET(outputFoot, 0, outputFootSz);
+
+ hashType = wc_OidGetHash(p7->hashOID);
+ hashSz = wc_HashGetDigestSize(hashType);
+ if (hashSz > WC_MAX_DIGEST_SIZE)
+ return WOLFSSL_FAILURE;
+
+ /* only SIGNED_DATA is supported */
+ switch (p7->contentOID) {
+ case SIGNED_DATA:
+ break;
+ default:
+ WOLFSSL_MSG("Unknown PKCS#7 Type");
+ return WOLFSSL_FAILURE;
+ };
+
+ if ((wc_PKCS7_EncodeSignedData_ex(p7, hashBuf, hashSz,
+ outputHead, &outputHeadSz, outputFoot, &outputFootSz)) != 0)
+ return WOLFSSL_FAILURE;
+
+ outputSz = outputHeadSz + p7->contentSz + outputFootSz;
+ output = (byte*)XMALLOC(outputSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ if (!output)
+ return WOLFSSL_FAILURE;
+
+ XMEMSET(output, 0, outputSz);
+ outputSz = 0;
+ XMEMCPY(&output[outputSz], outputHead, outputHeadSz);
+ outputSz += outputHeadSz;
+ XMEMCPY(&output[outputSz], p7->content, p7->contentSz);
+ outputSz += p7->contentSz;
+ XMEMCPY(&output[outputSz], outputFoot, outputFootSz);
+ outputSz += outputFootSz;
+
+ /* get PEM size */
+ pemSz = wc_DerToPemEx(output, outputSz, NULL, 0, NULL, CERT_TYPE);
+ if (pemSz < 0)
+ goto error;
+
+ pemSz++; /* for '\0'*/
+
+ /* create PEM buffer and convert from DER to PEM*/
+ if ((pem = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER)) == NULL)
+ goto error;
+
+ XMEMSET(pem, 0, pemSz);
+
+ if (wc_DerToPemEx(output, outputSz, pem, pemSz, NULL, CERT_TYPE) < 0) {
+ goto error;
+ }
+ if ((wolfSSL_BIO_write(bio, pem, pemSz) == pemSz)) {
+ XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return WOLFSSL_SUCCESS;
+ }
+
+error:
+#ifdef WOLFSSL_SMALL_STACK
+ if (outputHead) {
+ XFREE(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ if (outputFoot) {
+ XFREE(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ if (output) {
+ XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ if (pem) {
+ XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ return WOLFSSL_FAILURE;
+}
+#endif /* OPENSSL_ALL && HAVE_PKCS7 */
+
+#if defined(OPENSSL_EXTRA)
+WOLFSSL_STACK* wolfSSL_sk_X509_new(void)
+{
+ WOLFSSL_STACK* s = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+ DYNAMIC_TYPE_X509);
+ if (s != NULL) {
+ XMEMSET(s, 0, sizeof(*s));
+ s->type = STACK_TYPE_X509;
+ }
+
+ return s;
+}
+#endif
+
+#ifdef OPENSSL_ALL
+int wolfSSL_PEM_write_bio_PKCS8PrivateKey(WOLFSSL_BIO* bio,
+ WOLFSSL_EVP_PKEY* pkey,
+ const WOLFSSL_EVP_CIPHER* enc,
+ char* passwd, int passwdSz,
+ pem_password_cb* cb, void* ctx)
+{
+ int ret = 0;
+ char password[NAME_SZ];
+ byte* key = NULL;
+ word32 keySz;
+ byte* pem = NULL;
+ int pemSz;
+ int type = PKCS8_PRIVATEKEY_TYPE;
+ int algId;
+ const byte* curveOid;
+ word32 oidSz;
+ int encAlgId;
+
+ if (bio == NULL || pkey == NULL)
+ return -1;
+
+ keySz = pkey->pkey_sz + 128;
+ key = (byte*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (key == NULL)
+ ret = MEMORY_E;
+
+ if (ret == 0 && enc != NULL && passwd == NULL) {
+ passwdSz = cb(password, sizeof(password), 1, ctx);
+ if (passwdSz < 0)
+ ret = WOLFSSL_FAILURE;
+ passwd = password;
+ }
+
+ if (ret == 0 && enc != NULL) {
+ WC_RNG rng;
+ ret = wc_InitRng(&rng);
+ if (ret == 0) {
+ #ifndef NO_DES3
+ if (enc == EVP_DES_CBC)
+ encAlgId = DESb;
+ else if (enc == EVP_DES_EDE3_CBC)
+ encAlgId = DES3b;
+ else
+ #endif
+ #if !defined(NO_AES) && defined(HAVE_AES_CBC)
+ #ifdef WOLFSSL_AES_256
+ if (enc == EVP_AES_256_CBC)
+ encAlgId = AES256CBCb;
+ else
+ #endif
+ #endif
+ ret = -1;
+ if (ret == 0) {
+ ret = TraditionalEnc((byte*)pkey->pkey.ptr, pkey->pkey_sz, key,
+ &keySz, passwd, passwdSz, PKCS5, PBES2,
+ encAlgId, NULL, 0, WC_PKCS12_ITT_DEFAULT,
+ &rng, NULL);
+ if (ret > 0) {
+ keySz = ret;
+ ret = 0;
+ }
+ }
+ wc_FreeRng(&rng);
+ }
+ type = PKCS8_ENC_PRIVATEKEY_TYPE;
+ }
+ if (ret == 0 && enc == NULL) {
+ type = PKCS8_PRIVATEKEY_TYPE;
+ if (pkey->type == EVP_PKEY_EC) {
+ algId = ECDSAk;
+ ret = wc_ecc_get_oid(pkey->ecc->group->curve_oid, &curveOid,
+ &oidSz);
+ }
+ else {
+ algId = RSAk;
+ curveOid = NULL;
+ oidSz = 0;
+ }
+
+ if (ret >= 0) {
+ ret = wc_CreatePKCS8Key(key, &keySz, (byte*)pkey->pkey.ptr,
+ pkey->pkey_sz, algId, curveOid, oidSz);
+ keySz = ret;
+ }
+ }
+
+ if (password == passwd)
+ XMEMSET(password, 0, passwdSz);
+
+ if (ret >= 0) {
+ pemSz = 2 * keySz + 2 * 64;
+ pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pem == NULL)
+ ret = MEMORY_E;
+ }
+
+ if (ret >= 0)
+ ret = wc_DerToPemEx(key, keySz, pem, pemSz, NULL, type);
+
+ if (key != NULL)
+ XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ if (ret >= 0) {
+ if (wolfSSL_BIO_write(bio, pem, ret) != ret)
+ ret = -1;
+ }
+
+ if (pem != NULL)
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return ret < 0 ? 0 : ret;
+
+}
+
+static int bio_get_data(WOLFSSL_BIO* bio, byte** data)
+{
+ int ret = 0;
+ byte* mem = NULL;
+#ifndef NO_FILESYSTEM
+ long memSz;
+ XFILE file;
+ long curr;
+#endif
+
+ if ((ret = wolfSSL_BIO_pending(bio)) > 0) {
+ }
+#ifndef NO_FILESYSTEM
+ else if (bio->type == WOLFSSL_BIO_FILE) {
+ if (wolfSSL_BIO_get_fp(bio, &file) != WOLFSSL_SUCCESS)
+ ret = BAD_FUNC_ARG;
+ if (ret == 0) {
+ curr = XFTELL(file);
+ if (curr < 0) {
+ ret = WOLFSSL_BAD_FILE;
+ }
+ if (XFSEEK(file, 0, XSEEK_END) != 0)
+ ret = WOLFSSL_BAD_FILE;
+ }
+ if (ret == 0) {
+ memSz = XFTELL(file);
+ if (memSz > MAX_WOLFSSL_FILE_SIZE || memSz < 0) {
+ ret = WOLFSSL_BAD_FILE;
+ }
+ }
+ if (ret == 0) {
+ memSz -= curr;
+ ret = (int)memSz;
+ if (XFSEEK(file, curr, SEEK_SET) != 0)
+ ret = WOLFSSL_BAD_FILE;
+ }
+ }
+#endif
+
+ if (ret > 0) {
+ mem = (byte*)XMALLOC(ret, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ if (mem == NULL) {
+ WOLFSSL_MSG("Memory error");
+ ret = MEMORY_E;
+ }
+ if (ret >= 0) {
+ if ((ret = wolfSSL_BIO_read(bio, mem, ret)) <= 0) {
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ ret = MEMORY_E;
+ mem = NULL;
+ }
+ }
+ }
+
+ *data = mem;
+
+ return ret;
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_BIO_set_init(WOLFSSL_BIO* bio, int init)
+{
+ WOLFSSL_STUB("wolfSSL_BIO_set_init");
+ (void)bio;
+ (void)init;
+}
+
+void wolfSSL_BIO_set_shutdown(WOLFSSL_BIO* bio, int shut)
+{
+ WOLFSSL_STUB("wolfSSL_BIO_set_shutdown");
+ (void)bio;
+ (void)shut;
+
+}
+int wolfSSL_BIO_get_shutdown(WOLFSSL_BIO* bio)
+{
+ WOLFSSL_STUB("wolfSSL_BIO_get_shutdown");
+ (void)bio;
+ return 0;
+}
+#endif /* NO_WOLFSSL_STUB */
+
+void wolfSSL_BIO_clear_retry_flags(WOLFSSL_BIO* bio)
+{
+ WOLFSSL_ENTER("wolfSSL_BIO_clear_retry_flags");
+
+ if (bio)
+ bio->flags &= ~(WOLFSSL_BIO_FLAG_READ|WOLFSSL_BIO_FLAG_RETRY);
+}
+
+int wolfSSL_BIO_should_retry(WOLFSSL_BIO *bio)
+{
+ int ret = 0;
+ if (bio != NULL) {
+ ret = (int)(bio->flags & WOLFSSL_BIO_FLAG_RETRY);
+ }
+
+ return ret;
+}
+
+/* DER data is PKCS#8 encrypted. */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio,
+ WOLFSSL_EVP_PKEY** pkey,
+ pem_password_cb* cb,
+ void* ctx)
+{
+ int ret;
+ byte* der;
+ int len;
+ byte* p;
+ char password[NAME_SZ];
+ int passwordSz;
+ word32 algId;
+ WOLFSSL_EVP_PKEY* key;
+
+ if ((len = bio_get_data(bio, &der)) < 0)
+ return NULL;
+
+ if (cb != NULL) {
+ passwordSz = cb(password, sizeof(password), PEM_PASS_READ, ctx);
+ if (passwordSz < 0) {
+ XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ return NULL;
+ }
+
+ ret = ToTraditionalEnc(der, len, password, passwordSz, &algId);
+ if (ret < 0) {
+ XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ return NULL;
+ }
+
+ XMEMSET(password, 0, passwordSz);
+ }
+
+ p = der;
+ key = wolfSSL_d2i_PrivateKey_EVP(pkey, &p, len);
+ XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ return key;
+}
+
+/* Detect which type of key it is before decoding. */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey(WOLFSSL_EVP_PKEY** pkey,
+ const unsigned char** pp,
+ long length)
+{
+ int ret;
+ WOLFSSL_EVP_PKEY* key = NULL;
+ const byte* der = *pp;
+ word32 idx = 0;
+ int len = 0;
+ word32 end = 0;
+ int cnt = 0;
+ int type;
+ word32 algId;
+ word32 keyLen = (word32)length;
+
+ /* Take off PKCS#8 wrapper if found. */
+ if ((len = ToTraditionalInline_ex(der, &idx, keyLen, &algId)) >= 0) {
+ der += idx;
+ keyLen = len;
+ }
+ idx = 0;
+ len = 0;
+
+ /* Use the number of elements in the outer sequence to determine key type.
+ */
+ ret = GetSequence(der, &idx, &len, keyLen);
+ if (ret >= 0) {
+ end = idx + len;
+ while (ret >= 0 && idx < end) {
+ /* Skip type */
+ idx++;
+ /* Get length and skip over - keeping count */
+ len = 0;
+ ret = GetLength(der, &idx, &len, keyLen);
+ if (ret >= 0) {
+ if (idx + len > end)
+ ret = ASN_PARSE_E;
+ else {
+ idx += len;
+ cnt++;
+ }
+ }
+ }
+ }
+
+ if (ret >= 0) {
+ /* ECC includes version, private[, curve][, public key] */
+ if (cnt >= 2 && cnt <= 4)
+ type = EVP_PKEY_EC;
+ else
+ type = EVP_PKEY_RSA;
+
+ key = wolfSSL_d2i_PrivateKey(type, pkey, &der, keyLen);
+ *pp = der;
+ }
+
+ return key;
+}
+#endif
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \
+ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ)
+int wolfSSL_X509_set_subject_name(WOLFSSL_X509 *cert, WOLFSSL_X509_NAME *name)
+{
+ int i;
+ WOLFSSL_X509_NAME_ENTRY* ne;
+
+ WOLFSSL_ENTER("X509_set_subject_name");
+ if (cert == NULL || name == NULL)
+ return WOLFSSL_FAILURE;
+
+ FreeX509Name(&cert->subject, cert->heap);
+ InitX509Name(&cert->subject, 0);
+ if (name->dynamicName) {
+ cert->subject.name = (char*)XMALLOC(name->sz, cert->heap,
+ DYNAMIC_TYPE_SUBJECT_CN);
+ if (cert->subject.name == NULL)
+ return WOLFSSL_FAILURE;
+ }
+ XMEMCPY(cert->subject.name, name->name, name->sz);
+ cert->subject.sz = name->sz;
+
+ for (i = 0; i < 10; i++) {
+ ne = wolfSSL_X509_NAME_get_entry(name, i);
+ if (ne != NULL)
+ wolfSSL_X509_NAME_add_entry(&cert->subject, ne, i, 1);
+ }
+ cert->subject.x509 = cert;
+ cert->subject.name = cert->subject.fullName.fullName;
+ cert->subject.sz = cert->subject.fullName.fullNameLen;
+
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_X509_set_issuer_name(WOLFSSL_X509 *cert, WOLFSSL_X509_NAME *name)
+{
+ int i;
+ WOLFSSL_X509_NAME_ENTRY* ne;
+
+ WOLFSSL_ENTER("X509_set_issuer_name");
+ if (cert == NULL || name == NULL)
+ return WOLFSSL_FAILURE;
+
+ FreeX509Name(&cert->issuer, cert->heap);
+ InitX509Name(&cert->issuer, 0);
+ if (name->dynamicName) {
+ cert->issuer.name = (char*)XMALLOC(name->sz, cert->heap,
+ DYNAMIC_TYPE_SUBJECT_CN);
+ if (cert->issuer.name == NULL)
+ return WOLFSSL_FAILURE;
+ }
+ XMEMCPY(cert->issuer.name, name->name, name->sz);
+ cert->issuer.sz = name->sz;
+
+ for (i = 0; i < 10; i++) {
+ ne = wolfSSL_X509_NAME_get_entry(name, i);
+ if (ne != NULL)
+ wolfSSL_X509_NAME_add_entry(&cert->issuer, ne, i, 1);
+ }
+ cert->issuer.x509 = cert;
+ cert->issuer.name = cert->issuer.fullName.fullName;
+ cert->issuer.sz = cert->issuer.fullName.fullNameLen;
+ cert->issuerSet = 1;
+
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_X509_set_notAfter(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME* t)
+{
+ if (x509 == NULL || t == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ XMEMCPY(&x509->notAfter, t, sizeof(WOLFSSL_ASN1_TIME));
+
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_X509_set_notBefore(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME* t)
+{
+ if (x509 == NULL || t == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ XMEMCPY(&x509->notBefore, t, sizeof(WOLFSSL_ASN1_TIME));
+
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_X509_set_serialNumber(WOLFSSL_X509* x509, WOLFSSL_ASN1_INTEGER* s)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_set_serialNumber");
+ if (!x509 || !s || s->dataMax >= EXTERNAL_SERIAL_SIZE)
+ return WOLFSSL_FAILURE;
+
+ if (s->isDynamic)
+ XSTRNCPY((char*)x509->serial,(char*)s->data,s->dataMax);
+ else
+ XSTRNCPY((char*)x509->serial,(char*)s->intData,s->dataMax);
+
+ x509->serial[s->dataMax] = 0;
+ x509->serialSz = s->dataMax;
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey)
+{
+ byte* p;
+ WOLFSSL_ENTER("wolfSSL_X509_set_pubkey");
+
+ if (cert == NULL || pkey == NULL)
+ return WOLFSSL_FAILURE;
+
+ if (pkey->type == EVP_PKEY_RSA)
+ cert->pubKeyOID = RSAk;
+ else if (pkey->type == EVP_PKEY_EC)
+ cert->pubKeyOID = ECDSAk;
+ else
+ return WOLFSSL_FAILURE;
+
+ p = (byte*)XMALLOC(pkey->pkey_sz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ if (p == NULL)
+ return WOLFSSL_FAILURE;
+
+ if (cert->pubKey.buffer != NULL)
+ XFREE(cert->pubKey.buffer, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ cert->pubKey.buffer = p;
+ XMEMCPY(cert->pubKey.buffer, pkey->pkey.ptr, pkey->pkey_sz);
+ cert->pubKey.length = pkey->pkey_sz;
+
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_X509_set_version(WOLFSSL_X509* x509, long v)
+{
+ WOLFSSL_ENTER("wolfSSL_X509_set_version");
+ if ((x509 == NULL) || (v < 0) || (v > INT_MAX)) {
+ return WOLFSSL_FAILURE;
+ }
+ x509->version = (int) v + 1;
+
+ return WOLFSSL_SUCCESS;
+}
+
+#endif /* OPENSSL_EXTRA && !NO_CERTS && WOLFSSL_CERT_GEN && WOLFSSL_CERT_REQ */
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \
+ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ)
+
+void wolfSSL_X509V3_set_ctx(WOLFSSL_X509V3_CTX* ctx, WOLFSSL_X509* issuer,
+ WOLFSSL_X509* subject, WOLFSSL_X509* req, WOLFSSL_X509_CRL* crl,
+ int flag)
+{
+ int ret = WOLFSSL_SUCCESS;
+ WOLFSSL_ENTER("wolfSSL_X509V3_set_ctx");
+ if (!ctx || !ctx->x509)
+ return;
+
+ /* Set parameters in ctx as long as ret == WOLFSSL_SUCCESS */
+ if (issuer)
+ ret = wolfSSL_X509_set_issuer_name(ctx->x509,&issuer->issuer);
+
+ if (subject && ret == WOLFSSL_SUCCESS)
+ ret = wolfSSL_X509_set_subject_name(ctx->x509,&subject->subject);
+
+ if (req && ret == WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("req not implemented.");
+ }
+
+ if (crl && ret == WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("crl not implemented.");
+ }
+
+ if (flag && ret == WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("flag not implemented.");
+ }
+
+ if (!ret) {
+ WOLFSSL_MSG("Error setting WOLFSSL_X509V3_CTX parameters.");
+ }
+}
+
+int wolfSSL_i2d_X509_REQ(WOLFSSL_X509* req, unsigned char** out)
+{
+ const unsigned char* der;
+ int derSz = 0;
+ WOLFSSL_ENTER("wolfSSL_i2d_X509_REQ");
+
+ if (req == NULL || out == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ der = wolfSSL_X509_get_der(req, &derSz);
+ if (der == NULL) {
+ return MEMORY_E;
+ }
+
+ if (*out == NULL) {
+ *out = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (*out == NULL) {
+ return MEMORY_E;
+ }
+ }
+
+ XMEMCPY(*out, der, derSz);
+
+ return derSz;
+}
+
+WOLFSSL_X509* wolfSSL_X509_REQ_new(void)
+{
+ return wolfSSL_X509_new();
+}
+
+void wolfSSL_X509_REQ_free(WOLFSSL_X509* req)
+{
+ wolfSSL_X509_free(req);
+}
+
+int wolfSSL_X509_REQ_sign(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey,
+ const WOLFSSL_EVP_MD *md)
+{
+ byte der[2048];
+ int derSz = sizeof(der);
+
+ if (req == NULL || pkey == NULL || md == NULL)
+ return WOLFSSL_FAILURE;
+
+ /* Create a Cert that has the certificate request fields. */
+ req->sigOID = wolfSSL_sigTypeFromPKEY((WOLFSSL_EVP_MD*)md, pkey);
+ if (wolfSSL_X509_make_der(req, 1, der, &derSz) != WOLFSSL_SUCCESS) {
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_X509_resign_cert(req, 1, der, sizeof(der), derSz,
+ (WOLFSSL_EVP_MD*)md, pkey) <= 0) {
+ return WOLFSSL_FAILURE;
+ }
+ return WOLFSSL_SUCCESS;
+}
+
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_X509_REQ_add_extensions(WOLFSSL_X509* req,
+ WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* ext)
+{
+ (void)req;
+ (void)ext;
+ return WOLFSSL_FATAL_ERROR;
+}
+#endif
+
+int wolfSSL_X509_REQ_set_subject_name(WOLFSSL_X509 *req,
+ WOLFSSL_X509_NAME *name)
+{
+ return wolfSSL_X509_set_subject_name(req, name);
+}
+
+int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey)
+{
+ return wolfSSL_X509_set_pubkey(req, pkey);
+}
+#endif /* OPENSSL_EXTRA && !NO_CERTS && WOLFSSL_CERT_GEN && WOLFSSL_CERT_REQ */
+
+