summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.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/wolfcrypt/src/asn.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/wolfcrypt/src/asn.c')
-rw-r--r--FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c16530
1 files changed, 13130 insertions, 3400 deletions
diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c
index e3d9ff44b..c4e60043f 100644
--- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c
+++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c
@@ -1,8 +1,8 @@
/* asn.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,21 +16,47 @@
*
* 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>
-#ifndef NO_ASN
+/*
+ASN Options:
+ * NO_ASN_TIME: Disables time parts of the ASN code for systems without an RTC
+ or wishing to save space.
+ * IGNORE_NAME_CONSTRAINTS: Skip ASN name checks.
+ * ASN_DUMP_OID: Allows dump of OID information for debugging.
+ * RSA_DECODE_EXTRA: Decodes extra information in RSA public key.
+ * WOLFSSL_CERT_GEN: Cert generation. Saves extra certificate info in GetName.
+ * WOLFSSL_NO_ASN_STRICT: Disable strict RFC compliance checks to
+ restore 3.13.0 behavior.
+ * WOLFSSL_NO_OCSP_OPTIONAL_CERTS: Skip optional OCSP certs (responder issuer
+ must still be trusted)
+ * WOLFSSL_NO_TRUSTED_CERTS_VERIFY: Workaround for situation where entire cert
+ chain is not loaded. This only matches on subject and public key and
+ does not perform a PKI validation, so it is not a secure solution.
+ Only enabled for OCSP.
+ * WOLFSSL_NO_OCSP_ISSUER_CHECK: Can be defined for backwards compatibility to
+ disable checking of OCSP subject hash with issuer hash.
+ * WOLFSSL_SMALL_CERT_VERIFY: Verify the certificate signature without using
+ DecodedCert. Doubles up on some code but allows smaller dynamic memory
+ usage.
+ * WOLFSSL_NO_OCSP_DATE_CHECK: Disable date checks for OCSP responses. This
+ may be required when the system's real-time clock is not very accurate.
+ It is recommended to enforce the nonce check instead if possible.
+ * WOLFSSL_FORCE_OCSP_NONCE_CHECK: Require nonces to be available in OCSP
+ responses. The nonces are optional and may not be supported by all
+ responders. If it can be ensured that the used responder sends nonces this
+ option may improve security.
+*/
-#ifdef HAVE_RTP_SYS
- #include "os.h" /* dc_rtc_api needs */
- #include "dc_rtc_api.h" /* to get current time */
-#endif
+#ifndef NO_ASN
#include <wolfssl/wolfcrypt/asn.h>
#include <wolfssl/wolfcrypt/coding.h>
@@ -39,17 +65,25 @@
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/pwdbased.h>
#include <wolfssl/wolfcrypt/des3.h>
+#include <wolfssl/wolfcrypt/aes.h>
+#include <wolfssl/wolfcrypt/wc_encrypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/random.h>
-
+#include <wolfssl/wolfcrypt/hash.h>
+#ifdef NO_INLINE
+ #include <wolfssl/wolfcrypt/misc.h>
+#else
+ #define WOLFSSL_MISC_INCLUDED
+ #include <wolfcrypt/src/misc.c>
+#endif
#ifndef NO_RC4
#include <wolfssl/wolfcrypt/arc4.h>
#endif
#ifdef HAVE_NTRU
- #include "ntru_crypto.h"
+ #include "libntruencrypt/ntru_crypto.h"
#endif
#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
@@ -64,478 +98,640 @@
#include <wolfssl/wolfcrypt/ecc.h>
#endif
-#ifdef WOLFSSL_DEBUG_ENCODING
- #ifdef FREESCALE_MQX
- #include <fio.h>
- #else
- #include <stdio.h>
- #endif
+#ifdef HAVE_ED25519
+ #include <wolfssl/wolfcrypt/ed25519.h>
#endif
-#ifdef _MSC_VER
- /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */
- #pragma warning(disable: 4996)
+#ifdef HAVE_ED448
+ #include <wolfssl/wolfcrypt/ed448.h>
#endif
-
-#ifndef TRUE
- #define TRUE 1
+#ifndef NO_RSA
+ #include <wolfssl/wolfcrypt/rsa.h>
+#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL)
+extern int wc_InitRsaHw(RsaKey* key);
#endif
-#ifndef FALSE
- #define FALSE 0
#endif
+#ifdef WOLF_CRYPTO_CB
+ #include <wolfssl/wolfcrypt/cryptocb.h>
+#endif
-#ifdef HAVE_RTP_SYS
- /* uses parital <time.h> structures */
- #define XTIME(tl) (0)
- #define XGMTIME(c, t) my_gmtime((c))
- #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
-#elif defined(MICRIUM)
- #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
- #define XVALIDATE_DATE(d,f,t) NetSecure_ValidateDateHandler((d),(f),(t))
- #else
- #define XVALIDATE_DATE(d, f, t) (0)
- #endif
- #define NO_TIME_H
- /* since Micrium not defining XTIME or XGMTIME, CERT_GEN not available */
-#elif defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP)
- #include <time.h>
- #define XTIME(t1) pic32_time((t1))
- #define XGMTIME(c, t) gmtime((c))
- #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
-#elif defined(FREESCALE_MQX)
- #define XTIME(t1) mqx_time((t1))
- #define XGMTIME(c, t) mqx_gmtime((c), (t))
- #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
-#elif defined(WOLFSSL_MDK_ARM)
- #if defined(WOLFSSL_MDK5)
- #include "cmsis_os.h"
- #else
- #include <rtl.h>
- #endif
- #undef RNG
- #include "wolfssl_MDK_ARM.h"
- #undef RNG
- #define RNG wolfSSL_RNG /*for avoiding name conflict in "stm32f2xx.h" */
- #define XTIME(tl) (0)
- #define XGMTIME(c, t) wolfssl_MDK_gmtime((c))
- #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
-#elif defined(USER_TIME)
- /* user time, and gmtime compatible functions, there is a gmtime
- implementation here that WINCE uses, so really just need some ticks
- since the EPOCH
- */
-
- struct tm {
- int tm_sec; /* seconds after the minute [0-60] */
- int tm_min; /* minutes after the hour [0-59] */
- int tm_hour; /* hours since midnight [0-23] */
- int tm_mday; /* day of the month [1-31] */
- int tm_mon; /* months since January [0-11] */
- int tm_year; /* years since 1900 */
- int tm_wday; /* days since Sunday [0-6] */
- int tm_yday; /* days since January 1 [0-365] */
- int tm_isdst; /* Daylight Savings Time flag */
- long tm_gmtoff; /* offset from CUT in seconds */
- char *tm_zone; /* timezone abbreviation */
- };
- typedef long time_t;
-
- /* forward declaration */
- struct tm* gmtime(const time_t* timer);
- extern time_t XTIME(time_t * timer);
-
- #define XGMTIME(c, t) gmtime((c))
- #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
-
- #ifdef STACK_TRAP
- /* for stack trap tracking, don't call os gmtime on OS X/linux,
- uses a lot of stack spce */
- extern time_t time(time_t * timer);
- #define XTIME(tl) time((tl))
- #endif /* STACK_TRAP */
-
-#elif defined(TIME_OVERRIDES)
- /* user would like to override time() and gmtime() functionality */
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ #include <wolfssl/openssl/objects.h>
+#endif
- #ifndef HAVE_TIME_T_TYPE
- typedef long time_t;
- #endif
- extern time_t XTIME(time_t * timer);
-
- #ifndef HAVE_TM_TYPE
- struct tm {
- int tm_sec; /* seconds after the minute [0-60] */
- int tm_min; /* minutes after the hour [0-59] */
- int tm_hour; /* hours since midnight [0-23] */
- int tm_mday; /* day of the month [1-31] */
- int tm_mon; /* months since January [0-11] */
- int tm_year; /* years since 1900 */
- int tm_wday; /* days since Sunday [0-6] */
- int tm_yday; /* days since January 1 [0-365] */
- int tm_isdst; /* Daylight Savings Time flag */
- long tm_gmtoff; /* offset from CUT in seconds */
- char *tm_zone; /* timezone abbreviation */
- };
- #endif
- extern struct tm* XGMTIME(const time_t* timer, struct tm* tmp);
+#ifdef _MSC_VER
+ /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */
+ #pragma warning(disable: 4996)
+#endif
- #ifndef HAVE_VALIDATE_DATE
- #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
+#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
+
+#if defined(HAVE_SELFTEST) || ( !defined(NO_SKID) && \
+ ( !defined(HAVE_FIPS) || \
+ !defined(HAVE_FIPS_VERSION) ))
+ #ifndef WOLFSSL_AES_KEY_SIZE_ENUM
+ #define WOLFSSL_AES_KEY_SIZE_ENUM
+ enum Asn_Misc {
+ AES_IV_SIZE = 16,
+ AES_128_KEY_SIZE = 16,
+ AES_192_KEY_SIZE = 24,
+ AES_256_KEY_SIZE = 32
+ };
#endif
-#else
- /* default */
- /* uses complete <time.h> facility */
- #include <time.h>
- #define XTIME(tl) time((tl))
- #define XGMTIME(c, t) gmtime((c))
- #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
#endif
-
-
-#ifdef _WIN32_WCE
-/* no time() or gmtime() even though in time.h header?? */
-
-#include <windows.h>
-
-
-time_t time(time_t* timer)
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+void tsip_inform_key_position(const word32 key_n_start,
+ const word32 key_n_len, const word32 key_e_start,
+ const word32 key_e_len);
+int tsip_tls_CertVerify(const byte *cert, word32 certSz,
+ const byte *signature, word32 sigSz,
+ word32 key_n_start, word32 key_n_len,
+ word32 key_e_start, word32 key_e_len,
+ byte *tsip_encRsaKeyIdx);
+#endif
+int GetLength(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
{
- SYSTEMTIME sysTime;
- FILETIME fTime;
- ULARGE_INTEGER intTime;
- time_t localTime;
-
- if (timer == NULL)
- timer = &localTime;
-
- GetSystemTime(&sysTime);
- SystemTimeToFileTime(&sysTime, &fTime);
-
- XMEMCPY(&intTime, &fTime, sizeof(FILETIME));
- /* subtract EPOCH */
- intTime.QuadPart -= 0x19db1ded53e8000;
- /* to secs */
- intTime.QuadPart /= 10000000;
- *timer = (time_t)intTime.QuadPart;
-
- return *timer;
+ return GetLength_ex(input, inOutIdx, len, maxIdx, 1);
}
-#endif /* _WIN32_WCE */
-#if defined( _WIN32_WCE ) || defined( USER_TIME )
-struct tm* gmtime(const time_t* timer)
+/* give option to check length value found against index. 1 to check 0 to not */
+int GetLength_ex(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx, int check)
{
- #define YEAR0 1900
- #define EPOCH_YEAR 1970
- #define SECS_DAY (24L * 60L * 60L)
- #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) %400)))
- #define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
+ int length = 0;
+ word32 idx = *inOutIdx;
+ byte b;
- static const int _ytab[2][12] =
- {
- {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
- {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
- };
+ *len = 0; /* default length */
- static struct tm st_time;
- struct tm* ret = &st_time;
- time_t secs = *timer;
- unsigned long dayclock, dayno;
- int year = EPOCH_YEAR;
+ if ((idx + 1) > maxIdx) { /* for first read */
+ WOLFSSL_MSG("GetLength bad index on input");
+ return BUFFER_E;
+ }
- dayclock = (unsigned long)secs % SECS_DAY;
- dayno = (unsigned long)secs / SECS_DAY;
+ b = input[idx++];
+ if (b >= ASN_LONG_LENGTH) {
+ word32 bytes = b & 0x7F;
- ret->tm_sec = (int) dayclock % 60;
- ret->tm_min = (int)(dayclock % 3600) / 60;
- ret->tm_hour = (int) dayclock / 3600;
- ret->tm_wday = (int) (dayno + 4) % 7; /* day 0 a Thursday */
+ if ((idx + bytes) > maxIdx) { /* for reading bytes */
+ WOLFSSL_MSG("GetLength bad long length");
+ return BUFFER_E;
+ }
- while(dayno >= (unsigned long)YEARSIZE(year)) {
- dayno -= YEARSIZE(year);
- year++;
+ if (bytes > sizeof(length)) {
+ return ASN_PARSE_E;
+ }
+ while (bytes--) {
+ b = input[idx++];
+ length = (length << 8) | b;
+ }
+ if (length < 0) {
+ return ASN_PARSE_E;
+ }
}
+ else
+ length = b;
- ret->tm_year = year - YEAR0;
- ret->tm_yday = (int)dayno;
- ret->tm_mon = 0;
-
- while(dayno >= (unsigned long)_ytab[LEAPYEAR(year)][ret->tm_mon]) {
- dayno -= _ytab[LEAPYEAR(year)][ret->tm_mon];
- ret->tm_mon++;
+ if (check && (idx + length) > maxIdx) { /* for user of length */
+ WOLFSSL_MSG("GetLength value exceeds buffer length");
+ return BUFFER_E;
}
- ret->tm_mday = (int)++dayno;
- ret->tm_isdst = 0;
+ *inOutIdx = idx;
+ if (length > 0)
+ *len = length;
- return ret;
+ return length;
}
-#endif /* _WIN32_WCE || USER_TIME */
+/* input : buffer to read from
+ * inOutIdx : index to start reading from, gets advanced by 1 if successful
+ * maxIdx : maximum index value
+ * tag : ASN tag value found
+ *
+ * returns 0 on success
+ */
+int GetASNTag(const byte* input, word32* inOutIdx, byte* tag, word32 maxIdx)
+{
+ word32 idx;
-#ifdef HAVE_RTP_SYS
+ if (tag == NULL || inOutIdx == NULL || input == NULL) {
+ return BAD_FUNC_ARG;
+ }
-#define YEAR0 1900
+ idx = *inOutIdx;
+ if (idx + ASN_TAG_SZ > maxIdx) {
+ WOLFSSL_MSG("Buffer too small for ASN tag");
+ return BUFFER_E;
+ }
-struct tm* my_gmtime(const time_t* timer) /* has a gmtime() but hangs */
-{
- static struct tm st_time;
- struct tm* ret = &st_time;
+ *tag = input[idx];
+ *inOutIdx = idx + ASN_TAG_SZ;
+ return 0;
+}
- DC_RTC_CALENDAR cal;
- dc_rtc_time_get(&cal, TRUE);
- ret->tm_year = cal.year - YEAR0; /* gm starts at 1900 */
- ret->tm_mon = cal.month - 1; /* gm starts at 0 */
- ret->tm_mday = cal.day;
- ret->tm_hour = cal.hour;
- ret->tm_min = cal.minute;
- ret->tm_sec = cal.second;
+static int GetASNHeader_ex(const byte* input, byte tag, word32* inOutIdx, int* len,
+ word32 maxIdx, int check)
+{
+ word32 idx = *inOutIdx;
+ byte tagFound;
+ int length;
- return ret;
-}
+ if (GetASNTag(input, &idx, &tagFound, maxIdx) != 0)
+ return ASN_PARSE_E;
-#endif /* HAVE_RTP_SYS */
+ if (tagFound != tag)
+ return ASN_PARSE_E;
+
+ if (GetLength_ex(input, &idx, &length, maxIdx, check) < 0)
+ return ASN_PARSE_E;
+ *len = length;
+ *inOutIdx = idx;
+ return length;
+}
-#if defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP)
-/*
- * time() is just a stub in Microchip libraries. We need our own
- * implementation. Use SNTP client to get seconds since epoch.
+/* Get the DER/BER encoding of an ASN.1 header.
+ *
+ * input Buffer holding DER/BER encoded data.
+ * tag ASN.1 tag value expected in header.
+ * inOutIdx Current index into buffer to parse.
+ * len The number of bytes in the ASN.1 data.
+ * maxIdx Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ * ASN_PARSE_E when the expected tag is not found or length is invalid.
+ * Otherwise, the number of bytes in the ASN.1 data.
*/
-time_t pic32_time(time_t* timer)
+static int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len,
+ word32 maxIdx)
{
-#ifdef MICROCHIP_TCPIP_V5
- DWORD sec = 0;
-#else
- uint32_t sec = 0;
-#endif
- time_t localTime;
-
- if (timer == NULL)
- timer = &localTime;
+ return GetASNHeader_ex(input, tag, inOutIdx, len, maxIdx, 1);
+}
-#ifdef MICROCHIP_MPLAB_HARMONY
- sec = TCPIP_SNTP_UTCSecondsGet();
-#else
- sec = SNTPGetUTCSeconds();
-#endif
- *timer = (time_t) sec;
+static int GetHeader(const byte* input, byte* tag, word32* inOutIdx, int* len,
+ word32 maxIdx, int check)
+{
+ word32 idx = *inOutIdx;
+ int length;
- return *timer;
-}
+ if ((idx + 1) > maxIdx)
+ return BUFFER_E;
-#endif /* MICROCHIP_TCPIP */
+ *tag = input[idx++];
+ if (GetLength_ex(input, &idx, &length, maxIdx, check) < 0)
+ return ASN_PARSE_E;
-#ifdef FREESCALE_MQX
+ *len = length;
+ *inOutIdx = idx;
+ return length;
+}
-time_t mqx_time(time_t* timer)
+int GetSequence(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
{
- time_t localTime;
- TIME_STRUCT time_s;
-
- if (timer == NULL)
- timer = &localTime;
+ return GetASNHeader(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len,
+ maxIdx);
+}
- _time_get(&time_s);
- *timer = (time_t) time_s.SECONDS;
- return *timer;
+int GetSequence_ex(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx, int check)
+{
+ return GetASNHeader_ex(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len,
+ maxIdx, check);
}
-/* CodeWarrior GCC toolchain only has gmtime_r(), no gmtime() */
-struct tm* mqx_gmtime(const time_t* clock, struct tm* tmpTime)
+
+int GetSet(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
{
- return gmtime_r(clock, tmpTime);
+ return GetASNHeader(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len,
+ maxIdx);
}
-#endif /* FREESCALE_MQX */
-#ifdef WOLFSSL_TIRTOS
+int GetSet_ex(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx, int check)
+{
+ return GetASNHeader_ex(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len,
+ maxIdx, check);
+}
-time_t XTIME(time_t * timer)
+/* Get the DER/BER encoded ASN.1 NULL element.
+ * Ensure that the all fields are as expected and move index past the element.
+ *
+ * input Buffer holding DER/BER encoded data.
+ * inOutIdx Current index into buffer to parse.
+ * maxIdx Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ * ASN_TAG_NULL_E when the NULL tag is not found.
+ * ASN_EXPECT_0_E when the length is not zero.
+ * Otherwise, 0 to indicate success.
+ */
+static int GetASNNull(const byte* input, word32* inOutIdx, word32 maxIdx)
{
- time_t sec = 0;
+ word32 idx = *inOutIdx;
+ byte b;
+
+ if ((idx + 2) > maxIdx)
+ return BUFFER_E;
- sec = (time_t) Seconds_get();
+ b = input[idx++];
+ if (b != ASN_TAG_NULL)
+ return ASN_TAG_NULL_E;
- if (timer != NULL)
- *timer = sec;
+ if (input[idx++] != 0)
+ return ASN_EXPECT_0_E;
- return sec;
+ *inOutIdx = idx;
+ return 0;
}
-#endif /* WOLFSSL_TIRTOS */
-
-static INLINE word32 btoi(byte b)
+/* Set the DER/BER encoding of the ASN.1 NULL element.
+ *
+ * output Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+static int SetASNNull(byte* output)
{
- return b - 0x30;
-}
+ output[0] = ASN_TAG_NULL;
+ output[1] = 0;
+ return 2;
+}
-/* two byte date/time, add to value */
-static INLINE void GetTime(int* value, const byte* date, int* idx)
+/* Get the DER/BER encoding of an ASN.1 BOOLEAN.
+ *
+ * input Buffer holding DER/BER encoded data.
+ * inOutIdx Current index into buffer to parse.
+ * maxIdx Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ * ASN_PARSE_E when the BOOLEAN tag is not found or length is not 1.
+ * Otherwise, 0 to indicate the value was false and 1 to indicate true.
+ */
+static int GetBoolean(const byte* input, word32* inOutIdx, word32 maxIdx)
{
- int i = *idx;
+ word32 idx = *inOutIdx;
+ byte b;
- *value += btoi(date[i++]) * 10;
- *value += btoi(date[i++]);
+ if ((idx + 3) > maxIdx)
+ return BUFFER_E;
- *idx = i;
+ b = input[idx++];
+ if (b != ASN_BOOLEAN)
+ return ASN_PARSE_E;
+
+ if (input[idx++] != 1)
+ return ASN_PARSE_E;
+
+ b = input[idx++] != 0;
+
+ *inOutIdx = idx;
+ return b;
}
+#ifdef ASN1_SET_BOOLEAN
+/* Set the DER/BER encoding of the ASN.1 NULL element.
+ * Note: Function not required as yet.
+ *
+ * val Boolean value to encode.
+ * output Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+static int SetBoolean(int val, byte* output)
+{
+ output[0] = ASN_BOOLEAN;
+ output[1] = 1;
+ output[2] = val ? -1 : 0;
-#if defined(MICRIUM)
+ return 3;
+}
+#endif
-CPU_INT32S NetSecure_ValidateDateHandler(CPU_INT08U *date, CPU_INT08U format,
- CPU_INT08U dateType)
+/* Get the DER/BER encoding of an ASN.1 OCTET_STRING header.
+ *
+ * input Buffer holding DER/BER encoded data.
+ * inOutIdx Current index into buffer to parse.
+ * len The number of bytes in the ASN.1 data.
+ * maxIdx Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ * ASN_PARSE_E when the OCTET_STRING tag is not found or length is
+ * invalid.
+ * Otherwise, the number of bytes in the ASN.1 data.
+ */
+int GetOctetString(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
{
- CPU_BOOLEAN rtn_code;
- CPU_INT32S i;
- CPU_INT32S val;
- CPU_INT16U year;
- CPU_INT08U month;
- CPU_INT16U day;
- CPU_INT08U hour;
- CPU_INT08U min;
- CPU_INT08U sec;
+ return GetASNHeader(input, ASN_OCTET_STRING, inOutIdx, len, maxIdx);
+}
- i = 0;
- year = 0u;
+/* Get the DER/BER encoding of an ASN.1 INTEGER header.
+ * Removes the leading zero byte when found.
+ *
+ * input Buffer holding DER/BER encoded data.
+ * inOutIdx Current index into buffer to parse.
+ * len The number of bytes in the ASN.1 data (excluding any leading zero).
+ * maxIdx Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ * ASN_PARSE_E when the INTEGER tag is not found, length is invalid,
+ * or invalid use of or missing leading zero.
+ * Otherwise, 0 to indicate success.
+ */
+static int GetASNInt(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
+{
+ int ret;
- if (format == ASN_UTC_TIME) {
- if (btoi(date[0]) >= 5)
- year = 1900;
- else
- year = 2000;
- }
- else { /* format == GENERALIZED_TIME */
- year += btoi(date[i++]) * 1000;
- year += btoi(date[i++]) * 100;
- }
+ ret = GetASNHeader(input, ASN_INTEGER, inOutIdx, len, maxIdx);
+ if (ret < 0)
+ return ret;
- val = year;
- GetTime(&val, date, &i);
- year = (CPU_INT16U)val;
+ if (*len > 0) {
+ /* remove leading zero, unless there is only one 0x00 byte */
+ if ((input[*inOutIdx] == 0x00) && (*len > 1)) {
+ (*inOutIdx)++;
+ (*len)--;
- val = 0;
- GetTime(&val, date, &i);
- month = (CPU_INT08U)val;
+ if (*len > 0 && (input[*inOutIdx] & 0x80) == 0)
+ return ASN_PARSE_E;
+ }
+ }
- val = 0;
- GetTime(&val, date, &i);
- day = (CPU_INT16U)val;
+ return 0;
+}
- val = 0;
- GetTime(&val, date, &i);
- hour = (CPU_INT08U)val;
+/* Get the DER/BER encoding of an ASN.1 INTEGER that has a value of no more than
+ * 7 bits.
+ *
+ * input Buffer holding DER/BER encoded data.
+ * inOutIdx Current index into buffer to parse.
+ * maxIdx Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ * ASN_PARSE_E when the INTEGER tag is not found or length is invalid.
+ * Otherwise, the 7-bit value.
+ */
+static int GetInteger7Bit(const byte* input, word32* inOutIdx, word32 maxIdx)
+{
+ word32 idx = *inOutIdx;
+ byte b;
- val = 0;
- GetTime(&val, date, &i);
- min = (CPU_INT08U)val;
+ if ((idx + 3) > maxIdx)
+ return BUFFER_E;
- val = 0;
- GetTime(&val, date, &i);
- sec = (CPU_INT08U)val;
+ if (GetASNTag(input, &idx, &b, maxIdx) != 0)
+ return ASN_PARSE_E;
+ if (b != ASN_INTEGER)
+ return ASN_PARSE_E;
+ if (input[idx++] != 1)
+ return ASN_PARSE_E;
+ b = input[idx++];
- return NetSecure_ValidateDate(year, month, day, hour, min, sec, dateType);
+ *inOutIdx = idx;
+ return b;
}
-#endif /* MICRIUM */
+#if !defined(NO_DSA) && !defined(NO_SHA)
+static const char sigSha1wDsaName[] = "SHAwDSA";
+#endif /* NO_DSA */
+#ifndef NO_RSA
+#ifdef WOLFSSL_MD2
+ static const char sigMd2wRsaName[] = "md2WithRSAEncryption";
+#endif
+#ifndef NO_MD5
+ static const char sigMd5wRsaName[] = "md5WithRSAEncryption";
+#endif
+#ifndef NO_SHA
+ static const char sigSha1wRsaName[] = "sha1WithRSAEncryption";
+#endif
+#ifdef WOLFSSL_SHA224
+ static const char sigSha224wRsaName[] = "sha224WithRSAEncryption";
+#endif
+#ifndef NO_SHA256
+ static const char sigSha256wRsaName[] = "sha256WithRSAEncryption";
+#endif
+#ifdef WOLFSSL_SHA384
+ static const char sigSha384wRsaName[] = "sha384WithRSAEncryption";
+#endif
+#ifdef WOLFSSL_SHA512
+ static const char sigSha512wRsaName[] = "sha512WithRSAEncryption";
+#endif
+#endif /* NO_RSA */
+#ifdef HAVE_ECC
+#ifndef NO_SHA
+ static const char sigSha1wEcdsaName[] = "SHAwECDSA";
+#endif
+#ifdef WOLFSSL_SHA224
+ static const char sigSha224wEcdsaName[] = "SHA224wECDSA";
+#endif
+#ifndef NO_SHA256
+ static const char sigSha256wEcdsaName[] = "SHA256wECDSA";
+#endif
+#ifdef WOLFSSL_SHA384
+ static const char sigSha384wEcdsaName[] = "SHA384wECDSA";
+#endif
+#ifdef WOLFSSL_SHA512
+ static const char sigSha512wEcdsaName[] = "SHA512wECDSA";
+#endif
+#endif /* HAVE_ECC */
+static const char sigUnknownName[] = "Unknown";
-WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
- word32 maxIdx)
-{
- int length = 0;
- word32 i = *inOutIdx;
- byte b;
-
- *len = 0; /* default length */
- if ( (i+1) > maxIdx) { /* for first read */
- WOLFSSL_MSG("GetLength bad index on input");
- return BUFFER_E;
+/* Get the human readable string for a signature type
+ *
+ * oid Oid value for signature
+ */
+const char* GetSigName(int oid) {
+ switch (oid) {
+ #if !defined(NO_DSA) && !defined(NO_SHA)
+ case CTC_SHAwDSA:
+ return sigSha1wDsaName;
+ #endif /* NO_DSA && NO_SHA */
+ #ifndef NO_RSA
+ #ifdef WOLFSSL_MD2
+ case CTC_MD2wRSA:
+ return sigMd2wRsaName;
+ #endif
+ #ifndef NO_MD5
+ case CTC_MD5wRSA:
+ return sigMd5wRsaName;
+ #endif
+ #ifndef NO_SHA
+ case CTC_SHAwRSA:
+ return sigSha1wRsaName;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case CTC_SHA224wRSA:
+ return sigSha224wRsaName;
+ #endif
+ #ifndef NO_SHA256
+ case CTC_SHA256wRSA:
+ return sigSha256wRsaName;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case CTC_SHA384wRSA:
+ return sigSha384wRsaName;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case CTC_SHA512wRSA:
+ return sigSha512wRsaName;
+ #endif
+ #endif /* NO_RSA */
+ #ifdef HAVE_ECC
+ #ifndef NO_SHA
+ case CTC_SHAwECDSA:
+ return sigSha1wEcdsaName;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case CTC_SHA224wECDSA:
+ return sigSha224wEcdsaName;
+ #endif
+ #ifndef NO_SHA256
+ case CTC_SHA256wECDSA:
+ return sigSha256wEcdsaName;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case CTC_SHA384wECDSA:
+ return sigSha384wEcdsaName;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case CTC_SHA512wECDSA:
+ return sigSha512wEcdsaName;
+ #endif
+ #endif /* HAVE_ECC */
+ default:
+ return sigUnknownName;
}
+}
- b = input[i++];
- if (b >= ASN_LONG_LENGTH) {
- word32 bytes = b & 0x7F;
- if ( (i+bytes) > maxIdx) { /* for reading bytes */
- WOLFSSL_MSG("GetLength bad long length");
- return BUFFER_E;
- }
+#if !defined(NO_DSA) || defined(HAVE_ECC) || !defined(NO_CERTS) || \
+ (!defined(NO_RSA) && \
+ (defined(WOLFSSL_CERT_GEN) || \
+ ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(HAVE_USER_RSA))))
+/* Set the DER/BER encoding of the ASN.1 INTEGER header.
+ *
+ * len Length of data to encode.
+ * firstByte First byte of data, most significant byte of integer, to encode.
+ * output Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+static int SetASNInt(int len, byte firstByte, byte* output)
+{
+ word32 idx = 0;
- while (bytes--) {
- b = input[i++];
- length = (length << 8) | b;
- }
- }
- else
- length = b;
-
- if ( (i+length) > maxIdx) { /* for user of length */
- WOLFSSL_MSG("GetLength value exceeds buffer length");
- return BUFFER_E;
+ if (output)
+ output[idx] = ASN_INTEGER;
+ idx++;
+ if (firstByte & 0x80)
+ len++;
+ idx += SetLength(len, output ? output + idx : NULL);
+ if (firstByte & 0x80) {
+ if (output)
+ output[idx] = 0x00;
+ idx++;
}
- *inOutIdx = i;
- if (length > 0)
- *len = length;
-
- return length;
+ return idx;
}
+#endif
-
-WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len,
- word32 maxIdx)
+#if !defined(NO_DSA) || defined(HAVE_ECC) || (defined(WOLFSSL_CERT_GEN) && \
+ !defined(NO_RSA)) || ((defined(WOLFSSL_KEY_GEN) || \
+ defined(OPENSSL_EXTRA)) && !defined(NO_RSA) && !defined(HAVE_USER_RSA))
+/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int.
+ * The number is assumed to be positive.
+ *
+ * n Multi-precision integer to encode.
+ * maxSz Maximum size of the encoded integer.
+ * A negative value indicates no check of length requested.
+ * output Buffer to write into.
+ * returns BUFFER_E when the data is too long for the buffer.
+ * MP_TO_E when encoding the integer fails.
+ * Otherwise, the number of bytes added to the buffer.
+ */
+static int SetASNIntMP(mp_int* n, int maxSz, byte* output)
{
- int length = -1;
- word32 idx = *inOutIdx;
+ int idx = 0;
+ int leadingBit;
+ int length;
+ int err;
- if (input[idx++] != (ASN_SEQUENCE | ASN_CONSTRUCTED) ||
- GetLength(input, &idx, &length, maxIdx) < 0)
- return ASN_PARSE_E;
+ leadingBit = mp_leading_bit(n);
+ length = mp_unsigned_bin_size(n);
+ idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output);
+ if (maxSz >= 0 && (idx + length) > maxSz)
+ return BUFFER_E;
- *len = length;
- *inOutIdx = idx;
+ if (output) {
+ err = mp_to_unsigned_bin(n, output + idx);
+ if (err != MP_OKAY)
+ return MP_TO_E;
+ }
+ idx += length;
- return length;
+ return idx;
}
+#endif
-
-WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len,
- word32 maxIdx)
+#if !defined(NO_RSA) && defined(HAVE_USER_RSA) && \
+ (defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA))
+/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int from
+ * an RSA key.
+ * The number is assumed to be positive.
+ *
+ * n Multi-precision integer to encode.
+ * output Buffer to write into.
+ * returns BUFFER_E when the data is too long for the buffer.
+ * MP_TO_E when encoding the integer fails.
+ * Otherwise, the number of bytes added to the buffer.
+ */
+static int SetASNIntRSA(void* n, byte* output)
{
- int length = -1;
- word32 idx = *inOutIdx;
+ int idx = 0;
+ int leadingBit;
+ int length;
+ int err;
- if (input[idx++] != (ASN_SET | ASN_CONSTRUCTED) ||
- GetLength(input, &idx, &length, maxIdx) < 0)
- return ASN_PARSE_E;
+ leadingBit = wc_Rsa_leading_bit(n);
+ length = wc_Rsa_unsigned_bin_size(n);
+ idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output);
+ if ((idx + length) > MAX_RSA_INT_SZ)
+ return BUFFER_E;
- *len = length;
- *inOutIdx = idx;
+ if (output) {
+ err = wc_Rsa_to_unsigned_bin(n, output + idx, length);
+ if (err != MP_OKAY)
+ return MP_TO_E;
+ }
+ idx += length;
- return length;
+ return idx;
}
+#endif /* !NO_RSA && HAVE_USER_RSA && WOLFSSL_CERT_GEN */
-
-/* winodws header clash for WinCE using GetVersion */
-WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, int* version)
+/* Windows header clash for WinCE using GetVersion */
+int GetMyVersion(const byte* input, word32* inOutIdx,
+ int* version, word32 maxIdx)
{
word32 idx = *inOutIdx;
+ byte tag;
- WOLFSSL_ENTER("GetMyVersion");
+ if ((idx + MIN_VERSION_SZ) > maxIdx)
+ return ASN_PARSE_E;
- if (input[idx++] != ASN_INTEGER)
+ if (GetASNTag(input, &idx, &tag, maxIdx) != 0)
+ return ASN_PARSE_E;
+
+ if (tag != ASN_INTEGER)
return ASN_PARSE_E;
if (input[idx++] != 0x01)
@@ -550,20 +746,31 @@ WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, int* version
#ifndef NO_PWDBASED
/* Get small count integer, 32 bits or less */
-static int GetShortInt(const byte* input, word32* inOutIdx, int* number)
+int GetShortInt(const byte* input, word32* inOutIdx, int* number, word32 maxIdx)
{
word32 idx = *inOutIdx;
word32 len;
+ byte tag;
*number = 0;
- if (input[idx++] != ASN_INTEGER)
+ /* check for type and length bytes */
+ if ((idx + 2) > maxIdx)
+ return BUFFER_E;
+
+ if (GetASNTag(input, &idx, &tag, maxIdx) != 0)
+ return ASN_PARSE_E;
+
+ if (tag != ASN_INTEGER)
return ASN_PARSE_E;
len = input[idx++];
if (len > 4)
return ASN_PARSE_E;
+ if (len + idx > maxIdx)
+ return ASN_PARSE_E;
+
while (len--) {
*number = *number << 8 | input[idx++];
}
@@ -572,18 +779,68 @@ static int GetShortInt(const byte* input, word32* inOutIdx, int* number)
return *number;
}
-#endif /* !NO_PWDBASED */
+/* Set small integer, 32 bits or less. DER encoding with no leading 0s
+ * returns total amount written including ASN tag and length byte on success */
+int SetShortInt(byte* input, word32* inOutIdx, word32 number, word32 maxIdx)
+{
+ word32 idx = *inOutIdx;
+ word32 len = 0;
+ int i;
+ byte ar[MAX_LENGTH_SZ];
+
+ /* check for room for type and length bytes */
+ if ((idx + 2) > maxIdx)
+ return BUFFER_E;
+
+ input[idx++] = ASN_INTEGER;
+ idx++; /* place holder for length byte */
+ if (MAX_LENGTH_SZ + idx > maxIdx)
+ return ASN_PARSE_E;
+
+ /* find first non zero byte */
+ XMEMSET(ar, 0, MAX_LENGTH_SZ);
+ c32toa(number, ar);
+ for (i = 0; i < MAX_LENGTH_SZ; i++) {
+ if (ar[i] != 0) {
+ break;
+ }
+ }
+
+ /* handle case of 0 */
+ if (i == MAX_LENGTH_SZ) {
+ input[idx++] = 0; len++;
+ }
+
+ for (; i < MAX_LENGTH_SZ && idx < maxIdx; i++) {
+ input[idx++] = ar[i]; len++;
+ }
+
+ /* jump back to beginning of input buffer using unaltered inOutIdx value
+ * and set number of bytes for integer, then update the index value */
+ input[*inOutIdx + 1] = (byte)len;
+ *inOutIdx = idx;
+
+ return len + 2; /* size of integer bytes plus ASN TAG and length byte */
+}
+#endif /* !NO_PWDBASED */
+
/* May not have one, not an error */
-static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version)
+static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version,
+ word32 maxIdx)
{
word32 idx = *inOutIdx;
+ byte tag;
WOLFSSL_ENTER("GetExplicitVersion");
- if (input[idx++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
- *inOutIdx = ++idx; /* eat header */
- return GetMyVersion(input, inOutIdx, version);
+
+ if (GetASNTag(input, &idx, &tag, maxIdx) != 0)
+ return ASN_PARSE_E;
+
+ if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
+ *inOutIdx = ++idx; /* skip header */
+ return GetMyVersion(input, inOutIdx, version, maxIdx);
}
/* go back as is */
@@ -592,257 +849,2267 @@ static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version)
return 0;
}
-
-WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx,
- word32 maxIdx)
+int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, word32 maxIdx)
{
- word32 i = *inOutIdx;
- byte b = input[i++];
+ word32 idx = *inOutIdx;
+ int ret;
int length;
- if (b != ASN_INTEGER)
- return ASN_PARSE_E;
-
- if (GetLength(input, &i, &length, maxIdx) < 0)
- return ASN_PARSE_E;
-
- if ( (b = input[i++]) == 0x00)
- length--;
- else
- i--;
+ ret = GetASNInt(input, &idx, &length, maxIdx);
+ if (ret != 0)
+ return ret;
if (mp_init(mpi) != MP_OKAY)
return MP_INIT_E;
- if (mp_read_unsigned_bin(mpi, (byte*)input + i, length) != 0) {
+ if (mp_read_unsigned_bin(mpi, (byte*)input + idx, length) != 0) {
+ mp_clear(mpi);
+ return ASN_GETINT_E;
+ }
+
+#ifdef HAVE_WOLF_BIGINT
+ if (wc_bigint_from_unsigned_bin(&mpi->raw, input + idx, length) != 0) {
mp_clear(mpi);
return ASN_GETINT_E;
}
+#endif /* HAVE_WOLF_BIGINT */
+
+ *inOutIdx = idx + length;
- *inOutIdx = i + length;
return 0;
}
+#if (!defined(WOLFSSL_KEY_GEN) && !defined(OPENSSL_EXTRA) && defined(RSA_LOW_MEM)) \
+ || defined(WOLFSSL_RSA_PUBLIC_ONLY) || (!defined(NO_DSA) && defined(WOLFSSL_QT))
+#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+static int SkipInt(const byte* input, word32* inOutIdx, word32 maxIdx)
+{
+ word32 idx = *inOutIdx;
+ int ret;
+ int length;
-static int GetObjectId(const byte* input, word32* inOutIdx, word32* oid,
- word32 maxIdx)
+ ret = GetASNInt(input, &idx, &length, maxIdx);
+ if (ret != 0)
+ return ret;
+
+ *inOutIdx = idx + length;
+
+ return 0;
+}
+#endif
+#endif
+
+static int CheckBitString(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx, int zeroBits, byte* unusedBits)
{
+ word32 idx = *inOutIdx;
int length;
- word32 i = *inOutIdx;
byte b;
- *oid = 0;
-
- b = input[i++];
- if (b != ASN_OBJECT_ID)
- return ASN_OBJECT_ID_E;
-
- if (GetLength(input, &i, &length, maxIdx) < 0)
+
+ if (GetASNTag(input, &idx, &b, maxIdx) != 0) {
+ return ASN_BITSTR_E;
+ }
+
+ if (b != ASN_BIT_STRING) {
+ return ASN_BITSTR_E;
+ }
+
+ if (GetLength(input, &idx, &length, maxIdx) < 0)
return ASN_PARSE_E;
-
- while(length--)
- *oid += input[i++];
- /* just sum it up for now */
-
- *inOutIdx = i;
-
+
+ /* extra sanity check that length is greater than 0 */
+ if (length <= 0) {
+ WOLFSSL_MSG("Error length was 0 in CheckBitString");
+ return BUFFER_E;
+ }
+
+ if (idx + 1 > maxIdx) {
+ WOLFSSL_MSG("Attempted buffer read larger than input buffer");
+ return BUFFER_E;
+ }
+
+ b = input[idx];
+ if (zeroBits && b != 0x00)
+ return ASN_EXPECT_0_E;
+ if (b >= 0x08)
+ return ASN_PARSE_E;
+ if (b != 0) {
+ if ((byte)(input[idx + length - 1] << (8 - b)) != 0)
+ return ASN_PARSE_E;
+ }
+ idx++;
+ length--; /* length has been checked for greater than 0 */
+
+ *inOutIdx = idx;
+ if (len != NULL)
+ *len = length;
+ if (unusedBits != NULL)
+ *unusedBits = b;
+
return 0;
}
+/* RSA (with CertGen or KeyGen) OR ECC OR ED25519 OR ED448 (with CertGen or
+ * KeyGen) */
+#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && \
+ (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA))) || \
+ (defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)) || \
+ ((defined(HAVE_ED25519) || defined(HAVE_ED448)) && \
+ (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)))
-WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
- word32 maxIdx)
+/* Set the DER/BER encoding of the ASN.1 BIT_STRING header.
+ *
+ * len Length of data to encode.
+ * unusedBits The number of unused bits in the last byte of data.
+ * That is, the number of least significant zero bits before a one.
+ * The last byte is the most-significant non-zero byte of a number.
+ * output Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+word32 SetBitString(word32 len, byte unusedBits, byte* output)
{
- int length;
- word32 i = *inOutIdx;
- byte b;
- *oid = 0;
-
- WOLFSSL_ENTER("GetAlgoId");
+ word32 idx = 0;
- if (GetSequence(input, &i, &length, maxIdx) < 0)
- return ASN_PARSE_E;
-
- b = input[i++];
- if (b != ASN_OBJECT_ID)
- return ASN_OBJECT_ID_E;
-
- if (GetLength(input, &i, &length, maxIdx) < 0)
+ if (output)
+ output[idx] = ASN_BIT_STRING;
+ idx++;
+
+ idx += SetLength(len + 1, output ? output + idx : NULL);
+ if (output)
+ output[idx] = unusedBits;
+ idx++;
+
+ return idx;
+}
+#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 || HAVE_ED448 */
+
+#ifdef ASN_BER_TO_DER
+/* Pull informtation from the ASN.1 BER encoded item header */
+static int GetBerHeader(const byte* data, word32* idx, word32 maxIdx,
+ byte* pTag, word32* pLen, int* indef)
+{
+ int len = 0;
+ byte tag;
+ word32 i = *idx;
+
+ *indef = 0;
+
+ /* Check there is enough data for a minimal header */
+ if (i + 2 > maxIdx) {
return ASN_PARSE_E;
-
- while(length--) {
- /* odd HC08 compiler behavior here when input[i++] */
- *oid += input[i];
+ }
+
+ /* Retrieve tag */
+ tag = data[i++];
+
+ /* Indefinite length handled specially */
+ if (data[i] == 0x80) {
+ /* Check valid tag for indefinite */
+ if (((tag & 0xc0) == 0) && ((tag & ASN_CONSTRUCTED) == 0x00)) {
+ return ASN_PARSE_E;
+ }
i++;
+ *indef = 1;
}
- /* just sum it up for now */
-
- /* could have NULL tag and 0 terminator, but may not */
- b = input[i++];
-
- if (b == ASN_TAG_NULL) {
- b = input[i++];
- if (b != 0)
- return ASN_EXPECT_0_E;
+ else if (GetLength(data, &i, &len, maxIdx) < 0) {
+ return ASN_PARSE_E;
}
- else
- /* go back, didn't have it */
- i--;
-
- *inOutIdx = i;
-
+
+ /* Return tag, length and index after BER item header */
+ *pTag = tag;
+ *pLen = len;
+ *idx = i;
return 0;
}
+#ifndef INDEF_ITEMS_MAX
+#define INDEF_ITEMS_MAX 20
+#endif
+
+/* Indef length item data */
+typedef struct Indef {
+ word32 start;
+ int depth;
+ int headerLen;
+ word32 len;
+} Indef;
+
+/* Indef length items */
+typedef struct IndefItems
+{
+ Indef len[INDEF_ITEMS_MAX];
+ int cnt;
+ int idx;
+ int depth;
+} IndefItems;
+
+
+/* Get header length of current item */
+static int IndefItems_HeaderLen(IndefItems* items)
+{
+ return items->len[items->idx].headerLen;
+}
+
+/* Get data length of current item */
+static word32 IndefItems_Len(IndefItems* items)
+{
+ return items->len[items->idx].len;
+}
+
+/* Add a indefinite length item */
+static int IndefItems_AddItem(IndefItems* items, word32 start)
+{
+ int ret = 0;
+ int i;
+
+ if (items->cnt == INDEF_ITEMS_MAX) {
+ ret = MEMORY_E;
+ }
+ else {
+ i = items->cnt++;
+ items->len[i].start = start;
+ items->len[i].depth = items->depth++;
+ items->len[i].headerLen = 1;
+ items->len[i].len = 0;
+ items->idx = i;
+ }
+
+ return ret;
+}
+
+/* Increase data length of current item */
+static void IndefItems_AddData(IndefItems* items, word32 length)
+{
+ items->len[items->idx].len += length;
+}
+
+/* Update header length of current item to reflect data length */
+static void IndefItems_UpdateHeaderLen(IndefItems* items)
+{
+ items->len[items->idx].headerLen +=
+ SetLength(items->len[items->idx].len, NULL);
+}
+
+/* Go to indefinite parent of current item */
+static void IndefItems_Up(IndefItems* items)
+{
+ int i;
+ int depth = items->len[items->idx].depth - 1;
+
+ for (i = items->cnt - 1; i >= 0; i--) {
+ if (items->len[i].depth == depth) {
+ break;
+ }
+ }
+ items->idx = i;
+ items->depth = depth + 1;
+}
+
+/* Calculate final length by adding length of indefinite child items */
+static void IndefItems_CalcLength(IndefItems* items)
+{
+ int i;
+ int idx = items->idx;
+
+ for (i = idx + 1; i < items->cnt; i++) {
+ if (items->len[i].depth == items->depth) {
+ items->len[idx].len += items->len[i].headerLen;
+ items->len[idx].len += items->len[i].len;
+ }
+ }
+ items->len[idx].headerLen += SetLength(items->len[idx].len, NULL);
+}
+
+/* Add more data to indefinite length item */
+static void IndefItems_MoreData(IndefItems* items, word32 length)
+{
+ if (items->cnt > 0 && items->idx >= 0) {
+ items->len[items->idx].len += length;
+ }
+}
+
+/* Convert a BER encoding with indefinite length items to DER.
+ *
+ * ber BER encoded data.
+ * berSz Length of BER encoded data.
+ * der Buffer to hold DER encoded version of data.
+ * NULL indicates only the length is required.
+ * derSz The size of the buffer to hold the DER encoded data.
+ * Will be set if der is NULL, otherwise the value is checked as der is
+ * filled.
+ * returns ASN_PARSE_E if the BER data is invalid and BAD_FUNC_ARG if ber or
+ * derSz are NULL.
+ */
+int wc_BerToDer(const byte* ber, word32 berSz, byte* der, word32* derSz)
+{
+ int ret = 0;
+ word32 i, j;
+#ifdef WOLFSSL_SMALL_STACK
+ IndefItems* indefItems = NULL;
+#else
+ IndefItems indefItems[1];
+#endif
+ byte tag, basic;
+ word32 length;
+ int indef;
+
+ if (ber == NULL || derSz == NULL)
+ return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_SMALL_STACK
+ indefItems = XMALLOC(sizeof(IndefItems), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (indefItems == NULL) {
+ ret = MEMORY_E;
+ goto end;
+ }
+#endif
+
+ XMEMSET(indefItems, 0, sizeof(*indefItems));
+
+ /* Calculate indefinite item lengths */
+ for (i = 0; i < berSz; ) {
+ word32 start = i;
+
+ /* Get next BER item */
+ ret = GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
+ if (ret != 0) {
+ goto end;
+ }
+
+ if (indef) {
+ /* Indefinite item - add to list */
+ ret = IndefItems_AddItem(indefItems, i);
+ if (ret != 0) {
+ goto end;
+ }
+
+ if ((tag & 0xC0) == 0 &&
+ tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) &&
+ tag != (ASN_SET | ASN_CONSTRUCTED)) {
+ /* Constructed basic type - get repeating tag */
+ basic = tag & (~ASN_CONSTRUCTED);
+
+ /* Add up lengths of each item below */
+ for (; i < berSz; ) {
+ /* Get next BER_item */
+ ret = GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
+ if (ret != 0) {
+ goto end;
+ }
+
+ /* End of content closes item */
+ if (tag == ASN_EOC) {
+ /* Must be zero length */
+ if (length != 0) {
+ ret = ASN_PARSE_E;
+ goto end;
+ }
+ break;
+ }
+
+ /* Must not be indefinite and tag must match parent */
+ if (indef || tag != basic) {
+ ret = ASN_PARSE_E;
+ goto end;
+ }
+
+ /* Add to length */
+ IndefItems_AddData(indefItems, length);
+ /* Skip data */
+ i += length;
+ }
+
+ /* Ensure we got an EOC and not end of data */
+ if (tag != ASN_EOC) {
+ ret = ASN_PARSE_E;
+ goto end;
+ }
+
+ /* Set the header length to include the length field */
+ IndefItems_UpdateHeaderLen(indefItems);
+ /* Go to indefinte parent item */
+ IndefItems_Up(indefItems);
+ }
+ }
+ else if (tag == ASN_EOC) {
+ /* End-of-content must be 0 length */
+ if (length != 0) {
+ ret = ASN_PARSE_E;
+ goto end;
+ }
+ /* Check there is an item to close - missing EOC */
+ if (indefItems->depth == 0) {
+ ret = ASN_PARSE_E;
+ goto end;
+ }
+
+ /* Finish calculation of data length for indefinite item */
+ IndefItems_CalcLength(indefItems);
+ /* Go to indefinte parent item */
+ IndefItems_Up(indefItems);
+ }
+ else {
+ /* Known length item to add in - make sure enough data for it */
+ if (i + length > berSz) {
+ ret = ASN_PARSE_E;
+ goto end;
+ }
+
+ /* Include all data - can't have indefinite inside definite */
+ i += length;
+ /* Add entire item to current indefinite item */
+ IndefItems_MoreData(indefItems, i - start);
+ }
+ }
+ /* Check we had a EOC for each indefinite item */
+ if (indefItems->depth != 0) {
+ ret = ASN_PARSE_E;
+ goto end;
+ }
+
+ /* Write out DER */
+
+ j = 0;
+ /* Reset index */
+ indefItems->idx = 0;
+ for (i = 0; i < berSz; ) {
+ word32 start = i;
+
+ /* Get item - checked above */
+ (void)GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
+ if (indef) {
+ if (der != NULL) {
+ /* Check enough space for header */
+ if (j + IndefItems_HeaderLen(indefItems) > *derSz) {
+ ret = BUFFER_E;
+ goto end;
+ }
+
+ if ((tag & 0xC0) == 0 &&
+ tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) &&
+ tag != (ASN_SET | ASN_CONSTRUCTED)) {
+ /* Remove constructed tag for basic types */
+ tag &= ~ASN_CONSTRUCTED;
+ }
+ /* Add tag and length */
+ der[j] = tag;
+ (void)SetLength(IndefItems_Len(indefItems), der + j + 1);
+ }
+ /* Add header length of indefinite item */
+ j += IndefItems_HeaderLen(indefItems);
+
+ if ((tag & 0xC0) == 0 &&
+ tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) &&
+ tag != (ASN_SET | ASN_CONSTRUCTED)) {
+ /* For basic type - get each child item and add data */
+ for (; i < berSz; ) {
+ (void)GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
+ if (tag == ASN_EOC) {
+ break;
+ }
+ if (der != NULL) {
+ if (j + length > *derSz) {
+ ret = BUFFER_E;
+ goto end;
+ }
+ XMEMCPY(der + j, ber + i, length);
+ }
+ j += length;
+ i += length;
+ }
+ }
+
+ /* Move to next indef item in list */
+ indefItems->idx++;
+ }
+ else if (tag == ASN_EOC) {
+ /* End-Of-Content is not written out in DER */
+ }
+ else {
+ /* Write out definite length item as is. */
+ i += length;
+ if (der != NULL) {
+ /* Ensure space for item */
+ if (j + i - start > *derSz) {
+ ret = BUFFER_E;
+ goto end;
+ }
+ /* Copy item as is */
+ XMEMCPY(der + j, ber + start, i - start);
+ }
+ j += i - start;
+ }
+ }
+
+ /* Return the length of the DER encoded ASN.1 */
+ *derSz = j;
+ if (der == NULL) {
+ ret = LENGTH_ONLY_E;
+ }
+end:
+#ifdef WOLFSSL_SMALL_STACK
+ if (indefItems != NULL) {
+ XFREE(indefItems, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ return ret;
+}
+#endif
+
+#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)
+
+#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || \
+ defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+
+#ifdef WOLFSSL_CERT_EXT
+/* Set the DER/BER encoding of the ASN.1 BIT_STRING with a 16-bit value.
+ *
+ * val 16-bit value to encode.
+ * output Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+static word32 SetBitString16Bit(word16 val, byte* output)
+{
+ word32 idx;
+ int len;
+ byte lastByte;
+ byte unusedBits = 0;
+
+ if ((val >> 8) != 0) {
+ len = 2;
+ lastByte = (byte)(val >> 8);
+ }
+ else {
+ len = 1;
+ lastByte = (byte)val;
+ }
+
+ while (((lastByte >> unusedBits) & 0x01) == 0x00)
+ unusedBits++;
+
+ idx = SetBitString(len, unusedBits, output);
+ output[idx++] = (byte)val;
+ if (len > 1)
+ output[idx++] = (byte)(val >> 8);
+
+ return idx;
+}
+#endif /* WOLFSSL_CERT_EXT */
+#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 || defined(HAVE_ED448) */
+#endif /* WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN */
+
+
+
+/* hashType */
+#ifdef WOLFSSL_MD2
+ static const byte hashMd2hOid[] = {42, 134, 72, 134, 247, 13, 2, 2};
+#endif
+#ifndef NO_MD5
+ static const byte hashMd5hOid[] = {42, 134, 72, 134, 247, 13, 2, 5};
+#endif
+#ifndef NO_SHA
+ static const byte hashSha1hOid[] = {43, 14, 3, 2, 26};
+#endif
+#ifdef WOLFSSL_SHA224
+ static const byte hashSha224hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 4};
+#endif
+#ifndef NO_SHA256
+ static const byte hashSha256hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 1};
+#endif
+#ifdef WOLFSSL_SHA384
+ static const byte hashSha384hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 2};
+#endif
+#ifdef WOLFSSL_SHA512
+ static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3};
+#endif
+
+/* hmacType */
+#ifndef NO_HMAC
+ #ifdef WOLFSSL_SHA224
+ static const byte hmacSha224Oid[] = {42, 134, 72, 134, 247, 13, 2, 8};
+ #endif
+ #ifndef NO_SHA256
+ static const byte hmacSha256Oid[] = {42, 134, 72, 134, 247, 13, 2, 9};
+ #endif
+ #ifdef WOLFSSL_SHA384
+ static const byte hmacSha384Oid[] = {42, 134, 72, 134, 247, 13, 2, 10};
+ #endif
+ #ifdef WOLFSSL_SHA512
+ static const byte hmacSha512Oid[] = {42, 134, 72, 134, 247, 13, 2, 11};
+ #endif
+#endif
+
+/* sigType */
+#if !defined(NO_DSA) && !defined(NO_SHA)
+ static const byte sigSha1wDsaOid[] = {42, 134, 72, 206, 56, 4, 3};
+#endif /* NO_DSA */
#ifndef NO_RSA
+ #ifdef WOLFSSL_MD2
+ static const byte sigMd2wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 2};
+ #endif
+ #ifndef NO_MD5
+ static const byte sigMd5wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 4};
+ #endif
+ #ifndef NO_SHA
+ static const byte sigSha1wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 5};
+ #endif
+ #ifdef WOLFSSL_SHA224
+ static const byte sigSha224wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,14};
+ #endif
+ #ifndef NO_SHA256
+ static const byte sigSha256wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,11};
+ #endif
+ #ifdef WOLFSSL_SHA384
+ static const byte sigSha384wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,12};
+ #endif
+ #ifdef WOLFSSL_SHA512
+ static const byte sigSha512wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,13};
+ #endif
+#endif /* NO_RSA */
+#ifdef HAVE_ECC
+ #ifndef NO_SHA
+ static const byte sigSha1wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 1};
+ #endif
+ #ifdef WOLFSSL_SHA224
+ static const byte sigSha224wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 1};
+ #endif
+ #ifndef NO_SHA256
+ static const byte sigSha256wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 2};
+ #endif
+ #ifdef WOLFSSL_SHA384
+ static const byte sigSha384wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 3};
+ #endif
+ #ifdef WOLFSSL_SHA512
+ static const byte sigSha512wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 4};
+ #endif
+#endif /* HAVE_ECC */
+#ifdef HAVE_ED25519
+ static const byte sigEd25519Oid[] = {43, 101, 112};
+#endif /* HAVE_ED25519 */
+#ifdef HAVE_ED448
+ static const byte sigEd448Oid[] = {43, 101, 113};
+#endif /* HAVE_ED448 */
+
+/* keyType */
+#ifndef NO_DSA
+ static const byte keyDsaOid[] = {42, 134, 72, 206, 56, 4, 1};
+#endif /* NO_DSA */
+#ifndef NO_RSA
+ static const byte keyRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 1};
+#endif /* NO_RSA */
+#ifdef HAVE_NTRU
+ static const byte keyNtruOid[] = {43, 6, 1, 4, 1, 193, 22, 1, 1, 1, 1};
+#endif /* HAVE_NTRU */
+#ifdef HAVE_ECC
+ static const byte keyEcdsaOid[] = {42, 134, 72, 206, 61, 2, 1};
+#endif /* HAVE_ECC */
+#ifdef HAVE_ED25519
+ static const byte keyEd25519Oid[] = {43, 101, 112};
+#endif /* HAVE_ED25519 */
+#ifdef HAVE_ED448
+ static const byte keyEd448Oid[] = {43, 101, 113};
+#endif /* HAVE_ED448 */
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+ static const byte keyDhOid[] = {42, 134, 72, 134, 247, 13, 1, 3, 1};
+#endif /* ! NO_DH ... */
+
+/* curveType */
+#ifdef HAVE_ECC
+ /* See "ecc_sets" table in ecc.c */
+#endif /* HAVE_ECC */
+#ifdef HAVE_AES_CBC
+/* blkType */
+ #ifdef WOLFSSL_AES_128
+ static const byte blkAes128CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 2};
+ #endif
+ #ifdef WOLFSSL_AES_192
+ static const byte blkAes192CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 22};
+ #endif
+ #ifdef WOLFSSL_AES_256
+ static const byte blkAes256CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 42};
+ #endif
+#endif /* HAVE_AES_CBC */
+#ifdef HAVE_AESGCM
+ #ifdef WOLFSSL_AES_128
+ static const byte blkAes128GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 6};
+ #endif
+ #ifdef WOLFSSL_AES_192
+ static const byte blkAes192GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 26};
+ #endif
+ #ifdef WOLFSSL_AES_256
+ static const byte blkAes256GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 46};
+ #endif
+#endif /* HAVE_AESGCM */
+#ifdef HAVE_AESCCM
+ #ifdef WOLFSSL_AES_128
+ static const byte blkAes128CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 7};
+ #endif
+ #ifdef WOLFSSL_AES_192
+ static const byte blkAes192CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 27};
+ #endif
+ #ifdef WOLFSSL_AES_256
+ static const byte blkAes256CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 47};
+ #endif
+#endif /* HAVE_AESCCM */
-#ifdef HAVE_CAVIUM
+#ifndef NO_DES3
+ static const byte blkDesCbcOid[] = {43, 14, 3, 2, 7};
+ static const byte blkDes3CbcOid[] = {42, 134, 72, 134, 247, 13, 3, 7};
+#endif
-static int GetCaviumInt(byte** buff, word16* buffSz, const byte* input,
- word32* inOutIdx, word32 maxIdx, void* heap)
+/* keyWrapType */
+#ifdef WOLFSSL_AES_128
+ static const byte wrapAes128Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 5};
+#endif
+#ifdef WOLFSSL_AES_192
+ static const byte wrapAes192Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 25};
+#endif
+#ifdef WOLFSSL_AES_256
+ static const byte wrapAes256Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 45};
+#endif
+#ifdef HAVE_PKCS7
+/* From RFC 3211 */
+static const byte wrapPwriKekOid[] = {42, 134, 72, 134, 247, 13, 1, 9, 16, 3,9};
+#endif
+
+/* cmsKeyAgreeType */
+#ifndef NO_SHA
+ static const byte dhSinglePass_stdDH_sha1kdf_Oid[] =
+ {43, 129, 5, 16, 134, 72, 63, 0, 2};
+#endif
+#ifdef WOLFSSL_SHA224
+ static const byte dhSinglePass_stdDH_sha224kdf_Oid[] = {43, 129, 4, 1, 11, 0};
+#endif
+#ifndef NO_SHA256
+ static const byte dhSinglePass_stdDH_sha256kdf_Oid[] = {43, 129, 4, 1, 11, 1};
+#endif
+#ifdef WOLFSSL_SHA384
+ static const byte dhSinglePass_stdDH_sha384kdf_Oid[] = {43, 129, 4, 1, 11, 2};
+#endif
+#ifdef WOLFSSL_SHA512
+ static const byte dhSinglePass_stdDH_sha512kdf_Oid[] = {43, 129, 4, 1, 11, 3};
+#endif
+
+/* ocspType */
+#ifdef HAVE_OCSP
+ static const byte ocspBasicOid[] = {43, 6, 1, 5, 5, 7, 48, 1, 1};
+ static const byte ocspNonceOid[] = {43, 6, 1, 5, 5, 7, 48, 1, 2};
+#endif /* HAVE_OCSP */
+
+/* certExtType */
+static const byte extBasicCaOid[] = {85, 29, 19};
+static const byte extAltNamesOid[] = {85, 29, 17};
+static const byte extCrlDistOid[] = {85, 29, 31};
+static const byte extAuthInfoOid[] = {43, 6, 1, 5, 5, 7, 1, 1};
+static const byte extAuthKeyOid[] = {85, 29, 35};
+static const byte extSubjKeyOid[] = {85, 29, 14};
+static const byte extCertPolicyOid[] = {85, 29, 32};
+static const byte extKeyUsageOid[] = {85, 29, 15};
+static const byte extInhibitAnyOid[] = {85, 29, 54};
+static const byte extExtKeyUsageOid[] = {85, 29, 37};
+#ifndef IGNORE_NAME_CONSTRAINTS
+ static const byte extNameConsOid[] = {85, 29, 30};
+#endif
+
+/* certAuthInfoType */
+#ifdef HAVE_OCSP
+ static const byte extAuthInfoOcspOid[] = {43, 6, 1, 5, 5, 7, 48, 1};
+#endif
+static const byte extAuthInfoCaIssuerOid[] = {43, 6, 1, 5, 5, 7, 48, 2};
+
+/* certPolicyType */
+static const byte extCertPolicyAnyOid[] = {85, 29, 32, 0};
+
+/* certKeyUseType */
+static const byte extAltNamesHwNameOid[] = {43, 6, 1, 5, 5, 7, 8, 4};
+
+/* certKeyUseType */
+static const byte extExtKeyUsageAnyOid[] = {85, 29, 37, 0};
+static const byte extExtKeyUsageServerAuthOid[] = {43, 6, 1, 5, 5, 7, 3, 1};
+static const byte extExtKeyUsageClientAuthOid[] = {43, 6, 1, 5, 5, 7, 3, 2};
+static const byte extExtKeyUsageCodeSigningOid[] = {43, 6, 1, 5, 5, 7, 3, 3};
+static const byte extExtKeyUsageEmailProtectOid[] = {43, 6, 1, 5, 5, 7, 3, 4};
+static const byte extExtKeyUsageTimestampOid[] = {43, 6, 1, 5, 5, 7, 3, 8};
+static const byte extExtKeyUsageOcspSignOid[] = {43, 6, 1, 5, 5, 7, 3, 9};
+
+/* kdfType */
+static const byte pbkdf2Oid[] = {42, 134, 72, 134, 247, 13, 1, 5, 12};
+
+/* PKCS5 */
+#if !defined(NO_DES3) && !defined(NO_SHA)
+static const byte pbeSha1Des[] = {42, 134, 72, 134, 247, 13, 1, 5, 10};
+#endif
+static const byte pbes2[] = {42, 134, 72, 134, 247, 13, 1, 5, 13};
+
+/* PKCS12 */
+#if !defined(NO_RC4) && !defined(NO_SHA)
+static const byte pbeSha1RC4128[] = {42, 134, 72, 134, 247, 13, 1, 12, 1, 1};
+#endif
+#if !defined(NO_DES3) && !defined(NO_SHA)
+static const byte pbeSha1Des3[] = {42, 134, 72, 134, 247, 13, 1, 12, 1, 3};
+#endif
+
+#ifdef HAVE_LIBZ
+/* zlib compression */
+static const byte zlibCompress[] = {42, 134, 72, 134, 247, 13, 1, 9, 16, 3, 8};
+#endif
+#ifdef WOLFSSL_APACHE_HTTPD
+/* tlsExtType */
+static const byte tlsFeatureOid[] = {43, 6, 1, 5, 5, 7, 1, 24};
+/* certNameType */
+static const byte dnsSRVOid[] = {43, 6, 1, 5, 5, 7, 8, 7};
+#endif
+
+
+/* returns a pointer to the OID string on success and NULL on fail */
+const byte* OidFromId(word32 id, word32 type, word32* oidSz)
{
- word32 i = *inOutIdx;
- byte b = input[i++];
+ const byte* oid = NULL;
+
+ *oidSz = 0;
+
+ switch (type) {
+
+ case oidHashType:
+ switch (id) {
+ #ifdef WOLFSSL_MD2
+ case MD2h:
+ oid = hashMd2hOid;
+ *oidSz = sizeof(hashMd2hOid);
+ break;
+ #endif
+ #ifndef NO_MD5
+ case MD5h:
+ oid = hashMd5hOid;
+ *oidSz = sizeof(hashMd5hOid);
+ break;
+ #endif
+ #ifndef NO_SHA
+ case SHAh:
+ oid = hashSha1hOid;
+ *oidSz = sizeof(hashSha1hOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case SHA224h:
+ oid = hashSha224hOid;
+ *oidSz = sizeof(hashSha224hOid);
+ break;
+ #endif
+ #ifndef NO_SHA256
+ case SHA256h:
+ oid = hashSha256hOid;
+ *oidSz = sizeof(hashSha256hOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case SHA384h:
+ oid = hashSha384hOid;
+ *oidSz = sizeof(hashSha384hOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case SHA512h:
+ oid = hashSha512hOid;
+ *oidSz = sizeof(hashSha512hOid);
+ break;
+ #endif
+ }
+ break;
+
+ case oidSigType:
+ switch (id) {
+ #if !defined(NO_DSA) && !defined(NO_SHA)
+ case CTC_SHAwDSA:
+ oid = sigSha1wDsaOid;
+ *oidSz = sizeof(sigSha1wDsaOid);
+ break;
+ #endif /* NO_DSA */
+ #ifndef NO_RSA
+ #ifdef WOLFSSL_MD2
+ case CTC_MD2wRSA:
+ oid = sigMd2wRsaOid;
+ *oidSz = sizeof(sigMd2wRsaOid);
+ break;
+ #endif
+ #ifndef NO_MD5
+ case CTC_MD5wRSA:
+ oid = sigMd5wRsaOid;
+ *oidSz = sizeof(sigMd5wRsaOid);
+ break;
+ #endif
+ #ifndef NO_SHA
+ case CTC_SHAwRSA:
+ oid = sigSha1wRsaOid;
+ *oidSz = sizeof(sigSha1wRsaOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case CTC_SHA224wRSA:
+ oid = sigSha224wRsaOid;
+ *oidSz = sizeof(sigSha224wRsaOid);
+ break;
+ #endif
+ #ifndef NO_SHA256
+ case CTC_SHA256wRSA:
+ oid = sigSha256wRsaOid;
+ *oidSz = sizeof(sigSha256wRsaOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case CTC_SHA384wRSA:
+ oid = sigSha384wRsaOid;
+ *oidSz = sizeof(sigSha384wRsaOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case CTC_SHA512wRSA:
+ oid = sigSha512wRsaOid;
+ *oidSz = sizeof(sigSha512wRsaOid);
+ break;
+ #endif /* WOLFSSL_SHA512 */
+ #endif /* NO_RSA */
+ #ifdef HAVE_ECC
+ #ifndef NO_SHA
+ case CTC_SHAwECDSA:
+ oid = sigSha1wEcdsaOid;
+ *oidSz = sizeof(sigSha1wEcdsaOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case CTC_SHA224wECDSA:
+ oid = sigSha224wEcdsaOid;
+ *oidSz = sizeof(sigSha224wEcdsaOid);
+ break;
+ #endif
+ #ifndef NO_SHA256
+ case CTC_SHA256wECDSA:
+ oid = sigSha256wEcdsaOid;
+ *oidSz = sizeof(sigSha256wEcdsaOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case CTC_SHA384wECDSA:
+ oid = sigSha384wEcdsaOid;
+ *oidSz = sizeof(sigSha384wEcdsaOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case CTC_SHA512wECDSA:
+ oid = sigSha512wEcdsaOid;
+ *oidSz = sizeof(sigSha512wEcdsaOid);
+ break;
+ #endif
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case CTC_ED25519:
+ oid = sigEd25519Oid;
+ *oidSz = sizeof(sigEd25519Oid);
+ break;
+ #endif
+ #ifdef HAVE_ED448
+ case CTC_ED448:
+ oid = sigEd448Oid;
+ *oidSz = sizeof(sigEd448Oid);
+ break;
+ #endif
+ default:
+ break;
+ }
+ break;
+
+ case oidKeyType:
+ switch (id) {
+ #ifndef NO_DSA
+ case DSAk:
+ oid = keyDsaOid;
+ *oidSz = sizeof(keyDsaOid);
+ break;
+ #endif /* NO_DSA */
+ #ifndef NO_RSA
+ case RSAk:
+ oid = keyRsaOid;
+ *oidSz = sizeof(keyRsaOid);
+ break;
+ #endif /* NO_RSA */
+ #ifdef HAVE_NTRU
+ case NTRUk:
+ oid = keyNtruOid;
+ *oidSz = sizeof(keyNtruOid);
+ break;
+ #endif /* HAVE_NTRU */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ oid = keyEcdsaOid;
+ *oidSz = sizeof(keyEcdsaOid);
+ break;
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ oid = keyEd25519Oid;
+ *oidSz = sizeof(keyEd25519Oid);
+ break;
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ED448k:
+ oid = keyEd448Oid;
+ *oidSz = sizeof(keyEd448Oid);
+ break;
+ #endif /* HAVE_ED448 */
+ #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+ case DHk:
+ oid = keyDhOid;
+ *oidSz = sizeof(keyDhOid);
+ break;
+ #endif /* ! NO_DH && (WOLFSSL_QT || OPENSSL_ALL */
+ default:
+ break;
+ }
+ break;
+
+ #ifdef HAVE_ECC
+ case oidCurveType:
+ if (wc_ecc_get_oid(id, &oid, oidSz) < 0) {
+ WOLFSSL_MSG("ECC OID not found");
+ }
+ break;
+ #endif /* HAVE_ECC */
+
+ case oidBlkType:
+ switch (id) {
+ #ifdef HAVE_AES_CBC
+ #ifdef WOLFSSL_AES_128
+ case AES128CBCb:
+ oid = blkAes128CbcOid;
+ *oidSz = sizeof(blkAes128CbcOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_192
+ case AES192CBCb:
+ oid = blkAes192CbcOid;
+ *oidSz = sizeof(blkAes192CbcOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_256
+ case AES256CBCb:
+ oid = blkAes256CbcOid;
+ *oidSz = sizeof(blkAes256CbcOid);
+ break;
+ #endif
+ #endif /* HAVE_AES_CBC */
+ #ifdef HAVE_AESGCM
+ #ifdef WOLFSSL_AES_128
+ case AES128GCMb:
+ oid = blkAes128GcmOid;
+ *oidSz = sizeof(blkAes128GcmOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_192
+ case AES192GCMb:
+ oid = blkAes192GcmOid;
+ *oidSz = sizeof(blkAes192GcmOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_256
+ case AES256GCMb:
+ oid = blkAes256GcmOid;
+ *oidSz = sizeof(blkAes256GcmOid);
+ break;
+ #endif
+ #endif /* HAVE_AESGCM */
+ #ifdef HAVE_AESCCM
+ #ifdef WOLFSSL_AES_128
+ case AES128CCMb:
+ oid = blkAes128CcmOid;
+ *oidSz = sizeof(blkAes128CcmOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_192
+ case AES192CCMb:
+ oid = blkAes192CcmOid;
+ *oidSz = sizeof(blkAes192CcmOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_256
+ case AES256CCMb:
+ oid = blkAes256CcmOid;
+ *oidSz = sizeof(blkAes256CcmOid);
+ break;
+ #endif
+ #endif /* HAVE_AESCCM */
+ #ifndef NO_DES3
+ case DESb:
+ oid = blkDesCbcOid;
+ *oidSz = sizeof(blkDesCbcOid);
+ break;
+ case DES3b:
+ oid = blkDes3CbcOid;
+ *oidSz = sizeof(blkDes3CbcOid);
+ break;
+ #endif /* !NO_DES3 */
+ }
+ break;
+
+ #ifdef HAVE_OCSP
+ case oidOcspType:
+ switch (id) {
+ case OCSP_BASIC_OID:
+ oid = ocspBasicOid;
+ *oidSz = sizeof(ocspBasicOid);
+ break;
+ case OCSP_NONCE_OID:
+ oid = ocspNonceOid;
+ *oidSz = sizeof(ocspNonceOid);
+ break;
+ }
+ break;
+ #endif /* HAVE_OCSP */
+
+ case oidCertExtType:
+ switch (id) {
+ case BASIC_CA_OID:
+ oid = extBasicCaOid;
+ *oidSz = sizeof(extBasicCaOid);
+ break;
+ case ALT_NAMES_OID:
+ oid = extAltNamesOid;
+ *oidSz = sizeof(extAltNamesOid);
+ break;
+ case CRL_DIST_OID:
+ oid = extCrlDistOid;
+ *oidSz = sizeof(extCrlDistOid);
+ break;
+ case AUTH_INFO_OID:
+ oid = extAuthInfoOid;
+ *oidSz = sizeof(extAuthInfoOid);
+ break;
+ case AUTH_KEY_OID:
+ oid = extAuthKeyOid;
+ *oidSz = sizeof(extAuthKeyOid);
+ break;
+ case SUBJ_KEY_OID:
+ oid = extSubjKeyOid;
+ *oidSz = sizeof(extSubjKeyOid);
+ break;
+ case CERT_POLICY_OID:
+ oid = extCertPolicyOid;
+ *oidSz = sizeof(extCertPolicyOid);
+ break;
+ case KEY_USAGE_OID:
+ oid = extKeyUsageOid;
+ *oidSz = sizeof(extKeyUsageOid);
+ break;
+ case INHIBIT_ANY_OID:
+ oid = extInhibitAnyOid;
+ *oidSz = sizeof(extInhibitAnyOid);
+ break;
+ case EXT_KEY_USAGE_OID:
+ oid = extExtKeyUsageOid;
+ *oidSz = sizeof(extExtKeyUsageOid);
+ break;
+ #ifndef IGNORE_NAME_CONSTRAINTS
+ case NAME_CONS_OID:
+ oid = extNameConsOid;
+ *oidSz = sizeof(extNameConsOid);
+ break;
+ #endif
+ }
+ break;
+
+ case oidCrlExtType:
+ #ifdef HAVE_CRL
+ switch (id) {
+ case AUTH_KEY_OID:
+ oid = extAuthKeyOid;
+ *oidSz = sizeof(extAuthKeyOid);
+ break;
+ }
+ #endif
+ break;
+
+ case oidCertAuthInfoType:
+ switch (id) {
+ #ifdef HAVE_OCSP
+ case AIA_OCSP_OID:
+ oid = extAuthInfoOcspOid;
+ *oidSz = sizeof(extAuthInfoOcspOid);
+ break;
+ #endif
+ case AIA_CA_ISSUER_OID:
+ oid = extAuthInfoCaIssuerOid;
+ *oidSz = sizeof(extAuthInfoCaIssuerOid);
+ break;
+ }
+ break;
+
+ case oidCertPolicyType:
+ switch (id) {
+ case CP_ANY_OID:
+ oid = extCertPolicyAnyOid;
+ *oidSz = sizeof(extCertPolicyAnyOid);
+ break;
+ }
+ break;
+
+ case oidCertAltNameType:
+ switch (id) {
+ case HW_NAME_OID:
+ oid = extAltNamesHwNameOid;
+ *oidSz = sizeof(extAltNamesHwNameOid);
+ break;
+ }
+ break;
+
+ case oidCertKeyUseType:
+ switch (id) {
+ case EKU_ANY_OID:
+ oid = extExtKeyUsageAnyOid;
+ *oidSz = sizeof(extExtKeyUsageAnyOid);
+ break;
+ case EKU_SERVER_AUTH_OID:
+ oid = extExtKeyUsageServerAuthOid;
+ *oidSz = sizeof(extExtKeyUsageServerAuthOid);
+ break;
+ case EKU_CLIENT_AUTH_OID:
+ oid = extExtKeyUsageClientAuthOid;
+ *oidSz = sizeof(extExtKeyUsageClientAuthOid);
+ break;
+ case EKU_CODESIGNING_OID:
+ oid = extExtKeyUsageCodeSigningOid;
+ *oidSz = sizeof(extExtKeyUsageCodeSigningOid);
+ break;
+ case EKU_EMAILPROTECT_OID:
+ oid = extExtKeyUsageEmailProtectOid;
+ *oidSz = sizeof(extExtKeyUsageEmailProtectOid);
+ break;
+ case EKU_TIMESTAMP_OID:
+ oid = extExtKeyUsageTimestampOid;
+ *oidSz = sizeof(extExtKeyUsageTimestampOid);
+ break;
+ case EKU_OCSP_SIGN_OID:
+ oid = extExtKeyUsageOcspSignOid;
+ *oidSz = sizeof(extExtKeyUsageOcspSignOid);
+ break;
+ }
+ break;
+
+ case oidKdfType:
+ switch (id) {
+ case PBKDF2_OID:
+ oid = pbkdf2Oid;
+ *oidSz = sizeof(pbkdf2Oid);
+ break;
+ }
+ break;
+
+ case oidPBEType:
+ switch (id) {
+ #if !defined(NO_SHA) && !defined(NO_RC4)
+ case PBE_SHA1_RC4_128:
+ oid = pbeSha1RC4128;
+ *oidSz = sizeof(pbeSha1RC4128);
+ break;
+ #endif
+ #if !defined(NO_SHA) && !defined(NO_DES3)
+ case PBE_SHA1_DES:
+ oid = pbeSha1Des;
+ *oidSz = sizeof(pbeSha1Des);
+ break;
+
+ #endif
+ #if !defined(NO_SHA) && !defined(NO_DES3)
+ case PBE_SHA1_DES3:
+ oid = pbeSha1Des3;
+ *oidSz = sizeof(pbeSha1Des3);
+ break;
+ #endif
+ case PBES2:
+ oid = pbes2;
+ *oidSz = sizeof(pbes2);
+ break;
+ }
+ break;
+
+ case oidKeyWrapType:
+ switch (id) {
+ #ifdef WOLFSSL_AES_128
+ case AES128_WRAP:
+ oid = wrapAes128Oid;
+ *oidSz = sizeof(wrapAes128Oid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_192
+ case AES192_WRAP:
+ oid = wrapAes192Oid;
+ *oidSz = sizeof(wrapAes192Oid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_256
+ case AES256_WRAP:
+ oid = wrapAes256Oid;
+ *oidSz = sizeof(wrapAes256Oid);
+ break;
+ #endif
+ #ifdef HAVE_PKCS7
+ case PWRI_KEK_WRAP:
+ oid = wrapPwriKekOid;
+ *oidSz = sizeof(wrapPwriKekOid);
+ break;
+ #endif
+ }
+ break;
+
+ case oidCmsKeyAgreeType:
+ switch (id) {
+ #ifndef NO_SHA
+ case dhSinglePass_stdDH_sha1kdf_scheme:
+ oid = dhSinglePass_stdDH_sha1kdf_Oid;
+ *oidSz = sizeof(dhSinglePass_stdDH_sha1kdf_Oid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case dhSinglePass_stdDH_sha224kdf_scheme:
+ oid = dhSinglePass_stdDH_sha224kdf_Oid;
+ *oidSz = sizeof(dhSinglePass_stdDH_sha224kdf_Oid);
+ break;
+ #endif
+ #ifndef NO_SHA256
+ case dhSinglePass_stdDH_sha256kdf_scheme:
+ oid = dhSinglePass_stdDH_sha256kdf_Oid;
+ *oidSz = sizeof(dhSinglePass_stdDH_sha256kdf_Oid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case dhSinglePass_stdDH_sha384kdf_scheme:
+ oid = dhSinglePass_stdDH_sha384kdf_Oid;
+ *oidSz = sizeof(dhSinglePass_stdDH_sha384kdf_Oid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case dhSinglePass_stdDH_sha512kdf_scheme:
+ oid = dhSinglePass_stdDH_sha512kdf_Oid;
+ *oidSz = sizeof(dhSinglePass_stdDH_sha512kdf_Oid);
+ break;
+ #endif
+ }
+ break;
+
+#ifndef NO_HMAC
+ case oidHmacType:
+ switch (id) {
+ #ifdef WOLFSSL_SHA224
+ case HMAC_SHA224_OID:
+ oid = hmacSha224Oid;
+ *oidSz = sizeof(hmacSha224Oid);
+ break;
+ #endif
+ #ifndef NO_SHA256
+ case HMAC_SHA256_OID:
+ oid = hmacSha256Oid;
+ *oidSz = sizeof(hmacSha256Oid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case HMAC_SHA384_OID:
+ oid = hmacSha384Oid;
+ *oidSz = sizeof(hmacSha384Oid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case HMAC_SHA512_OID:
+ oid = hmacSha512Oid;
+ *oidSz = sizeof(hmacSha512Oid);
+ break;
+ #endif
+ }
+ break;
+#endif /* !NO_HMAC */
+
+#ifdef HAVE_LIBZ
+ case oidCompressType:
+ switch (id) {
+ case ZLIBc:
+ oid = zlibCompress;
+ *oidSz = sizeof(zlibCompress);
+ break;
+ }
+ break;
+#endif /* HAVE_LIBZ */
+#ifdef WOLFSSL_APACHE_HTTPD
+ case oidCertNameType:
+ switch (id) {
+ case NID_id_on_dnsSRV:
+ oid = dnsSRVOid;
+ *oidSz = sizeof(dnsSRVOid);
+ break;
+ }
+ break;
+ case oidTlsExtType:
+ switch (id) {
+ case TLS_FEATURE_OID:
+ oid = tlsFeatureOid;
+ *oidSz = sizeof(tlsFeatureOid);
+ break;
+ }
+ break;
+#endif /* WOLFSSL_APACHE_HTTPD */
+ case oidIgnoreType:
+ default:
+ break;
+ }
+
+ return oid;
+}
+
+#ifdef HAVE_OID_ENCODING
+int EncodeObjectId(const word16* in, word32 inSz, byte* out, word32* outSz)
+{
+ int i, x, len;
+ word32 d, t;
+
+ /* check args */
+ if (in == NULL || outSz == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* compute length of encoded OID */
+ d = (in[0] * 40) + in[1];
+ len = 0;
+ for (i = 1; i < (int)inSz; i++) {
+ x = 0;
+ t = d;
+ while (t) {
+ x++;
+ t >>= 1;
+ }
+ len += (x / 7) + ((x % 7) ? 1 : 0) + (d == 0 ? 1 : 0);
+
+ if (i < (int)inSz - 1) {
+ d = in[i + 1];
+ }
+ }
+
+ if (out) {
+ /* verify length */
+ if ((int)*outSz < len) {
+ return BUFFER_E; /* buffer provided is not large enough */
+ }
+
+ /* calc first byte */
+ d = (in[0] * 40) + in[1];
+
+ /* encode bytes */
+ x = 0;
+ for (i = 1; i < (int)inSz; i++) {
+ if (d) {
+ int y = x, z;
+ byte mask = 0;
+ while (d) {
+ out[x++] = (byte)((d & 0x7F) | mask);
+ d >>= 7;
+ mask |= 0x80; /* upper bit is set on all but the last byte */
+ }
+ /* now swap bytes y...x-1 */
+ z = x - 1;
+ while (y < z) {
+ mask = out[y];
+ out[y] = out[z];
+ out[z] = mask;
+ ++y;
+ --z;
+ }
+ }
+ else {
+ out[x++] = 0x00; /* zero value */
+ }
+
+ /* next word */
+ if (i < (int)inSz - 1) {
+ d = in[i + 1];
+ }
+ }
+ }
+
+ /* return length */
+ *outSz = len;
+
+ return 0;
+}
+#endif /* HAVE_OID_ENCODING */
+
+#ifdef HAVE_OID_DECODING
+int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz)
+{
+ int x = 0, y = 0;
+ word32 t = 0;
+
+ /* check args */
+ if (in == NULL || outSz == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* decode bytes */
+ while (inSz--) {
+ t = (t << 7) | (in[x] & 0x7F);
+ if (!(in[x] & 0x80)) {
+ if (y >= (int)*outSz) {
+ return BUFFER_E;
+ }
+ if (y == 0) {
+ out[0] = (t / 40);
+ out[1] = (t % 40);
+ y = 2;
+ }
+ else {
+ out[y++] = t;
+ }
+ t = 0; /* reset tmp */
+ }
+ x++;
+ }
+
+ /* return length */
+ *outSz = y;
+
+ return 0;
+}
+#endif /* HAVE_OID_DECODING */
+
+/* Get the DER/BER encoding of an ASN.1 OBJECT_ID header.
+ *
+ * input Buffer holding DER/BER encoded data.
+ * inOutIdx Current index into buffer to parse.
+ * len The number of bytes in the ASN.1 data.
+ * maxIdx Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ * ASN_OBJECt_ID_E when the OBJECT_ID tag is not found.
+ * ASN_PARSE_E when length is invalid.
+ * Otherwise, 0 to indicate success.
+ */
+int GetASNObjectId(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
+{
+ word32 idx = *inOutIdx;
int length;
+ byte tag;
- if (b != ASN_INTEGER)
+ if ((idx + 1) > maxIdx)
+ return BUFFER_E;
+
+ if (GetASNTag(input, &idx, &tag, maxIdx) != 0)
return ASN_PARSE_E;
- if (GetLength(input, &i, &length, maxIdx) < 0)
+ if (tag != ASN_OBJECT_ID)
+ return ASN_OBJECT_ID_E;
+
+ if (GetLength(input, &idx, &length, maxIdx) < 0)
return ASN_PARSE_E;
- if ( (b = input[i++]) == 0x00)
- length--;
- else
- i--;
+ *len = length;
+ *inOutIdx = idx;
+ return 0;
+}
- *buffSz = (word16)length;
- *buff = XMALLOC(*buffSz, heap, DYNAMIC_TYPE_CAVIUM_RSA);
- if (*buff == NULL)
- return MEMORY_E;
+/* Set the DER/BER encoding of the ASN.1 OBJECT_ID header.
+ *
+ * len Length of the OBJECT_ID data.
+ * output Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+int SetObjectId(int len, byte* output)
+{
+ int idx = 0;
+
+ output[idx++] = ASN_OBJECT_ID;
+ idx += SetLength(len, output + idx);
- XMEMCPY(*buff, input + i, *buffSz);
+ return idx;
+}
+
+int GetObjectId(const byte* input, word32* inOutIdx, word32* oid,
+ word32 oidType, word32 maxIdx)
+{
+ int ret = 0, length;
+ word32 idx = *inOutIdx;
+#ifndef NO_VERIFY_OID
+ word32 actualOidSz = 0;
+ const byte* actualOid;
+#endif /* NO_VERIFY_OID */
+
+ (void)oidType;
+ WOLFSSL_ENTER("GetObjectId()");
+ *oid = 0;
+
+ ret = GetASNObjectId(input, &idx, &length, maxIdx);
+ if (ret != 0)
+ return ret;
+
+#ifndef NO_VERIFY_OID
+ actualOid = &input[idx];
+ if (length > 0)
+ actualOidSz = (word32)length;
+#endif /* NO_VERIFY_OID */
+
+ while (length--) {
+ /* odd HC08 compiler behavior here when input[idx++] */
+ *oid += (word32)input[idx];
+ idx++;
+ }
+ /* just sum it up for now */
+
+ *inOutIdx = idx;
+
+#ifndef NO_VERIFY_OID
+ {
+ const byte* checkOid = NULL;
+ word32 checkOidSz;
+ #ifdef ASN_DUMP_OID
+ word32 i;
+ #endif
+
+ if (oidType != oidIgnoreType) {
+ checkOid = OidFromId(*oid, oidType, &checkOidSz);
+
+ #ifdef ASN_DUMP_OID
+ /* support for dumping OID information */
+ printf("OID (Type %d, Sz %d, Sum %d): ", oidType, actualOidSz, *oid);
+ for (i=0; i<actualOidSz; i++) {
+ printf("%d, ", actualOid[i]);
+ }
+ printf("\n");
+ #ifdef HAVE_OID_DECODING
+ {
+ word16 decOid[16];
+ word32 decOidSz = sizeof(decOid);
+ ret = DecodeObjectId(actualOid, actualOidSz, decOid, &decOidSz);
+ if (ret == 0) {
+ printf(" Decoded (Sz %d): ", decOidSz);
+ for (i=0; i<decOidSz; i++) {
+ printf("%d.", decOid[i]);
+ }
+ printf("\n");
+ }
+ else {
+ printf("DecodeObjectId failed: %d\n", ret);
+ }
+ }
+ #endif /* HAVE_OID_DECODING */
+ #endif /* ASN_DUMP_OID */
+
+ if (checkOid != NULL &&
+ (checkOidSz != actualOidSz ||
+ XMEMCMP(actualOid, checkOid, checkOidSz) != 0)) {
+ WOLFSSL_MSG("OID Check Failed");
+ return ASN_UNKNOWN_OID_E;
+ }
+ }
+ }
+#endif /* NO_VERIFY_OID */
+
+ return ret;
+}
+
+static int SkipObjectId(const byte* input, word32* inOutIdx, word32 maxIdx)
+{
+ word32 idx = *inOutIdx;
+ int length;
+ int ret;
+
+ ret = GetASNObjectId(input, &idx, &length, maxIdx);
+ if (ret != 0)
+ return ret;
+
+ idx += length;
+ *inOutIdx = idx;
- *inOutIdx = i + length;
return 0;
}
-static int CaviumRsaPrivateKeyDecode(const byte* input, word32* inOutIdx,
- RsaKey* key, word32 inSz)
+int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
+ word32 oidType, word32 maxIdx)
{
- int version, length;
- void* h = key->heap;
+ int length;
+ word32 idx = *inOutIdx;
+ int ret;
+ *oid = 0;
- if (GetSequence(input, inOutIdx, &length, inSz) < 0)
- return ASN_PARSE_E;
+ WOLFSSL_ENTER("GetAlgoId");
- if (GetMyVersion(input, inOutIdx, &version) < 0)
+ if (GetSequence(input, &idx, &length, maxIdx) < 0)
return ASN_PARSE_E;
- key->type = RSA_PRIVATE;
+ if (GetObjectId(input, &idx, oid, oidType, maxIdx) < 0)
+ return ASN_OBJECT_ID_E;
- if (GetCaviumInt(&key->c_n, &key->c_nSz, input, inOutIdx, inSz, h) < 0 ||
- GetCaviumInt(&key->c_e, &key->c_eSz, input, inOutIdx, inSz, h) < 0 ||
- GetCaviumInt(&key->c_d, &key->c_dSz, input, inOutIdx, inSz, h) < 0 ||
- GetCaviumInt(&key->c_p, &key->c_pSz, input, inOutIdx, inSz, h) < 0 ||
- GetCaviumInt(&key->c_q, &key->c_qSz, input, inOutIdx, inSz, h) < 0 ||
- GetCaviumInt(&key->c_dP, &key->c_dP_Sz, input, inOutIdx, inSz, h) < 0 ||
- GetCaviumInt(&key->c_dQ, &key->c_dQ_Sz, input, inOutIdx, inSz, h) < 0 ||
- GetCaviumInt(&key->c_u, &key->c_uSz, input, inOutIdx, inSz, h) < 0 )
- return ASN_RSA_KEY_E;
+ /* could have NULL tag and 0 terminator, but may not */
+ if (idx < maxIdx) {
+ word32 localIdx = idx; /*use localIdx to not advance when checking tag*/
+ byte tag;
+
+ if (GetASNTag(input, &localIdx, &tag, maxIdx) == 0) {
+ if (tag == ASN_TAG_NULL) {
+ ret = GetASNNull(input, &idx, maxIdx);
+ if (ret != 0)
+ return ret;
+ }
+ }
+ }
+
+ *inOutIdx = idx;
return 0;
}
+#ifndef NO_RSA
-#endif /* HAVE_CAVIUM */
-
+#ifndef HAVE_USER_RSA
int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
word32 inSz)
{
- int version, length;
-
-#ifdef HAVE_CAVIUM
- if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC)
- return CaviumRsaPrivateKeyDecode(input, inOutIdx, key, inSz);
-#endif
+ int version, length;
+ if (inOutIdx == NULL) {
+ return BAD_FUNC_ARG;
+ }
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
- if (GetMyVersion(input, inOutIdx, &version) < 0)
+ if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
return ASN_PARSE_E;
key->type = RSA_PRIVATE;
if (GetInt(&key->n, input, inOutIdx, inSz) < 0 ||
GetInt(&key->e, input, inOutIdx, inSz) < 0 ||
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
GetInt(&key->d, input, inOutIdx, inSz) < 0 ||
GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->q, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->dP, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->q, input, inOutIdx, inSz) < 0)
+#else
+ SkipInt(input, inOutIdx, inSz) < 0 ||
+ SkipInt(input, inOutIdx, inSz) < 0 ||
+ SkipInt(input, inOutIdx, inSz) < 0 )
+
+#endif
+ return ASN_RSA_KEY_E;
+#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)) \
+ && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
+ if (GetInt(&key->dP, input, inOutIdx, inSz) < 0 ||
GetInt(&key->dQ, input, inOutIdx, inSz) < 0 ||
GetInt(&key->u, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E;
+#else
+ if (SkipInt(input, inOutIdx, inSz) < 0 ||
+ SkipInt(input, inOutIdx, inSz) < 0 ||
+ SkipInt(input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E;
+#endif
+
+#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL)
+ if (wc_InitRsaHw(key) != 0) {
+ return BAD_STATE_E;
+ }
+#endif
return 0;
}
-
+#endif /* HAVE_USER_RSA */
#endif /* NO_RSA */
-/* Remove PKCS8 header, move beginning of traditional to beginning of input */
-int ToTraditional(byte* input, word32 sz)
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
+
+/* Remove PKCS8 header, place inOutIdx at beginning of traditional,
+ * return traditional length on success, negative on error */
+int ToTraditionalInline_ex(const byte* input, word32* inOutIdx, word32 sz,
+ word32* algId)
{
- word32 inOutIdx = 0, oid;
+ word32 idx;
int version, length;
+ int ret;
+ byte tag;
+
+ if (input == NULL || inOutIdx == NULL)
+ return BAD_FUNC_ARG;
+
+ idx = *inOutIdx;
- if (GetSequence(input, &inOutIdx, &length, sz) < 0)
+ if (GetSequence(input, &idx, &length, sz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetMyVersion(input, &idx, &version, sz) < 0)
return ASN_PARSE_E;
- if (GetMyVersion(input, &inOutIdx, &version) < 0)
+ if (GetAlgoId(input, &idx, algId, oidKeyType, sz) < 0)
return ASN_PARSE_E;
- if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0)
+ if (GetASNTag(input, &idx, &tag, sz) < 0)
return ASN_PARSE_E;
+ idx = idx - 1; /* reset idx after finding tag */
- if (input[inOutIdx] == ASN_OBJECT_ID) {
- /* pkcs8 ecc uses slightly different format */
- inOutIdx++; /* past id */
- if (GetLength(input, &inOutIdx, &length, sz) < 0)
+ if (tag == ASN_OBJECT_ID) {
+ if (SkipObjectId(input, &idx, sz) < 0)
return ASN_PARSE_E;
- inOutIdx += length; /* over sub id, key input will verify */
}
- if (input[inOutIdx++] != ASN_OCTET_STRING)
- return ASN_PARSE_E;
+ ret = GetOctetString(input, &idx, &length, sz);
+ if (ret < 0) {
+ if (ret == BUFFER_E)
+ return ASN_PARSE_E;
+ /* Some private keys don't expect an octet string */
+ WOLFSSL_MSG("Couldn't find Octet string");
+ }
- if (GetLength(input, &inOutIdx, &length, sz) < 0)
- return ASN_PARSE_E;
+ *inOutIdx = idx;
+
+ return length;
+}
+
+int ToTraditionalInline(const byte* input, word32* inOutIdx, word32 sz)
+{
+ word32 oid;
+
+ return ToTraditionalInline_ex(input, inOutIdx, sz, &oid);
+}
+
+/* Remove PKCS8 header, move beginning of traditional to beginning of input */
+int ToTraditional_ex(byte* input, word32 sz, word32* algId)
+{
+ word32 inOutIdx = 0;
+ int length;
+
+ if (input == NULL)
+ return BAD_FUNC_ARG;
+
+ length = ToTraditionalInline_ex(input, &inOutIdx, sz, algId);
+ if (length < 0)
+ return length;
XMEMMOVE(input, input + inOutIdx, length);
return length;
}
+int ToTraditional(byte* input, word32 sz)
+{
+ word32 oid;
+
+ return ToTraditional_ex(input, sz, &oid);
+}
+
+#endif /* HAVE_PKCS8 || HAVE_PKCS12 */
+
+#ifdef HAVE_PKCS8
+
+/* find beginning of traditional key inside PKCS#8 unencrypted buffer
+ * return traditional length on success, with inOutIdx at beginning of
+ * traditional
+ * return negative on failure/error */
+int wc_GetPkcs8TraditionalOffset(byte* input, word32* inOutIdx, word32 sz)
+{
+ int length;
+ word32 algId;
+
+ if (input == NULL || inOutIdx == NULL || (*inOutIdx > sz))
+ return BAD_FUNC_ARG;
+
+ length = ToTraditionalInline_ex(input, inOutIdx, sz, &algId);
+
+ return length;
+}
+
+
+/* PKCS#8 from RFC 5208
+ * This function takes in a DER key and converts it to PKCS#8 format. Used
+ * in creating PKCS#12 shrouded key bags.
+ * Reverse of ToTraditional
+ *
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version Version,
+ * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ * privateKey PrivateKey,
+ * attributes optional
+ * }
+ * Version ::= INTEGER
+ * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
+ * PrivateKey ::= OCTET STRING
+ *
+ * out buffer to place result in
+ * outSz size of out buffer
+ * key buffer with DER key
+ * keySz size of key buffer
+ * algoID algorithm ID i.e. RSAk
+ * curveOID ECC curve oid if used. Should be NULL for RSA keys.
+ * oidSz size of curve oid. Is set to 0 if curveOID is NULL.
+ *
+ * Returns the size of PKCS#8 placed into out. In error cases returns negative
+ * values.
+ */
+int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz,
+ int algoID, const byte* curveOID, word32 oidSz)
+{
+ word32 keyIdx = 0;
+ word32 tmpSz = 0;
+ word32 sz;
+
+
+ /* If out is NULL then return the max size needed
+ * + 2 for ASN_OBJECT_ID and ASN_OCTET_STRING tags */
+ if (out == NULL && outSz != NULL) {
+ *outSz = keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ
+ + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2;
+
+ if (curveOID != NULL)
+ *outSz += oidSz + MAX_LENGTH_SZ + 1;
+
+ WOLFSSL_MSG("Checking size of PKCS8");
+
+ return LENGTH_ONLY_E;
+ }
+
+ WOLFSSL_ENTER("wc_CreatePKCS8Key()");
+
+ if (key == NULL || out == NULL || outSz == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* check the buffer has enough room for largest possible size */
+ if (curveOID != NULL) {
+ if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ
+ + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 3 + oidSz + MAX_LENGTH_SZ))
+ return BUFFER_E;
+ }
+ else {
+ oidSz = 0; /* with no curveOID oid size must be 0 */
+ if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ
+ + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2))
+ return BUFFER_E;
+ }
+
+ /* PrivateKeyInfo ::= SEQUENCE */
+ keyIdx += MAX_SEQ_SZ; /* save room for sequence */
+
+ /* version Version
+ * no header information just INTEGER */
+ sz = SetMyVersion(PKCS8v0, out + keyIdx, 0);
+ tmpSz += sz; keyIdx += sz;
+
+ /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier */
+ sz = 0; /* set sz to 0 and get privateKey oid buffer size needed */
+ if (curveOID != NULL && oidSz > 0) {
+ byte buf[MAX_LENGTH_SZ];
+ sz = SetLength(oidSz, buf);
+ sz += 1; /* plus one for ASN object id */
+ }
+ sz = SetAlgoID(algoID, out + keyIdx, oidKeyType, oidSz + sz);
+ tmpSz += sz; keyIdx += sz;
+
+ /* privateKey PrivateKey *
+ * pkcs8 ecc uses slightly different format. Places curve oid in
+ * buffer */
+ if (curveOID != NULL && oidSz > 0) {
+ sz = SetObjectId(oidSz, out + keyIdx);
+ keyIdx += sz; tmpSz += sz;
+ XMEMCPY(out + keyIdx, curveOID, oidSz);
+ keyIdx += oidSz; tmpSz += oidSz;
+ }
+
+ sz = SetOctetString(keySz, out + keyIdx);
+ keyIdx += sz; tmpSz += sz;
+ XMEMCPY(out + keyIdx, key, keySz);
+ tmpSz += keySz;
+
+ /* attributes optional
+ * No attributes currently added */
+
+ /* rewind and add sequence */
+ sz = SetSequence(tmpSz, out);
+ XMEMMOVE(out + sz, out + MAX_SEQ_SZ, tmpSz);
+
+ return tmpSz + sz;
+}
+
+#endif /* HAVE_PKCS8 */
+
+#if defined(HAVE_PKCS12) || !defined(NO_CHECK_PRIVATE_KEY)
+/* check that the private key is a pair for the public key in certificate
+ * return 1 (true) on match
+ * return 0 or negative value on failure/error
+ *
+ * key : buffer holding DER format key
+ * keySz : size of key buffer
+ * der : a initialized and parsed DecodedCert holding a certificate */
+int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der)
+{
+ int ret;
+ (void)keySz;
+
+ if (key == NULL || der == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ #if !defined(NO_RSA) && !defined(NO_ASN_CRYPT)
+ /* test if RSA key */
+ if (der->keyOID == RSAk) {
+ #ifdef WOLFSSL_SMALL_STACK
+ RsaKey* a;
+ RsaKey* b = NULL;
+ #else
+ RsaKey a[1], b[1];
+ #endif
+ word32 keyIdx = 0;
+
+ #ifdef WOLFSSL_SMALL_STACK
+ a = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
+ if (a == NULL)
+ return MEMORY_E;
+ b = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
+ if (b == NULL) {
+ XFREE(a, NULL, DYNAMIC_TYPE_RSA);
+ return MEMORY_E;
+ }
+ #endif
+
+ if ((ret = wc_InitRsaKey(a, NULL)) < 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(b, NULL, DYNAMIC_TYPE_RSA);
+ XFREE(a, NULL, DYNAMIC_TYPE_RSA);
+ #endif
+ return ret;
+ }
+ if ((ret = wc_InitRsaKey(b, NULL)) < 0) {
+ wc_FreeRsaKey(a);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(b, NULL, DYNAMIC_TYPE_RSA);
+ XFREE(a, NULL, DYNAMIC_TYPE_RSA);
+ #endif
+ return ret;
+ }
+ if ((ret = wc_RsaPrivateKeyDecode(key, &keyIdx, a, keySz)) == 0) {
+ WOLFSSL_MSG("Checking RSA key pair");
+ keyIdx = 0; /* reset to 0 for parsing public key */
+
+ if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx, b,
+ der->pubKeySize)) == 0) {
+ /* limit for user RSA crypto because of RsaKey
+ * dereference. */
+ #if defined(HAVE_USER_RSA)
+ WOLFSSL_MSG("Cannot verify RSA pair with user RSA");
+ ret = 1; /* return first RSA cert as match */
+ #else
+ /* both keys extracted successfully now check n and e
+ * values are the same. This is dereferencing RsaKey */
+ if (mp_cmp(&(a->n), &(b->n)) != MP_EQ ||
+ mp_cmp(&(a->e), &(b->e)) != MP_EQ) {
+ ret = MP_CMP_E;
+ }
+ else
+ ret = 1;
+ #endif
+ }
+ }
+ wc_FreeRsaKey(b);
+ wc_FreeRsaKey(a);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(b, NULL, DYNAMIC_TYPE_RSA);
+ XFREE(a, NULL, DYNAMIC_TYPE_RSA);
+ #endif
+ }
+ else
+ #endif /* !NO_RSA && !NO_ASN_CRYPT */
+
+ #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT)
+ if (der->keyOID == ECDSAk) {
+ #ifdef WOLFSSL_SMALL_STACK
+ ecc_key* key_pair;
+ byte* privDer;
+ #else
+ ecc_key key_pair[1];
+ byte privDer[MAX_ECC_BYTES];
+ #endif
+ word32 privSz = MAX_ECC_BYTES;
+ word32 keyIdx = 0;
+
+ #ifdef WOLFSSL_SMALL_STACK
+ key_pair = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC);
+ if (key_pair == NULL)
+ return MEMORY_E;
+ privDer = (byte*)XMALLOC(MAX_ECC_BYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (privDer == NULL) {
+ XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC);
+ return MEMORY_E;
+ }
+ #endif
+
+ if ((ret = wc_ecc_init(key_pair)) < 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(privDer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC);
+ #endif
+ return ret;
+ }
+
+ if ((ret = wc_EccPrivateKeyDecode(key, &keyIdx, key_pair,
+ keySz)) == 0) {
+ WOLFSSL_MSG("Checking ECC key pair");
+
+ if ((ret = wc_ecc_export_private_only(key_pair, privDer, &privSz))
+ == 0) {
+ wc_ecc_free(key_pair);
+ ret = wc_ecc_init(key_pair);
+ if (ret == 0) {
+ ret = wc_ecc_import_private_key((const byte*)privDer,
+ privSz, (const byte*)der->publicKey,
+ der->pubKeySize, key_pair);
+ }
+
+ /* public and private extracted successfully now check if is
+ * a pair and also do sanity checks on key. wc_ecc_check_key
+ * checks that private * base generator equals pubkey */
+ if (ret == 0) {
+ if ((ret = wc_ecc_check_key(key_pair)) == 0) {
+ ret = 1;
+ }
+ }
+ ForceZero(privDer, privSz);
+ }
+ }
+ wc_ecc_free(key_pair);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(privDer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC);
+ #endif
+ }
+ else
+ #endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */
+
+ #if defined(HAVE_ED25519) && !defined(NO_ASN_CRYPT)
+ if (der->keyOID == ED25519k) {
+ #ifdef WOLFSSL_SMALL_STACK
+ ed25519_key* key_pair;
+ #else
+ ed25519_key key_pair[1];
+ #endif
+ word32 keyIdx = 0;
+
+ #ifdef WOLFSSL_SMALL_STACK
+ key_pair = (ed25519_key*)XMALLOC(sizeof(ed25519_key), NULL,
+ DYNAMIC_TYPE_ED25519);
+ if (key_pair == NULL)
+ return MEMORY_E;
+ #endif
+
+ if ((ret = wc_ed25519_init(key_pair)) < 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(key_pair, NULL, DYNAMIC_TYPE_ED25519);
+ #endif
+ return ret;
+ }
+ if ((ret = wc_Ed25519PrivateKeyDecode(key, &keyIdx, key_pair,
+ keySz)) == 0) {
+ WOLFSSL_MSG("Checking ED25519 key pair");
+ keyIdx = 0;
+ if ((ret = wc_ed25519_import_public(der->publicKey, der->pubKeySize,
+ key_pair)) == 0) {
+ /* public and private extracted successfully no check if is
+ * a pair and also do sanity checks on key. wc_ecc_check_key
+ * checks that private * base generator equals pubkey */
+ if ((ret = wc_ed25519_check_key(key_pair)) == 0)
+ ret = 1;
+ }
+ }
+ wc_ed25519_free(key_pair);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(key_pair, NULL, DYNAMIC_TYPE_ED25519);
+ #endif
+ }
+ else
+ #endif /* HAVE_ED25519 && !NO_ASN_CRYPT */
+
+ #if defined(HAVE_ED448) && !defined(NO_ASN_CRYPT)
+ if (der->keyOID == ED448k) {
+ #ifdef WOLFSSL_SMALL_STACK
+ ed448_key* key_pair = NULL;
+ #else
+ ed448_key key_pair[1];
+ #endif
+ word32 keyIdx = 0;
+
+ #ifdef WOLFSSL_SMALL_STACK
+ key_pair = (ed448_key*)XMALLOC(sizeof(ed448_key), NULL,
+ DYNAMIC_TYPE_ED448);
+ if (key_pair == NULL)
+ return MEMORY_E;
+ #endif
+
+ if ((ret = wc_ed448_init(key_pair)) < 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(key_pair, NULL, DYNAMIC_TYPE_ED448);
+ #endif
+ return ret;
+ }
+ if ((ret = wc_Ed448PrivateKeyDecode(key, &keyIdx, key_pair,
+ keySz)) == 0) {
+ WOLFSSL_MSG("Checking ED448 key pair");
+ keyIdx = 0;
+ if ((ret = wc_ed448_import_public(der->publicKey, der->pubKeySize,
+ key_pair)) == 0) {
+ /* public and private extracted successfully no check if is
+ * a pair and also do sanity checks on key. wc_ecc_check_key
+ * checks that private * base generator equals pubkey */
+ if ((ret = wc_ed448_check_key(key_pair)) == 0)
+ ret = 1;
+ }
+ }
+ wc_ed448_free(key_pair);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(key_pair, NULL, DYNAMIC_TYPE_ED448);
+ #endif
+ }
+ else
+ #endif /* HAVE_ED448 && !NO_ASN_CRYPT */
+ {
+ ret = 0;
+ }
+
+ (void)keySz;
+
+ return ret;
+}
+
+#endif /* HAVE_PKCS12 || !NO_CHECK_PRIVATE_KEY */
#ifndef NO_PWDBASED
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
/* Check To see if PKCS version algo is supported, set id if it is return 0
< 0 on error */
-static int CheckAlgo(int first, int second, int* id, int* version)
+static int CheckAlgo(int first, int second, int* id, int* version, int* blockSz)
{
*id = ALGO_ID_E;
*version = PKCS5; /* default */
+ if (blockSz) *blockSz = 8; /* default */
if (first == 1) {
switch (second) {
- case 1:
+#if !defined(NO_SHA)
+ #ifndef NO_RC4
+ case PBE_SHA1_RC4_128:
*id = PBE_SHA1_RC4_128;
- *version = PKCS12;
+ *version = PKCS12v1;
return 0;
- case 3:
+ #endif
+ #ifndef NO_DES3
+ case PBE_SHA1_DES3:
*id = PBE_SHA1_DES3;
- *version = PKCS12;
+ *version = PKCS12v1;
+ if (blockSz) *blockSz = DES_BLOCK_SIZE;
return 0;
+ case PBE_SHA1_DES:
+ *id = PBE_SHA1_DES;
+ *version = PKCS12v1;
+ if (blockSz) *blockSz = DES_BLOCK_SIZE;
+ return 0;
+ #endif
+#endif /* !NO_SHA */
default:
return ALGO_ID_E;
}
@@ -857,213 +3124,655 @@ static int CheckAlgo(int first, int second, int* id, int* version)
}
switch (second) {
+#ifndef NO_DES3
+ #ifndef NO_MD5
case 3: /* see RFC 2898 for ids */
*id = PBE_MD5_DES;
+ if (blockSz) *blockSz = DES_BLOCK_SIZE;
return 0;
+ #endif
+ #ifndef NO_SHA
case 10:
*id = PBE_SHA1_DES;
+ if (blockSz) *blockSz = DES_BLOCK_SIZE;
return 0;
+ #endif
+#endif /* !NO_DES3 */
default:
return ALGO_ID_E;
}
}
-
/* Check To see if PKCS v2 algo is supported, set id if it is return 0
< 0 on error */
-static int CheckAlgoV2(int oid, int* id)
+static int CheckAlgoV2(int oid, int* id, int* blockSz)
{
+ if (blockSz) *blockSz = 8; /* default */
+ (void)id; /* not used if AES and DES3 disabled */
switch (oid) {
- case 69:
+#if !defined(NO_DES3) && !defined(NO_SHA)
+ case DESb:
*id = PBE_SHA1_DES;
+ if (blockSz) *blockSz = DES_BLOCK_SIZE;
return 0;
- case 652:
+ case DES3b:
*id = PBE_SHA1_DES3;
+ if (blockSz) *blockSz = DES_BLOCK_SIZE;
return 0;
+#endif
+#ifdef WOLFSSL_AES_256
+ case AES256CBCb:
+ *id = PBE_AES256_CBC;
+ if (blockSz) *blockSz = AES_BLOCK_SIZE;
+ return 0;
+#endif
+#ifdef WOLFSSL_AES_128
+ case AES128CBCb:
+ *id = PBE_AES128_CBC;
+ if (blockSz) *blockSz = AES_BLOCK_SIZE;
+ return 0;
+#endif
default:
+ WOLFSSL_MSG("No PKCS v2 algo found");
return ALGO_ID_E;
}
}
+#endif /* HAVE_PKCS8 || HAVE_PKCS12 */
+
+#ifdef HAVE_PKCS8
-/* Decrypt intput in place from parameters based on id */
-static int DecryptKey(const char* password, int passwordSz, byte* salt,
- int saltSz, int iterations, int id, byte* input,
- int length, int version, byte* cbcIv)
+int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz,
+ int* algoID, void* heap)
{
- int typeH;
- int derivedLen;
- int decryptionType;
- int ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
- byte* key;
-#else
- byte key[MAX_KEY_SIZE];
-#endif
+ word32 tmpIdx = 0;
- switch (id) {
- case PBE_MD5_DES:
- typeH = MD5;
- derivedLen = 16; /* may need iv for v1.5 */
- decryptionType = DES_TYPE;
- break;
+ if (key == NULL || algoID == NULL)
+ return BAD_FUNC_ARG;
- case PBE_SHA1_DES:
- typeH = SHA;
- derivedLen = 16; /* may need iv for v1.5 */
- decryptionType = DES_TYPE;
- break;
+ *algoID = 0;
- case PBE_SHA1_DES3:
- typeH = SHA;
- derivedLen = 32; /* may need iv for v1.5 */
- decryptionType = DES3_TYPE;
- break;
+ #if !defined(NO_RSA) && !defined(NO_ASN_CRYPT)
+ {
+ RsaKey rsa;
- case PBE_SHA1_RC4_128:
- typeH = SHA;
- derivedLen = 16;
- decryptionType = RC4_TYPE;
- break;
+ wc_InitRsaKey(&rsa, heap);
+ if (wc_RsaPrivateKeyDecode(key, &tmpIdx, &rsa, keySz) == 0) {
+ *algoID = RSAk;
+ }
+ else {
+ WOLFSSL_MSG("Not RSA DER key");
+ }
+ wc_FreeRsaKey(&rsa);
+ }
+ #endif /* !NO_RSA && !NO_ASN_CRYPT */
+ #if defined(HAVE_ECC) && !defined(NO_ASN_CRYPT)
+ if (*algoID == 0) {
+ ecc_key ecc;
+
+ tmpIdx = 0;
+ wc_ecc_init_ex(&ecc, heap, INVALID_DEVID);
+ if (wc_EccPrivateKeyDecode(key, &tmpIdx, &ecc, keySz) == 0) {
+ *algoID = ECDSAk;
+
+ /* now find oid */
+ if (wc_ecc_get_oid(ecc.dp->oidSum, curveOID, oidSz) < 0) {
+ WOLFSSL_MSG("Error getting ECC curve OID");
+ wc_ecc_free(&ecc);
+ return BAD_FUNC_ARG;
+ }
+ }
+ else {
+ WOLFSSL_MSG("Not ECC DER key either");
+ }
+ wc_ecc_free(&ecc);
+ }
+#endif /* HAVE_ECC && !NO_ASN_CRYPT */
+#if defined(HAVE_ED25519) && !defined(NO_ASN_CRYPT)
+ if (*algoID != RSAk && *algoID != ECDSAk) {
+ ed25519_key ed25519;
+
+ tmpIdx = 0;
+ if (wc_ed25519_init(&ed25519) == 0) {
+ if (wc_Ed25519PrivateKeyDecode(key, &tmpIdx, &ed25519, keySz)
+ == 0) {
+ *algoID = ED25519k;
+ }
+ else {
+ WOLFSSL_MSG("Not ED25519 DER key");
+ }
+ wc_ed25519_free(&ed25519);
+ }
+ else {
+ WOLFSSL_MSG("GetKeyOID wc_ed25519_init failed");
+ }
+ }
+#endif /* HAVE_ED25519 && !NO_ASN_CRYPT */
+#if defined(HAVE_ED448) && !defined(NO_ASN_CRYPT)
+ if (*algoID != RSAk && *algoID != ECDSAk && *algoID != ED25519k) {
+ ed448_key ed448;
+
+ tmpIdx = 0;
+ if (wc_ed448_init(&ed448) == 0) {
+ if (wc_Ed448PrivateKeyDecode(key, &tmpIdx, &ed448, keySz) == 0) {
+ *algoID = ED448k;
+ }
+ else {
+ WOLFSSL_MSG("Not ED448 DER key");
+ }
+ wc_ed448_free(&ed448);
+ }
+ else {
+ WOLFSSL_MSG("GetKeyOID wc_ed448_init failed");
+ }
+ }
+#endif /* HAVE_ED448 && !NO_ASN_CRYPT */
- default:
- return ALGO_ID_E;
+ /* if flag is not set then is neither RSA or ECC key that could be
+ * found */
+ if (*algoID == 0) {
+ WOLFSSL_MSG("Bad key DER or compile options");
+ return BAD_FUNC_ARG;
}
-#ifdef WOLFSSL_SMALL_STACK
- key = (byte*)XMALLOC(MAX_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (key == NULL)
- return MEMORY_E;
-#endif
+ (void)tmpIdx;
+ (void)curveOID;
+ (void)oidSz;
+ (void)keySz;
+ (void)heap;
- if (version == PKCS5v2)
- ret = wc_PBKDF2(key, (byte*)password, passwordSz, salt, saltSz, iterations,
- derivedLen, typeH);
-#ifndef NO_SHA
- else if (version == PKCS5)
- ret = wc_PBKDF1(key, (byte*)password, passwordSz, salt, saltSz, iterations,
- derivedLen, typeH);
-#endif
- else if (version == PKCS12) {
- int i, idx = 0;
- byte unicodePasswd[MAX_UNICODE_SZ];
+ return 1;
+}
+
+#endif /* HAVE_PKCS8 */
+
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
+
+#define PKCS8_MIN_BLOCK_SIZE 8
+static int Pkcs8Pad(byte* buf, int sz, int blockSz)
+{
+ int i, padSz;
+
+ /* calculate pad size */
+ padSz = blockSz - (sz & (blockSz - 1));
+
+ /* pad with padSz value */
+ if (buf) {
+ for (i = 0; i < padSz; i++) {
+ buf[sz+i] = (byte)(padSz & 0xFF);
+ }
+ }
+
+ /* return adjusted length */
+ return sz + padSz;
+}
+
+#endif /* HAVE_PKCS8 || HAVE_PKCS12 */
+
+#ifdef HAVE_PKCS8
+
+/*
+ * Used when creating PKCS12 shrouded key bags
+ * vPKCS is the version of PKCS to use
+ * vAlgo is the algorithm version to use
+ *
+ * if salt is NULL a random number is generated
+ *
+ * returns the size of encrypted data on success
+ */
+int UnTraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
+ const char* password, int passwordSz, int vPKCS, int vAlgo,
+ byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap)
+{
+ int algoID = 0;
+ byte* tmp;
+ word32 tmpSz = 0;
+ word32 sz;
+ word32 seqSz;
+ word32 inOutIdx = 0;
+ word32 totalSz = 0;
+ int version, id;
+ int ret;
+ int blockSz = 0;
+
+ const byte* curveOID = NULL;
+ word32 oidSz = 0;
- if ( (passwordSz * 2 + 2) > (int)sizeof(unicodePasswd)) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ byte* saltTmp = NULL;
+ byte* cbcIv = NULL;
+#else
+ byte saltTmp[MAX_IV_SIZE];
+ byte cbcIv[MAX_IV_SIZE];
#endif
- return UNICODE_SIZE_E;
+
+ WOLFSSL_ENTER("UnTraditionalEnc()");
+
+ if (saltSz > MAX_SALT_SIZE)
+ return ASN_PARSE_E;
+
+
+ inOutIdx += MAX_SEQ_SZ; /* leave room for size of finished shroud */
+ if (CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz) < 0) {
+ WOLFSSL_MSG("Bad/Unsupported algorithm ID");
+ return ASN_INPUT_E; /* Algo ID error */
+ }
+
+ if (out != NULL) {
+ if (*outSz < inOutIdx + MAX_ALGO_SZ + MAX_SALT_SIZE + MAX_SEQ_SZ + 1 +
+ MAX_LENGTH_SZ + MAX_SHORT_SZ + 1)
+ return BUFFER_E;
+
+ if (version == PKCS5v2) {
+ WOLFSSL_MSG("PKCS5v2 Not supported yet\n");
+ return ASN_VERSION_E;
}
- for (i = 0; i < passwordSz; i++) {
- unicodePasswd[idx++] = 0x00;
- unicodePasswd[idx++] = (byte)password[i];
+ if (salt == NULL || saltSz == 0) {
+ saltSz = 8;
+ #ifdef WOLFSSL_SMALL_STACK
+ saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (saltTmp == NULL)
+ return MEMORY_E;
+ #endif
+ salt = saltTmp;
+
+ if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) {
+ WOLFSSL_MSG("Error generating random salt");
+ #ifdef WOLFSSL_SMALL_STACK
+ if (saltTmp != NULL)
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return ret;
+ }
}
- /* add trailing NULL */
- unicodePasswd[idx++] = 0x00;
- unicodePasswd[idx++] = 0x00;
- ret = wc_PKCS12_PBKDF(key, unicodePasswd, idx, salt, saltSz,
- iterations, derivedLen, typeH, 1);
- if (decryptionType != RC4_TYPE)
- ret += wc_PKCS12_PBKDF(cbcIv, unicodePasswd, idx, salt, saltSz,
- iterations, 8, typeH, 2);
+
+ /* leave room for a sequence (contains salt and iterations int) */
+ inOutIdx += MAX_SEQ_SZ; sz = 0;
+ inOutIdx += MAX_ALGO_SZ;
+
+ /* place salt in buffer */
+ out[inOutIdx++] = ASN_OCTET_STRING; sz++;
+ tmpSz = SetLength(saltSz, out + inOutIdx);
+ inOutIdx += tmpSz; sz += tmpSz;
+ XMEMCPY(out + inOutIdx, salt, saltSz);
+ inOutIdx += saltSz; sz += saltSz;
+
+ /* place iteration count in buffer */
+ ret = SetShortInt(out, &inOutIdx, itt, *outSz);
+ if (ret < 0) {
+ return ret;
+ }
+ sz += (word32)ret;
+
+ /* wind back index and set sequence then clean up buffer */
+ inOutIdx -= (sz + MAX_SEQ_SZ);
+ tmpSz = SetSequence(sz, out + inOutIdx);
+ XMEMMOVE(out + inOutIdx + tmpSz, out + inOutIdx + MAX_SEQ_SZ, sz);
+ totalSz += tmpSz + sz; sz += tmpSz;
+
+ /* add in algo ID */
+ inOutIdx -= MAX_ALGO_SZ;
+ tmpSz = SetAlgoID(id, out + inOutIdx, oidPBEType, sz);
+ XMEMMOVE(out + inOutIdx + tmpSz, out + inOutIdx + MAX_ALGO_SZ, sz);
+ totalSz += tmpSz; inOutIdx += tmpSz + sz;
+
+ /* octet string containing encrypted key */
+ out[inOutIdx++] = ASN_OCTET_STRING; totalSz++;
}
- else {
+
+ /* check key type and get OID if ECC */
+ if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap))< 0) {
+ WOLFSSL_MSG("Error getting key OID");
+ return ret;
+ }
+
+ /* PKCS#8 wrapping around key */
+ if (wc_CreatePKCS8Key(NULL, &tmpSz, key, keySz, algoID, curveOID, oidSz)
+ != LENGTH_ONLY_E) {
+ #ifdef WOLFSSL_SMALL_STACK
+ if (saltTmp != NULL)
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return MEMORY_E;
+ }
+
+ /* check if should return max size */
+ if (out == NULL) {
+ /* account for salt size */
+ if (salt == NULL || saltSz == 0) {
+ tmpSz += MAX_SALT_SIZE;
+ }
+ else {
+ tmpSz += saltSz;
+ }
+
+ /* plus 3 for tags */
+ *outSz = tmpSz + MAX_ALGO_SZ + MAX_LENGTH_SZ +MAX_LENGTH_SZ + MAX_SEQ_SZ
+ + MAX_LENGTH_SZ + MAX_SEQ_SZ + 3;
+ return LENGTH_ONLY_E;
+ }
+
+ /* reserve buffer for crypto and make sure it supports full blocks */
+ tmp = (byte*)XMALLOC(tmpSz + (blockSz-1), heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (tmp == NULL) {
+ #ifdef WOLFSSL_SMALL_STACK
+ if (saltTmp != NULL)
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return MEMORY_E;
+ }
+
+ if ((ret = wc_CreatePKCS8Key(tmp, &tmpSz, key, keySz, algoID, curveOID,
+ oidSz)) < 0) {
+ XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ WOLFSSL_MSG("Error wrapping key with PKCS#8");
+ #ifdef WOLFSSL_SMALL_STACK
+ if (saltTmp != NULL)
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return ret;
+ }
+ tmpSz = ret;
+
+ /* adjust size to pad */
+ tmpSz = Pkcs8Pad(tmp, tmpSz, blockSz);
+
#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (cbcIv == NULL) {
+ if (saltTmp != NULL)
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(salt, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
#endif
- return ALGO_ID_E;
+
+ /* encrypt PKCS#8 wrapped key */
+ if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id,
+ tmp, tmpSz, version, cbcIv, 1, 0)) < 0) {
+ XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ WOLFSSL_MSG("Error encrypting key");
+ #ifdef WOLFSSL_SMALL_STACK
+ if (saltTmp != NULL)
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (cbcIv != NULL)
+ XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return ret; /* encryption failure */
}
+ totalSz += tmpSz;
- if (ret != 0) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (saltTmp != NULL)
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (cbcIv != NULL)
+ XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- return ret;
+
+ if (*outSz < inOutIdx + tmpSz + MAX_LENGTH_SZ) {
+ XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return BUFFER_E;
}
- switch (decryptionType) {
-#ifndef NO_DES3
- case DES_TYPE:
- {
- Des dec;
- byte* desIv = key + 8;
+ /* set length of key and copy over encrypted key */
+ seqSz = SetLength(tmpSz, out + inOutIdx);
+ inOutIdx += seqSz; totalSz += seqSz;
+ XMEMCPY(out + inOutIdx, tmp, tmpSz);
+ XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (version == PKCS5v2 || version == PKCS12)
- desIv = cbcIv;
+ /* set total size at beginning */
+ sz = SetSequence(totalSz, out);
+ XMEMMOVE(out + sz, out + MAX_SEQ_SZ, totalSz);
- ret = wc_Des_SetKey(&dec, key, desIv, DES_DECRYPTION);
- if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return ret;
- }
+ (void)rng;
- wc_Des_CbcDecrypt(&dec, input, input, length);
- break;
- }
+ return totalSz + sz;
+}
- case DES3_TYPE:
- {
- Des3 dec;
- byte* desIv = key + 24;
+static int GetAlgoV2(int encAlgId, const byte** oid, int *len, int* id,
+ int *blkSz)
+{
+ int ret = 0;
- if (version == PKCS5v2 || version == PKCS12)
- desIv = cbcIv;
- ret = wc_Des3_SetKey(&dec, key, desIv, DES_DECRYPTION);
- if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ switch (encAlgId) {
+#if !defined(NO_DES3) && !defined(NO_SHA)
+ case DESb:
+ *len = sizeof(blkDesCbcOid);
+ *oid = blkDesCbcOid;
+ *id = PBE_SHA1_DES;
+ *blkSz = 8;
+ break;
+ case DES3b:
+ *len = sizeof(blkDes3CbcOid);
+ *oid = blkDes3CbcOid;
+ *id = PBE_SHA1_DES3;
+ *blkSz = 8;
+ break;
#endif
- return ret;
- }
- ret = wc_Des3_CbcDecrypt(&dec, input, input, length);
- if (ret != 0) {
+#if defined(WOLFSSL_AES_256) && defined(HAVE_AES_CBC)
+ case AES256CBCb:
+ *len = sizeof(blkAes256CbcOid);
+ *oid = blkAes256CbcOid;
+ *id = PBE_AES256_CBC;
+ *blkSz = 16;
+ break;
+#endif
+ default:
+ (void)len;
+ (void)oid;
+ (void)id;
+ (void)blkSz;
+ ret = ALGO_ID_E;
+ }
+
+ return ret;
+}
+
+/* Converts Encrypted PKCS#8 to 'traditional' (i.e. PKCS#8 removed from
+ * decrypted key.)
+ */
+int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
+ const char* password, int passwordSz, int vPKCS, int vAlgo,
+ int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng,
+ void* heap)
+{
+ int ret = 0;
+ int version, blockSz, id;
+ word32 idx = 0, encIdx;
#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ byte* saltTmp = NULL;
+#else
+ byte saltTmp[MAX_SALT_SIZE];
#endif
- return ret;
- }
- break;
+ byte cbcIv[MAX_IV_SIZE];
+ byte *pkcs8Key = NULL;
+ word32 pkcs8KeySz = 0, padSz = 0;
+ int algId = 0;
+ const byte* curveOid = NULL;
+ word32 curveOidSz = 0;
+ const byte* pbeOid = NULL;
+ word32 pbeOidSz = 0;
+ const byte* encOid = NULL;
+ int encOidSz = 0;
+ word32 pbeLen = 0, kdfLen = 0, encLen = 0;
+ word32 innerLen = 0, outerLen;
+
+ ret = CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz);
+ /* create random salt if one not provided */
+ if (ret == 0 && (salt == NULL || saltSz == 0)) {
+ saltSz = 8;
+ #ifdef WOLFSSL_SMALL_STACK
+ saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (saltTmp == NULL)
+ return MEMORY_E;
+ #endif
+ salt = saltTmp;
+
+ if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) {
+ WOLFSSL_MSG("Error generating random salt");
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return ret;
}
-#endif
-#ifndef NO_RC4
- case RC4_TYPE:
- {
- Arc4 dec;
+ }
- wc_Arc4SetKey(&dec, key, derivedLen);
- wc_Arc4Process(&dec, input, input, length);
- break;
+ if (ret == 0) {
+ /* check key type and get OID if ECC */
+ ret = wc_GetKeyOID(key, keySz, &curveOid, &curveOidSz, &algId, heap);
+ if (ret == 1)
+ ret = 0;
+ }
+ if (ret == 0) {
+ ret = wc_CreatePKCS8Key(NULL, &pkcs8KeySz, key, keySz, algId, curveOid,
+ curveOidSz);
+ if (ret == LENGTH_ONLY_E)
+ ret = 0;
+ }
+ if (ret == 0) {
+ pkcs8Key = (byte*)XMALLOC(pkcs8KeySz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pkcs8Key == NULL)
+ ret = MEMORY_E;
+ }
+ if (ret == 0) {
+ ret = wc_CreatePKCS8Key(pkcs8Key, &pkcs8KeySz, key, keySz, algId,
+ curveOid, curveOidSz);
+ if (ret >= 0) {
+ pkcs8KeySz = ret;
+ ret = 0;
}
-#endif
+ }
- default:
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return ALGO_ID_E;
+ if (ret == 0 && version == PKCS5v2)
+ ret = GetAlgoV2(encAlgId, &encOid, &encOidSz, &id, &blockSz);
+
+ if (ret == 0) {
+ padSz = (blockSz - (pkcs8KeySz & (blockSz - 1))) & (blockSz - 1);
+ /* inner = OCT salt INT itt */
+ innerLen = 2 + saltSz + 2 + (itt < 256 ? 1 : 2);
+
+ if (version != PKCS5v2) {
+ pbeOid = OidFromId(id, oidPBEType, &pbeOidSz);
+ /* pbe = OBJ pbse1 SEQ [ inner ] */
+ pbeLen = 2 + pbeOidSz + 2 + innerLen;
+ }
+ else {
+ pbeOid = pbes2;
+ pbeOidSz = sizeof(pbes2);
+ /* kdf = OBJ pbkdf2 [ SEQ innerLen ] */
+ kdfLen = 2 + sizeof(pbkdf2Oid) + 2 + innerLen;
+ /* enc = OBJ enc_alg OCT iv */
+ encLen = 2 + encOidSz + 2 + blockSz;
+ /* pbe = OBJ pbse2 SEQ [ SEQ [ kdf ] SEQ [ enc ] ] */
+ pbeLen = 2 + sizeof(pbes2) + 2 + 2 + kdfLen + 2 + encLen;
+
+ ret = wc_RNG_GenerateBlock(rng, cbcIv, blockSz);
+ }
+ }
+ if (ret == 0) {
+ /* outer = SEQ [ pbe ] OCT encrypted_PKCS#8_key */
+ outerLen = 2 + pbeLen;
+ outerLen += SetOctetString(pkcs8KeySz + padSz, out);
+ outerLen += pkcs8KeySz + padSz;
+
+ idx += SetSequence(outerLen, out + idx);
+
+ encIdx = idx + outerLen - pkcs8KeySz - padSz;
+ /* Put Encrypted content in place. */
+ XMEMCPY(out + encIdx, pkcs8Key, pkcs8KeySz);
+ if (padSz > 0) {
+ XMEMSET(out + encIdx + pkcs8KeySz, padSz, padSz);
+ pkcs8KeySz += padSz;
+ }
+ ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id,
+ out + encIdx, pkcs8KeySz, version, cbcIv, 1, 0);
+ }
+ if (ret == 0) {
+ if (version != PKCS5v2) {
+ /* PBE algorithm */
+ idx += SetSequence(pbeLen, out + idx);
+ idx += SetObjectId(pbeOidSz, out + idx);
+ XMEMCPY(out + idx, pbeOid, pbeOidSz);
+ idx += pbeOidSz;
+ }
+ else {
+ /* PBES2 algorithm identifier */
+ idx += SetSequence(pbeLen, out + idx);
+ idx += SetObjectId(pbeOidSz, out + idx);
+ XMEMCPY(out + idx, pbeOid, pbeOidSz);
+ idx += pbeOidSz;
+ /* PBES2 Parameters: SEQ [ kdf ] SEQ [ enc ] */
+ idx += SetSequence(2 + kdfLen + 2 + encLen, out + idx);
+ /* KDF Algorithm Identifier */
+ idx += SetSequence(kdfLen, out + idx);
+ idx += SetObjectId(sizeof(pbkdf2Oid), out + idx);
+ XMEMCPY(out + idx, pbkdf2Oid, sizeof(pbkdf2Oid));
+ idx += sizeof(pbkdf2Oid);
+ }
+ idx += SetSequence(innerLen, out + idx);
+ idx += SetOctetString(saltSz, out + idx);
+ XMEMCPY(out + idx, salt, saltSz); idx += saltSz;
+ ret = SetShortInt(out, &idx, itt, *outSz);
+ if (ret > 0)
+ ret = 0;
+ }
+ if (ret == 0) {
+ if (version == PKCS5v2) {
+ /* Encryption Algorithm Identifier */
+ idx += SetSequence(encLen, out + idx);
+ idx += SetObjectId(encOidSz, out + idx);
+ XMEMCPY(out + idx, encOid, encOidSz);
+ idx += encOidSz;
+ /* Encryption Algorithm Parameter: CBC IV */
+ idx += SetOctetString(blockSz, out + idx);
+ XMEMCPY(out + idx, cbcIv, blockSz);
+ idx += blockSz;
+ }
+ idx += SetOctetString(pkcs8KeySz, out + idx);
+ /* Default PRF - no need to write out OID */
+ idx += pkcs8KeySz;
+
+ ret = idx;
}
+ if (pkcs8Key != NULL) {
+ ForceZero(pkcs8Key, pkcs8KeySz);
+ XFREE(pkcs8Key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (saltTmp != NULL) {
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
#endif
- return 0;
+ (void)rng;
+
+ return ret;
}
+#endif /* HAVE_PKCS8 */
-/* Remove Encrypted PKCS8 header, move beginning of traditional to beginning
- of input */
-int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz)
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
+/* decrypt PKCS
+ *
+ * NOTE: input buffer is overwritten with decrypted data!
+ *
+ * input[in/out] data to decrypt and results are written to
+ * sz size of input buffer
+ * password password if used. Can be NULL for no password
+ * passwordSz size of password buffer
+ *
+ * returns the total size of decrypted content on success.
+ */
+int DecryptContent(byte* input, word32 sz, const char* password, int passwordSz)
{
- word32 inOutIdx = 0, oid;
- int first, second, length, version, saltSz, id;
- int iterations = 0;
+ word32 inOutIdx = 0, seqEnd, oid, shaOid = 0;
+ int ret = 0, first, second, length = 0, version, saltSz, id;
+ int iterations = 0, keySz = 0;
#ifdef WOLFSSL_SMALL_STACK
byte* salt = NULL;
byte* cbcIv = NULL;
@@ -1071,205 +3780,560 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz)
byte salt[MAX_SALT_SIZE];
byte cbcIv[MAX_IV_SIZE];
#endif
-
- if (GetSequence(input, &inOutIdx, &length, sz) < 0)
- return ASN_PARSE_E;
+ byte tag;
- if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0)
- return ASN_PARSE_E;
-
- first = input[inOutIdx - 2]; /* PKCS version alwyas 2nd to last byte */
+ if (passwordSz < 0) {
+ WOLFSSL_MSG("Bad password size");
+ return BAD_FUNC_ARG;
+ }
+
+ if (GetAlgoId(input, &inOutIdx, &oid, oidIgnoreType, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+
+ first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */
second = input[inOutIdx - 1]; /* version.algo, algo id last byte */
- if (CheckAlgo(first, second, &id, &version) < 0)
- return ASN_INPUT_E; /* Algo ID error */
+ if (CheckAlgo(first, second, &id, &version, NULL) < 0) {
+ ERROR_OUT(ASN_INPUT_E, exit_dc); /* Algo ID error */
+ }
if (version == PKCS5v2) {
+ if (GetSequence(input, &inOutIdx, &length, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
- if (GetSequence(input, &inOutIdx, &length, sz) < 0)
- return ASN_PARSE_E;
+ if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
- if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0)
- return ASN_PARSE_E;
+ if (oid != PBKDF2_OID) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+ }
- if (oid != PBKDF2_OID)
- return ASN_PARSE_E;
+ if (GetSequence(input, &inOutIdx, &length, sz) <= 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
}
+ /* Find the end of this SEQUENCE so we can check for the OPTIONAL and
+ * DEFAULT items. */
+ seqEnd = inOutIdx + length;
- if (GetSequence(input, &inOutIdx, &length, sz) < 0)
- return ASN_PARSE_E;
+ ret = GetOctetString(input, &inOutIdx, &saltSz, sz);
+ if (ret < 0)
+ goto exit_dc;
- if (input[inOutIdx++] != ASN_OCTET_STRING)
- return ASN_PARSE_E;
-
- if (GetLength(input, &inOutIdx, &saltSz, sz) < 0)
- return ASN_PARSE_E;
+ if (saltSz > MAX_SALT_SIZE) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
- if (saltSz > MAX_SALT_SIZE)
- return ASN_PARSE_E;
-
#ifdef WOLFSSL_SMALL_STACK
salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (salt == NULL)
- return MEMORY_E;
+ if (salt == NULL) {
+ ERROR_OUT(MEMORY_E, exit_dc);
+ }
#endif
XMEMCPY(salt, &input[inOutIdx], saltSz);
inOutIdx += saltSz;
- if (GetShortInt(input, &inOutIdx, &iterations) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return ASN_PARSE_E;
+ if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+
+ /* OPTIONAL key length */
+ if (seqEnd > inOutIdx) {
+ word32 localIdx = inOutIdx;
+
+ if (GetASNTag(input, &localIdx, &tag, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+
+ if (tag == ASN_INTEGER &&
+ GetShortInt(input, &inOutIdx, &keySz, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+ }
+
+ /* DEFAULT HMAC is SHA-1 */
+ if (seqEnd > inOutIdx) {
+ if (GetAlgoId(input, &inOutIdx, &oid, oidHmacType, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+
+ shaOid = oid;
}
#ifdef WOLFSSL_SMALL_STACK
cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (cbcIv == NULL) {
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
+ ERROR_OUT(MEMORY_E, exit_dc);
}
#endif
if (version == PKCS5v2) {
/* get encryption algo */
- if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return ASN_PARSE_E;
+ if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
}
- if (CheckAlgoV2(oid, &id) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return ASN_PARSE_E; /* PKCS v2 algo id error */
+ if (CheckAlgoV2(oid, &id, NULL) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc); /* PKCS v2 algo id error */
}
- if (input[inOutIdx++] != ASN_OCTET_STRING) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return ASN_PARSE_E;
- }
-
- if (GetLength(input, &inOutIdx, &length, sz) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return ASN_PARSE_E;
+ if (shaOid == 0)
+ shaOid = oid;
+
+ ret = GetOctetString(input, &inOutIdx, &length, sz);
+ if (ret < 0)
+ goto exit_dc;
+
+ if (length > MAX_IV_SIZE) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
}
XMEMCPY(cbcIv, &input[inOutIdx], length);
inOutIdx += length;
}
- if (input[inOutIdx++] != ASN_OCTET_STRING) {
+ if (GetASNTag(input, &inOutIdx, &tag, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+
+ if (tag != (ASN_CONTEXT_SPECIFIC | 0) && tag != ASN_OCTET_STRING) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+
+ if (GetLength(input, &inOutIdx, &length, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+
+ ret = wc_CryptKey(password, passwordSz, salt, saltSz, iterations, id,
+ input + inOutIdx, length, version, cbcIv, 0, shaOid);
+
+exit_dc:
#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- return ASN_PARSE_E;
+
+ if (ret == 0) {
+ XMEMMOVE(input, input + inOutIdx, length);
+ ret = length;
}
- if (GetLength(input, &inOutIdx, &length, sz) < 0) {
+ return ret;
+}
+
+
+/* Remove Encrypted PKCS8 header, move beginning of traditional to beginning
+ of input */
+int ToTraditionalEnc(byte* input, word32 sz,const char* password,
+ int passwordSz, word32* algId)
+{
+ int ret, length;
+ word32 inOutIdx = 0;
+
+ if (GetSequence(input, &inOutIdx, &length, sz) < 0) {
+ ret = ASN_PARSE_E;
+ }
+ else {
+ ret = DecryptContent(input + inOutIdx, sz - inOutIdx, password,
+ passwordSz);
+ if (ret > 0) {
+ XMEMMOVE(input, input + inOutIdx, ret);
+ ret = ToTraditional_ex(input, ret, algId);
+ }
+ }
+
+ return ret;
+}
+
+#endif /* HAVE_PKCS8 || HAVE_PKCS12 */
+
+#ifdef HAVE_PKCS12
+
+/* encrypt PKCS 12 content
+ *
+ * NOTE: if out is NULL then outSz is set with the total buffer size needed and
+ * the error value LENGTH_ONLY_E is returned.
+ *
+ * input data to encrypt
+ * inputSz size of input buffer
+ * out buffer to hold the result
+ * outSz size of out buffer
+ * password password if used. Can be NULL for no password
+ * passwordSz size of password buffer
+ * vPKCS version of PKCS i.e. PKCS5v2
+ * vAlgo algorithm version
+ * salt buffer holding salt if used. If NULL then a random salt is created
+ * saltSz size of salt buffer if it is not NULL
+ * itt number of iterations used
+ * rng random number generator to use
+ * heap possible heap hint for mallocs/frees
+ *
+ * returns the total size of encrypted content on success.
+ *
+ * data returned is :
+ * [ seq - obj [ seq -salt,itt]] , construct with encrypted data
+ */
+int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
+ const char* password, int passwordSz, int vPKCS, int vAlgo,
+ byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap)
+{
+ word32 sz;
+ word32 inOutIdx = 0;
+ word32 tmpIdx = 0;
+ word32 totalSz = 0;
+ word32 seqSz;
+ word32 innerSz;
+ int ret;
+ int version, id, blockSz = 0;
#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ byte* saltTmp = NULL;
+ byte* cbcIv = NULL;
+#else
+ byte saltTmp[MAX_SALT_SIZE];
+ byte cbcIv[MAX_IV_SIZE];
#endif
+ byte seq[MAX_SEQ_SZ];
+ byte shr[MAX_SHORT_SZ];
+ word32 maxShr = MAX_SHORT_SZ;
+ word32 algoSz;
+ const byte* algoName;
+
+ (void)heap;
+
+ WOLFSSL_ENTER("EncryptContent()");
+
+ if (CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz) < 0)
+ return ASN_INPUT_E; /* Algo ID error */
+
+ if (version == PKCS5v2) {
+ WOLFSSL_MSG("PKCS#5 version 2 not supported yet");
+ return BAD_FUNC_ARG;
+ }
+
+ if (saltSz > MAX_SALT_SIZE)
return ASN_PARSE_E;
+
+ if (outSz == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* calculate size */
+ /* size of constructed string at end */
+ sz = Pkcs8Pad(NULL, inputSz, blockSz);
+ totalSz = ASN_TAG_SZ;
+ totalSz += SetLength(sz, seq);
+ totalSz += sz;
+
+ /* size of sequence holding object id and sub sequence of salt and itt */
+ algoName = OidFromId(id, oidPBEType, &algoSz);
+ if (algoName == NULL) {
+ WOLFSSL_MSG("Unknown Algorithm");
+ return 0;
+ }
+ innerSz = SetObjectId(algoSz, seq);
+ innerSz += algoSz;
+
+ /* get subsequence of salt and itt */
+ if (salt == NULL || saltSz == 0) {
+ sz = 8;
+ }
+ else {
+ sz = saltSz;
+ }
+ seqSz = SetOctetString(sz, seq);
+ seqSz += sz;
+
+ tmpIdx = 0;
+ seqSz += SetShortInt(shr, &tmpIdx, itt, maxShr);
+ innerSz += seqSz + SetSequence(seqSz, seq);
+ totalSz += innerSz + SetSequence(innerSz, seq);
+
+ if (out == NULL) {
+ *outSz = totalSz;
+ return LENGTH_ONLY_E;
+ }
+
+ inOutIdx = 0;
+ if (totalSz > *outSz)
+ return BUFFER_E;
+
+ inOutIdx += SetSequence(innerSz, out + inOutIdx);
+ inOutIdx += SetObjectId(algoSz, out + inOutIdx);
+ XMEMCPY(out + inOutIdx, algoName, algoSz);
+ inOutIdx += algoSz;
+ inOutIdx += SetSequence(seqSz, out + inOutIdx);
+
+ /* create random salt if one not provided */
+ if (salt == NULL || saltSz == 0) {
+ saltSz = 8;
+ #ifdef WOLFSSL_SMALL_STACK
+ saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (saltTmp == NULL)
+ return MEMORY_E;
+ #endif
+ salt = saltTmp;
+
+ if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) {
+ WOLFSSL_MSG("Error generating random salt");
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return ret;
+ }
+ }
+ inOutIdx += SetOctetString(saltSz, out + inOutIdx);
+ if (saltSz + inOutIdx > *outSz) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return BUFFER_E;
}
+ XMEMCPY(out + inOutIdx, salt, saltSz);
+ inOutIdx += saltSz;
- if (DecryptKey(password, passwordSz, salt, saltSz, iterations, id,
- input + inOutIdx, length, version, cbcIv) < 0) {
+ /* place iteration setting in buffer */
+ ret = SetShortInt(out, &inOutIdx, itt, *outSz);
+ if (ret < 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return ret;
+ }
+
+ if (inOutIdx + 1 > *outSz) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return BUFFER_E;
+ }
+ out[inOutIdx++] = ASN_CONTEXT_SPECIFIC | 0;
+
+ /* get pad size and verify buffer room */
+ sz = Pkcs8Pad(NULL, inputSz, blockSz);
+ if (sz + inOutIdx > *outSz) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return BUFFER_E;
+ }
+ inOutIdx += SetLength(sz, out + inOutIdx);
+
+ /* copy input to output buffer and pad end */
+ XMEMCPY(out + inOutIdx, input, inputSz);
+ sz = Pkcs8Pad(out + inOutIdx, inputSz, blockSz);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (cbcIv == NULL) {
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
#endif
- return ASN_INPUT_E; /* decrypt failure */
+
+ /* encrypt */
+ if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id,
+ out + inOutIdx, sz, version, cbcIv, 1, 0)) < 0) {
+
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return ret; /* encrypt failure */
}
#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- XMEMMOVE(input, input + inOutIdx, length);
- return ToTraditional(input, length);
+ (void)rng;
+
+ return inOutIdx + sz;
}
+
+#endif /* HAVE_PKCS12 */
#endif /* NO_PWDBASED */
#ifndef NO_RSA
-int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
- word32 inSz)
+#ifndef HAVE_USER_RSA
+#ifdef WOLFSSL_RENESAS_TSIP
+/* This function is to retrieve key position information in a cert.*
+ * The information will be used to call TSIP TLS-linked API for *
+ * certificate verification. */
+static int RsaPublicKeyDecodeRawIndex(const byte* input, word32* inOutIdx,
+ word32 inSz, word32* key_n,
+ word32* key_n_len, word32* key_e,
+ word32* key_e_len)
{
- int length;
+
+ int ret = 0;
+ int length = 0;
+#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
+ byte b;
+#endif
+
+ if (input == NULL || inOutIdx == NULL)
+ return BAD_FUNC_ARG;
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
- key->type = RSA_PUBLIC;
-
#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
- {
- byte b = input[*inOutIdx];
+ if ((*inOutIdx + 1) > inSz)
+ return BUFFER_E;
+
+ b = input[*inOutIdx];
if (b != ASN_INTEGER) {
/* not from decoded cert, will have algo id, skip past */
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
-
- b = input[(*inOutIdx)++];
- if (b != ASN_OBJECT_ID)
- return ASN_OBJECT_ID_E;
-
- if (GetLength(input, inOutIdx, &length, inSz) < 0)
+
+ if (SkipObjectId(input, inOutIdx, inSz) < 0)
return ASN_PARSE_E;
-
- *inOutIdx += length; /* skip past */
-
- /* could have NULL tag and 0 terminator, but may not */
- b = input[(*inOutIdx)++];
-
- if (b == ASN_TAG_NULL) {
- b = input[(*inOutIdx)++];
- if (b != 0)
- return ASN_EXPECT_0_E;
+
+ /* Option NULL ASN.1 tag */
+ if (*inOutIdx >= inSz) {
+ return BUFFER_E;
}
- else
- /* go back, didn't have it */
- (*inOutIdx)--;
-
+ if (input[*inOutIdx] == ASN_TAG_NULL) {
+ ret = GetASNNull(input, inOutIdx, inSz);
+ if (ret != 0)
+ return ret;
+ }
+
/* should have bit tag length and seq next */
- b = input[(*inOutIdx)++];
- if (b != ASN_BIT_STRING)
- return ASN_BITSTR_E;
-
- if (GetLength(input, inOutIdx, &length, inSz) < 0)
+ ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
-
- /* could have 0 */
- b = input[(*inOutIdx)++];
- if (b != 0)
- (*inOutIdx)--;
-
+ }
+#endif /* OPENSSL_EXTRA */
+
+ /* Get modulus */
+ ret = GetASNInt(input, inOutIdx, &length, inSz);
+ *key_n += *inOutIdx;
+ if (ret < 0) {
+ return ASN_RSA_KEY_E;
+ }
+ if (key_n_len)
+ *key_n_len = length;
+ *inOutIdx += length;
+
+ /* Get exponent */
+ ret = GetASNInt(input, inOutIdx, &length, inSz);
+ *key_e += *inOutIdx;
+ if (ret < 0) {
+ return ASN_RSA_KEY_E;
+ }
+ if (key_e_len)
+ *key_e_len = length;
+
+ return ret;
+}
+#endif /* WOLFSSL_RENESAS_TSIP */
+
+int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, word32 inSz,
+ const byte** n, word32* nSz, const byte** e, word32* eSz)
+{
+ int ret = 0;
+ int length = 0;
+#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
+ word32 localIdx;
+ byte tag;
+#endif
+
+ if (input == NULL || inOutIdx == NULL)
+ return BAD_FUNC_ARG;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
+ localIdx = *inOutIdx;
+ if (GetASNTag(input, &localIdx, &tag, inSz) < 0)
+ return BUFFER_E;
+
+ if (tag != ASN_INTEGER) {
+ /* not from decoded cert, will have algo id, skip past */
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
- } /* end if */
- } /* openssl var block */
+
+ if (SkipObjectId(input, inOutIdx, inSz) < 0)
+ return ASN_PARSE_E;
+
+ /* Option NULL ASN.1 tag */
+ if (*inOutIdx >= inSz) {
+ return BUFFER_E;
+ }
+
+ localIdx = *inOutIdx;
+ if (GetASNTag(input, &localIdx, &tag, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (tag == ASN_TAG_NULL) {
+ ret = GetASNNull(input, inOutIdx, inSz);
+ if (ret != 0)
+ return ret;
+ }
+
+ /* should have bit tag length and seq next */
+ ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+ }
#endif /* OPENSSL_EXTRA */
- if (GetInt(&key->n, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->e, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E;
+ /* Get modulus */
+ ret = GetASNInt(input, inOutIdx, &length, inSz);
+ if (ret < 0) {
+ return ASN_RSA_KEY_E;
+ }
+ if (nSz)
+ *nSz = length;
+ if (n)
+ *n = &input[*inOutIdx];
+ *inOutIdx += length;
- return 0;
+ /* Get exponent */
+ ret = GetASNInt(input, inOutIdx, &length, inSz);
+ if (ret < 0) {
+ return ASN_RSA_KEY_E;
+ }
+ if (eSz)
+ *eSz = length;
+ if (e)
+ *e = &input[*inOutIdx];
+ *inOutIdx += length;
+
+ return ret;
+}
+
+int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
+ word32 inSz)
+{
+ int ret;
+ const byte *n = NULL, *e = NULL;
+ word32 nSz = 0, eSz = 0;
+
+ if (key == NULL)
+ return BAD_FUNC_ARG;
+
+ ret = wc_RsaPublicKeyDecode_ex(input, inOutIdx, inSz, &n, &nSz, &e, &eSz);
+ if (ret == 0) {
+ ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, key);
+ }
+
+ return ret;
}
/* import RSA public key elements (n, e) into RsaKey structure (key) */
@@ -1288,6 +4352,12 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e,
mp_clear(&key->n);
return ASN_GETINT_E;
}
+#ifdef HAVE_WOLF_BIGINT
+ if ((int)nSz > 0 && wc_bigint_from_unsigned_bin(&key->n.raw, n, nSz) != 0) {
+ mp_clear(&key->n);
+ return ASN_GETINT_E;
+ }
+#endif /* HAVE_WOLF_BIGINT */
if (mp_init(&key->e) != MP_OKAY) {
mp_clear(&key->n);
@@ -1299,76 +4369,143 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e,
mp_clear(&key->e);
return ASN_GETINT_E;
}
+#ifdef HAVE_WOLF_BIGINT
+ if ((int)eSz > 0 && wc_bigint_from_unsigned_bin(&key->e.raw, e, eSz) != 0) {
+ mp_clear(&key->n);
+ mp_clear(&key->e);
+ return ASN_GETINT_E;
+ }
+#endif /* HAVE_WOLF_BIGINT */
+
+#ifdef WOLFSSL_XILINX_CRYPT
+ if (wc_InitRsaHw(key) != 0) {
+ return BAD_STATE_E;
+ }
+#endif
return 0;
}
-
-#endif
+#endif /* HAVE_USER_RSA */
+#endif /* !NO_RSA */
#ifndef NO_DH
int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz)
{
- int length;
+ int ret = 0;
+ int length;
+ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ word32 oid = 0, temp = 0;
+ #endif
+
+ WOLFSSL_ENTER("wc_DhKeyDecode");
+
+ if (inOutIdx == NULL)
+ return BAD_FUNC_ARG;
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
+ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ temp = *inOutIdx;
+ #endif
+
+ /* Assume input started after 1.2.840.113549.1.3.1 dhKeyAgreement */
if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->g, input, inOutIdx, inSz) < 0 ) return ASN_DH_KEY_E;
+ GetInt(&key->g, input, inOutIdx, inSz) < 0) {
+ ret = ASN_DH_KEY_E;
+ }
- return 0;
+ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ /* If ASN_DH_KEY_E: Check if input started at beginning of key */
+ if (ret == ASN_DH_KEY_E) {
+ /* rewind back to after the first sequence */
+ *inOutIdx = temp;
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ /* Check for dhKeyAgreement */
+ ret = GetObjectId(input, inOutIdx, &oid, oidKeyType, inSz);
+ if (oid != DHk || ret < 0)
+ return ASN_DH_KEY_E;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->g, input, inOutIdx, inSz) < 0) {
+ return ASN_DH_KEY_E;
+ }
+ }
+
+ temp = *inOutIdx;
+ ret = (CheckBitString(input, inOutIdx, &length, inSz, 0, NULL) == 0);
+ if (ret > 0) {
+ /* Found Bit String */
+ if (GetInt(&key->pub, input, inOutIdx, inSz) == 0) {
+ WOLFSSL_MSG("Found Public Key");
+ ret = 0;
+ }
+ } else {
+ *inOutIdx = temp;
+ ret = (GetOctetString(input, inOutIdx, &length, inSz) >= 0);
+ if (ret > 0) {
+ /* Found Octet String */
+ if (GetInt(&key->priv, input, inOutIdx, inSz) == 0) {
+ WOLFSSL_MSG("Found Private Key");
+ ret = 0;
+ }
+ } else {
+ /* Don't use length from failed CheckBitString/GetOctetString */
+ *inOutIdx = temp;
+ ret = 0;
+ }
+ }
+ #endif /* WOLFSSL_QT || OPENSSL_ALL */
+
+ WOLFSSL_MSG("wc_DhKeyDecode Success");
+
+ return ret;
}
int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz,
byte* g, word32* gInOutSz)
{
- word32 i = 0;
- byte b;
+ word32 idx = 0;
+ int ret;
int length;
- if (GetSequence(input, &i, &length, inSz) < 0)
- return ASN_PARSE_E;
-
- b = input[i++];
- if (b != ASN_INTEGER)
- return ASN_PARSE_E;
-
- if (GetLength(input, &i, &length, inSz) < 0)
+ if (GetSequence(input, &idx, &length, inSz) <= 0)
return ASN_PARSE_E;
- if ( (b = input[i++]) == 0x00)
- length--;
- else
- i--;
+ ret = GetASNInt(input, &idx, &length, inSz);
+ if (ret != 0)
+ return ret;
if (length <= (int)*pInOutSz) {
- XMEMCPY(p, &input[i], length);
+ XMEMCPY(p, &input[idx], length);
*pInOutSz = length;
}
- else
+ else {
return BUFFER_E;
+ }
+ idx += length;
- i += length;
-
- b = input[i++];
- if (b != ASN_INTEGER)
- return ASN_PARSE_E;
-
- if (GetLength(input, &i, &length, inSz) < 0)
- return ASN_PARSE_E;
+ ret = GetASNInt(input, &idx, &length, inSz);
+ if (ret != 0)
+ return ret;
if (length <= (int)*gInOutSz) {
- XMEMCPY(g, &input[i], length);
+ XMEMCPY(g, &input[idx], length);
*gInOutSz = length;
}
- else
+ else {
return BUFFER_E;
+ }
return 0;
}
-
#endif /* NO_DH */
@@ -1378,6 +4515,11 @@ int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
word32 inSz)
{
int length;
+ int ret = 0;
+ word32 oid;
+
+ if (input == NULL || inOutIdx == NULL || key == NULL)
+ return BAD_FUNC_ARG;
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
@@ -1385,148 +4527,431 @@ int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
GetInt(&key->q, input, inOutIdx, inSz) < 0 ||
GetInt(&key->g, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->y, input, inOutIdx, inSz) < 0 ) return ASN_DH_KEY_E;
+ GetInt(&key->y, input, inOutIdx, inSz) < 0 )
+ ret = ASN_DH_KEY_E;
+
+ if (ret != 0) {
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ ret = GetObjectId(input, inOutIdx, &oid, oidIgnoreType, inSz);
+ if (ret != 0)
+ return ret;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->q, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->g, input, inOutIdx, inSz) < 0)
+ return ASN_DH_KEY_E;
+
+ if (CheckBitString(input, inOutIdx, &length, inSz, 0, NULL) < 0)
+ return ASN_PARSE_E;
+
+ if (GetInt(&key->y, input, inOutIdx, inSz) < 0 )
+ return ASN_DH_KEY_E;
+
+ ret = 0;
+ }
key->type = DSA_PUBLIC;
- return 0;
+ return ret;
}
int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
word32 inSz)
{
- int length, version;
+ int length, version, ret = 0, temp = 0;
+
+ /* Sanity checks on input */
+ if (input == NULL || inOutIdx == NULL || key == NULL) {
+ return BAD_FUNC_ARG;
+ }
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
- if (GetMyVersion(input, inOutIdx, &version) < 0)
- return ASN_PARSE_E;
+ temp = (int)*inOutIdx;
- if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->q, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->g, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->y, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->x, input, inOutIdx, inSz) < 0 ) return ASN_DH_KEY_E;
+ /* Default case expects a certificate with OctetString but no version ID */
+ ret = GetInt(&key->p, input, inOutIdx, inSz);
+ if (ret < 0) {
+ mp_clear(&key->p);
+ ret = ASN_PARSE_E;
+ }
+ else {
+ ret = GetInt(&key->q, input, inOutIdx, inSz);
+ if (ret < 0) {
+ mp_clear(&key->p);
+ mp_clear(&key->q);
+ ret = ASN_PARSE_E;
+ }
+ else {
+ ret = GetInt(&key->g, input, inOutIdx, inSz);
+ if (ret < 0) {
+ mp_clear(&key->p);
+ mp_clear(&key->q);
+ mp_clear(&key->g);
+ ret = ASN_PARSE_E;
+ }
+ else {
+ ret = GetOctetString(input, inOutIdx, &length, inSz);
+ if (ret < 0) {
+ mp_clear(&key->p);
+ mp_clear(&key->q);
+ mp_clear(&key->g);
+ ret = ASN_PARSE_E;
+ }
+ else {
+ ret = GetInt(&key->y, input, inOutIdx, inSz);
+ if (ret < 0) {
+ mp_clear(&key->p);
+ mp_clear(&key->q);
+ mp_clear(&key->g);
+ mp_clear(&key->y);
+ ret = ASN_PARSE_E;
+ }
+ }
+ }
+ }
+ }
+ /* An alternate pass if default certificate fails parsing */
+ if (ret == ASN_PARSE_E) {
+ *inOutIdx = temp;
+ if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->q, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->g, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->y, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->x, input, inOutIdx, inSz) < 0 )
+ return ASN_DH_KEY_E;
+ }
key->type = DSA_PRIVATE;
return 0;
}
-#endif /* NO_DSA */
+static mp_int* GetDsaInt(DsaKey* key, int idx)
+{
+ if (idx == 0)
+ return &key->p;
+ if (idx == 1)
+ return &key->q;
+ if (idx == 2)
+ return &key->g;
+ if (idx == 3)
+ return &key->y;
+ if (idx == 4)
+ return &key->x;
+
+ return NULL;
+}
+
+/* Release Tmp DSA resources */
+static WC_INLINE void FreeTmpDsas(byte** tmps, void* heap)
+{
+ int i;
+
+ for (i = 0; i < DSA_INTS; i++)
+ XFREE(tmps[i], heap, DYNAMIC_TYPE_DSA);
+ (void)heap;
+}
-void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap)
+#if !defined(HAVE_SELFTEST) && defined(WOLFSSL_KEY_GEN)
+/* Write a public DSA key to output */
+int wc_SetDsaPublicKey(byte* output, DsaKey* key,
+ int outLen, int with_header)
{
- cert->publicKey = 0;
- cert->pubKeySize = 0;
- cert->pubKeyStored = 0;
- cert->version = 0;
- cert->signature = 0;
- cert->subjectCN = 0;
- cert->subjectCNLen = 0;
- cert->subjectCNEnc = CTC_UTF8;
- cert->subjectCNStored = 0;
- cert->weOwnAltNames = 0;
- cert->altNames = NULL;
-#ifndef IGNORE_NAME_CONSTRAINTS
- cert->altEmailNames = NULL;
- cert->permittedNames = NULL;
- cert->excludedNames = NULL;
-#endif /* IGNORE_NAME_CONSTRAINTS */
- cert->issuer[0] = '\0';
- cert->subject[0] = '\0';
- cert->source = source; /* don't own */
- cert->srcIdx = 0;
- cert->maxIdx = inSz; /* can't go over this index */
- cert->heap = heap;
- XMEMSET(cert->serial, 0, EXTERNAL_SERIAL_SIZE);
- cert->serialSz = 0;
- cert->extensions = 0;
- cert->extensionsSz = 0;
- cert->extensionsIdx = 0;
- cert->extAuthInfo = NULL;
- cert->extAuthInfoSz = 0;
- cert->extCrlInfo = NULL;
- cert->extCrlInfoSz = 0;
- XMEMSET(cert->extSubjKeyId, 0, KEYID_SIZE);
- cert->extSubjKeyIdSet = 0;
- XMEMSET(cert->extAuthKeyId, 0, KEYID_SIZE);
- cert->extAuthKeyIdSet = 0;
- cert->extKeyUsageSet = 0;
- cert->extKeyUsage = 0;
- cert->extExtKeyUsageSet = 0;
- cert->extExtKeyUsage = 0;
- cert->isCA = 0;
-#ifdef HAVE_PKCS7
- cert->issuerRaw = NULL;
- cert->issuerRawLen = 0;
+ /* p, g, q = DSA params, y = public exponent */
+#ifdef WOLFSSL_SMALL_STACK
+ byte* p = NULL;
+ byte* g = NULL;
+ byte* q = NULL;
+ byte* y = NULL;
+#else
+ byte p[MAX_DSA_INT_SZ];
+ byte g[MAX_DSA_INT_SZ];
+ byte q[MAX_DSA_INT_SZ];
+ byte y[MAX_DSA_INT_SZ];
#endif
-#ifdef WOLFSSL_CERT_GEN
- cert->subjectSN = 0;
- cert->subjectSNLen = 0;
- cert->subjectSNEnc = CTC_UTF8;
- cert->subjectC = 0;
- cert->subjectCLen = 0;
- cert->subjectCEnc = CTC_PRINTABLE;
- cert->subjectL = 0;
- cert->subjectLLen = 0;
- cert->subjectLEnc = CTC_UTF8;
- cert->subjectST = 0;
- cert->subjectSTLen = 0;
- cert->subjectSTEnc = CTC_UTF8;
- cert->subjectO = 0;
- cert->subjectOLen = 0;
- cert->subjectOEnc = CTC_UTF8;
- cert->subjectOU = 0;
- cert->subjectOULen = 0;
- cert->subjectOUEnc = CTC_UTF8;
- cert->subjectEmail = 0;
- cert->subjectEmailLen = 0;
-#endif /* WOLFSSL_CERT_GEN */
- cert->beforeDate = NULL;
- cert->beforeDateLen = 0;
- cert->afterDate = NULL;
- cert->afterDateLen = 0;
-#ifdef OPENSSL_EXTRA
- XMEMSET(&cert->issuerName, 0, sizeof(DecodedName));
- XMEMSET(&cert->subjectName, 0, sizeof(DecodedName));
- cert->extBasicConstSet = 0;
- cert->extBasicConstCrit = 0;
- cert->extBasicConstPlSet = 0;
- cert->pathLength = 0;
- cert->extSubjAltNameSet = 0;
- cert->extSubjAltNameCrit = 0;
- cert->extAuthKeyIdCrit = 0;
- cert->extSubjKeyIdCrit = 0;
- cert->extKeyUsageCrit = 0;
- cert->extExtKeyUsageCrit = 0;
- cert->extExtKeyUsageSrc = NULL;
- cert->extExtKeyUsageSz = 0;
- cert->extExtKeyUsageCount = 0;
- cert->extAuthKeyIdSrc = NULL;
- cert->extAuthKeyIdSz = 0;
- cert->extSubjKeyIdSrc = NULL;
- cert->extSubjKeyIdSz = 0;
-#endif /* OPENSSL_EXTRA */
-#if defined(OPENSSL_EXTRA) || !defined(IGNORE_NAME_CONSTRAINTS)
- cert->extNameConstraintSet = 0;
-#endif /* OPENSSL_EXTRA || !IGNORE_NAME_CONSTRAINTS */
-#ifdef HAVE_ECC
- cert->pkCurveOID = 0;
-#endif /* HAVE_ECC */
-#ifdef WOLFSSL_SEP
- cert->deviceTypeSz = 0;
- cert->deviceType = NULL;
- cert->hwTypeSz = 0;
- cert->hwType = NULL;
- cert->hwSerialNumSz = 0;
- cert->hwSerialNum = NULL;
- #ifdef OPENSSL_EXTRA
- cert->extCertPolicySet = 0;
- cert->extCertPolicyCrit = 0;
- #endif /* OPENSSL_EXTRA */
-#endif /* WOLFSSL_SEP */
+ byte innerSeq[MAX_SEQ_SZ];
+ byte outerSeq[MAX_SEQ_SZ];
+ byte bitString[1 + MAX_LENGTH_SZ + 1];
+ int idx, pSz, gSz, qSz, ySz, innerSeqSz, outerSeqSz, bitStringSz = 0;
+
+ WOLFSSL_ENTER("wc_SetDsaPublicKey");
+
+ if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* p */
+#ifdef WOLFSSL_SMALL_STACK
+ p = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (p == NULL)
+ return MEMORY_E;
+#endif
+ if ((pSz = SetASNIntMP(&key->p, MAX_DSA_INT_SZ, p)) < 0) {
+ WOLFSSL_MSG("SetASNIntMP Error with p");
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return pSz;
+ }
+
+ /* q */
+#ifdef WOLFSSL_SMALL_STACK
+ q = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (q == NULL)
+ return MEMORY_E;
+#endif
+ if ((qSz = SetASNIntMP(&key->q, MAX_DSA_INT_SZ, q)) < 0) {
+ WOLFSSL_MSG("SetASNIntMP Error with q");
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return qSz;
+ }
+
+ /* g */
+#ifdef WOLFSSL_SMALL_STACK
+ g = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (g == NULL)
+ return MEMORY_E;
+#endif
+ if ((gSz = SetASNIntMP(&key->g, MAX_DSA_INT_SZ, g)) < 0) {
+ WOLFSSL_MSG("SetASNIntMP Error with g");
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return gSz;
+ }
+
+ /* y */
+#ifdef WOLFSSL_SMALL_STACK
+ y = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (y == NULL)
+ return MEMORY_E;
+#endif
+ if ((ySz = SetASNIntMP(&key->y, MAX_DSA_INT_SZ, y)) < 0) {
+ WOLFSSL_MSG("SetASNIntMP Error with y");
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return ySz;
+ }
+
+ innerSeqSz = SetSequence(pSz + qSz + gSz, innerSeq);
+
+ /* check output size */
+ if ((innerSeqSz + pSz + qSz + gSz) > outLen) {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ WOLFSSL_MSG("Error, output size smaller than outlen");
+ return BUFFER_E;
+ }
+
+ if (with_header) {
+ int algoSz;
+#ifdef WOLFSSL_SMALL_STACK
+ byte* algo = NULL;
+
+ algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (algo == NULL) {
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
+#else
+ byte algo[MAX_ALGO_SZ];
+#endif
+ algoSz = SetAlgoID(DSAk, algo, oidKeyType, 0);
+ bitStringSz = SetBitString(ySz, 0, bitString);
+ outerSeqSz = SetSequence(algoSz + innerSeqSz + pSz + qSz + gSz,
+ outerSeq);
+
+ idx = SetSequence(algoSz + innerSeqSz + pSz + qSz + gSz + bitStringSz +
+ ySz + outerSeqSz, output);
+
+ /* check output size */
+ if ((idx + algoSz + bitStringSz + innerSeqSz + pSz + qSz + gSz + ySz) >
+ outLen) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ WOLFSSL_MSG("Error, output size smaller than outlen");
+ return BUFFER_E;
+ }
+
+ /* outerSeq */
+ XMEMCPY(output + idx, outerSeq, outerSeqSz);
+ idx += outerSeqSz;
+ /* algo */
+ XMEMCPY(output + idx, algo, algoSz);
+ idx += algoSz;
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ } else {
+ idx = 0;
+ }
+
+ /* innerSeq */
+ XMEMCPY(output + idx, innerSeq, innerSeqSz);
+ idx += innerSeqSz;
+ /* p */
+ XMEMCPY(output + idx, p, pSz);
+ idx += pSz;
+ /* q */
+ XMEMCPY(output + idx, q, qSz);
+ idx += qSz;
+ /* g */
+ XMEMCPY(output + idx, g, gSz);
+ idx += gSz;
+ /* bit string */
+ XMEMCPY(output + idx, bitString, bitStringSz);
+ idx += bitStringSz;
+ /* y */
+ XMEMCPY(output + idx, y, ySz);
+ idx += ySz;
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return idx;
+}
+
+/* Convert DSA Public key to DER format, write to output (inLen), return bytes
+ written */
+int wc_DsaKeyToPublicDer(DsaKey* key, byte* output, word32 inLen)
+{
+ return wc_SetDsaPublicKey(output, key, inLen, 1);
+}
+#endif /* !HAVE_SELFTEST && WOLFSSL_KEY_GEN */
+
+/* Convert private DsaKey key to DER format, write to output (inLen),
+ return bytes written */
+int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen)
+{
+ word32 seqSz, verSz, rawLen, intTotalLen = 0;
+ word32 sizes[DSA_INTS];
+ int i, j, outLen, ret = 0, mpSz;
+
+ byte seq[MAX_SEQ_SZ];
+ byte ver[MAX_VERSION_SZ];
+ byte* tmps[DSA_INTS];
+
+ if (!key || !output)
+ return BAD_FUNC_ARG;
+
+ if (key->type != DSA_PRIVATE)
+ return BAD_FUNC_ARG;
+
+ for (i = 0; i < DSA_INTS; i++)
+ tmps[i] = NULL;
+
+ /* write all big ints from key to DER tmps */
+ for (i = 0; i < DSA_INTS; i++) {
+ mp_int* keyInt = GetDsaInt(key, i);
+
+ rawLen = mp_unsigned_bin_size(keyInt) + 1;
+ tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap,
+ DYNAMIC_TYPE_DSA);
+ if (tmps[i] == NULL) {
+ ret = MEMORY_E;
+ break;
+ }
+
+ mpSz = SetASNIntMP(keyInt, -1, tmps[i]);
+ if (mpSz < 0) {
+ ret = mpSz;
+ break;
+ }
+ intTotalLen += (sizes[i] = mpSz);
+ }
+
+ if (ret != 0) {
+ FreeTmpDsas(tmps, key->heap);
+ return ret;
+ }
+
+ /* make headers */
+ verSz = SetMyVersion(0, ver, FALSE);
+ seqSz = SetSequence(verSz + intTotalLen, seq);
+
+ outLen = seqSz + verSz + intTotalLen;
+ if (outLen > (int)inLen) {
+ FreeTmpDsas(tmps, key->heap);
+ return BAD_FUNC_ARG;
+ }
+
+ /* write to output */
+ XMEMCPY(output, seq, seqSz);
+ j = seqSz;
+ XMEMCPY(output + j, ver, verSz);
+ j += verSz;
+
+ for (i = 0; i < DSA_INTS; i++) {
+ XMEMCPY(output + j, tmps[i], sizes[i]);
+ j += sizes[i];
+ }
+ FreeTmpDsas(tmps, key->heap);
+
+ return outLen;
+}
+
+#endif /* NO_DSA */
+
+void InitDecodedCert(DecodedCert* cert,
+ const byte* source, word32 inSz, void* heap)
+{
+ if (cert != NULL) {
+ XMEMSET(cert, 0, sizeof(DecodedCert));
+
+ cert->subjectCNEnc = CTC_UTF8;
+ cert->issuer[0] = '\0';
+ cert->subject[0] = '\0';
+ cert->source = source; /* don't own */
+ cert->maxIdx = inSz; /* can't go over this index */
+ cert->heap = heap;
+ cert->maxPathLen = WOLFSSL_MAX_PATH_LEN;
+ #ifdef WOLFSSL_CERT_GEN
+ cert->subjectSNEnc = CTC_UTF8;
+ cert->subjectCEnc = CTC_PRINTABLE;
+ cert->subjectLEnc = CTC_UTF8;
+ cert->subjectSTEnc = CTC_UTF8;
+ cert->subjectOEnc = CTC_UTF8;
+ cert->subjectOUEnc = CTC_UTF8;
+ #endif /* WOLFSSL_CERT_GEN */
+
+ #ifndef NO_CERTS
+ InitSignatureCtx(&cert->sigCtx, heap, INVALID_DEVID);
+ #endif
+ }
}
@@ -1562,10 +4987,12 @@ void FreeNameSubtrees(Base_entry* names, void* heap)
void FreeDecodedCert(DecodedCert* cert)
{
+ if (cert == NULL)
+ return;
if (cert->subjectCNStored == 1)
XFREE(cert->subjectCN, cert->heap, DYNAMIC_TYPE_SUBJECT_CN);
if (cert->pubKeyStored == 1)
- XFREE(cert->publicKey, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE((void*)cert->publicKey, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if (cert->weOwnAltNames && cert->altNames)
FreeAltNames(cert->altNames, cert->heap);
#ifndef IGNORE_NAME_CONSTRAINTS
@@ -1577,126 +5004,92 @@ void FreeDecodedCert(DecodedCert* cert)
FreeNameSubtrees(cert->excludedNames, cert->heap);
#endif /* IGNORE_NAME_CONSTRAINTS */
#ifdef WOLFSSL_SEP
- XFREE(cert->deviceType, cert->heap, 0);
- XFREE(cert->hwType, cert->heap, 0);
- XFREE(cert->hwSerialNum, cert->heap, 0);
+ XFREE(cert->deviceType, cert->heap, DYNAMIC_TYPE_X509_EXT);
+ XFREE(cert->hwType, cert->heap, DYNAMIC_TYPE_X509_EXT);
+ XFREE(cert->hwSerialNum, cert->heap, DYNAMIC_TYPE_X509_EXT);
#endif /* WOLFSSL_SEP */
-#ifdef OPENSSL_EXTRA
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
if (cert->issuerName.fullName != NULL)
- XFREE(cert->issuerName.fullName, NULL, DYNAMIC_TYPE_X509);
+ XFREE(cert->issuerName.fullName, cert->heap, DYNAMIC_TYPE_X509);
if (cert->subjectName.fullName != NULL)
- XFREE(cert->subjectName.fullName, NULL, DYNAMIC_TYPE_X509);
+ XFREE(cert->subjectName.fullName, cert->heap, DYNAMIC_TYPE_X509);
#endif /* OPENSSL_EXTRA */
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+ if (cert->tsip_encRsaKeyIdx != NULL)
+ XFREE(cert->tsip_encRsaKeyIdx, cert->heap, DYNAMIC_TYPE_RSA);
+#endif
+#ifndef NO_CERTS
+ FreeSignatureCtx(&cert->sigCtx);
+#endif
}
-
static int GetCertHeader(DecodedCert* cert)
{
int ret = 0, len;
- byte serialTmp[EXTERNAL_SERIAL_SIZE];
-#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH)
- mp_int* mpi = NULL;
-#else
- mp_int stack_mpi;
- mp_int* mpi = &stack_mpi;
-#endif
if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0)
return ASN_PARSE_E;
+ /* Reset the max index for the size indicated in the outer wrapper. */
+ cert->maxIdx = len + cert->srcIdx;
cert->certBegin = cert->srcIdx;
if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0)
return ASN_PARSE_E;
- cert->sigIndex = len + cert->srcIdx;
- if (GetExplicitVersion(cert->source, &cert->srcIdx, &cert->version) < 0)
+ cert->sigIndex = len + cert->srcIdx;
+ if (cert->sigIndex > cert->maxIdx)
return ASN_PARSE_E;
-#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH)
- mpi = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (mpi == NULL)
- return MEMORY_E;
-#endif
-
- if (GetInt(mpi, cert->source, &cert->srcIdx, cert->maxIdx) < 0) {
-#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH)
- XFREE(mpi, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ if (GetExplicitVersion(cert->source, &cert->srcIdx, &cert->version,
+ cert->sigIndex) < 0)
return ASN_PARSE_E;
- }
- len = mp_unsigned_bin_size(mpi);
- if (len < (int)sizeof(serialTmp)) {
- if ( (ret = mp_to_unsigned_bin(mpi, serialTmp)) == MP_OKAY) {
- XMEMCPY(cert->serial, serialTmp, len);
- cert->serialSz = len;
- }
- }
- mp_clear(mpi);
-
-#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH)
- XFREE(mpi, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ if (GetSerialNumber(cert->source, &cert->srcIdx, cert->serial,
+ &cert->serialSz, cert->sigIndex) < 0)
+ return ASN_PARSE_E;
return ret;
}
#if !defined(NO_RSA)
/* Store Rsa Key, may save later, Dsa could use in future */
-static int StoreRsaKey(DecodedCert* cert)
+static int StoreRsaKey(DecodedCert* cert, word32 bitStringEnd)
{
int length;
word32 recvd = cert->srcIdx;
- if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
+ if (GetSequence(cert->source, &cert->srcIdx, &length, bitStringEnd) < 0)
return ASN_PARSE_E;
-
+
recvd = cert->srcIdx - recvd;
length += recvd;
while (recvd--)
cert->srcIdx--;
-
+#if defined(WOLFSSL_RENESAS_TSIP)
+ cert->sigCtx.pubkey_n_start = cert->sigCtx.pubkey_e_start = cert->srcIdx;
+#endif
cert->pubKeySize = length;
cert->publicKey = cert->source + cert->srcIdx;
cert->srcIdx += length;
return 0;
}
-#endif
-
+#endif /* !NO_RSA */
#ifdef HAVE_ECC
- /* return 0 on sucess if the ECC curve oid sum is supported */
+ /* return 0 on success if the ECC curve oid sum is supported */
static int CheckCurve(word32 oid)
{
int ret = 0;
+ word32 oidSz = 0;
- switch (oid) {
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160)
- case ECC_160R1:
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192)
- case ECC_192R1:
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224)
- case ECC_224R1:
-#endif
-#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256)
- case ECC_256R1:
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384)
- case ECC_384R1:
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521)
- case ECC_521R1:
-#endif
- break;
-
- default:
- ret = ALGO_ID_E;
+ ret = wc_ecc_get_oid(oid, NULL, &oidSz);
+ if (ret < 0 || oidSz == 0) {
+ WOLFSSL_MSG("CheckCurve not found");
+ ret = ALGO_ID_E;
}
return ret;
@@ -1704,35 +5097,46 @@ static int StoreRsaKey(DecodedCert* cert)
#endif /* HAVE_ECC */
-
static int GetKey(DecodedCert* cert)
{
int length;
-#ifdef HAVE_NTRU
+#if !defined(NO_DSA) && defined(WOLFSSL_QT)
+ int tmpLen;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_NTRU)
int tmpIdx = cert->srcIdx;
#endif
if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
return ASN_PARSE_E;
-
- if (GetAlgoId(cert->source, &cert->srcIdx, &cert->keyOID, cert->maxIdx) < 0)
+
+#if !defined(NO_DSA) && defined(WOLFSSL_QT)
+ tmpLen = length + 4;
+#endif
+
+ if (GetAlgoId(cert->source, &cert->srcIdx,
+ &cert->keyOID, oidKeyType, cert->maxIdx) < 0)
return ASN_PARSE_E;
switch (cert->keyOID) {
#ifndef NO_RSA
case RSAk:
{
- byte b = cert->source[cert->srcIdx++];
- if (b != ASN_BIT_STRING)
- return ASN_BITSTR_E;
+ int ret;
- if (GetLength(cert->source,&cert->srcIdx,&length,cert->maxIdx) < 0)
- return ASN_PARSE_E;
- b = cert->source[cert->srcIdx++];
- if (b != 0x00)
- return ASN_EXPECT_0_E;
-
- return StoreRsaKey(cert);
+ ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+ cert->maxIdx, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ #ifdef HAVE_OCSP
+ ret = CalcHashId(cert->source + cert->srcIdx, length,
+ cert->subjectKeyHash);
+ if (ret != 0)
+ return ret;
+ #endif
+
+ return StoreRsaKey(cert, cert->srcIdx + length);
}
#endif /* NO_RSA */
@@ -1744,6 +5148,7 @@ static int GetKey(DecodedCert* cert)
word16 keyLen;
word32 rc;
word32 remaining = cert->maxIdx - cert->srcIdx;
+ byte* publicKey;
#ifdef WOLFSSL_SMALL_STACK
byte* keyBlob = NULL;
#else
@@ -1757,8 +5162,8 @@ static int GetKey(DecodedCert* cert)
return ASN_NTRU_KEY_E;
#ifdef WOLFSSL_SMALL_STACK
- keyBlob = (byte*)XMALLOC(MAX_NTRU_KEY_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
+ keyBlob = (byte*)XMALLOC(MAX_NTRU_KEY_SZ, cert->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
if (keyBlob == NULL)
return MEMORY_E;
#endif
@@ -1767,34 +5172,35 @@ static int GetKey(DecodedCert* cert)
&keyLen, keyBlob, &next, &remaining);
if (rc != NTRU_OK) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ASN_NTRU_KEY_E;
}
if ( (next - key) < 0) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ASN_NTRU_KEY_E;
}
cert->srcIdx = tmpIdx + (int)(next - key);
- cert->publicKey = (byte*) XMALLOC(keyLen, cert->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (cert->publicKey == NULL) {
+ publicKey = (byte*)XMALLOC(keyLen, cert->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (publicKey == NULL) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return MEMORY_E;
}
- XMEMCPY(cert->publicKey, keyBlob, keyLen);
+ XMEMCPY(publicKey, keyBlob, keyLen);
+ cert->publicKey = publicKey;
cert->pubKeyStored = 1;
cert->pubKeySize = keyLen;
#ifdef WOLFSSL_SMALL_STACK
- XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return 0;
@@ -1803,40 +5209,78 @@ static int GetKey(DecodedCert* cert)
#ifdef HAVE_ECC
case ECDSAk:
{
- int oidSz = 0;
- byte b = cert->source[cert->srcIdx++];
-
- if (b != ASN_OBJECT_ID)
- return ASN_OBJECT_ID_E;
-
- if (GetLength(cert->source,&cert->srcIdx,&oidSz,cert->maxIdx) < 0)
+ int ret;
+ byte seq[5];
+ int pubLen = length + 1 + SetLength(length, seq);
+ word32 localIdx;
+ byte* publicKey;
+ byte tag;
+
+ localIdx = cert->srcIdx;
+ if (GetASNTag(cert->source, &localIdx, &tag, cert->maxIdx) < 0)
return ASN_PARSE_E;
- while(oidSz--)
- cert->pkCurveOID += cert->source[cert->srcIdx++];
+ if (tag != (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
+ if (GetObjectId(cert->source, &cert->srcIdx,
+ &cert->pkCurveOID, oidCurveType, cert->maxIdx) < 0)
+ return ASN_PARSE_E;
- if (CheckCurve(cert->pkCurveOID) < 0)
- return ECC_CURVE_OID_E;
+ if (CheckCurve(cert->pkCurveOID) < 0)
+ return ECC_CURVE_OID_E;
+
+ /* key header */
+ ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+ cert->maxIdx, 1, NULL);
+ if (ret != 0)
+ return ret;
+ #ifdef HAVE_OCSP
+ ret = CalcHashId(cert->source + cert->srcIdx, length,
+ cert->subjectKeyHash);
+ if (ret != 0)
+ return ret;
+ #endif
+ }
- /* key header */
- b = cert->source[cert->srcIdx++];
- if (b != ASN_BIT_STRING)
- return ASN_BITSTR_E;
+ publicKey = (byte*)XMALLOC(pubLen, cert->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (publicKey == NULL)
+ return MEMORY_E;
+ XMEMCPY(publicKey, &cert->source[tmpIdx], pubLen);
+ cert->publicKey = publicKey;
+ cert->pubKeyStored = 1;
+ cert->pubKeySize = pubLen;
- if (GetLength(cert->source,&cert->srcIdx,&length,cert->maxIdx) < 0)
- return ASN_PARSE_E;
- b = cert->source[cert->srcIdx++];
- if (b != 0x00)
- return ASN_EXPECT_0_E;
+ cert->srcIdx = tmpIdx + pubLen;
- /* actual key, use length - 1 since ate preceding 0 */
- length -= 1;
+ return 0;
+ }
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ {
+ byte* publicKey;
+ int ret;
+
+ cert->pkCurveOID = ED25519k;
- cert->publicKey = (byte*) XMALLOC(length, cert->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (cert->publicKey == NULL)
+ ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+ cert->maxIdx, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ #ifdef HAVE_OCSP
+ ret = CalcHashId(cert->source + cert->srcIdx, length,
+ cert->subjectKeyHash);
+ if (ret != 0)
+ return ret;
+ #endif
+
+ publicKey = (byte*) XMALLOC(length, cert->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (publicKey == NULL)
return MEMORY_E;
- XMEMCPY(cert->publicKey, &cert->source[cert->srcIdx], length);
+ XMEMCPY(publicKey, &cert->source[cert->srcIdx], length);
+ cert->publicKey = publicKey;
cert->pubKeyStored = 1;
cert->pubKeySize = length;
@@ -1844,25 +5288,238 @@ static int GetKey(DecodedCert* cert)
return 0;
}
- #endif /* HAVE_ECC */
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ED448k:
+ {
+ byte* publicKey;
+ int ret;
+
+ cert->pkCurveOID = ED448k;
+
+ ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+ cert->maxIdx, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ #ifdef HAVE_OCSP
+ ret = CalcHashId(cert->source + cert->srcIdx, length,
+ cert->subjectKeyHash);
+ if (ret != 0)
+ return ret;
+ #endif
+
+ publicKey = (byte*) XMALLOC(length, cert->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (publicKey == NULL)
+ return MEMORY_E;
+ XMEMCPY(publicKey, &cert->source[cert->srcIdx], length);
+ cert->publicKey = publicKey;
+ cert->pubKeyStored = 1;
+ cert->pubKeySize = length;
+
+ cert->srcIdx += length;
+
+ return 0;
+ }
+ #endif /* HAVE_ED448 */
+ #if !defined(NO_DSA) && defined(WOLFSSL_QT)
+ case DSAk:
+ {
+ int ret;
+ ret = GetSequence(cert->source, &cert->srcIdx, &length,
+ cert->maxIdx);
+ if (ret < 0)
+ return ret;
+
+ ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx);
+ if (ret != 0)
+ return ret;
+ ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx);
+ if (ret != 0)
+ return ret;
+ ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx);
+ if (ret != 0)
+ return ret;
+
+ ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+ cert->maxIdx, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ ret = GetASNInt(cert->source, &cert->srcIdx, &length, cert->maxIdx);
+ if (ret !=0)
+ return ASN_PARSE_E;
+
+ cert->publicKey = cert->source + tmpIdx;
+ cert->pubKeySize = tmpLen;
+ cert->srcIdx += length;
+ return 0;
+ }
+ #endif /* NO_DSA && QT */
default:
return ASN_UNKNOWN_OID_E;
}
}
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+#if defined(HAVE_ECC)
+/* Converts ECC curve enum values in ecc_curve_id to the associated OpenSSL NID
+ value */
+WOLFSSL_API int EccEnumToNID(int n)
+{
+ WOLFSSL_ENTER("EccEnumToNID()");
+
+ switch(n) {
+ case ECC_SECP192R1:
+ return NID_X9_62_prime192v1;
+ case ECC_PRIME192V2:
+ return NID_X9_62_prime192v2;
+ case ECC_PRIME192V3:
+ return NID_X9_62_prime192v3;
+ case ECC_PRIME239V1:
+ return NID_X9_62_prime239v1;
+ case ECC_PRIME239V2:
+ return NID_X9_62_prime239v2;
+ case ECC_PRIME239V3:
+ return NID_X9_62_prime239v3;
+ case ECC_SECP256R1:
+ return NID_X9_62_prime256v1;
+ case ECC_SECP112R1:
+ return NID_secp112r1;
+ case ECC_SECP112R2:
+ return NID_secp112r2;
+ case ECC_SECP128R1:
+ return NID_secp128r1;
+ case ECC_SECP128R2:
+ return NID_secp128r2;
+ case ECC_SECP160R1:
+ return NID_secp160r1;
+ case ECC_SECP160R2:
+ return NID_secp160r2;
+ case ECC_SECP224R1:
+ return NID_secp224r1;
+ case ECC_SECP384R1:
+ return NID_secp384r1;
+ case ECC_SECP521R1:
+ return NID_secp521r1;
+ case ECC_SECP160K1:
+ return NID_secp160k1;
+ case ECC_SECP192K1:
+ return NID_secp192k1;
+ case ECC_SECP224K1:
+ return NID_secp224k1;
+ case ECC_SECP256K1:
+ return NID_secp256k1;
+ case ECC_BRAINPOOLP160R1:
+ return NID_brainpoolP160r1;
+ case ECC_BRAINPOOLP192R1:
+ return NID_brainpoolP192r1;
+ case ECC_BRAINPOOLP224R1:
+ return NID_brainpoolP224r1;
+ case ECC_BRAINPOOLP256R1:
+ return NID_brainpoolP256r1;
+ case ECC_BRAINPOOLP320R1:
+ return NID_brainpoolP320r1;
+ case ECC_BRAINPOOLP384R1:
+ return NID_brainpoolP384r1;
+ case ECC_BRAINPOOLP512R1:
+ return NID_brainpoolP512r1;
+ default:
+ WOLFSSL_MSG("NID not found");
+ return -1;
+ }
+}
+#endif /* HAVE_ECC */
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+int wc_OBJ_sn2nid(const char *sn)
+{
+ const struct {
+ const char *sn;
+ int nid;
+ } sn2nid[] = {
+ {WOLFSSL_COMMON_NAME, NID_commonName},
+ {WOLFSSL_COUNTRY_NAME, NID_countryName},
+ {WOLFSSL_LOCALITY_NAME, NID_localityName},
+ {WOLFSSL_STATE_NAME, NID_stateOrProvinceName},
+ {WOLFSSL_ORG_NAME, NID_organizationName},
+ {WOLFSSL_ORGUNIT_NAME, NID_organizationalUnitName},
+ {WOLFSSL_EMAIL_ADDR, NID_emailAddress},
+ {NULL, -1}};
+
+ int i;
+ #ifdef HAVE_ECC
+ int eccEnum;
+ #endif
+ WOLFSSL_ENTER("OBJ_sn2nid");
+ for(i=0; sn2nid[i].sn != NULL; i++) {
+ if(XSTRNCMP(sn, sn2nid[i].sn, XSTRLEN(sn2nid[i].sn)) == 0) {
+ return sn2nid[i].nid;
+ }
+ }
+ #ifdef HAVE_ECC
+ /* Nginx uses this OpenSSL string. */
+ if (XSTRNCMP(sn, "prime256v1", 10) == 0)
+ sn = "SECP256R1";
+ if (XSTRNCMP(sn, "secp384r1", 10) == 0)
+ sn = "SECP384R1";
+ /* find based on name and return NID */
+ for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++) {
+ if (XSTRNCMP(sn, ecc_sets[i].name, ECC_MAXNAME) == 0) {
+ eccEnum = ecc_sets[i].id;
+ /* Convert enum value in ecc_curve_id to OpenSSL NID */
+ return EccEnumToNID(eccEnum);
+ }
+ }
+ #endif
+
+ return NID_undef;
+}
+#endif
+
+/* Routine for calculating hashId */
+int CalcHashId(const byte* data, word32 len, byte* hash)
+{
+ int ret;
+
+#ifdef WOLF_CRYPTO_CB
+ /* try to use a registered crypto callback */
+ ret = wc_CryptoCb_Sha256Hash(NULL, data, len, hash);
+ if (ret != CRYPTOCB_UNAVAILABLE)
+ return ret;
+ /* fall-through when unavailable */
+#endif
+
+#if defined(NO_SHA) && !defined(NO_SHA256)
+ ret = wc_Sha256Hash(data, len, hash);
+#elif !defined(NO_SHA)
+ ret = wc_ShaHash(data, len, hash);
+#else
+ ret = NOT_COMPILED_IN;
+#endif
+
+ return ret;
+}
/* process NAME, either issuer or subject */
-static int GetName(DecodedCert* cert, int nameType)
+static int GetName(DecodedCert* cert, int nameType, int maxIdx)
{
int length; /* length of all distinguished names */
int dummy;
int ret;
char* full;
byte* hash;
- word32 idx;
- #ifdef OPENSSL_EXTRA
+ word32 idx, localIdx = 0;
+ byte tag;
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
DecodedName* dName =
(nameType == ISSUER) ? &cert->issuerName : &cert->subjectName;
+ int dcnum = 0;
+ #ifdef OPENSSL_EXTRA
+ int count = 0;
+ #endif
#endif /* OPENSSL_EXTRA */
WOLFSSL_MSG("Getting Cert Name");
@@ -1876,13 +5533,20 @@ static int GetName(DecodedCert* cert, int nameType)
hash = cert->subjectHash;
}
- if (cert->source[cert->srcIdx] == ASN_OBJECT_ID) {
+ if (cert->srcIdx >= (word32)maxIdx) {
+ return BUFFER_E;
+ }
+
+ localIdx = cert->srcIdx;
+ if (GetASNTag(cert->source, &localIdx, &tag, maxIdx) < 0) {
+ return ASN_PARSE_E;
+ }
+
+ if (tag == ASN_OBJECT_ID) {
WOLFSSL_MSG("Trying optional prefix...");
- if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
+ if (SkipObjectId(cert->source, &cert->srcIdx, maxIdx) < 0)
return ASN_PARSE_E;
-
- cert->srcIdx += length;
WOLFSSL_MSG("Got optional prefix");
}
@@ -1890,21 +5554,17 @@ static int GetName(DecodedCert* cert, int nameType)
* calculated over the entire DER encoding of the Name field, including
* the tag and length. */
idx = cert->srcIdx;
- if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
+ if (GetSequence(cert->source, &cert->srcIdx, &length, maxIdx) < 0)
return ASN_PARSE_E;
-#ifdef NO_SHA
- ret = wc_Sha256Hash(&cert->source[idx], length + cert->srcIdx - idx, hash);
-#else
- ret = wc_ShaHash(&cert->source[idx], length + cert->srcIdx - idx, hash);
-#endif
+ ret = CalcHashId(&cert->source[idx], length + cert->srcIdx - idx, hash);
if (ret != 0)
return ret;
length += cert->srcIdx;
idx = 0;
-#ifdef HAVE_PKCS7
+#if defined(HAVE_PKCS7) || defined(WOLFSSL_CERT_EXT)
/* store pointer to raw issuer */
if (nameType == ISSUER) {
cert->issuerRaw = &cert->source[cert->srcIdx];
@@ -1919,45 +5579,39 @@ static int GetName(DecodedCert* cert, int nameType)
#endif
while (cert->srcIdx < (word32)length) {
- byte b;
- byte joint[2];
- byte tooBig = FALSE;
- int oidSz;
-
- if (GetSet(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) < 0) {
+ byte b = 0;
+ byte joint[3];
+ byte tooBig = FALSE;
+ int oidSz;
+ const char* copy = NULL;
+ int copyLen = 0;
+ int strLen = 0;
+ byte id = 0;
+
+ if (GetSet(cert->source, &cert->srcIdx, &dummy, maxIdx) < 0) {
WOLFSSL_MSG("Cert name lacks set header, trying sequence");
}
- if (GetSequence(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) < 0)
+ if (GetSequence(cert->source, &cert->srcIdx, &dummy, maxIdx) <= 0)
return ASN_PARSE_E;
- b = cert->source[cert->srcIdx++];
- if (b != ASN_OBJECT_ID)
- return ASN_OBJECT_ID_E;
+ ret = GetASNObjectId(cert->source, &cert->srcIdx, &oidSz, maxIdx);
+ if (ret != 0)
+ return ret;
- if (GetLength(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx) < 0)
+ /* make sure there is room for joint */
+ if ((cert->srcIdx + sizeof(joint)) > (word32)maxIdx)
return ASN_PARSE_E;
XMEMCPY(joint, &cert->source[cert->srcIdx], sizeof(joint));
/* v1 name types */
if (joint[0] == 0x55 && joint[1] == 0x04) {
- byte id;
- byte copy = FALSE;
- int strLen;
-
- cert->srcIdx += 2;
- id = cert->source[cert->srcIdx++];
- b = cert->source[cert->srcIdx++]; /* encoding */
-
- if (GetLength(cert->source, &cert->srcIdx, &strLen,
- cert->maxIdx) < 0)
+ cert->srcIdx += 3;
+ id = joint[2];
+ if (GetHeader(cert->source, &b, &cert->srcIdx, &strLen,
+ maxIdx, 1) < 0) {
return ASN_PARSE_E;
-
- if ( (strLen + 14) > (int)(ASN_NAME_MAX - idx)) {
- /* include biggest pre fix header too 4 = "/serialNumber=" */
- WOLFSSL_MSG("ASN Name too big, skipping");
- tooBig = TRUE;
}
if (id == ASN_COMMON_NAME) {
@@ -1967,22 +5621,16 @@ static int GetName(DecodedCert* cert, int nameType)
cert->subjectCNEnc = b;
}
- if (!tooBig) {
- XMEMCPY(&full[idx], "/CN=", 4);
- idx += 4;
- copy = TRUE;
- }
- #ifdef OPENSSL_EXTRA
+ copy = WOLFSSL_COMMON_NAME;
+ copyLen = sizeof(WOLFSSL_COMMON_NAME) - 1;
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->cnIdx = cert->srcIdx;
dName->cnLen = strLen;
#endif /* OPENSSL_EXTRA */
}
else if (id == ASN_SUR_NAME) {
- if (!tooBig) {
- XMEMCPY(&full[idx], "/SN=", 4);
- idx += 4;
- copy = TRUE;
- }
+ copy = WOLFSSL_SUR_NAME;
+ copyLen = sizeof(WOLFSSL_SUR_NAME) - 1;
#ifdef WOLFSSL_CERT_GEN
if (nameType == SUBJECT) {
cert->subjectSN = (char*)&cert->source[cert->srcIdx];
@@ -1990,17 +5638,14 @@ static int GetName(DecodedCert* cert, int nameType)
cert->subjectSNEnc = b;
}
#endif /* WOLFSSL_CERT_GEN */
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->snIdx = cert->srcIdx;
dName->snLen = strLen;
#endif /* OPENSSL_EXTRA */
}
else if (id == ASN_COUNTRY_NAME) {
- if (!tooBig) {
- XMEMCPY(&full[idx], "/C=", 3);
- idx += 3;
- copy = TRUE;
- }
+ copy = WOLFSSL_COUNTRY_NAME;
+ copyLen = sizeof(WOLFSSL_COUNTRY_NAME) - 1;
#ifdef WOLFSSL_CERT_GEN
if (nameType == SUBJECT) {
cert->subjectC = (char*)&cert->source[cert->srcIdx];
@@ -2008,17 +5653,14 @@ static int GetName(DecodedCert* cert, int nameType)
cert->subjectCEnc = b;
}
#endif /* WOLFSSL_CERT_GEN */
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->cIdx = cert->srcIdx;
dName->cLen = strLen;
#endif /* OPENSSL_EXTRA */
}
else if (id == ASN_LOCALITY_NAME) {
- if (!tooBig) {
- XMEMCPY(&full[idx], "/L=", 3);
- idx += 3;
- copy = TRUE;
- }
+ copy = WOLFSSL_LOCALITY_NAME;
+ copyLen = sizeof(WOLFSSL_LOCALITY_NAME) - 1;
#ifdef WOLFSSL_CERT_GEN
if (nameType == SUBJECT) {
cert->subjectL = (char*)&cert->source[cert->srcIdx];
@@ -2026,17 +5668,14 @@ static int GetName(DecodedCert* cert, int nameType)
cert->subjectLEnc = b;
}
#endif /* WOLFSSL_CERT_GEN */
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->lIdx = cert->srcIdx;
dName->lLen = strLen;
#endif /* OPENSSL_EXTRA */
}
else if (id == ASN_STATE_NAME) {
- if (!tooBig) {
- XMEMCPY(&full[idx], "/ST=", 4);
- idx += 4;
- copy = TRUE;
- }
+ copy = WOLFSSL_STATE_NAME;
+ copyLen = sizeof(WOLFSSL_STATE_NAME) - 1;
#ifdef WOLFSSL_CERT_GEN
if (nameType == SUBJECT) {
cert->subjectST = (char*)&cert->source[cert->srcIdx];
@@ -2044,17 +5683,14 @@ static int GetName(DecodedCert* cert, int nameType)
cert->subjectSTEnc = b;
}
#endif /* WOLFSSL_CERT_GEN */
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->stIdx = cert->srcIdx;
dName->stLen = strLen;
#endif /* OPENSSL_EXTRA */
}
else if (id == ASN_ORG_NAME) {
- if (!tooBig) {
- XMEMCPY(&full[idx], "/O=", 3);
- idx += 3;
- copy = TRUE;
- }
+ copy = WOLFSSL_ORG_NAME;
+ copyLen = sizeof(WOLFSSL_ORG_NAME) - 1;
#ifdef WOLFSSL_CERT_GEN
if (nameType == SUBJECT) {
cert->subjectO = (char*)&cert->source[cert->srcIdx];
@@ -2062,17 +5698,14 @@ static int GetName(DecodedCert* cert, int nameType)
cert->subjectOEnc = b;
}
#endif /* WOLFSSL_CERT_GEN */
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->oIdx = cert->srcIdx;
dName->oLen = strLen;
#endif /* OPENSSL_EXTRA */
}
else if (id == ASN_ORGUNIT_NAME) {
- if (!tooBig) {
- XMEMCPY(&full[idx], "/OU=", 4);
- idx += 4;
- copy = TRUE;
- }
+ copy = WOLFSSL_ORGUNIT_NAME;
+ copyLen = sizeof(WOLFSSL_ORGUNIT_NAME) - 1;
#ifdef WOLFSSL_CERT_GEN
if (nameType == SUBJECT) {
cert->subjectOU = (char*)&cert->source[cert->srcIdx];
@@ -2080,75 +5713,148 @@ static int GetName(DecodedCert* cert, int nameType)
cert->subjectOUEnc = b;
}
#endif /* WOLFSSL_CERT_GEN */
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->ouIdx = cert->srcIdx;
dName->ouLen = strLen;
#endif /* OPENSSL_EXTRA */
}
else if (id == ASN_SERIAL_NUMBER) {
- if (!tooBig) {
- XMEMCPY(&full[idx], "/serialNumber=", 14);
- idx += 14;
- copy = TRUE;
- }
- #ifdef OPENSSL_EXTRA
+ copy = WOLFSSL_SERIAL_NUMBER;
+ copyLen = sizeof(WOLFSSL_SERIAL_NUMBER) - 1;
+ #ifdef WOLFSSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectSND = (char*)&cert->source[cert->srcIdx];
+ cert->subjectSNDLen = strLen;
+ cert->subjectSNDEnc = b;
+ }
+ #endif /* WOLFSSL_CERT_GEN */
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->snIdx = cert->srcIdx;
dName->snLen = strLen;
#endif /* OPENSSL_EXTRA */
}
+ #ifdef WOLFSSL_CERT_EXT
+ else if (id == ASN_BUS_CAT) {
+ copy = WOLFSSL_BUS_CAT;
+ copyLen = sizeof(WOLFSSL_BUS_CAT) - 1;
+ #ifdef WOLFSSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectBC = (char*)&cert->source[cert->srcIdx];
+ cert->subjectBCLen = strLen;
+ cert->subjectBCEnc = b;
+ }
+ #endif /* WOLFSSL_CERT_GEN */
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ dName->bcIdx = cert->srcIdx;
+ dName->bcLen = strLen;
+ #endif /* OPENSSL_EXTRA */
+ }
+ #endif /* WOLFSSL_CERT_EXT */
+ }
+ #ifdef WOLFSSL_CERT_EXT
+ else if ((cert->srcIdx + ASN_JOI_PREFIX_SZ + 2 <= (word32)maxIdx) &&
+ (0 == XMEMCMP(&cert->source[cert->srcIdx], ASN_JOI_PREFIX,
+ ASN_JOI_PREFIX_SZ)) &&
+ ((cert->source[cert->srcIdx+ASN_JOI_PREFIX_SZ] == ASN_JOI_C) ||
+ (cert->source[cert->srcIdx+ASN_JOI_PREFIX_SZ] == ASN_JOI_ST)))
+ {
+ cert->srcIdx += ASN_JOI_PREFIX_SZ;
+ id = cert->source[cert->srcIdx++];
+ b = cert->source[cert->srcIdx++]; /* encoding */
- if (copy && !tooBig) {
- XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen);
- idx += strLen;
+ if (GetLength(cert->source, &cert->srcIdx, &strLen,
+ maxIdx) < 0)
+ return ASN_PARSE_E;
+
+ /* Check for jurisdiction of incorporation country name */
+ if (id == ASN_JOI_C) {
+ copy = WOLFSSL_JOI_C;
+ copyLen = sizeof(WOLFSSL_JOI_C) - 1;
+ #ifdef WOLFSSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectJC = (char*)&cert->source[cert->srcIdx];
+ cert->subjectJCLen = strLen;
+ cert->subjectJCEnc = b;
+ }
+ #endif /* WOLFSSL_CERT_GEN */
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ dName->jcIdx = cert->srcIdx;
+ dName->jcLen = strLen;
+ #endif /* OPENSSL_EXTRA */
+ }
+
+ /* Check for jurisdiction of incorporation state name */
+ else if (id == ASN_JOI_ST) {
+ copy = WOLFSSL_JOI_ST;
+ copyLen = sizeof(WOLFSSL_JOI_ST) - 1;
+ #ifdef WOLFSSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectJS = (char*)&cert->source[cert->srcIdx];
+ cert->subjectJSLen = strLen;
+ cert->subjectJSEnc = b;
+ }
+ #endif /* WOLFSSL_CERT_GEN */
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ dName->jsIdx = cert->srcIdx;
+ dName->jsLen = strLen;
+ #endif /* OPENSSL_EXTRA */
}
- cert->srcIdx += strLen;
+ if ((strLen + copyLen) > (int)(ASN_NAME_MAX - idx)) {
+ WOLFSSL_MSG("ASN Name too big, skipping");
+ tooBig = TRUE;
+ }
}
+ #endif /* WOLFSSL_CERT_EXT */
else {
/* skip */
byte email = FALSE;
- byte uid = FALSE;
- int adv;
+ byte pilot = FALSE;
- if (joint[0] == 0x2a && joint[1] == 0x86) /* email id hdr */
+ if (joint[0] == 0x2a && joint[1] == 0x86) { /* email id hdr */
+ id = ASN_EMAIL_NAME;
email = TRUE;
+ }
- if (joint[0] == 0x9 && joint[1] == 0x92) /* uid id hdr */
- uid = TRUE;
+ if (joint[0] == 0x9 && joint[1] == 0x92) { /* uid id hdr */
+ /* last value of OID is the type of pilot attribute */
+ id = cert->source[cert->srcIdx + oidSz - 1];
+ pilot = TRUE;
+ }
cert->srcIdx += oidSz + 1;
- if (GetLength(cert->source, &cert->srcIdx, &adv, cert->maxIdx) < 0)
+ if (GetLength(cert->source, &cert->srcIdx, &strLen, maxIdx) < 0)
return ASN_PARSE_E;
- if (adv > (int)(ASN_NAME_MAX - idx)) {
+ if (strLen > (int)(ASN_NAME_MAX - idx)) {
WOLFSSL_MSG("ASN name too big, skipping");
tooBig = TRUE;
}
if (email) {
- if ( (14 + adv) > (int)(ASN_NAME_MAX - idx)) {
+ copyLen = sizeof(WOLFSSL_EMAIL_ADDR) - 1;
+ if ((copyLen + strLen) > (int)(ASN_NAME_MAX - idx)) {
WOLFSSL_MSG("ASN name too big, skipping");
tooBig = TRUE;
}
- if (!tooBig) {
- XMEMCPY(&full[idx], "/emailAddress=", 14);
- idx += 14;
+ else {
+ copy = WOLFSSL_EMAIL_ADDR;
}
#ifdef WOLFSSL_CERT_GEN
if (nameType == SUBJECT) {
cert->subjectEmail = (char*)&cert->source[cert->srcIdx];
- cert->subjectEmailLen = adv;
+ cert->subjectEmailLen = strLen;
}
#endif /* WOLFSSL_CERT_GEN */
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->emailIdx = cert->srcIdx;
- dName->emailLen = adv;
+ dName->emailLen = strLen;
#endif /* OPENSSL_EXTRA */
#ifndef IGNORE_NAME_CONSTRAINTS
{
- DNS_entry* emailName = NULL;
+ DNS_entry* emailName;
emailName = (DNS_entry*)XMALLOC(sizeof(DNS_entry),
cert->heap, DYNAMIC_TYPE_ALTNAME);
@@ -2156,52 +5862,85 @@ static int GetName(DecodedCert* cert, int nameType)
WOLFSSL_MSG("\tOut of Memory");
return MEMORY_E;
}
- emailName->name = (char*)XMALLOC(adv + 1,
+ emailName->type = 0;
+ emailName->name = (char*)XMALLOC(strLen + 1,
cert->heap, DYNAMIC_TYPE_ALTNAME);
if (emailName->name == NULL) {
WOLFSSL_MSG("\tOut of Memory");
+ XFREE(emailName, cert->heap, DYNAMIC_TYPE_ALTNAME);
return MEMORY_E;
}
- XMEMCPY(emailName->name,
- &cert->source[cert->srcIdx], adv);
- emailName->name[adv] = 0;
+ emailName->len = strLen;
+ XMEMCPY(emailName->name, &cert->source[cert->srcIdx],
+ strLen);
+ emailName->name[strLen] = '\0';
emailName->next = cert->altEmailNames;
cert->altEmailNames = emailName;
}
#endif /* IGNORE_NAME_CONSTRAINTS */
- if (!tooBig) {
- XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv);
- idx += adv;
- }
}
- if (uid) {
- if ( (5 + adv) > (int)(ASN_NAME_MAX - idx)) {
- WOLFSSL_MSG("ASN name too big, skipping");
- tooBig = TRUE;
- }
- if (!tooBig) {
- XMEMCPY(&full[idx], "/UID=", 5);
- idx += 5;
+ if (pilot) {
+ switch (id) {
+ case ASN_USER_ID:
+ copy = WOLFSSL_USER_ID;
+ copyLen = sizeof(WOLFSSL_USER_ID) - 1;
+ #if defined(OPENSSL_EXTRA) || \
+ defined(OPENSSL_EXTRA_X509_SMALL)
+ dName->uidIdx = cert->srcIdx;
+ dName->uidLen = strLen;
+ #endif /* OPENSSL_EXTRA */
+ break;
- XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv);
- idx += adv;
+ case ASN_DOMAIN_COMPONENT:
+ copy = WOLFSSL_DOMAIN_COMPONENT;
+ copyLen = sizeof(WOLFSSL_DOMAIN_COMPONENT) - 1;
+ #if defined(OPENSSL_EXTRA) || \
+ defined(OPENSSL_EXTRA_X509_SMALL)
+ dName->dcIdx[dcnum] = cert->srcIdx;
+ dName->dcLen[dcnum] = strLen;
+ dName->dcNum = dcnum + 1;
+ dcnum++;
+ #endif /* OPENSSL_EXTRA */
+ break;
+
+ default:
+ WOLFSSL_MSG("Unknown pilot attribute type");
+ return ASN_PARSE_E;
}
- #ifdef OPENSSL_EXTRA
- dName->uidIdx = cert->srcIdx;
- dName->uidLen = adv;
- #endif /* OPENSSL_EXTRA */
}
+ }
+ if ((copyLen + strLen) > (int)(ASN_NAME_MAX - idx))
+ {
+ WOLFSSL_MSG("ASN Name too big, skipping");
+ tooBig = TRUE;
+ }
+ if ((copy != NULL) && !tooBig) {
+ XMEMCPY(&full[idx], copy, copyLen);
+ idx += copyLen;
+ XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen);
+ idx += strLen;
- cert->srcIdx += adv;
+ #ifdef OPENSSL_EXTRA
+ if (count < DOMAIN_COMPONENT_MAX) {
+ /* store order that DN was parsed */
+ dName->loc[count++] = id;
+ }
+ #endif
}
+ cert->srcIdx += strLen;
}
full[idx++] = 0;
+#if defined(OPENSSL_EXTRA)
+ /* store order that DN was parsed */
+ dName->locSz = count;
+#endif
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
{
int totalLen = 0;
+ int i = 0;
if (dName->cnLen != 0)
totalLen += dName->cnLen + 4;
@@ -2223,14 +5962,20 @@ static int GetName(DecodedCert* cert, int nameType)
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;
+ }
- dName->fullName = (char*)XMALLOC(totalLen + 1, NULL, DYNAMIC_TYPE_X509);
+ dName->fullName = (char*)XMALLOC(totalLen + 1, cert->heap,
+ DYNAMIC_TYPE_X509);
if (dName->fullName != NULL) {
idx = 0;
if (dName->cnLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/CN=", 4);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_COMMON_NAME, 4);
+ dName->cnNid = wc_OBJ_sn2nid((const char *)WOLFSSL_COMMON_NAME);
idx += 4;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->cnIdx], dName->cnLen);
@@ -2239,7 +5984,8 @@ static int GetName(DecodedCert* cert, int nameType)
}
if (dName->snLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/SN=", 4);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_SUR_NAME, 4);
+ dName->snNid = wc_OBJ_sn2nid((const char *)WOLFSSL_SUR_NAME);
idx += 4;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->snIdx], dName->snLen);
@@ -2248,7 +5994,8 @@ static int GetName(DecodedCert* cert, int nameType)
}
if (dName->cLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/C=", 3);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_COUNTRY_NAME, 3);
+ dName->cNid = wc_OBJ_sn2nid((const char *)WOLFSSL_COUNTRY_NAME);
idx += 3;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->cIdx], dName->cLen);
@@ -2257,7 +6004,8 @@ static int GetName(DecodedCert* cert, int nameType)
}
if (dName->lLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/L=", 3);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_LOCALITY_NAME, 3);
+ dName->lNid = wc_OBJ_sn2nid((const char *)WOLFSSL_LOCALITY_NAME);
idx += 3;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->lIdx], dName->lLen);
@@ -2266,7 +6014,8 @@ static int GetName(DecodedCert* cert, int nameType)
}
if (dName->stLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/ST=", 4);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_STATE_NAME, 4);
+ dName->stNid = wc_OBJ_sn2nid((const char *)WOLFSSL_STATE_NAME);
idx += 4;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->stIdx], dName->stLen);
@@ -2275,7 +6024,8 @@ static int GetName(DecodedCert* cert, int nameType)
}
if (dName->oLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/O=", 3);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_ORG_NAME, 3);
+ dName->oNid = wc_OBJ_sn2nid((const char *)WOLFSSL_ORG_NAME);
idx += 3;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->oIdx], dName->oLen);
@@ -2284,7 +6034,8 @@ static int GetName(DecodedCert* cert, int nameType)
}
if (dName->ouLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/OU=", 4);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_ORGUNIT_NAME, 4);
+ dName->ouNid = wc_OBJ_sn2nid((const char *)WOLFSSL_ORGUNIT_NAME);
idx += 4;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->ouIdx], dName->ouLen);
@@ -2294,15 +6045,28 @@ static int GetName(DecodedCert* cert, int nameType)
if (dName->emailLen != 0) {
dName->entryCount++;
XMEMCPY(&dName->fullName[idx], "/emailAddress=", 14);
+ dName->emailNid = wc_OBJ_sn2nid((const char *)"/emailAddress=");
idx += 14;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->emailIdx], dName->emailLen);
dName->emailIdx = idx;
idx += dName->emailLen;
}
+ for (i = 0;i < dName->dcNum;i++){
+ if (dName->dcLen[i] != 0) {
+ dName->entryCount++;
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_DOMAIN_COMPONENT, 4);
+ idx += 4;
+ XMEMCPY(&dName->fullName[idx],
+ &cert->source[dName->dcIdx[i]], dName->dcLen[i]);
+ dName->dcIdx[i] = idx;
+ idx += dName->dcLen[i];
+ }
+ }
if (dName->uidLen != 0) {
dName->entryCount++;
XMEMCPY(&dName->fullName[idx], "/UID=", 5);
+ dName->uidNid = wc_OBJ_sn2nid((const char *)"/UID=");
idx += 5;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->uidIdx], dName->uidLen);
@@ -2311,7 +6075,8 @@ static int GetName(DecodedCert* cert, int nameType)
}
if (dName->serialLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/serialNumber=", 14);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_SERIAL_NUMBER, 14);
+ dName->serialNid = wc_OBJ_sn2nid((const char *)WOLFSSL_SERIAL_NUMBER);
idx += 14;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->serialIdx], dName->serialLen);
@@ -2328,17 +6093,203 @@ static int GetName(DecodedCert* cert, int nameType)
}
-#ifndef NO_TIME_H
+#ifndef NO_ASN_TIME
+
+/* two byte date/time, add to value */
+static WC_INLINE int GetTime(int* value, const byte* date, int* idx)
+{
+ int i = *idx;
+
+ if (date[i] < 0x30 || date[i] > 0x39 || date[i+1] < 0x30 ||
+ date[i+1] > 0x39) {
+ return ASN_PARSE_E;
+ }
+
+ *value += btoi(date[i++]) * 10;
+ *value += btoi(date[i++]);
+
+ *idx = i;
+
+ return 0;
+}
+
+int ExtractDate(const unsigned char* date, unsigned char format,
+ struct tm* certTime, int* idx)
+{
+ XMEMSET(certTime, 0, sizeof(struct tm));
+
+ if (format == ASN_UTC_TIME) {
+ if (btoi(date[*idx]) >= 5)
+ certTime->tm_year = 1900;
+ else
+ certTime->tm_year = 2000;
+ }
+ else { /* format == GENERALIZED_TIME */
+ if (GetTime(&certTime->tm_year, date, idx) != 0) return 0;
+ certTime->tm_year *= 100;
+ }
+
+ /* adjust tm_year, tm_mon */
+ if (GetTime(&certTime->tm_year, date, idx) != 0) return 0;
+ certTime->tm_year -= 1900;
+ if (GetTime(&certTime->tm_mon , date, idx) != 0) return 0;
+ certTime->tm_mon -= 1;
+ if (GetTime(&certTime->tm_mday, date, idx) != 0) return 0;
+ if (GetTime(&certTime->tm_hour, date, idx) != 0) return 0;
+ if (GetTime(&certTime->tm_min , date, idx) != 0) return 0;
+ if (GetTime(&certTime->tm_sec , date, idx) != 0) return 0;
+
+ return 1;
+}
+
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \
+ defined(OPENSSL_EXTRA) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+int GetTimeString(byte* date, int format, char* buf, int len)
+{
+ struct tm t;
+ int idx = 0;
+
+ if (!ExtractDate(date, (unsigned char)format, &t, &idx)) {
+ return 0;
+ }
+
+ if (date[idx] != 'Z') {
+ WOLFSSL_MSG("UTCtime, not Zulu") ;
+ return 0;
+ }
+
+ /* place month in buffer */
+ buf[0] = '\0';
+ switch(t.tm_mon) {
+ case 0: XSTRNCAT(buf, "Jan ", 5); break;
+ case 1: XSTRNCAT(buf, "Feb ", 5); break;
+ case 2: XSTRNCAT(buf, "Mar ", 5); break;
+ case 3: XSTRNCAT(buf, "Apr ", 5); break;
+ case 4: XSTRNCAT(buf, "May ", 5); break;
+ case 5: XSTRNCAT(buf, "Jun ", 5); break;
+ case 6: XSTRNCAT(buf, "Jul ", 5); break;
+ case 7: XSTRNCAT(buf, "Aug ", 5); break;
+ case 8: XSTRNCAT(buf, "Sep ", 5); break;
+ case 9: XSTRNCAT(buf, "Oct ", 5); break;
+ case 10: XSTRNCAT(buf, "Nov ", 5); break;
+ case 11: XSTRNCAT(buf, "Dec ", 5); break;
+ default:
+ return 0;
+
+ }
+ idx = 4; /* use idx now for char buffer */
+
+ XSNPRINTF(buf + idx, len - idx, "%2d %02d:%02d:%02d %d GMT",
+ t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, t.tm_year + 1900);
+
+ return 1;
+}
+#endif /* OPENSSL_ALL || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+
+#if !defined(NO_ASN_TIME) && defined(HAVE_PKCS7)
+
+/* Set current time string, either UTC or GeneralizedTime.
+ * (void*) tm should be a pointer to time_t, output is placed in buf.
+ *
+ * Return time string length placed in buf on success, negative on error */
+int GetAsnTimeString(void* currTime, byte* buf, word32 len)
+{
+ struct tm* ts = NULL;
+ struct tm* tmpTime = NULL;
+#if defined(NEED_TMP_TIME)
+ struct tm tmpTimeStorage;
+ tmpTime = &tmpTimeStorage;
+#else
+ (void)tmpTime;
+#endif
+ byte* data_ptr = buf;
+ word32 data_len = 0;
+ int year, mon, day, hour, mini, sec;
+
+ WOLFSSL_ENTER("SetAsnTimeString");
+
+ if (buf == NULL || len == 0)
+ return BAD_FUNC_ARG;
+
+ ts = (struct tm *)XGMTIME((time_t*)currTime, tmpTime);
+ if (ts == NULL){
+ WOLFSSL_MSG("failed to get time data.");
+ return ASN_TIME_E;
+ }
+
+ /* Note ASN_UTC_TIME_SIZE and ASN_GENERALIZED_TIME_SIZE include space for
+ * the null terminator. ASN encoded values leave off the terminator. */
+
+ if (ts->tm_year >= 50 && ts->tm_year < 150) {
+ /* UTC Time */
+ char utc_str[ASN_UTC_TIME_SIZE];
+ data_len = ASN_UTC_TIME_SIZE - 1 + 2;
+
+ if (len < data_len)
+ return BUFFER_E;
+
+ if (ts->tm_year >= 50 && ts->tm_year < 100) {
+ year = ts->tm_year;
+ } else if (ts->tm_year >= 100 && ts->tm_year < 150) {
+ year = ts->tm_year - 100;
+ }
+ else {
+ WOLFSSL_MSG("unsupported year range");
+ return BAD_FUNC_ARG;
+ }
+ mon = ts->tm_mon + 1;
+ day = ts->tm_mday;
+ hour = ts->tm_hour;
+ mini = ts->tm_min;
+ sec = ts->tm_sec;
+ XSNPRINTF((char *)utc_str, ASN_UTC_TIME_SIZE,
+ "%02d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec);
+ *data_ptr = (byte) ASN_UTC_TIME; data_ptr++;
+ /* -1 below excludes null terminator */
+ *data_ptr = (byte) ASN_UTC_TIME_SIZE - 1; data_ptr++;
+ XMEMCPY(data_ptr,(byte *)utc_str, ASN_UTC_TIME_SIZE - 1);
+
+ } else {
+ /* GeneralizedTime */
+ char gt_str[ASN_GENERALIZED_TIME_SIZE];
+ data_len = ASN_GENERALIZED_TIME_SIZE - 1 + 2;
+
+ if (len < data_len)
+ return BUFFER_E;
+
+ year = ts->tm_year + 1900;
+ mon = ts->tm_mon + 1;
+ day = ts->tm_mday;
+ hour = ts->tm_hour;
+ mini = ts->tm_min;
+ sec = ts->tm_sec;
+ XSNPRINTF((char *)gt_str, ASN_GENERALIZED_TIME_SIZE,
+ "%4d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec);
+ *data_ptr = (byte) ASN_GENERALIZED_TIME; data_ptr++;
+ /* -1 below excludes null terminator */
+ *data_ptr = (byte) ASN_GENERALIZED_TIME_SIZE - 1; data_ptr++;
+ XMEMCPY(data_ptr,(byte *)gt_str, ASN_GENERALIZED_TIME_SIZE - 1);
+ }
+
+ return data_len;
+}
+
+#endif /* !NO_ASN_TIME && HAVE_PKCS7 */
+
+
+#if defined(USE_WOLF_VALIDDATE)
/* to the second */
-static int DateGreaterThan(const struct tm* a, const struct tm* b)
+int DateGreaterThan(const struct tm* a, const struct tm* b)
{
if (a->tm_year > b->tm_year)
return 1;
if (a->tm_year == b->tm_year && a->tm_mon > b->tm_mon)
return 1;
-
+
if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
a->tm_mday > b->tm_mday)
return 1;
@@ -2361,12 +6312,11 @@ static int DateGreaterThan(const struct tm* a, const struct tm* b)
}
-static INLINE int DateLessThan(const struct tm* a, const struct tm* b)
+static WC_INLINE int DateLessThan(const struct tm* a, const struct tm* b)
{
return DateGreaterThan(b,a);
}
-
/* like atoi but only use first byte */
/* Make sure before and after dates are valid */
int ValidateDate(const byte* date, byte format, int dateType)
@@ -2374,64 +6324,142 @@ int ValidateDate(const byte* date, byte format, int dateType)
time_t ltime;
struct tm certTime;
struct tm* localTime;
- struct tm* tmpTime = NULL;
+ struct tm* tmpTime;
int i = 0;
+ int timeDiff = 0 ;
+ int diffHH = 0 ; int diffMM = 0 ;
+ int diffSign = 0 ;
-#if defined(FREESCALE_MQX) || defined(TIME_OVERRIDES)
+#if defined(NEED_TMP_TIME)
struct tm tmpTimeStorage;
tmpTime = &tmpTimeStorage;
#else
- (void)tmpTime;
+ tmpTime = NULL;
#endif
+ (void)tmpTime;
ltime = XTIME(0);
- XMEMSET(&certTime, 0, sizeof(certTime));
- if (format == ASN_UTC_TIME) {
- if (btoi(date[0]) >= 5)
- certTime.tm_year = 1900;
- else
- certTime.tm_year = 2000;
+#ifdef WOLFSSL_BEFORE_DATE_CLOCK_SKEW
+ if (dateType == BEFORE) {
+ WOLFSSL_MSG("Skewing local time for before date check");
+ ltime += WOLFSSL_BEFORE_DATE_CLOCK_SKEW;
}
- else { /* format == GENERALIZED_TIME */
- certTime.tm_year += btoi(date[i++]) * 1000;
- certTime.tm_year += btoi(date[i++]) * 100;
+#endif
+
+#ifdef WOLFSSL_AFTER_DATE_CLOCK_SKEW
+ if (dateType == AFTER) {
+ WOLFSSL_MSG("Skewing local time for after date check");
+ ltime -= WOLFSSL_AFTER_DATE_CLOCK_SKEW;
}
+#endif
- /* adjust tm_year, tm_mon */
- GetTime((int*)&certTime.tm_year, date, &i); certTime.tm_year -= 1900;
- GetTime((int*)&certTime.tm_mon, date, &i); certTime.tm_mon -= 1;
- GetTime((int*)&certTime.tm_mday, date, &i);
- GetTime((int*)&certTime.tm_hour, date, &i);
- GetTime((int*)&certTime.tm_min, date, &i);
- GetTime((int*)&certTime.tm_sec, date, &i);
-
- if (date[i] != 'Z') { /* only Zulu supported for this profile */
- WOLFSSL_MSG("Only Zulu time supported for this profile");
+ if (!ExtractDate(date, format, &certTime, &i)) {
+ WOLFSSL_MSG("Error extracting the date");
return 0;
}
+ if ((date[i] == '+') || (date[i] == '-')) {
+ WOLFSSL_MSG("Using time differential, not Zulu") ;
+ diffSign = date[i++] == '+' ? 1 : -1 ;
+ if (GetTime(&diffHH, date, &i) != 0)
+ return 0;
+ if (GetTime(&diffMM, date, &i) != 0)
+ return 0;
+ timeDiff = diffSign * (diffHH*60 + diffMM) * 60 ;
+ } else if (date[i] != 'Z') {
+ WOLFSSL_MSG("UTCtime, neither Zulu or time differential") ;
+ return 0;
+ }
+
+ ltime -= (time_t)timeDiff ;
localTime = XGMTIME(&ltime, tmpTime);
+ if (localTime == NULL) {
+ WOLFSSL_MSG("XGMTIME failed");
+ return 0;
+ }
+
if (dateType == BEFORE) {
- if (DateLessThan(localTime, &certTime))
+ if (DateLessThan(localTime, &certTime)) {
+ WOLFSSL_MSG("Date BEFORE check failed");
return 0;
+ }
}
- else
- if (DateGreaterThan(localTime, &certTime))
+ else { /* dateType == AFTER */
+ if (DateGreaterThan(localTime, &certTime)) {
+ WOLFSSL_MSG("Date AFTER check failed");
return 0;
+ }
+ }
return 1;
}
+#endif /* USE_WOLF_VALIDDATE */
+
+int wc_GetTime(void* timePtr, word32 timeSize)
+{
+ time_t* ltime = (time_t*)timePtr;
+
+ if (timePtr == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if ((word32)sizeof(time_t) > timeSize) {
+ return BUFFER_E;
+ }
+
+ *ltime = XTIME(0);
+
+ return 0;
+}
-#endif /* NO_TIME_H */
+#endif /* !NO_ASN_TIME */
-static int GetDate(DecodedCert* cert, int dateType)
+/* Get date buffer, format and length. Returns 0=success or error */
+static int GetDateInfo(const byte* source, word32* idx, const byte** pDate,
+ byte* pFormat, int* pLength, word32 maxIdx)
{
- int length;
+ int length;
+ byte format;
+
+ if (source == NULL || idx == NULL)
+ return BAD_FUNC_ARG;
+
+ /* get ASN format header */
+ if (*idx+1 > maxIdx)
+ return BUFFER_E;
+ format = source[*idx];
+ *idx += 1;
+ if (format != ASN_UTC_TIME && format != ASN_GENERALIZED_TIME)
+ return ASN_TIME_E;
+
+ /* get length */
+ if (GetLength(source, idx, &length, maxIdx) < 0)
+ return ASN_PARSE_E;
+ if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE)
+ return ASN_DATE_SZ_E;
+
+ /* return format, date and length */
+ if (pFormat)
+ *pFormat = format;
+ if (pDate)
+ *pDate = &source[*idx];
+ if (pLength)
+ *pLength = length;
+
+ *idx += length;
+
+ return 0;
+}
+
+static int GetDate(DecodedCert* cert, int dateType, int verify, int maxIdx)
+{
+ int ret, length;
+ const byte *datePtr = NULL;
byte date[MAX_DATE_SIZE];
- byte b;
+ byte format;
word32 startIdx = 0;
if (dateType == BEFORE)
@@ -2440,49 +6468,50 @@ static int GetDate(DecodedCert* cert, int dateType)
cert->afterDate = &cert->source[cert->srcIdx];
startIdx = cert->srcIdx;
- b = cert->source[cert->srcIdx++];
- if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME)
- return ASN_TIME_E;
-
- if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
- return ASN_PARSE_E;
-
- if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE)
- return ASN_DATE_SZ_E;
+ ret = GetDateInfo(cert->source, &cert->srcIdx, &datePtr, &format,
+ &length, maxIdx);
+ if (ret < 0)
+ return ret;
- XMEMCPY(date, &cert->source[cert->srcIdx], length);
- cert->srcIdx += length;
+ XMEMSET(date, 0, MAX_DATE_SIZE);
+ XMEMCPY(date, datePtr, length);
if (dateType == BEFORE)
cert->beforeDateLen = cert->srcIdx - startIdx;
else
cert->afterDateLen = cert->srcIdx - startIdx;
- if (!XVALIDATE_DATE(date, b, dateType)) {
+#ifndef NO_ASN_TIME
+ if (verify != NO_VERIFY && verify != VERIFY_SKIP_DATE &&
+ !XVALIDATE_DATE(date, format, dateType)) {
if (dateType == BEFORE)
return ASN_BEFORE_DATE_E;
else
return ASN_AFTER_DATE_E;
}
+#else
+ (void)verify;
+#endif
return 0;
}
-
-static int GetValidity(DecodedCert* cert, int verify)
+static int GetValidity(DecodedCert* cert, int verify, int maxIdx)
{
int length;
int badDate = 0;
- if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
+ if (GetSequence(cert->source, &cert->srcIdx, &length, maxIdx) < 0)
return ASN_PARSE_E;
- if (GetDate(cert, BEFORE) < 0 && verify)
- badDate = ASN_BEFORE_DATE_E; /* continue parsing */
-
- if (GetDate(cert, AFTER) < 0 && verify)
+ maxIdx = cert->srcIdx + length;
+
+ if (GetDate(cert, BEFORE, verify, maxIdx) < 0)
+ badDate = ASN_BEFORE_DATE_E; /* continue parsing */
+
+ if (GetDate(cert, AFTER, verify, maxIdx) < 0)
return ASN_AFTER_DATE_E;
-
+
if (badDate != 0)
return badDate;
@@ -2490,32 +6519,111 @@ static int GetValidity(DecodedCert* cert, int verify)
}
-int DecodeToKey(DecodedCert* cert, int verify)
+int wc_GetDateInfo(const byte* certDate, int certDateSz, const byte** date,
+ byte* format, int* length)
{
- int badDate = 0;
int ret;
+ word32 idx = 0;
+
+ ret = GetDateInfo(certDate, &idx, date, format, length, certDateSz);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+#ifndef NO_ASN_TIME
+int wc_GetDateAsCalendarTime(const byte* date, int length, byte format,
+ struct tm* timearg)
+{
+ int idx = 0;
+ (void)length;
+ if (!ExtractDate(date, format, timearg, &idx))
+ return ASN_TIME_E;
+ return 0;
+}
+
+#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_ALT_NAMES)
+int wc_GetCertDates(Cert* cert, struct tm* before, struct tm* after)
+{
+ int ret = 0;
+ const byte* date;
+ byte format;
+ int length;
+ if (cert == NULL)
+ return BAD_FUNC_ARG;
+
+ if (before && cert->beforeDateSz > 0) {
+ ret = wc_GetDateInfo(cert->beforeDate, cert->beforeDateSz, &date,
+ &format, &length);
+ if (ret == 0)
+ ret = wc_GetDateAsCalendarTime(date, length, format, before);
+ }
+ if (after && cert->afterDateSz > 0) {
+ ret = wc_GetDateInfo(cert->afterDate, cert->afterDateSz, &date,
+ &format, &length);
+ if (ret == 0)
+ ret = wc_GetDateAsCalendarTime(date, length, format, after);
+ }
+
+ return ret;
+}
+#endif /* WOLFSSL_CERT_GEN && WOLFSSL_ALT_NAMES */
+#endif /* !NO_ASN_TIME */
+
+/* parses certificate up to point of X.509 public key
+ *
+ * if cert date is invalid then badDate gets set to error value, otherwise is 0
+ *
+ * returns a negative value on fail case
+ */
+int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate)
+{
+ int ret;
+
+ if (cert == NULL || badDate == NULL)
+ return BAD_FUNC_ARG;
+
+ *badDate = 0;
if ( (ret = GetCertHeader(cert)) < 0)
return ret;
WOLFSSL_MSG("Got Cert Header");
+ /* Using the sigIndex as the upper bound because that's where the
+ * actual certificate data ends. */
if ( (ret = GetAlgoId(cert->source, &cert->srcIdx, &cert->signatureOID,
- cert->maxIdx)) < 0)
+ oidSigType, cert->sigIndex)) < 0)
return ret;
WOLFSSL_MSG("Got Algo ID");
- if ( (ret = GetName(cert, ISSUER)) < 0)
+ if ( (ret = GetName(cert, ISSUER, cert->sigIndex)) < 0)
return ret;
- if ( (ret = GetValidity(cert, verify)) < 0)
- badDate = ret;
+ if ( (ret = GetValidity(cert, verify, cert->sigIndex)) < 0)
+ *badDate = ret;
- if ( (ret = GetName(cert, SUBJECT)) < 0)
+ if ( (ret = GetName(cert, SUBJECT, cert->sigIndex)) < 0)
return ret;
WOLFSSL_MSG("Got Subject Name");
+ return ret;
+}
+
+int DecodeToKey(DecodedCert* cert, int verify)
+{
+ int badDate = 0;
+ int ret;
+
+ if ( (ret = wc_GetPubX509(cert, verify, &badDate)) < 0)
+ return ret;
+
+ /* Determine if self signed */
+ cert->selfSigned = XMEMCMP(cert->issuerHash,
+ cert->subjectHash,
+ KEYID_SIZE) == 0 ? 1 : 0;
if ( (ret = GetKey(cert)) < 0)
return ret;
@@ -2528,40 +6636,36 @@ int DecodeToKey(DecodedCert* cert, int verify)
return ret;
}
-
static int GetSignature(DecodedCert* cert)
{
- int length;
- byte b = cert->source[cert->srcIdx++];
-
- if (b != ASN_BIT_STRING)
- return ASN_BITSTR_E;
-
- if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
- return ASN_PARSE_E;
+ int length;
+ int ret;
+ ret = CheckBitString(cert->source, &cert->srcIdx, &length, cert->maxIdx, 1,
+ NULL);
+ if (ret != 0)
+ return ret;
cert->sigLength = length;
-
- b = cert->source[cert->srcIdx++];
- if (b != 0x00)
- return ASN_EXPECT_0_E;
-
- cert->sigLength--;
cert->signature = &cert->source[cert->srcIdx];
cert->srcIdx += cert->sigLength;
return 0;
}
+static word32 SetOctetString8Bit(word32 len, byte* output)
+{
+ output[0] = ASN_OCTET_STRING;
+ output[1] = (byte)len;
+ return 2;
+}
static word32 SetDigest(const byte* digest, word32 digSz, byte* output)
{
- output[0] = ASN_OCTET_STRING;
- output[1] = (byte)digSz;
- XMEMCPY(&output[2], digest, digSz);
+ word32 idx = SetOctetString8Bit(digSz, output);
+ XMEMCPY(&output[idx], digest, digSz);
- return digSz + 2;
-}
+ return idx + digSz;
+}
static word32 BytePrecision(word32 value)
@@ -2575,17 +6679,23 @@ static word32 BytePrecision(word32 value)
}
-WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output)
+word32 SetLength(word32 length, byte* output)
{
word32 i = 0, j;
- if (length < ASN_LONG_LENGTH)
- output[i++] = (byte)length;
+ if (length < ASN_LONG_LENGTH) {
+ if (output)
+ output[i] = (byte)length;
+ i++;
+ }
else {
- output[i++] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH);
-
+ if (output)
+ output[i] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH);
+ i++;
+
for (j = BytePrecision(length); j; --j) {
- output[i] = (byte)(length >> ((j - 1) * WOLFSSL_BIT_SIZE));
+ if (output)
+ output[i] = (byte)(length >> ((j - 1) * WOLFSSL_BIT_SIZE));
i++;
}
}
@@ -2593,27 +6703,27 @@ WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output)
return i;
}
-
-WOLFSSL_LOCAL word32 SetSequence(word32 len, byte* output)
+word32 SetSequence(word32 len, byte* output)
{
- output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED;
- return SetLength(len, output + 1) + 1;
+ if (output)
+ output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED;
+ return SetLength(len, output ? output + 1 : NULL) + 1;
}
-WOLFSSL_LOCAL word32 SetOctetString(word32 len, byte* output)
+word32 SetOctetString(word32 len, byte* output)
{
output[0] = ASN_OCTET_STRING;
return SetLength(len, output + 1) + 1;
}
/* Write a set header to output */
-WOLFSSL_LOCAL word32 SetSet(word32 len, byte* output)
+word32 SetSet(word32 len, byte* output)
{
output[0] = ASN_SET | ASN_CONSTRUCTED;
return SetLength(len, output + 1) + 1;
}
-WOLFSSL_LOCAL word32 SetImplicit(byte tag, byte number, word32 len, byte* output)
+word32 SetImplicit(byte tag, byte number, word32 len, byte* output)
{
output[0] = ((tag == ASN_SEQUENCE || tag == ASN_SET) ? ASN_CONSTRUCTED : 0)
@@ -2621,323 +6731,121 @@ WOLFSSL_LOCAL word32 SetImplicit(byte tag, byte number, word32 len, byte* output
return SetLength(len, output + 1) + 1;
}
-WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output)
+word32 SetExplicit(byte number, word32 len, byte* output)
{
output[0] = ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | number;
return SetLength(len, output + 1) + 1;
}
-#if defined(HAVE_ECC) && (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))
+#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
-static word32 SetCurve(ecc_key* key, byte* output)
+static int SetCurve(ecc_key* key, byte* output)
{
-
- /* curve types */
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192)
- static const byte ECC_192v1_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
- 0x03, 0x01, 0x01};
-#endif
-#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256)
- static const byte ECC_256v1_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
- 0x03, 0x01, 0x07};
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160)
- static const byte ECC_160r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
- 0x02};
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224)
- static const byte ECC_224r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
- 0x21};
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384)
- static const byte ECC_384r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
- 0x22};
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521)
- static const byte ECC_521r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
- 0x23};
-#endif
-
- int oidSz = 0;
- int idx = 0;
- int lenSz = 0;
- const byte* oid = 0;
-
- output[0] = ASN_OBJECT_ID;
- idx++;
-
- switch (key->dp->size) {
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160)
- case 20:
- oidSz = sizeof(ECC_160r1_AlgoID);
- oid = ECC_160r1_AlgoID;
- break;
-#endif
-
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192)
- case 24:
- oidSz = sizeof(ECC_192v1_AlgoID);
- oid = ECC_192v1_AlgoID;
- break;
-#endif
-
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224)
- case 28:
- oidSz = sizeof(ECC_224r1_AlgoID);
- oid = ECC_224r1_AlgoID;
- break;
+#ifdef HAVE_OID_ENCODING
+ int ret;
#endif
+ int idx = 0;
+ word32 oidSz = 0;
-#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256)
- case 32:
- oidSz = sizeof(ECC_256v1_AlgoID);
- oid = ECC_256v1_AlgoID;
- break;
-#endif
+ /* validate key */
+ if (key == NULL || key->dp == NULL) {
+ return BAD_FUNC_ARG;
+ }
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384)
- case 48:
- oidSz = sizeof(ECC_384r1_AlgoID);
- oid = ECC_384r1_AlgoID;
- break;
+#ifdef HAVE_OID_ENCODING
+ ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, NULL, &oidSz);
+ if (ret != 0) {
+ return ret;
+ }
+#else
+ oidSz = key->dp->oidSz;
#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521)
- case 66:
- oidSz = sizeof(ECC_521r1_AlgoID);
- oid = ECC_521r1_AlgoID;
- break;
-#endif
+ idx += SetObjectId(oidSz, output);
- default:
- return ASN_UNKNOWN_OID_E;
+#ifdef HAVE_OID_ENCODING
+ ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, output+idx, &oidSz);
+ if (ret != 0) {
+ return ret;
}
- lenSz = SetLength(oidSz, output+idx);
- idx += lenSz;
-
- XMEMCPY(output+idx, oid, oidSz);
+#else
+ XMEMCPY(output+idx, key->dp->oid, oidSz);
+#endif
idx += oidSz;
return idx;
}
-#endif /* HAVE_ECC && WOLFSSL_CERT_GEN */
+#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */
-WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
+#ifdef HAVE_ECC
+static WC_INLINE int IsSigAlgoECDSA(int algoOID)
{
- /* adding TAG_NULL and 0 to end */
-
- /* hashTypes */
- static const byte shaAlgoID[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a,
- 0x05, 0x00 };
- static const byte sha256AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
- 0x04, 0x02, 0x01, 0x05, 0x00 };
- static const byte sha384AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
- 0x04, 0x02, 0x02, 0x05, 0x00 };
- static const byte sha512AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
- 0x04, 0x02, 0x03, 0x05, 0x00 };
- static const byte md5AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x02, 0x05, 0x05, 0x00 };
- static const byte md2AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x02, 0x02, 0x05, 0x00};
-
- /* blkTypes, no NULL tags because IV is there instead */
- static const byte desCbcAlgoID[] = { 0x2B, 0x0E, 0x03, 0x02, 0x07 };
- static const byte des3CbcAlgoID[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x03, 0x07 };
-
- /* RSA sigTypes */
- #ifndef NO_RSA
- static const byte md5wRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00};
- static const byte shawRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00};
- static const byte sha256wRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00};
- static const byte sha384wRSA_AlgoID[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00};
- static const byte sha512wRSA_AlgoID[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00};
- #endif /* NO_RSA */
-
- /* ECDSA sigTypes */
- #ifdef HAVE_ECC
- static const byte shawECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
- 0x04, 0x01, 0x05, 0x00};
- static const byte sha256wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d,
- 0x04, 0x03, 0x02, 0x05, 0x00};
- static const byte sha384wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d,
- 0x04, 0x03, 0x03, 0x05, 0x00};
- static const byte sha512wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d,
- 0x04, 0x03, 0x04, 0x05, 0x00};
- #endif /* HAVE_ECC */
-
- /* RSA keyType */
- #ifndef NO_RSA
- static const byte RSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x01, 0x05, 0x00};
- #endif /* NO_RSA */
+ /* ECDSA sigAlgo must not have ASN1 NULL parameters */
+ if (algoOID == CTC_SHAwECDSA || algoOID == CTC_SHA256wECDSA ||
+ algoOID == CTC_SHA384wECDSA || algoOID == CTC_SHA512wECDSA) {
+ return 1;
+ }
- #ifdef HAVE_ECC
- /* ECC keyType */
- /* no tags, so set tagSz smaller later */
- static const byte ECC_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
- 0x02, 0x01};
- #endif /* HAVE_ECC */
+ return 0;
+}
+#endif
- int algoSz = 0;
- int tagSz = 2; /* tag null and terminator */
- word32 idSz, seqSz;
+word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
+{
+ word32 tagSz, idSz, seqSz, algoSz = 0;
const byte* algoName = 0;
- byte ID_Length[MAX_LENGTH_SZ];
- byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */
-
- if (type == hashType) {
- switch (algoOID) {
- case SHAh:
- algoSz = sizeof(shaAlgoID);
- algoName = shaAlgoID;
- break;
-
- case SHA256h:
- algoSz = sizeof(sha256AlgoID);
- algoName = sha256AlgoID;
- break;
-
- case SHA384h:
- algoSz = sizeof(sha384AlgoID);
- algoName = sha384AlgoID;
- break;
-
- case SHA512h:
- algoSz = sizeof(sha512AlgoID);
- algoName = sha512AlgoID;
- break;
+ byte ID_Length[1 + MAX_LENGTH_SZ];
+ byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */
+ int length = 0;
+
+ tagSz = (type == oidHashType ||
+ (type == oidSigType
+ #ifdef HAVE_ECC
+ && !IsSigAlgoECDSA(algoOID)
+ #endif
+ #ifdef HAVE_ED25519
+ && algoOID != ED25519k
+ #endif
+ #ifdef HAVE_ED448
+ && algoOID != ED448k
+ #endif
+ ) ||
+ (type == oidKeyType && algoOID == RSAk)) ? 2 : 0;
- case MD2h:
- algoSz = sizeof(md2AlgoID);
- algoName = md2AlgoID;
- break;
+ algoName = OidFromId(algoOID, type, &algoSz);
- case MD5h:
- algoSz = sizeof(md5AlgoID);
- algoName = md5AlgoID;
- break;
-
- default:
- WOLFSSL_MSG("Unknown Hash Algo");
- return 0; /* UNKOWN_HASH_E; */
- }
- }
- else if (type == blkType) {
- switch (algoOID) {
- case DESb:
- algoSz = sizeof(desCbcAlgoID);
- algoName = desCbcAlgoID;
- tagSz = 0;
- break;
- case DES3b:
- algoSz = sizeof(des3CbcAlgoID);
- algoName = des3CbcAlgoID;
- tagSz = 0;
- break;
- default:
- WOLFSSL_MSG("Unknown Block Algo");
- return 0;
- }
+ if (algoName == NULL) {
+ WOLFSSL_MSG("Unknown Algorithm");
+ return 0;
}
- else if (type == sigType) { /* sigType */
- switch (algoOID) {
- #ifndef NO_RSA
- case CTC_MD5wRSA:
- algoSz = sizeof(md5wRSA_AlgoID);
- algoName = md5wRSA_AlgoID;
- break;
- case CTC_SHAwRSA:
- algoSz = sizeof(shawRSA_AlgoID);
- algoName = shawRSA_AlgoID;
- break;
-
- case CTC_SHA256wRSA:
- algoSz = sizeof(sha256wRSA_AlgoID);
- algoName = sha256wRSA_AlgoID;
- break;
-
- case CTC_SHA384wRSA:
- algoSz = sizeof(sha384wRSA_AlgoID);
- algoName = sha384wRSA_AlgoID;
- break;
-
- case CTC_SHA512wRSA:
- algoSz = sizeof(sha512wRSA_AlgoID);
- algoName = sha512wRSA_AlgoID;
- break;
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- case CTC_SHAwECDSA:
- algoSz = sizeof(shawECDSA_AlgoID);
- algoName = shawECDSA_AlgoID;
- break;
-
- case CTC_SHA256wECDSA:
- algoSz = sizeof(sha256wECDSA_AlgoID);
- algoName = sha256wECDSA_AlgoID;
- break;
-
- case CTC_SHA384wECDSA:
- algoSz = sizeof(sha384wECDSA_AlgoID);
- algoName = sha384wECDSA_AlgoID;
- break;
+ idSz = SetObjectId(algoSz, ID_Length);
+ seqSz = SetSequence(idSz + algoSz + tagSz + curveSz, seqArray);
- case CTC_SHA512wECDSA:
- algoSz = sizeof(sha512wECDSA_AlgoID);
- algoName = sha512wECDSA_AlgoID;
- break;
- #endif /* HAVE_ECC */
- default:
- WOLFSSL_MSG("Unknown Signature Algo");
- return 0;
- }
- }
- else if (type == keyType) { /* keyType */
- switch (algoOID) {
- #ifndef NO_RSA
- case RSAk:
- algoSz = sizeof(RSA_AlgoID);
- algoName = RSA_AlgoID;
- break;
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- case ECDSAk:
- algoSz = sizeof(ECC_AlgoID);
- algoName = ECC_AlgoID;
- tagSz = 0;
- break;
- #endif /* HAVE_ECC */
- default:
- WOLFSSL_MSG("Unknown Key Algo");
- return 0;
- }
+ /* Copy only algo to output for DSA keys */
+ if (algoOID == DSAk && output) {
+ XMEMCPY(output, ID_Length, idSz);
+ XMEMCPY(output + idSz, algoName, algoSz);
+ if (tagSz == 2)
+ SetASNNull(&output[seqSz + idSz + algoSz]);
}
- else {
- WOLFSSL_MSG("Unknown Algo type");
- return 0;
+ else if (output) {
+ XMEMCPY(output, seqArray, seqSz);
+ XMEMCPY(output + seqSz, ID_Length, idSz);
+ XMEMCPY(output + seqSz + idSz, algoName, algoSz);
+ if (tagSz == 2)
+ SetASNNull(&output[seqSz + idSz + algoSz]);
}
- idSz = SetLength(algoSz - tagSz, ID_Length); /* don't include tags */
- seqSz = SetSequence(idSz + algoSz + 1 + curveSz, seqArray);
- /* +1 for object id, curveID of curveSz follows for ecc */
- seqArray[seqSz++] = ASN_OBJECT_ID;
-
- XMEMCPY(output, seqArray, seqSz);
- XMEMCPY(output + seqSz, ID_Length, idSz);
- XMEMCPY(output + seqSz + idSz, algoName, algoSz);
-
- return seqSz + idSz + algoSz;
+ if (algoOID == DSAk)
+ length = idSz + algoSz + tagSz;
+ else
+ length = seqSz + idSz + algoSz + tagSz;
+ return length;
}
@@ -2950,7 +6858,7 @@ word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz,
word32 encDigSz, algoSz, seqSz;
encDigSz = SetDigest(digest, digSz, digArray);
- algoSz = SetAlgoID(hashOID, algoArray, hashType, 0);
+ algoSz = SetAlgoID(hashOID, algoArray, oidHashType, 0);
seqSz = SetSequence(encDigSz + algoSz, seqArray);
XMEMCPY(out, seqArray, seqSz);
@@ -2961,288 +6869,569 @@ word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz,
}
+#ifndef NO_CERTS
+
int wc_GetCTC_HashOID(int type)
{
- switch (type) {
-#ifdef WOLFSSL_MD2
- case MD2:
- return MD2h;
-#endif
-#ifndef NO_MD5
- case MD5:
- return MD5h;
-#endif
-#ifndef NO_SHA
- case SHA:
- return SHAh;
-#endif
-#ifndef NO_SHA256
- case SHA256:
- return SHA256h;
-#endif
-#ifdef WOLFSSL_SHA384
- case SHA384:
- return SHA384h;
-#endif
-#ifdef WOLFSSL_SHA512
- case SHA512:
- return SHA512h;
-#endif
- default:
- return 0;
- };
+ int ret;
+ enum wc_HashType hType;
+
+ hType = wc_HashTypeConvert(type);
+ ret = wc_HashGetOID(hType);
+ if (ret < 0)
+ ret = 0; /* backwards compatibility */
+
+ return ret;
}
+void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId)
+{
+ if (sigCtx) {
+ XMEMSET(sigCtx, 0, sizeof(SignatureCtx));
+ sigCtx->devId = devId;
+ sigCtx->heap = heap;
+ }
+}
-/* return true (1) or false (0) for Confirmation */
-static int ConfirmSignature(const byte* buf, word32 bufSz,
- const byte* key, word32 keySz, word32 keyOID,
- const byte* sig, word32 sigSz, word32 sigOID,
- void* heap)
+void FreeSignatureCtx(SignatureCtx* sigCtx)
{
- int typeH = 0, digestSz = 0, ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
- byte* digest;
-#else
- byte digest[MAX_DIGEST_SIZE];
-#endif
+ if (sigCtx == NULL)
+ return;
-#ifdef WOLFSSL_SMALL_STACK
- digest = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (digest == NULL)
- return 0; /* not confirmed */
+ if (sigCtx->digest) {
+ XFREE(sigCtx->digest, sigCtx->heap, DYNAMIC_TYPE_DIGEST);
+ sigCtx->digest = NULL;
+ }
+#ifndef NO_RSA
+ if (sigCtx->plain) {
+ XFREE(sigCtx->plain, sigCtx->heap, DYNAMIC_TYPE_SIGNATURE);
+ sigCtx->plain = NULL;
+ }
+#endif
+#ifndef NO_ASN_CRYPT
+ if (sigCtx->key.ptr) {
+ switch (sigCtx->keyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ wc_FreeRsaKey(sigCtx->key.rsa);
+ XFREE(sigCtx->key.ptr, sigCtx->heap, DYNAMIC_TYPE_RSA);
+ break;
+ #endif /* !NO_RSA */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ wc_ecc_free(sigCtx->key.ecc);
+ XFREE(sigCtx->key.ecc, sigCtx->heap, DYNAMIC_TYPE_ECC);
+ break;
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ wc_ed25519_free(sigCtx->key.ed25519);
+ XFREE(sigCtx->key.ed25519, sigCtx->heap, DYNAMIC_TYPE_ED25519);
+ break;
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ED448k:
+ wc_ed448_free(sigCtx->key.ed448);
+ XFREE(sigCtx->key.ed448, sigCtx->heap, DYNAMIC_TYPE_ED448);
+ break;
+ #endif /* HAVE_ED448 */
+ default:
+ break;
+ } /* switch (keyOID) */
+ sigCtx->key.ptr = NULL;
+ }
#endif
- (void)key;
- (void)keySz;
- (void)sig;
- (void)sigSz;
- (void)heap;
+ /* reset state, we are done */
+ sigCtx->state = SIG_STATE_BEGIN;
+}
+
+#ifndef NO_ASN_CRYPT
+static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID,
+ byte* digest, int* typeH, int* digestSz, int verify)
+{
+ int ret = 0;
+
+ (void)verify;
switch (sigOID) {
- #ifndef NO_MD5
- case CTC_MD5wRSA:
- if (wc_Md5Hash(buf, bufSz, digest) == 0) {
- typeH = MD5h;
- digestSz = MD5_DIGEST_SIZE;
- }
- break;
- #endif
#if defined(WOLFSSL_MD2)
case CTC_MD2wRSA:
- if (wc_Md2Hash(buf, bufSz, digest) == 0) {
- typeH = MD2h;
- digestSz = MD2_DIGEST_SIZE;
- }
+ if (!verify) {
+ ret = HASH_TYPE_E;
+ WOLFSSL_MSG("MD2 not supported for signing");
+ }
+ else if ((ret = wc_Md2Hash(buf, bufSz, digest)) == 0) {
+ *typeH = MD2h;
+ *digestSz = MD2_DIGEST_SIZE;
+ }
break;
#endif
+ #ifndef NO_MD5
+ case CTC_MD5wRSA:
+ if ((ret = wc_Md5Hash(buf, bufSz, digest)) == 0) {
+ *typeH = MD5h;
+ *digestSz = WC_MD5_DIGEST_SIZE;
+ }
+ break;
+ #endif
#ifndef NO_SHA
case CTC_SHAwRSA:
case CTC_SHAwDSA:
case CTC_SHAwECDSA:
- if (wc_ShaHash(buf, bufSz, digest) == 0) {
- typeH = SHAh;
- digestSz = SHA_DIGEST_SIZE;
- }
- break;
+ if ((ret = wc_ShaHash(buf, bufSz, digest)) == 0) {
+ *typeH = SHAh;
+ *digestSz = WC_SHA_DIGEST_SIZE;
+ }
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case CTC_SHA224wRSA:
+ case CTC_SHA224wECDSA:
+ if ((ret = wc_Sha224Hash(buf, bufSz, digest)) == 0) {
+ *typeH = SHA224h;
+ *digestSz = WC_SHA224_DIGEST_SIZE;
+ }
+ break;
#endif
#ifndef NO_SHA256
case CTC_SHA256wRSA:
case CTC_SHA256wECDSA:
- if (wc_Sha256Hash(buf, bufSz, digest) == 0) {
- typeH = SHA256h;
- digestSz = SHA256_DIGEST_SIZE;
- }
- break;
+ if ((ret = wc_Sha256Hash(buf, bufSz, digest)) == 0) {
+ *typeH = SHA256h;
+ *digestSz = WC_SHA256_DIGEST_SIZE;
+ }
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case CTC_SHA384wRSA:
+ case CTC_SHA384wECDSA:
+ if ((ret = wc_Sha384Hash(buf, bufSz, digest)) == 0) {
+ *typeH = SHA384h;
+ *digestSz = WC_SHA384_DIGEST_SIZE;
+ }
+ break;
#endif
#ifdef WOLFSSL_SHA512
case CTC_SHA512wRSA:
case CTC_SHA512wECDSA:
- if (wc_Sha512Hash(buf, bufSz, digest) == 0) {
- typeH = SHA512h;
- digestSz = SHA512_DIGEST_SIZE;
- }
- break;
+ if ((ret = wc_Sha512Hash(buf, bufSz, digest)) == 0) {
+ *typeH = SHA512h;
+ *digestSz = WC_SHA512_DIGEST_SIZE;
+ }
+ break;
#endif
- #ifdef WOLFSSL_SHA384
- case CTC_SHA384wRSA:
- case CTC_SHA384wECDSA:
- if (wc_Sha384Hash(buf, bufSz, digest) == 0) {
- typeH = SHA384h;
- digestSz = SHA384_DIGEST_SIZE;
- }
- break;
+ #ifdef HAVE_ED25519
+ case CTC_ED25519:
+ /* Hashes done in signing operation.
+ * Two dependent hashes with prefixes performed.
+ */
+ break;
+ #endif
+ #ifdef HAVE_ED448
+ case CTC_ED448:
+ /* Hashes done in signing operation.
+ * Two dependent hashes with prefixes performed.
+ */
+ break;
#endif
default:
- WOLFSSL_MSG("Verify Signautre has unsupported type");
+ ret = HASH_TYPE_E;
+ WOLFSSL_MSG("Hash for Signature has unsupported type");
}
-
- if (typeH == 0) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return ret;
+}
+#endif /* !NO_ASN_CRYPT */
+
+/* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */
+static int ConfirmSignature(SignatureCtx* sigCtx,
+ const byte* buf, word32 bufSz,
+ const byte* key, word32 keySz, word32 keyOID,
+ const byte* sig, word32 sigSz, word32 sigOID, byte* rsaKeyIdx)
+{
+ int ret = 0;
+#ifndef WOLFSSL_RENESAS_TSIP_TLS
+ (void)rsaKeyIdx;
#endif
- return 0; /* not confirmed */
+ if (sigCtx == NULL || buf == NULL || bufSz == 0 || key == NULL ||
+ keySz == 0 || sig == NULL || sigSz == 0) {
+ return BAD_FUNC_ARG;
}
- switch (keyOID) {
- #ifndef NO_RSA
- case RSAk:
+ (void)key;
+ (void)keySz;
+ (void)sig;
+ (void)sigSz;
+
+ WOLFSSL_ENTER("ConfirmSignature");
+
+#ifndef NO_ASN_CRYPT
+ switch (sigCtx->state) {
+ case SIG_STATE_BEGIN:
{
- word32 idx = 0;
- int encodedSigSz, verifySz;
- byte* out;
-#ifdef WOLFSSL_SMALL_STACK
- RsaKey* pubKey;
- byte* plain;
- byte* encodedSig;
-#else
- RsaKey pubKey[1];
- byte plain[MAX_ENCODED_SIG_SZ];
- byte encodedSig[MAX_ENCODED_SIG_SZ];
-#endif
+ sigCtx->keyOID = keyOID; /* must set early for cleanup */
-#ifdef WOLFSSL_SMALL_STACK
- pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
-
- if (pubKey == NULL || plain == NULL || encodedSig == NULL) {
- WOLFSSL_MSG("Failed to allocate memory at ConfirmSignature");
-
- if (pubKey)
- XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (plain)
- XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (encodedSig)
- XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
- break; /* not confirmed */
+ sigCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, sigCtx->heap,
+ DYNAMIC_TYPE_DIGEST);
+ if (sigCtx->digest == NULL) {
+ ERROR_OUT(MEMORY_E, exit_cs);
}
-#endif
- if (sigSz > MAX_ENCODED_SIG_SZ) {
- WOLFSSL_MSG("Verify Signautre is too big");
+ sigCtx->state = SIG_STATE_HASH;
+ } /* SIG_STATE_BEGIN */
+ FALL_THROUGH;
+
+ case SIG_STATE_HASH:
+ {
+ ret = HashForSignature(buf, bufSz, sigOID, sigCtx->digest,
+ &sigCtx->typeH, &sigCtx->digestSz, 1);
+ if (ret != 0) {
+ goto exit_cs;
}
- else if (wc_InitRsaKey(pubKey, heap) != 0) {
- WOLFSSL_MSG("InitRsaKey failed");
+
+ sigCtx->state = SIG_STATE_KEY;
+ } /* SIG_STATE_HASH */
+ FALL_THROUGH;
+
+ case SIG_STATE_KEY:
+ {
+ switch (keyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ {
+ word32 idx = 0;
+
+ sigCtx->key.rsa = (RsaKey*)XMALLOC(sizeof(RsaKey),
+ sigCtx->heap, DYNAMIC_TYPE_RSA);
+ sigCtx->plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
+ sigCtx->heap, DYNAMIC_TYPE_SIGNATURE);
+ if (sigCtx->key.rsa == NULL || sigCtx->plain == NULL) {
+ ERROR_OUT(MEMORY_E, exit_cs);
+ }
+ if ((ret = wc_InitRsaKey_ex(sigCtx->key.rsa, sigCtx->heap,
+ sigCtx->devId)) != 0) {
+ goto exit_cs;
+ }
+ if (sigSz > MAX_ENCODED_SIG_SZ) {
+ WOLFSSL_MSG("Verify Signature is too big");
+ ERROR_OUT(BUFFER_E, exit_cs);
+ }
+ if ((ret = wc_RsaPublicKeyDecode(key, &idx, sigCtx->key.rsa,
+ keySz)) != 0) {
+ WOLFSSL_MSG("ASN Key decode error RSA");
+ goto exit_cs;
+ }
+ XMEMCPY(sigCtx->plain, sig, sigSz);
+ sigCtx->out = NULL;
+
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ sigCtx->asyncDev = &sigCtx->key.rsa->asyncDev;
+ #endif
+ break;
+ }
+ #endif /* !NO_RSA */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ {
+ word32 idx = 0;
+
+ sigCtx->verify = 0;
+ sigCtx->key.ecc = (ecc_key*)XMALLOC(sizeof(ecc_key),
+ sigCtx->heap, DYNAMIC_TYPE_ECC);
+ if (sigCtx->key.ecc == NULL) {
+ ERROR_OUT(MEMORY_E, exit_cs);
+ }
+ if ((ret = wc_ecc_init_ex(sigCtx->key.ecc, sigCtx->heap,
+ sigCtx->devId)) < 0) {
+ goto exit_cs;
+ }
+ ret = wc_EccPublicKeyDecode(key, &idx, sigCtx->key.ecc,
+ keySz);
+ if (ret < 0) {
+ WOLFSSL_MSG("ASN Key import error ECC");
+ goto exit_cs;
+ }
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ sigCtx->asyncDev = &sigCtx->key.ecc->asyncDev;
+ #endif
+ break;
+ }
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ {
+ sigCtx->verify = 0;
+ sigCtx->key.ed25519 = (ed25519_key*)XMALLOC(
+ sizeof(ed25519_key), sigCtx->heap,
+ DYNAMIC_TYPE_ED25519);
+ if (sigCtx->key.ed25519 == NULL) {
+ ERROR_OUT(MEMORY_E, exit_cs);
+ }
+ if ((ret = wc_ed25519_init(sigCtx->key.ed25519)) < 0) {
+ goto exit_cs;
+ }
+ if ((ret = wc_ed25519_import_public(key, keySz,
+ sigCtx->key.ed25519)) < 0) {
+ WOLFSSL_MSG("ASN Key import error ED25519");
+ goto exit_cs;
+ }
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ sigCtx->asyncDev = &sigCtx->key.ed25519->asyncDev;
+ #endif
+ break;
+ }
+ #endif
+ #ifdef HAVE_ED448
+ case ED448k:
+ {
+ sigCtx->verify = 0;
+ sigCtx->key.ed448 = (ed448_key*)XMALLOC(
+ sizeof(ed448_key), sigCtx->heap,
+ DYNAMIC_TYPE_ED448);
+ if (sigCtx->key.ed448 == NULL) {
+ ERROR_OUT(MEMORY_E, exit_cs);
+ }
+ if ((ret = wc_ed448_init(sigCtx->key.ed448)) < 0) {
+ goto exit_cs;
+ }
+ if ((ret = wc_ed448_import_public(key, keySz,
+ sigCtx->key.ed448)) < 0) {
+ WOLFSSL_MSG("ASN Key import error ED448");
+ goto exit_cs;
+ }
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ sigCtx->asyncDev = &sigCtx->key.ed448->asyncDev;
+ #endif
+ break;
+ }
+ #endif
+ default:
+ WOLFSSL_MSG("Verify Key type unknown");
+ ret = ASN_UNKNOWN_OID_E;
+ break;
+ } /* switch (keyOID) */
+
+ if (ret != 0) {
+ goto exit_cs;
}
- else if (wc_RsaPublicKeyDecode(key, &idx, pubKey, keySz) < 0) {
- WOLFSSL_MSG("ASN Key decode error RSA");
+
+ sigCtx->state = SIG_STATE_DO;
+
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (sigCtx->devId != INVALID_DEVID && sigCtx->asyncDev && sigCtx->asyncCtx) {
+ /* make sure event is initialized */
+ WOLF_EVENT* event = &sigCtx->asyncDev->event;
+ ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL,
+ sigCtx->asyncCtx, WC_ASYNC_FLAG_CALL_AGAIN);
}
- else {
- XMEMCPY(plain, sig, sigSz);
+ #endif
+ } /* SIG_STATE_KEY */
+ FALL_THROUGH;
- if ((verifySz = wc_RsaSSL_VerifyInline(plain, sigSz, &out,
- pubKey)) < 0) {
- WOLFSSL_MSG("Rsa SSL verify error");
+ case SIG_STATE_DO:
+ {
+ switch (keyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ {
+ #ifdef HAVE_PK_CALLBACKS
+ if (sigCtx->pkCbRsa) {
+ ret = sigCtx->pkCbRsa(
+ sigCtx->plain, sigSz, &sigCtx->out,
+ key, keySz,
+ sigCtx->pkCtxRsa);
+ }
+ else
+ #endif /* HAVE_PK_CALLBACKS */
+ {
+ #ifdef WOLFSSL_RENESAS_TSIP_TLS
+ if (rsaKeyIdx != NULL)
+ {
+ ret = tsip_tls_CertVerify(buf, bufSz, sigCtx->plain,
+ sigSz,
+ sigCtx->pubkey_n_start - sigCtx->certBegin,
+ sigCtx->pubkey_n_len - 1,
+ sigCtx->pubkey_e_start - sigCtx->certBegin,
+ sigCtx->pubkey_e_len - 1,
+ rsaKeyIdx);
+
+ if (ret == 0){
+ sigCtx->verifyByTSIP = 1;
+ ret = 0;
+ } else {
+ WOLFSSL_MSG("RSA Verify by tsip didn't match");
+ ret = ASN_SIG_CONFIRM_E;
+ }
+ } else
+ #endif
+ ret = wc_RsaSSL_VerifyInline(sigCtx->plain, sigSz,
+ &sigCtx->out, sigCtx->key.rsa);
+ }
+ break;
}
- else {
- /* make sure we're right justified */
- encodedSigSz =
- wc_EncodeSignature(encodedSig, digest, digestSz, typeH);
- if (encodedSigSz != verifySz ||
- XMEMCMP(out, encodedSig, encodedSigSz) != 0) {
- WOLFSSL_MSG("Rsa SSL verify match encode error");
+ #endif /* !NO_RSA */
+ #if defined(HAVE_ECC)
+ case ECDSAk:
+ {
+ #ifdef HAVE_PK_CALLBACKS
+ if (sigCtx->pkCbEcc) {
+ ret = sigCtx->pkCbEcc(
+ sig, sigSz,
+ sigCtx->digest, sigCtx->digestSz,
+ key, keySz, &sigCtx->verify,
+ sigCtx->pkCtxEcc);
}
else
- ret = 1; /* match */
-
- #ifdef WOLFSSL_DEBUG_ENCODING
+ #endif /* HAVE_PK_CALLBACKS */
{
- int x;
-
- printf("wolfssl encodedSig:\n");
+ ret = wc_ecc_verify_hash(sig, sigSz, sigCtx->digest,
+ sigCtx->digestSz, &sigCtx->verify,
+ sigCtx->key.ecc);
+ }
+ break;
+ }
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ {
+ ret = wc_ed25519_verify_msg(sig, sigSz, buf, bufSz,
+ &sigCtx->verify, sigCtx->key.ed25519);
+ break;
+ }
+ #endif
+ #ifdef HAVE_ED448
+ case ED448k:
+ {
+ ret = wc_ed448_verify_msg(sig, sigSz, buf, bufSz,
+ &sigCtx->verify, sigCtx->key.ed448,
+ NULL, 0);
+ break;
+ }
+ #endif
+ default:
+ break;
+ } /* switch (keyOID) */
- for (x = 0; x < encodedSigSz; x++) {
- printf("%02x ", encodedSig[x]);
- if ( (x % 16) == 15)
- printf("\n");
- }
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ goto exit_cs;
+ }
+ #endif
- printf("\n");
- printf("actual digest:\n");
+ if (ret < 0) {
+ /* treat all RSA errors as ASN_SIG_CONFIRM_E */
+ ret = ASN_SIG_CONFIRM_E;
+ goto exit_cs;
+ }
- for (x = 0; x < verifySz; x++) {
- printf("%02x ", out[x]);
- if ( (x % 16) == 15)
- printf("\n");
- }
+ sigCtx->state = SIG_STATE_CHECK;
+ } /* SIG_STATE_DO */
+ FALL_THROUGH;
- printf("\n");
+ case SIG_STATE_CHECK:
+ {
+ switch (keyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ {
+ int encodedSigSz, verifySz;
+ #ifdef WOLFSSL_RENESAS_TSIP
+ if (sigCtx->verifyByTSIP == 1) break;
+ #endif
+ #ifdef WOLFSSL_SMALL_STACK
+ byte* encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
+ sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (encodedSig == NULL) {
+ ERROR_OUT(MEMORY_E, exit_cs);
}
- #endif /* WOLFSSL_DEBUG_ENCODING */
+ #else
+ byte encodedSig[MAX_ENCODED_SIG_SZ];
+ #endif
- }
+ verifySz = ret;
- }
+ /* make sure we're right justified */
+ encodedSigSz = wc_EncodeSignature(encodedSig,
+ sigCtx->digest, sigCtx->digestSz, sigCtx->typeH);
+ if (encodedSigSz == verifySz && sigCtx->out != NULL &&
+ XMEMCMP(sigCtx->out, encodedSig, encodedSigSz) == 0) {
+ ret = 0;
+ }
+ else {
+ WOLFSSL_MSG("RSA SSL verify match encode error");
+ ret = ASN_SIG_CONFIRM_E;
+ }
- wc_FreeRsaKey(pubKey);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(encodedSig, sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ break;
+ }
+ #endif /* NO_RSA */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ {
+ if (sigCtx->verify == 1) {
+ ret = 0;
+ }
+ else {
+ WOLFSSL_MSG("ECC Verify didn't match");
+ ret = ASN_SIG_CONFIRM_E;
+ }
+ break;
+ }
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ {
+ if (sigCtx->verify == 1) {
+ ret = 0;
+ }
+ else {
+ WOLFSSL_MSG("ED25519 Verify didn't match");
+ ret = ASN_SIG_CONFIRM_E;
+ }
+ break;
+ }
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ED448k:
+ {
+ if (sigCtx->verify == 1) {
+ ret = 0;
+ }
+ else {
+ WOLFSSL_MSG("ED448 Verify didn't match");
+ ret = ASN_SIG_CONFIRM_E;
+ }
+ break;
+ }
+ #endif /* HAVE_ED448 */
+ default:
+ break;
+ } /* switch (keyOID) */
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
break;
- }
+ } /* SIG_STATE_CHECK */
+ } /* switch (sigCtx->state) */
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- case ECDSAk:
- {
- int verify = 0;
-#ifdef WOLFSSL_SMALL_STACK
- ecc_key* pubKey;
-#else
- ecc_key pubKey[1];
-#endif
+exit_cs:
-#ifdef WOLFSSL_SMALL_STACK
- pubKey = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (pubKey == NULL) {
- WOLFSSL_MSG("Failed to allocate pubKey");
- break; /* not confirmed */
- }
-#endif
+#endif /* !NO_ASN_CRYPT */
- if (wc_ecc_init(pubKey) < 0) {
- WOLFSSL_MSG("Failed to initialize key");
- break; /* not confirmed */
- }
- if (wc_ecc_import_x963(key, keySz, pubKey) < 0) {
- WOLFSSL_MSG("ASN Key import error ECC");
- }
- else {
- if (wc_ecc_verify_hash(sig, sigSz, digest, digestSz, &verify,
- pubKey) != 0) {
- WOLFSSL_MSG("ECC verify hash error");
- }
- else if (1 != verify) {
- WOLFSSL_MSG("ECC Verify didn't match");
- } else
- ret = 1; /* match */
+ (void)keyOID;
+ (void)sigOID;
- }
- wc_ecc_free(pubKey);
+ WOLFSSL_LEAVE("ConfirmSignature", ret);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- break;
- }
- #endif /* HAVE_ECC */
- default:
- WOLFSSL_MSG("Verify Key type unknown");
- }
-
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E)
+ return ret;
#endif
+ FreeSignatureCtx(sigCtx);
+
return ret;
}
@@ -3250,7 +7439,7 @@ static int ConfirmSignature(const byte* buf, word32 bufSz,
#ifndef IGNORE_NAME_CONSTRAINTS
static int MatchBaseName(int type, const char* name, int nameSz,
- const char* base, int baseSz)
+ const char* base, int baseSz)
{
if (base == NULL || baseSz <= 0 || name == NULL || nameSz <= 0 ||
name[0] == '.' || nameSz < baseSz ||
@@ -3302,7 +7491,7 @@ static int MatchBaseName(int type, const char* name, int nameSz,
}
while (nameSz > 0) {
- if (XTOLOWER((unsigned char)*name++) !=
+ if (XTOLOWER((unsigned char)*name++) !=
XTOLOWER((unsigned char)*base++))
return 0;
nameSz--;
@@ -3322,34 +7511,44 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
Base_entry* base = signer->excludedNames;
while (base != NULL) {
- if (base->type == ASN_DNS_TYPE) {
- DNS_entry* name = cert->altNames;
- while (name != NULL) {
- if (MatchBaseName(ASN_DNS_TYPE,
- name->name, (int)XSTRLEN(name->name),
- base->name, base->nameSz))
- return 0;
- name = name->next;
+ switch (base->type) {
+ case ASN_DNS_TYPE:
+ {
+ DNS_entry* name = cert->altNames;
+ while (name != NULL) {
+ if (MatchBaseName(ASN_DNS_TYPE,
+ name->name, name->len,
+ base->name, base->nameSz)) {
+ return 0;
+ }
+ name = name->next;
+ }
+ break;
}
- }
- else if (base->type == ASN_RFC822_TYPE) {
- DNS_entry* name = cert->altEmailNames;
- while (name != NULL) {
- if (MatchBaseName(ASN_RFC822_TYPE,
- name->name, (int)XSTRLEN(name->name),
- base->name, base->nameSz))
- return 0;
-
- name = name->next;
+ case ASN_RFC822_TYPE:
+ {
+ DNS_entry* name = cert->altEmailNames;
+ while (name != NULL) {
+ if (MatchBaseName(ASN_RFC822_TYPE,
+ name->name, name->len,
+ base->name, base->nameSz)) {
+ return 0;
+ }
+ name = name->next;
+ }
+ break;
}
- }
- else if (base->type == ASN_DIR_TYPE) {
- if (cert->subjectRawLen == base->nameSz &&
- XMEMCMP(cert->subjectRaw, base->name, base->nameSz) == 0) {
-
- return 0;
+ case ASN_DIR_TYPE:
+ {
+ /* allow permitted dirName smaller than actual subject */
+ if (cert->subjectRawLen >= base->nameSz &&
+ XMEMCMP(cert->subjectRaw, base->name,
+ base->nameSz) == 0) {
+ return 0;
+ }
+ break;
}
- }
+ }; /* switch */
base = base->next;
}
}
@@ -3365,47 +7564,56 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
Base_entry* base = signer->permittedNames;
while (base != NULL) {
- if (base->type == ASN_DNS_TYPE) {
- DNS_entry* name = cert->altNames;
+ switch (base->type) {
+ case ASN_DNS_TYPE:
+ {
+ DNS_entry* name = cert->altNames;
- if (name != NULL)
- needDns = 1;
+ if (name != NULL)
+ needDns = 1;
- while (name != NULL) {
- matchDns = MatchBaseName(ASN_DNS_TYPE,
- name->name, (int)XSTRLEN(name->name),
+ while (name != NULL) {
+ matchDns = MatchBaseName(ASN_DNS_TYPE,
+ name->name, name->len,
base->name, base->nameSz);
- name = name->next;
+ name = name->next;
+ }
+ break;
}
- }
- else if (base->type == ASN_RFC822_TYPE) {
- DNS_entry* name = cert->altEmailNames;
+ case ASN_RFC822_TYPE:
+ {
+ DNS_entry* name = cert->altEmailNames;
- if (name != NULL)
- needEmail = 1;
+ if (name != NULL)
+ needEmail = 1;
- while (name != NULL) {
- matchEmail = MatchBaseName(ASN_DNS_TYPE,
- name->name, (int)XSTRLEN(name->name),
+ while (name != NULL) {
+ matchEmail = MatchBaseName(ASN_DNS_TYPE,
+ name->name, name->len,
base->name, base->nameSz);
- name = name->next;
+ name = name->next;
+ }
+ break;
}
- }
- else if (base->type == ASN_DIR_TYPE) {
- needDir = 1;
- if (cert->subjectRaw != NULL &&
- cert->subjectRawLen == base->nameSz &&
- XMEMCMP(cert->subjectRaw, base->name, base->nameSz) == 0) {
-
- matchDir = 1;
+ case ASN_DIR_TYPE:
+ {
+ /* allow permitted dirName smaller than actual subject */
+ needDir = 1;
+ if (cert->subjectRaw != NULL &&
+ cert->subjectRawLen >= base->nameSz &&
+ XMEMCMP(cert->subjectRaw, base->name,
+ base->nameSz) == 0) {
+ matchDir = 1;
+ }
+ break;
}
- }
+ } /* switch */
base = base->next;
}
- if ((needDns && !matchDns) || (needEmail && !matchEmail) ||
- (needDir && !matchDir)) {
-
+ if ((needDns && !matchDns) ||
+ (needEmail && !matchEmail) ||
+ (needDir && !matchDir)) {
return 0;
}
}
@@ -3415,8 +7623,7 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
#endif /* IGNORE_NAME_CONSTRAINTS */
-
-static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
+static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
int length = 0;
@@ -3428,10 +7635,17 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
return ASN_PARSE_E;
}
+ if (length == 0) {
+ /* RFC 5280 4.2.1.6. Subject Alternative Name
+ If the subjectAltName extension is present, the sequence MUST
+ contain at least one entry. */
+ return ASN_PARSE_E;
+ }
+
cert->weOwnAltNames = 1;
while (length > 0) {
- byte b = input[idx++];
+ byte b = input[idx++];
length--;
@@ -3452,17 +7666,18 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
DYNAMIC_TYPE_ALTNAME);
if (dnsEntry == NULL) {
WOLFSSL_MSG("\tOut of Memory");
- return ASN_PARSE_E;
+ return MEMORY_E;
}
+ dnsEntry->type = ASN_DNS_TYPE;
dnsEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
DYNAMIC_TYPE_ALTNAME);
if (dnsEntry->name == NULL) {
WOLFSSL_MSG("\tOut of Memory");
XFREE(dnsEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
- return ASN_PARSE_E;
+ return MEMORY_E;
}
-
+ dnsEntry->len = strLen;
XMEMCPY(dnsEntry->name, &input[idx], strLen);
dnsEntry->name[strLen] = '\0';
@@ -3472,7 +7687,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
length -= strLen;
idx += strLen;
}
-#ifndef IGNORE_NAME_CONSTRAINTS
+ #ifndef IGNORE_NAME_CONSTRAINTS
else if (b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE)) {
DNS_entry* emailEntry;
int strLen;
@@ -3488,17 +7703,18 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
DYNAMIC_TYPE_ALTNAME);
if (emailEntry == NULL) {
WOLFSSL_MSG("\tOut of Memory");
- return ASN_PARSE_E;
+ return MEMORY_E;
}
+ emailEntry->type = ASN_RFC822_TYPE;
emailEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
DYNAMIC_TYPE_ALTNAME);
if (emailEntry->name == NULL) {
WOLFSSL_MSG("\tOut of Memory");
XFREE(emailEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
- return ASN_PARSE_E;
+ return MEMORY_E;
}
-
+ emailEntry->len = strLen;
XMEMCPY(emailEntry->name, &input[idx], strLen);
emailEntry->name[strLen] = '\0';
@@ -3508,6 +7724,120 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
length -= strLen;
idx += strLen;
}
+ else if (b == (ASN_CONTEXT_SPECIFIC | ASN_URI_TYPE)) {
+ DNS_entry* uriEntry;
+ int strLen;
+ word32 lenStartIdx = idx;
+
+ WOLFSSL_MSG("\tPutting URI into list but not using");
+ if (GetLength(input, &idx, &strLen, sz) < 0) {
+ WOLFSSL_MSG("\tfail: str length");
+ return ASN_PARSE_E;
+ }
+ length -= (idx - lenStartIdx);
+
+ /* check that strLen at index is not past input buffer */
+ if (strLen + (int)idx > sz) {
+ return BUFFER_E;
+ }
+
+ #ifndef WOLFSSL_NO_ASN_STRICT
+ /* Verify RFC 5280 Sec 4.2.1.6 rule:
+ "The name MUST NOT be a relative URI" */
+
+ {
+ int i;
+
+ /* skip past scheme (i.e http,ftp,...) finding first ':' char */
+ for (i = 0; i < strLen; i++) {
+ if (input[idx + i] == ':') {
+ break;
+ }
+ if (input[idx + i] == '/') {
+ i = strLen; /* error, found relative path since '/' was
+ * encountered before ':'. Returning error
+ * value in next if statement. */
+ }
+ }
+
+ /* test if no ':' char was found and test that the next two
+ * chars are // to match the pattern "://" */
+ if (i >= strLen - 2 || (input[idx + i + 1] != '/' ||
+ input[idx + i + 2] != '/')) {
+ WOLFSSL_MSG("\tAlt Name must be absolute URI");
+ return ASN_ALT_NAME_E;
+ }
+ }
+ #endif
+
+ uriEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
+ DYNAMIC_TYPE_ALTNAME);
+ if (uriEntry == NULL) {
+ WOLFSSL_MSG("\tOut of Memory");
+ return MEMORY_E;
+ }
+
+ uriEntry->type = ASN_URI_TYPE;
+ uriEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
+ DYNAMIC_TYPE_ALTNAME);
+ if (uriEntry->name == NULL) {
+ WOLFSSL_MSG("\tOut of Memory");
+ XFREE(uriEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
+ return MEMORY_E;
+ }
+ uriEntry->len = strLen;
+ XMEMCPY(uriEntry->name, &input[idx], strLen);
+ uriEntry->name[strLen] = '\0';
+
+ uriEntry->next = cert->altNames;
+ cert->altNames = uriEntry;
+
+ length -= strLen;
+ idx += strLen;
+ }
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ else if (b == (ASN_CONTEXT_SPECIFIC | ASN_IP_TYPE)) {
+ DNS_entry* ipAddr;
+ int strLen;
+ word32 lenStartIdx = idx;
+ WOLFSSL_MSG("Decoding Subject Alt. Name: IP Address");
+
+ if (GetLength(input, &idx, &strLen, sz) < 0) {
+ WOLFSSL_MSG("\tfail: str length");
+ return ASN_PARSE_E;
+ }
+ length -= (idx - lenStartIdx);
+ /* check that strLen at index is not past input buffer */
+ if (strLen + (int)idx > sz) {
+ return BUFFER_E;
+ }
+
+ ipAddr = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
+ DYNAMIC_TYPE_ALTNAME);
+ if (ipAddr == NULL) {
+ WOLFSSL_MSG("\tOut of Memory");
+ return MEMORY_E;
+ }
+
+ ipAddr->type = ASN_IP_TYPE;
+ ipAddr->name = (char*)XMALLOC(strLen + 1, cert->heap,
+ DYNAMIC_TYPE_ALTNAME);
+ if (ipAddr->name == NULL) {
+ WOLFSSL_MSG("\tOut of Memory");
+ XFREE(ipAddr, cert->heap, DYNAMIC_TYPE_ALTNAME);
+ return MEMORY_E;
+ }
+ ipAddr->len = strLen;
+ XMEMCPY(ipAddr->name, &input[idx], strLen);
+ ipAddr->name[strLen] = '\0';
+
+ ipAddr->next = cert->altNames;
+ cert->altNames = ipAddr;
+
+ length -= strLen;
+ idx += strLen;
+ }
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
#endif /* IGNORE_NAME_CONSTRAINTS */
#ifdef WOLFSSL_SEP
else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_OTHER_TYPE))
@@ -3515,6 +7845,8 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
int strLen;
word32 lenStartIdx = idx;
word32 oid = 0;
+ int ret;
+ byte tag;
if (GetLength(input, &idx, &strLen, sz) < 0) {
WOLFSSL_MSG("\tfail: other name length");
@@ -3523,7 +7855,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
/* Consume the rest of this sequence. */
length -= (strLen + idx - lenStartIdx);
- if (GetObjectId(input, &idx, &oid, sz) < 0) {
+ if (GetObjectId(input, &idx, &oid, oidCertAltNameType, sz) < 0) {
WOLFSSL_MSG("\tbad OID");
return ASN_PARSE_E;
}
@@ -3533,7 +7865,11 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
return ASN_PARSE_E;
}
- if (input[idx++] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
+ if (GetASNTag(input, &idx, &tag, sz) < 0) {
+ return ASN_PARSE_E;
+ }
+
+ if (tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
WOLFSSL_MSG("\twrong type");
return ASN_PARSE_E;
}
@@ -3548,17 +7884,14 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
return ASN_PARSE_E;
}
- if (input[idx++] != ASN_OBJECT_ID) {
- WOLFSSL_MSG("\texpected OID");
- return ASN_PARSE_E;
- }
-
- if (GetLength(input, &idx, &strLen, sz) < 0) {
- WOLFSSL_MSG("\tfailed: str len");
- return ASN_PARSE_E;
+ ret = GetASNObjectId(input, &idx, &strLen, sz);
+ if (ret != 0) {
+ WOLFSSL_MSG("\tbad OID");
+ return ret;
}
- cert->hwType = (byte*)XMALLOC(strLen, cert->heap, 0);
+ cert->hwType = (byte*)XMALLOC(strLen, cert->heap,
+ DYNAMIC_TYPE_X509_EXT);
if (cert->hwType == NULL) {
WOLFSSL_MSG("\tOut of Memory");
return MEMORY_E;
@@ -3568,17 +7901,12 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
cert->hwTypeSz = strLen;
idx += strLen;
- if (input[idx++] != ASN_OCTET_STRING) {
- WOLFSSL_MSG("\texpected Octet String");
- return ASN_PARSE_E;
- }
-
- if (GetLength(input, &idx, &strLen, sz) < 0) {
- WOLFSSL_MSG("\tfailed: str len");
- return ASN_PARSE_E;
- }
+ ret = GetOctetString(input, &idx, &strLen, sz);
+ if (ret < 0)
+ return ret;
- cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap, 0);
+ cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap,
+ DYNAMIC_TYPE_X509_EXT);
if (cert->hwSerialNum == NULL) {
WOLFSSL_MSG("\tOut of Memory");
return MEMORY_E;
@@ -3589,7 +7917,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
cert->hwSerialNumSz = strLen;
idx += strLen;
}
-#endif /* WOLFSSL_SEP */
+ #endif /* WOLFSSL_SEP */
else {
int strLen;
word32 lenStartIdx = idx;
@@ -3607,13 +7935,14 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
return 0;
}
-
-static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert)
+static int DecodeBasicCaConstraint(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
int length = 0;
+ int ret;
WOLFSSL_ENTER("DecodeBasicCaConstraint");
+
if (GetSequence(input, &idx, &length, sz) < 0) {
WOLFSSL_MSG("\tfail: bad SEQUENCE");
return ASN_PARSE_E;
@@ -3625,40 +7954,35 @@ static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert)
/* If the basic ca constraint is false, this extension may be named, but
* left empty. So, if the length is 0, just return. */
- if (input[idx++] != ASN_BOOLEAN)
- {
- WOLFSSL_MSG("\tfail: constraint not BOOLEAN");
- return ASN_PARSE_E;
- }
+ ret = GetBoolean(input, &idx, sz);
- if (GetLength(input, &idx, &length, sz) < 0)
- {
- WOLFSSL_MSG("\tfail: length");
- return ASN_PARSE_E;
+#ifndef WOLFSSL_X509_BASICCONS_INT
+ if (ret < 0) {
+ WOLFSSL_MSG("\tfail: constraint not valid BOOLEAN");
+ return ret;
}
- if (input[idx++])
- cert->isCA = 1;
-
- #ifdef OPENSSL_EXTRA
- /* If there isn't any more data, return. */
- if (idx >= (word32)sz)
- return 0;
-
- /* Anything left should be the optional pathlength */
- if (input[idx++] != ASN_INTEGER) {
- WOLFSSL_MSG("\tfail: pathlen not INTEGER");
- return ASN_PARSE_E;
- }
+ cert->isCA = (byte)ret;
+#else
+ if (ret < 0) {
+ if(input[idx] == ASN_INTEGER) {
+ /* For OpenSSL compatibility, if ASN_INTEGER it is valid format */
+ cert->isCA = FALSE;
+ } else return ret;
+ } else
+ cert->isCA = (byte)ret;
+#endif
- if (input[idx++] != 1) {
- WOLFSSL_MSG("\tfail: pathlen too long");
- return ASN_PARSE_E;
- }
+ /* If there isn't any more data, return. */
+ if (idx >= (word32)sz) {
+ return 0;
+ }
- cert->pathLength = input[idx];
- cert->extBasicConstPlSet = 1;
- #endif /* OPENSSL_EXTRA */
+ ret = GetInteger7Bit(input, &idx, sz);
+ if (ret < 0)
+ return ret;
+ cert->pathLength = (byte)ret;
+ cert->pathLengthSet = 1;
return 0;
}
@@ -3669,10 +7993,11 @@ static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert)
#define GENERALNAME_URI 6
/* From RFC3280 SS4.2.1.7, GeneralName */
-static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert)
+static int DecodeCrlDist(const byte* input, int sz, DecodedCert* cert)
{
- word32 idx = 0;
+ word32 idx = 0, localIdx;
int length = 0;
+ byte tag = 0;
WOLFSSL_ENTER("DecodeCrlDist");
@@ -3687,20 +8012,26 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert)
/* The Distribution Point has three explicit optional members
* First check for a DistributionPointName
*/
- if (input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
+ localIdx = idx;
+ if (GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+ tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
{
idx++;
if (GetLength(input, &idx, &length, sz) < 0)
return ASN_PARSE_E;
- if (input[idx] ==
- (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CRLDP_FULL_NAME))
+ localIdx = idx;
+ if (GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+ tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED |
+ CRLDP_FULL_NAME))
{
idx++;
if (GetLength(input, &idx, &length, sz) < 0)
return ASN_PARSE_E;
- if (input[idx] == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI))
+ localIdx = idx;
+ if (GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+ tag == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI))
{
idx++;
if (GetLength(input, &idx, &length, sz) < 0)
@@ -3714,14 +8045,17 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert)
/* This isn't a URI, skip it. */
idx += length;
}
- else
+ else {
/* This isn't a FULLNAME, skip it. */
idx += length;
+ }
}
/* Check for reasonFlags */
+ localIdx = idx;
if (idx < (word32)sz &&
- input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
+ GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+ tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
{
idx++;
if (GetLength(input, &idx, &length, sz) < 0)
@@ -3730,8 +8064,10 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert)
}
/* Check for cRLIssuer */
+ localIdx = idx;
if (idx < (word32)sz &&
- input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2))
+ GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+ tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2))
{
idx++;
if (GetLength(input, &idx, &length, sz) < 0)
@@ -3749,15 +8085,16 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert)
}
-static int DecodeAuthInfo(byte* input, int sz, DecodedCert* cert)
+static int DecodeAuthInfo(const byte* input, int sz, DecodedCert* cert)
/*
- * Read the first of the Authority Information Access records. If there are
+ * Read Authority Information Access records. If there are
* any issues, return without saving the record.
*/
{
word32 idx = 0;
int length = 0;
- byte b;
+ int count = 0;
+ byte b = 0;
word32 oid;
WOLFSSL_ENTER("DecodeAuthInfo");
@@ -3766,27 +8103,43 @@ static int DecodeAuthInfo(byte* input, int sz, DecodedCert* cert)
if (GetSequence(input, &idx, &length, sz) < 0)
return ASN_PARSE_E;
- while (idx < (word32)sz) {
+ while ((idx < (word32)sz) && (count < MAX_AIA_SZ)) {
/* Unwrap a single AIA */
if (GetSequence(input, &idx, &length, sz) < 0)
return ASN_PARSE_E;
oid = 0;
- if (GetObjectId(input, &idx, &oid, sz) < 0)
+ if (GetObjectId(input, &idx, &oid, oidCertAuthInfoType, sz) < 0)
return ASN_PARSE_E;
/* Only supporting URIs right now. */
- b = input[idx++];
+ if (GetASNTag(input, &idx, &b, sz) < 0)
+ return ASN_PARSE_E;
+
if (GetLength(input, &idx, &length, sz) < 0)
return ASN_PARSE_E;
+ /* Set ocsp entry */
if (b == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI) &&
oid == AIA_OCSP_OID)
{
cert->extAuthInfoSz = length;
cert->extAuthInfo = input + idx;
+ count++;
+ #if !defined(OPENSSL_ALL) || !defined(WOLFSSL_QT)
break;
+ #endif
+ }
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ /* Set CaIssuers entry */
+ else if ((b == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI)) &&
+ oid == AIA_CA_ISSUER_OID)
+ {
+ cert->extAuthInfoCaIssuerSz = length;
+ cert->extAuthInfoCaIssuer = input + idx;
+ count++;
}
+ #endif
idx += length;
}
@@ -3794,10 +8147,11 @@ static int DecodeAuthInfo(byte* input, int sz, DecodedCert* cert)
}
-static int DecodeAuthKeyId(byte* input, int sz, DecodedCert* cert)
+static int DecodeAuthKeyId(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
int length = 0, ret = 0;
+ byte tag;
WOLFSSL_ENTER("DecodeAuthKeyId");
@@ -3806,124 +8160,107 @@ static int DecodeAuthKeyId(byte* input, int sz, DecodedCert* cert)
return ASN_PARSE_E;
}
- if (input[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) {
+ if (GetASNTag(input, &idx, &tag, sz) < 0) {
+ return ASN_PARSE_E;
+ }
+
+ if (tag != (ASN_CONTEXT_SPECIFIC | 0)) {
WOLFSSL_MSG("\tinfo: OPTIONAL item 0, not available\n");
+ cert->extAuthKeyIdSet = 0;
return 0;
}
- if (GetLength(input, &idx, &length, sz) < 0) {
+ if (GetLength(input, &idx, &length, sz) <= 0) {
WOLFSSL_MSG("\tfail: extension data length");
return ASN_PARSE_E;
}
- #ifdef OPENSSL_EXTRA
- cert->extAuthKeyIdSrc = &input[idx];
- cert->extAuthKeyIdSz = length;
- #endif /* OPENSSL_EXTRA */
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ cert->extAuthKeyIdSrc = &input[idx];
+ cert->extAuthKeyIdSz = length;
+#endif /* OPENSSL_EXTRA */
if (length == KEYID_SIZE) {
XMEMCPY(cert->extAuthKeyId, input + idx, length);
}
- else {
- #ifdef NO_SHA
- ret = wc_Sha256Hash(input + idx, length, cert->extAuthKeyId);
- #else
- ret = wc_ShaHash(input + idx, length, cert->extAuthKeyId);
- #endif
- }
+ else
+ ret = CalcHashId(input + idx, length, cert->extAuthKeyId);
return ret;
}
-static int DecodeSubjKeyId(byte* input, int sz, DecodedCert* cert)
+static int DecodeSubjKeyId(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
int length = 0, ret = 0;
WOLFSSL_ENTER("DecodeSubjKeyId");
- if (input[idx++] != ASN_OCTET_STRING) {
- WOLFSSL_MSG("\tfail: should be an OCTET STRING");
+ if (sz <= 0)
return ASN_PARSE_E;
- }
- if (GetLength(input, &idx, &length, sz) < 0) {
- WOLFSSL_MSG("\tfail: extension data length");
- return ASN_PARSE_E;
- }
+ ret = GetOctetString(input, &idx, &length, sz);
+ if (ret < 0)
+ return ret;
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extSubjKeyIdSrc = &input[idx];
cert->extSubjKeyIdSz = length;
#endif /* OPENSSL_EXTRA */
- if (length == SIGNER_DIGEST_SIZE) {
+ if (length == KEYID_SIZE) {
XMEMCPY(cert->extSubjKeyId, input + idx, length);
}
- else {
- #ifdef NO_SHA
- ret = wc_Sha256Hash(input + idx, length, cert->extSubjKeyId);
- #else
- ret = wc_ShaHash(input + idx, length, cert->extSubjKeyId);
- #endif
- }
+ else
+ ret = CalcHashId(input + idx, length, cert->extSubjKeyId);
return ret;
}
-static int DecodeKeyUsage(byte* input, int sz, DecodedCert* cert)
+static int DecodeKeyUsage(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
int length;
- byte unusedBits;
+ int ret;
WOLFSSL_ENTER("DecodeKeyUsage");
- if (input[idx++] != ASN_BIT_STRING) {
- WOLFSSL_MSG("\tfail: key usage expected bit string");
- return ASN_PARSE_E;
- }
-
- if (GetLength(input, &idx, &length, sz) < 0) {
- WOLFSSL_MSG("\tfail: key usage bad length");
- return ASN_PARSE_E;
- }
-
- unusedBits = input[idx++];
- length--;
+ ret = CheckBitString(input, &idx, &length, sz, 0, NULL);
+ if (ret != 0)
+ return ret;
- if (length == 2) {
- cert->extKeyUsage = (word16)((input[idx] << 8) | input[idx+1]);
- cert->extKeyUsage >>= unusedBits;
- }
- else if (length == 1)
- cert->extKeyUsage = (word16)(input[idx] << 1);
+ cert->extKeyUsage = (word16)(input[idx]);
+ if (length == 2)
+ cert->extKeyUsage |= (word16)(input[idx+1] << 8);
return 0;
}
-static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert)
+static int DecodeExtKeyUsage(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0, oid;
- int length;
+ int length, ret;
- WOLFSSL_ENTER("DecodeExtKeyUsage");
+ WOLFSSL_MSG("DecodeExtKeyUsage");
if (GetSequence(input, &idx, &length, sz) < 0) {
WOLFSSL_MSG("\tfail: should be a SEQUENCE");
return ASN_PARSE_E;
}
- #ifdef OPENSSL_EXTRA
- cert->extExtKeyUsageSrc = input + idx;
- cert->extExtKeyUsageSz = length;
- #endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ cert->extExtKeyUsageSrc = input + idx;
+ cert->extExtKeyUsageSz = length;
+#endif
while (idx < (word32)sz) {
- if (GetObjectId(input, &idx, &oid, sz) < 0)
- return ASN_PARSE_E;
+ ret = GetObjectId(input, &idx, &oid, oidCertKeyUseType, sz);
+ if (ret == ASN_UNKNOWN_OID_E)
+ continue;
+ else if (ret < 0)
+ return ret;
switch (oid) {
case EKU_ANY_OID:
@@ -3935,14 +8272,23 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert)
case EKU_CLIENT_AUTH_OID:
cert->extExtKeyUsage |= EXTKEYUSE_CLIENT_AUTH;
break;
+ case EKU_CODESIGNING_OID:
+ cert->extExtKeyUsage |= EXTKEYUSE_CODESIGN;
+ break;
+ case EKU_EMAILPROTECT_OID:
+ cert->extExtKeyUsage |= EXTKEYUSE_EMAILPROT;
+ break;
+ case EKU_TIMESTAMP_OID:
+ cert->extExtKeyUsage |= EXTKEYUSE_TIMESTAMP;
+ break;
case EKU_OCSP_SIGN_OID:
cert->extExtKeyUsage |= EXTKEYUSE_OCSP_SIGN;
break;
}
- #ifdef OPENSSL_EXTRA
- cert->extExtKeyUsageCount++;
- #endif
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ cert->extExtKeyUsageCount++;
+ #endif
}
return 0;
@@ -3950,7 +8296,9 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert)
#ifndef IGNORE_NAME_CONSTRAINTS
-static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap)
+#define ASN_TYPE_MASK 0xF
+static int DecodeSubtree(const byte* input, int sz,
+ Base_entry** head, void* heap)
{
word32 idx = 0;
@@ -3959,27 +8307,37 @@ static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap)
while (idx < (word32)sz) {
int seqLength, strLength;
word32 nameIdx;
- byte b;
+ byte b, bType;
if (GetSequence(input, &idx, &seqLength, sz) < 0) {
WOLFSSL_MSG("\tfail: should be a SEQUENCE");
return ASN_PARSE_E;
}
-
nameIdx = idx;
b = input[nameIdx++];
+
if (GetLength(input, &nameIdx, &strLength, sz) <= 0) {
WOLFSSL_MSG("\tinvalid length");
return ASN_PARSE_E;
}
- if (b == (ASN_CONTEXT_SPECIFIC | ASN_DNS_TYPE) ||
- b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE) ||
- b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_DIR_TYPE)) {
+ /* Get type, LSB 4-bits */
+ bType = (b & ASN_TYPE_MASK);
+
+ if (bType == ASN_DNS_TYPE || bType == ASN_RFC822_TYPE ||
+ bType == ASN_DIR_TYPE) {
+ Base_entry* entry;
- Base_entry* entry = (Base_entry*)XMALLOC(sizeof(Base_entry),
- heap, DYNAMIC_TYPE_ALTNAME);
+ /* if constructed has leading sequence */
+ if (b & ASN_CONSTRUCTED) {
+ if (GetSequence(input, &nameIdx, &strLength, sz) < 0) {
+ WOLFSSL_MSG("\tfail: constructed be a SEQUENCE");
+ return ASN_PARSE_E;
+ }
+ }
+ entry = (Base_entry*)XMALLOC(sizeof(Base_entry), heap,
+ DYNAMIC_TYPE_ALTNAME);
if (entry == NULL) {
WOLFSSL_MSG("allocate error");
return MEMORY_E;
@@ -3988,12 +8346,13 @@ static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap)
entry->name = (char*)XMALLOC(strLength, heap, DYNAMIC_TYPE_ALTNAME);
if (entry->name == NULL) {
WOLFSSL_MSG("allocate error");
+ XFREE(entry, heap, DYNAMIC_TYPE_ALTNAME);
return MEMORY_E;
}
XMEMCPY(entry->name, &input[nameIdx], strLength);
entry->nameSz = strLength;
- entry->type = b & 0x0F;
+ entry->type = bType;
entry->next = *head;
*head = entry;
@@ -4006,7 +8365,7 @@ static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap)
}
-static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert)
+static int DecodeNameConstraints(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
int length = 0;
@@ -4045,51 +8404,176 @@ static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert)
}
#endif /* IGNORE_NAME_CONSTRAINTS */
+#if (defined(WOLFSSL_CERT_EXT) && !defined(WOLFSSL_SEP)) || defined(OPENSSL_EXTRA)
-#ifdef WOLFSSL_SEP
- static int DecodeCertPolicy(byte* input, int sz, DecodedCert* cert)
+/* Decode ITU-T X.690 OID format to a string representation
+ * return string length */
+int DecodePolicyOID(char *out, word32 outSz, const byte *in, word32 inSz)
+{
+ word32 val, inIdx = 0, outIdx = 0;
+ int w = 0;
+
+ if (out == NULL || in == NULL || outSz < 4 || inSz < 2)
+ return BAD_FUNC_ARG;
+
+ /* The first byte expands into b/40 dot b%40. */
+ val = in[inIdx++];
+
+ w = XSNPRINTF(out, outSz, "%u.%u", val / 40, val % 40);
+ if (w < 0)
+ goto exit;
+ outIdx += w;
+ val = 0;
+
+ while (inIdx < inSz && outIdx < outSz) {
+ /* extract the next OID digit from in to val */
+ /* first bit is used to set if value is coded on 1 or multiple bytes */
+ if (in[inIdx] & 0x80) {
+ val += in[inIdx] & 0x7F;
+ val *= 128;
+ }
+ else {
+ /* write val as text into out */
+ val += in[inIdx];
+ w = XSNPRINTF(out + outIdx, outSz - outIdx, ".%u", val);
+ if (w < 0)
+ goto exit;
+ outIdx += w;
+ val = 0;
+ }
+ inIdx++;
+ }
+ if (outIdx == outSz)
+ outIdx--;
+ out[outIdx] = 0;
+
+ w = (int)outIdx;
+
+exit:
+ return w;
+}
+#endif /* WOLFSSL_CERT_EXT && !WOLFSSL_SEP */
+
+#if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_QT)
+ /* Reference: https://tools.ietf.org/html/rfc5280#section-4.2.1.4 */
+ static int DecodeCertPolicy(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
- int length = 0;
+ word32 oldIdx;
+ int ret;
+ int total_length = 0, policy_length = 0, length = 0;
+ #if !defined(WOLFSSL_SEP) && defined(WOLFSSL_CERT_EXT) && \
+ !defined(WOLFSSL_DUP_CERTPOL)
+ int i;
+ #endif
WOLFSSL_ENTER("DecodeCertPolicy");
+ #if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT)
+ /* Check if cert is null before dereferencing below */
+ if (cert == NULL)
+ return BAD_FUNC_ARG;
+ #endif
- /* Unwrap certificatePolicies */
- if (GetSequence(input, &idx, &length, sz) < 0) {
- WOLFSSL_MSG("\tdeviceType isn't OID");
- return ASN_PARSE_E;
- }
+ #if defined(WOLFSSL_CERT_EXT)
+ cert->extCertPoliciesNb = 0;
+ #endif
- if (GetSequence(input, &idx, &length, sz) < 0) {
- WOLFSSL_MSG("\tdeviceType isn't OID");
+ if (GetSequence(input, &idx, &total_length, sz) < 0) {
+ WOLFSSL_MSG("\tGet CertPolicy total seq failed");
return ASN_PARSE_E;
}
- if (input[idx++] != ASN_OBJECT_ID) {
- WOLFSSL_MSG("\tdeviceType isn't OID");
+ /* Validate total length */
+ if (total_length > (sz - (int)idx)) {
+ WOLFSSL_MSG("\tCertPolicy length mismatch");
return ASN_PARSE_E;
}
- if (GetLength(input, &idx, &length, sz) < 0) {
- WOLFSSL_MSG("\tCouldn't read length of deviceType");
- return ASN_PARSE_E;
- }
+ /* Unwrap certificatePolicies */
+ do {
+ if (GetSequence(input, &idx, &policy_length, sz) < 0) {
+ WOLFSSL_MSG("\tGet CertPolicy seq failed");
+ return ASN_PARSE_E;
+ }
- if (length > 0) {
- cert->deviceType = (byte*)XMALLOC(length, cert->heap, 0);
- if (cert->deviceType == NULL) {
- WOLFSSL_MSG("\tCouldn't alloc memory for deviceType");
- return MEMORY_E;
+ oldIdx = idx;
+ ret = GetASNObjectId(input, &idx, &length, sz);
+ if (ret != 0)
+ return ret;
+ policy_length -= idx - oldIdx;
+
+ if (length > 0) {
+ /* Verify length won't overrun buffer */
+ if (length > (sz - (int)idx)) {
+ WOLFSSL_MSG("\tCertPolicy length exceeds input buffer");
+ return ASN_PARSE_E;
+ }
+
+ #if defined(WOLFSSL_SEP)
+ cert->deviceType = (byte*)XMALLOC(length, cert->heap,
+ DYNAMIC_TYPE_X509_EXT);
+ if (cert->deviceType == NULL) {
+ WOLFSSL_MSG("\tCouldn't alloc memory for deviceType");
+ return MEMORY_E;
+ }
+ cert->deviceTypeSz = length;
+ XMEMCPY(cert->deviceType, input + idx, length);
+ break;
+ #elif defined(WOLFSSL_CERT_EXT)
+ /* decode cert policy */
+ if (DecodePolicyOID(cert->extCertPolicies[
+ cert->extCertPoliciesNb], MAX_CERTPOL_SZ,
+ input + idx, length) <= 0) {
+ WOLFSSL_MSG("\tCouldn't decode CertPolicy");
+ return ASN_PARSE_E;
+ }
+ #ifndef WOLFSSL_DUP_CERTPOL
+ /* From RFC 5280 section 4.2.1.3 "A certificate policy OID MUST
+ * NOT appear more than once in a certificate policies
+ * extension". This is a sanity check for duplicates.
+ * extCertPolicies should only have OID values, additional
+ * qualifiers need to be stored in a separate array. */
+ for (i = 0; i < cert->extCertPoliciesNb; i++) {
+ if (XMEMCMP(cert->extCertPolicies[i],
+ cert->extCertPolicies[cert->extCertPoliciesNb],
+ MAX_CERTPOL_SZ) == 0) {
+ WOLFSSL_MSG("Duplicate policy OIDs not allowed");
+ WOLFSSL_MSG("Use WOLFSSL_DUP_CERTPOL if wanted");
+ return CERTPOLICIES_E;
+ }
+ }
+ #endif /* !WOLFSSL_DUP_CERTPOL */
+ cert->extCertPoliciesNb++;
+ #else
+ WOLFSSL_LEAVE("DecodeCertPolicy : unsupported mode", 0);
+ return 0;
+ #endif
}
- cert->deviceTypeSz = length;
- XMEMCPY(cert->deviceType, input + idx, length);
- }
+ idx += policy_length;
+ } while((int)idx < total_length
+ #if defined(WOLFSSL_CERT_EXT)
+ && cert->extCertPoliciesNb < MAX_CERTPOL_NB
+ #endif
+ );
WOLFSSL_LEAVE("DecodeCertPolicy", 0);
return 0;
}
#endif /* WOLFSSL_SEP */
+/* Macro to check if bit is set, if not sets and return success.
+ Otherwise returns failure */
+/* Macro required here because bit-field operation */
+#ifndef WOLFSSL_NO_ASN_STRICT
+ #define VERIFY_AND_SET_OID(bit) \
+ if (bit == 0) \
+ bit = 1; \
+ else \
+ return ASN_OBJECT_ID_E;
+#else
+ /* With no strict defined, the verify is skipped */
+#define VERIFY_AND_SET_OID(bit) bit = 1;
+#endif
static int DecodeCertExtensions(DecodedCert* cert)
/*
@@ -4097,68 +8581,85 @@ static int DecodeCertExtensions(DecodedCert* cert)
* index. It is works starting with the recorded extensions pointer.
*/
{
+ int ret = 0;
word32 idx = 0;
int sz = cert->extensionsSz;
- byte* input = cert->extensions;
+ const byte* input = cert->extensions;
int length;
word32 oid;
byte critical = 0;
byte criticalFail = 0;
+ byte tag = 0;
WOLFSSL_ENTER("DecodeCertExtensions");
if (input == NULL || sz == 0)
return BAD_FUNC_ARG;
- if (input[idx++] != ASN_EXTENSIONS)
+ if (GetASNTag(input, &idx, &tag, sz) < 0) {
return ASN_PARSE_E;
+ }
- if (GetLength(input, &idx, &length, sz) < 0)
+ if (tag != ASN_EXTENSIONS) {
+ WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
return ASN_PARSE_E;
+ }
- if (GetSequence(input, &idx, &length, sz) < 0)
+ if (GetLength(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: invalid length");
return ASN_PARSE_E;
-
+ }
+
+ if (GetSequence(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)");
+ return ASN_PARSE_E;
+ }
+
while (idx < (word32)sz) {
+ word32 localIdx;
+
if (GetSequence(input, &idx, &length, sz) < 0) {
WOLFSSL_MSG("\tfail: should be a SEQUENCE");
return ASN_PARSE_E;
}
oid = 0;
- if (GetObjectId(input, &idx, &oid, sz) < 0) {
+ if ((ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz)) < 0) {
WOLFSSL_MSG("\tfail: OBJECT ID");
- return ASN_PARSE_E;
+ return ret;
}
/* check for critical flag */
critical = 0;
- if (input[idx] == ASN_BOOLEAN) {
- int boolLength = 0;
- idx++;
- if (GetLength(input, &idx, &boolLength, sz) < 0) {
- WOLFSSL_MSG("\tfail: critical boolean length");
- return ASN_PARSE_E;
- }
- if (input[idx++])
- critical = 1;
+ if ((idx + 1) > (word32)sz) {
+ WOLFSSL_MSG("\tfail: malformed buffer");
+ return BUFFER_E;
}
- /* process the extension based on the OID */
- if (input[idx++] != ASN_OCTET_STRING) {
- WOLFSSL_MSG("\tfail: should be an OCTET STRING");
- return ASN_PARSE_E;
+ localIdx = idx;
+ if (GetASNTag(input, &localIdx, &tag, sz) == 0) {
+ if (tag == ASN_BOOLEAN) {
+ ret = GetBoolean(input, &idx, sz);
+ if (ret < 0) {
+ WOLFSSL_MSG("\tfail: critical boolean");
+ return ret;
+ }
+
+ critical = (byte)ret;
+ }
}
- if (GetLength(input, &idx, &length, sz) < 0) {
- WOLFSSL_MSG("\tfail: extension data length");
- return ASN_PARSE_E;
+ /* process the extension based on the OID */
+ ret = GetOctetString(input, &idx, &length, sz);
+ if (ret < 0) {
+ WOLFSSL_MSG("\tfail: bad OCTET STRING");
+ return ret;
}
switch (oid) {
case BASIC_CA_OID:
- #ifdef OPENSSL_EXTRA
- cert->extBasicConstSet = 1;
+ VERIFY_AND_SET_OID(cert->extBasicConstSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extBasicConstCrit = critical;
#endif
if (DecodeBasicCaConstraint(&input[idx], length, cert) < 0)
@@ -4166,57 +8667,95 @@ static int DecodeCertExtensions(DecodedCert* cert)
break;
case CRL_DIST_OID:
+ VERIFY_AND_SET_OID(cert->extCRLdistSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ cert->extCRLdistCrit = critical;
+ #endif
if (DecodeCrlDist(&input[idx], length, cert) < 0)
return ASN_PARSE_E;
break;
case AUTH_INFO_OID:
+ VERIFY_AND_SET_OID(cert->extAuthInfoSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ cert->extAuthInfoCrit = critical;
+ #endif
if (DecodeAuthInfo(&input[idx], length, cert) < 0)
return ASN_PARSE_E;
break;
case ALT_NAMES_OID:
- #ifdef OPENSSL_EXTRA
- cert->extSubjAltNameSet = 1;
+ VERIFY_AND_SET_OID(cert->extSubjAltNameSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extSubjAltNameCrit = critical;
#endif
- if (DecodeAltNames(&input[idx], length, cert) < 0)
- return ASN_PARSE_E;
+ ret = DecodeAltNames(&input[idx], length, cert);
+ if (ret < 0)
+ return ret;
break;
case AUTH_KEY_OID:
- cert->extAuthKeyIdSet = 1;
- #ifdef OPENSSL_EXTRA
+ VERIFY_AND_SET_OID(cert->extAuthKeyIdSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extAuthKeyIdCrit = critical;
#endif
+ #ifndef WOLFSSL_ALLOW_CRIT_SKID
+ /* This check is added due to RFC 5280 section 4.2.1.1
+ * stating that conforming CA's must mark this extension
+ * as non-critical. When parsing extensions check that
+ * certificate was made in compliance with this. */
+ if (critical) {
+ WOLFSSL_MSG("Critical Auth Key ID is not allowed");
+ WOLFSSL_MSG("Use macro WOLFSSL_ALLOW_CRIT_SKID if wanted");
+ return ASN_CRIT_EXT_E;
+ }
+ #endif
if (DecodeAuthKeyId(&input[idx], length, cert) < 0)
return ASN_PARSE_E;
break;
case SUBJ_KEY_OID:
- cert->extSubjKeyIdSet = 1;
- #ifdef OPENSSL_EXTRA
+ VERIFY_AND_SET_OID(cert->extSubjKeyIdSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extSubjKeyIdCrit = critical;
#endif
+ #ifndef WOLFSSL_ALLOW_CRIT_SKID
+ /* This check is added due to RFC 5280 section 4.2.1.2
+ * stating that conforming CA's must mark this extension
+ * as non-critical. When parsing extensions check that
+ * certificate was made in compliance with this. */
+ if (critical) {
+ WOLFSSL_MSG("Critical Subject Key ID is not allowed");
+ WOLFSSL_MSG("Use macro WOLFSSL_ALLOW_CRIT_SKID if wanted");
+ return ASN_CRIT_EXT_E;
+ }
+ #endif
+
if (DecodeSubjKeyId(&input[idx], length, cert) < 0)
return ASN_PARSE_E;
break;
case CERT_POLICY_OID:
- WOLFSSL_MSG("Certificate Policy extension not supported yet.");
- #ifdef WOLFSSL_SEP
- #ifdef OPENSSL_EXTRA
- cert->extCertPolicySet = 1;
+ #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT)
+ VERIFY_AND_SET_OID(cert->extCertPolicySet);
+ #if defined(OPENSSL_EXTRA) || \
+ defined(OPENSSL_EXTRA_X509_SMALL)
cert->extCertPolicyCrit = critical;
#endif
- if (DecodeCertPolicy(&input[idx], length, cert) < 0)
+ #endif
+ #if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT) || \
+ defined(WOLFSSL_QT)
+ if (DecodeCertPolicy(&input[idx], length, cert) < 0) {
return ASN_PARSE_E;
+ }
+ #else
+ WOLFSSL_MSG("Certificate Policy extension not supported yet.");
#endif
break;
case KEY_USAGE_OID:
- cert->extKeyUsageSet = 1;
- #ifdef OPENSSL_EXTRA
+ VERIFY_AND_SET_OID(cert->extKeyUsageSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extKeyUsageCrit = critical;
#endif
if (DecodeKeyUsage(&input[idx], length, cert) < 0)
@@ -4224,8 +8763,8 @@ static int DecodeCertExtensions(DecodedCert* cert)
break;
case EXT_KEY_USAGE_OID:
- cert->extExtKeyUsageSet = 1;
- #ifdef OPENSSL_EXTRA
+ VERIFY_AND_SET_OID(cert->extExtKeyUsageSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extExtKeyUsageCrit = critical;
#endif
if (DecodeExtKeyUsage(&input[idx], length, cert) < 0)
@@ -4234,8 +8773,17 @@ static int DecodeCertExtensions(DecodedCert* cert)
#ifndef IGNORE_NAME_CONSTRAINTS
case NAME_CONS_OID:
- cert->extNameConstraintSet = 1;
- #ifdef OPENSSL_EXTRA
+ #ifndef WOLFSSL_NO_ASN_STRICT
+ /* Verify RFC 5280 Sec 4.2.1.10 rule:
+ "The name constraints extension,
+ which MUST be used only in a CA certificate" */
+ if (!cert->isCA) {
+ WOLFSSL_MSG("Name constraints allowed only for CA certs");
+ return ASN_NAME_INVALID_E;
+ }
+ #endif
+ VERIFY_AND_SET_OID(cert->extNameConstraintSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extNameConstraintCrit = critical;
#endif
if (DecodeNameConstraints(&input[idx], length, cert) < 0)
@@ -4244,17 +8792,31 @@ static int DecodeCertExtensions(DecodedCert* cert)
#endif /* IGNORE_NAME_CONSTRAINTS */
case INHIBIT_ANY_OID:
+ VERIFY_AND_SET_OID(cert->inhibitAnyOidSet);
WOLFSSL_MSG("Inhibit anyPolicy extension not supported yet.");
break;
+ #ifndef IGNORE_NETSCAPE_CERT_TYPE
+ case NETSCAPE_CT_OID:
+ WOLFSSL_MSG("Netscape certificate type extension not supported "
+ "yet.");
+ if (CheckBitString(input, &idx, &length, idx + length, 0,
+ NULL) < 0) {
+ return ASN_PARSE_E;
+ }
+ break;
+ #endif
+
default:
+ #ifndef WOLFSSL_NO_ASN_STRICT
/* While it is a failure to not support critical extensions,
* still parse the certificate ignoring the unsupported
- * extention to allow caller to accept it with the verify
+ * extension to allow caller to accept it with the verify
* callback. */
if (critical)
criticalFail = 1;
- break;
+ #endif
+ break;
}
idx += length;
}
@@ -4262,7 +8824,6 @@ static int DecodeCertExtensions(DecodedCert* cert)
return criticalFail ? ASN_CRIT_EXT_E : 0;
}
-
int ParseCert(DecodedCert* cert, int type, int verify, void* cm)
{
int ret;
@@ -4297,126 +8858,662 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm)
return ret;
}
-
/* from SSL proper, for locking can't do find here anymore */
#ifdef __cplusplus
extern "C" {
#endif
- WOLFSSL_LOCAL Signer* GetCA(void* signers, byte* hash);
+ Signer* GetCA(void* signers, byte* hash);
#ifndef NO_SKID
- WOLFSSL_LOCAL Signer* GetCAByName(void* signers, byte* hash);
+ Signer* GetCAByName(void* signers, byte* hash);
#endif
#ifdef __cplusplus
- }
+ }
#endif
+#if defined(WOLFCRYPT_ONLY) || defined(NO_CERTS)
+
+/* dummy functions, not using wolfSSL so don't need actual ones */
+Signer* GetCA(void* signers, byte* hash)
+{
+ (void)hash;
+
+ return (Signer*)signers;
+}
+
+#ifndef NO_SKID
+Signer* GetCAByName(void* signers, byte* hash)
+{
+ (void)hash;
+
+ return (Signer*)signers;
+}
+#endif /* NO_SKID */
+
+#endif /* WOLFCRYPT_ONLY || NO_CERTS */
+
+#if defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY) && !defined(NO_SKID)
+static Signer* GetCABySubjectAndPubKey(DecodedCert* cert, void* cm)
+{
+ Signer* ca = NULL;
+ if (cert->extSubjKeyIdSet)
+ ca = GetCA(cm, cert->extSubjKeyId);
+ if (ca == NULL)
+ ca = GetCAByName(cm, cert->subjectHash);
+ if (ca) {
+ if ((ca->pubKeySize == cert->pubKeySize) &&
+ (XMEMCMP(ca->publicKey, cert->publicKey, ca->pubKeySize) == 0)) {
+ return ca;
+ }
+ }
+ return NULL;
+}
+#endif
+
+#if defined(WOLFSSL_SMALL_CERT_VERIFY) || defined(OPENSSL_EXTRA)
+/* Only quick step through the certificate to find fields that are then used
+ * in certificate signature verification.
+ * Must use the signature OID from the signed part of the certificate.
+ *
+ * This is only for minimizing dynamic memory usage during TLS certificate
+ * chain processing.
+ * Doesn't support:
+ * OCSP Only: alt lookup using subject and pub key w/o sig check
+ */
+static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
+ void* cm, const byte* pubKey, word32 pubKeySz, int pubKeyOID)
+{
+#ifndef WOLFSSL_SMALL_STACK
+ SignatureCtx sigCtx[1];
+#else
+ SignatureCtx* sigCtx;
+#endif
+ byte hash[KEYID_SIZE];
+ Signer* ca = NULL;
+ word32 idx = 0;
+ int len;
+ word32 tbsCertIdx = 0;
+ word32 sigIndex = 0;
+ word32 signatureOID = 0;
+ word32 oid = 0;
+ word32 issuerIdx = 0;
+ word32 issuerSz = 0;
+#ifndef NO_SKID
+ int extLen = 0;
+ word32 extIdx = 0;
+ word32 extEndIdx = 0;
+ int extAuthKeyIdSet = 0;
+#endif
+ int ret = 0;
+ word32 localIdx;
+ byte tag;
+
+
+ if (cert == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ sigCtx = (SignatureCtx*)XMALLOC(sizeof(*sigCtx), heap, DYNAMIC_TYPE_SIGNATURE);
+ if (sigCtx == NULL)
+ return MEMORY_E;
+#endif
+ InitSignatureCtx(sigCtx, heap, INVALID_DEVID);
+
+ /* Certificate SEQUENCE */
+ if (GetSequence(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ if (ret == 0) {
+ tbsCertIdx = idx;
+
+ /* TBSCertificate SEQUENCE */
+ if (GetSequence(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ sigIndex = len + idx;
+
+ if ((idx + 1) > certSz)
+ ret = BUFFER_E;
+ }
+ if (ret == 0) {
+ /* version - optional */
+ localIdx = idx;
+ if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
+ if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
+ idx++;
+ if (GetLength(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ idx += len;
+ }
+ }
+ }
+
+ if (ret == 0) {
+ /* serialNumber */
+ if (GetASNHeader(cert, ASN_INTEGER, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ idx += len;
+
+ /* signature */
+ if (GetAlgoId(cert, &idx, &signatureOID, oidSigType, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+
+ if (ret == 0) {
+ issuerIdx = idx;
+ /* issuer */
+ if (GetSequence(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ issuerSz = len + idx - issuerIdx;
+ }
+#ifndef NO_SKID
+ if (ret == 0) {
+ idx += len;
+
+ /* validity */
+ if (GetSequence(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ idx += len;
+
+ /* subject */
+ if (GetSequence(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ idx += len;
+
+ /* subjectPublicKeyInfo */
+ if (GetSequence(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ idx += len;
+
+ if ((idx + 1) > certSz)
+ ret = BUFFER_E;
+ }
+ if (ret == 0) {
+ /* issuerUniqueID - optional */
+ localIdx = idx;
+ if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
+ if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) {
+ idx++;
+ if (GetLength(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ idx += len;
+ }
+ }
+ }
+ if (ret == 0) {
+ if ((idx + 1) > certSz)
+ ret = BUFFER_E;
+ }
+ if (ret == 0) {
+ /* subjectUniqueID - optional */
+ localIdx = idx;
+ if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
+ if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)) {
+ idx++;
+ if (GetLength(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ idx += len;
+ }
+ }
+ }
+
+ if (ret == 0) {
+ if ((idx + 1) > certSz)
+ ret = BUFFER_E;
+ }
+ /* extensions - optional */
+ localIdx = idx;
+ if (ret == 0 && GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
+ tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 3)) {
+ idx++;
+ if (GetLength(cert, &idx, &extLen, certSz) < 0)
+ ret = ASN_PARSE_E;
+ if (ret == 0) {
+ if (GetSequence(cert, &idx, &extLen, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ extEndIdx = idx + extLen;
+
+ /* Check each extension for the ones we want. */
+ while (ret == 0 && idx < extEndIdx) {
+ if (GetSequence(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ if (ret == 0) {
+ extIdx = idx;
+ if (GetObjectId(cert, &extIdx, &oid, oidCertExtType,
+ certSz) < 0) {
+ ret = ASN_PARSE_E;
+ }
+
+ if (ret == 0) {
+ if ((extIdx + 1) > certSz)
+ ret = BUFFER_E;
+ }
+ }
+
+ if (ret == 0) {
+ localIdx = extIdx;
+ if (GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
+ tag == ASN_BOOLEAN) {
+ if (GetBoolean(cert, &extIdx, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ }
+ if (ret == 0) {
+ if (GetOctetString(cert, &extIdx, &extLen, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+
+ if (ret == 0) {
+ switch (oid) {
+ case AUTH_KEY_OID:
+ if (GetSequence(cert, &extIdx, &extLen, certSz) < 0)
+ ret = ASN_PARSE_E;
+
+ if (ret == 0 && (extIdx + 1) >= certSz)
+ ret = BUFFER_E;
+
+ if (ret == 0 &&
+ GetASNTag(cert, &extIdx, &tag, certSz) == 0 &&
+ tag == (ASN_CONTEXT_SPECIFIC | 0)) {
+ if (GetLength(cert, &extIdx, &extLen, certSz) <= 0)
+ ret = ASN_PARSE_E;
+ if (ret == 0) {
+ extAuthKeyIdSet = 1;
+ if (extLen == KEYID_SIZE)
+ XMEMCPY(hash, cert + extIdx, extLen);
+ else {
+ ret = CalcHashId(cert + extIdx, extLen,
+ hash);
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ idx += len;
+ }
+ }
+ }
+
+ if (ret == 0 && pubKey == NULL) {
+ if (extAuthKeyIdSet)
+ ca = GetCA(cm, hash);
+ if (ca == NULL) {
+ ret = CalcHashId(cert + issuerIdx, issuerSz, hash);
+ if (ret == 0)
+ ca = GetCAByName(cm, hash);
+ }
+ }
+#else
+ if (ret == 0 && pubKey == NULL) {
+ ret = CalcHashId(cert + issuerIdx, issuerSz, hash);
+ if (ret == 0)
+ ca = GetCA(cm, hash);
+ }
+#endif /* !NO_SKID */
+ if (ca == NULL && pubKey == NULL)
+ ret = ASN_NO_SIGNER_E;
+
+ if (ret == 0) {
+ idx = sigIndex;
+ /* signatureAlgorithm */
+ if (GetAlgoId(cert, &idx, &oid, oidSigType, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ if (oid != signatureOID)
+ ret = ASN_SIG_OID_E;
+ }
+ if (ret == 0) {
+ /* signatureValue */
+ if (CheckBitString(cert, &idx, &len, certSz, 1, NULL) < 0)
+ ret = ASN_PARSE_E;
+ }
+
+ if (ret == 0) {
+ if (pubKey != NULL) {
+ ret = ConfirmSignature(sigCtx, cert + tbsCertIdx,
+ sigIndex - tbsCertIdx,
+ pubKey, pubKeySz, pubKeyOID,
+ cert + idx, len, signatureOID, NULL);
+ }
+ else {
+ ret = ConfirmSignature(sigCtx, cert + tbsCertIdx,
+ sigIndex - tbsCertIdx,
+ ca->publicKey, ca->pubKeySize, ca->keyOID,
+ cert + idx, len, signatureOID, NULL);
+ }
+ if (ret != 0) {
+ WOLFSSL_MSG("Confirm signature failed");
+ }
+ }
+
+ FreeSignatureCtx(sigCtx);
+#ifdef WOLFSSL_SMALL_STACK
+ if (sigCtx != NULL)
+ XFREE(sigCtx, heap, DYNAMIC_TYPE_SIGNATURE);
+#endif
+ return ret;
+}
+
+#ifdef OPENSSL_EXTRA
+/* Call CheckCertSignature_ex using a public key buffer for verification
+ */
+int CheckCertSignaturePubKey(const byte* cert, word32 certSz, void* heap,
+ const byte* pubKey, word32 pubKeySz, int pubKeyOID)
+{
+ return CheckCertSignature_ex(cert, certSz, heap, NULL,
+ pubKey, pubKeySz, pubKeyOID);
+}
+#endif /* OPENSSL_EXTRA */
+#ifdef WOLFSSL_SMALL_CERT_VERIFY
+/* Call CheckCertSignature_ex using a certificate manager (cm)
+ */
+int CheckCertSignature(const byte* cert, word32 certSz, void* heap, void* cm)
+{
+ return CheckCertSignature_ex(cert, certSz, heap, cm, NULL, 0, 0);
+}
+#endif /* WOLFSSL_SMALL_CERT_VERIFY */
+#endif /* WOLFSSL_SMALL_CERT_VERIFY || OPENSSL_EXTRA */
int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
{
+ int ret = 0;
+ int checkPathLen = 0;
+ int decrementMaxPathLen = 0;
word32 confirmOID;
- int ret;
- int badDate = 0;
- int criticalExt = 0;
+#if defined(WOLFSSL_RENESAS_TSIP)
+ int idx = 0;
+#endif
+ byte* tsip_encRsaKeyIdx;
- if ((ret = DecodeToKey(cert, verify)) < 0) {
- if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E)
- badDate = ret;
- else
- return ret;
+ if (cert == NULL) {
+ return BAD_FUNC_ARG;
}
- WOLFSSL_MSG("Parsed Past Key");
+ if (cert->sigCtx.state == SIG_STATE_BEGIN) {
+ cert->badDate = 0;
+ cert->criticalExt = 0;
+ if ((ret = DecodeToKey(cert, verify)) < 0) {
+ if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E)
+ cert->badDate = ret;
+ else
+ return ret;
+ }
+
+ WOLFSSL_MSG("Parsed Past Key");
- if (cert->srcIdx < cert->sigIndex) {
+ if (cert->srcIdx < cert->sigIndex) {
#ifndef ALLOW_V1_EXTENSIONS
if (cert->version < 2) {
- WOLFSSL_MSG(" v1 and v2 certs not allowed extensions");
+ WOLFSSL_MSG("\tv1 and v2 certs not allowed extensions");
return ASN_VERSION_E;
}
#endif
- /* save extensions */
- cert->extensions = &cert->source[cert->srcIdx];
- cert->extensionsSz = cert->sigIndex - cert->srcIdx;
- cert->extensionsIdx = cert->srcIdx; /* for potential later use */
-
- if ((ret = DecodeCertExtensions(cert)) < 0) {
- if (ret == ASN_CRIT_EXT_E)
- criticalExt = ret;
- else
- return ret;
- }
- /* advance past extensions */
- cert->srcIdx = cert->sigIndex;
- }
+ /* save extensions */
+ cert->extensions = &cert->source[cert->srcIdx];
+ cert->extensionsSz = cert->sigIndex - cert->srcIdx;
+ cert->extensionsIdx = cert->srcIdx; /* for potential later use */
- if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID,
- cert->maxIdx)) < 0)
- return ret;
+ if ((ret = DecodeCertExtensions(cert)) < 0) {
+ if (ret == ASN_CRIT_EXT_E)
+ cert->criticalExt = ret;
+ else
+ return ret;
+ }
- if ((ret = GetSignature(cert)) < 0)
- return ret;
+ /* advance past extensions */
+ cert->srcIdx = cert->sigIndex;
+ }
+
+ if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID,
+ oidSigType, cert->maxIdx)) < 0)
+ return ret;
+
+ if ((ret = GetSignature(cert)) < 0)
+ return ret;
- if (confirmOID != cert->signatureOID)
- return ASN_SIG_OID_E;
+ if (confirmOID != cert->signatureOID)
+ return ASN_SIG_OID_E;
#ifndef NO_SKID
- if (cert->extSubjKeyIdSet == 0
- && cert->publicKey != NULL && cert->pubKeySize > 0) {
- #ifdef NO_SHA
- ret = wc_Sha256Hash(cert->publicKey, cert->pubKeySize,
+ if (cert->extSubjKeyIdSet == 0 && cert->publicKey != NULL &&
+ cert->pubKeySize > 0) {
+ ret = CalcHashId(cert->publicKey, cert->pubKeySize,
cert->extSubjKeyId);
- #else
- ret = wc_ShaHash(cert->publicKey, cert->pubKeySize,
- cert->extSubjKeyId);
- #endif
if (ret != 0)
return ret;
}
- #endif
+ #endif /* !NO_SKID */
- if (verify && type != CA_TYPE) {
- Signer* ca = NULL;
- #ifndef NO_SKID
- if (cert->extAuthKeyIdSet)
- ca = GetCA(cm, cert->extAuthKeyId);
- if (ca == NULL)
- ca = GetCAByName(cm, cert->issuerHash);
- #else /* NO_SKID */
- ca = GetCA(cm, cert->issuerHash);
- #endif /* NO SKID */
- WOLFSSL_MSG("About to verify certificate signature");
-
- if (ca) {
-#ifdef HAVE_OCSP
- /* Need the ca's public key hash for OCSP */
- #ifdef NO_SHA
- ret = wc_Sha256Hash(ca->publicKey, ca->pubKeySize,
- cert->issuerKeyHash);
- #else /* NO_SHA */
- ret = wc_ShaHash(ca->publicKey, ca->pubKeySize,
- cert->issuerKeyHash);
- #endif /* NO_SHA */
- if (ret != 0)
- return ret;
-#endif /* HAVE_OCSP */
- /* try to confirm/verify signature */
- if (!ConfirmSignature(cert->source + cert->certBegin,
+ if (!cert->selfSigned || (verify != NO_VERIFY && type != CA_TYPE &&
+ type != TRUSTED_PEER_TYPE)) {
+ cert->ca = NULL;
+ #ifndef NO_SKID
+ if (cert->extAuthKeyIdSet) {
+ cert->ca = GetCA(cm, cert->extAuthKeyId);
+ }
+ if (cert->ca == NULL && cert->extSubjKeyIdSet
+ && verify != VERIFY_OCSP) {
+ cert->ca = GetCA(cm, cert->extSubjKeyId);
+ }
+ if (cert->ca != NULL && XMEMCMP(cert->issuerHash,
+ cert->ca->subjectNameHash, KEYID_SIZE) != 0) {
+ cert->ca = NULL;
+ }
+ if (cert->ca == NULL) {
+ cert->ca = GetCAByName(cm, cert->issuerHash);
+ /* If AKID is available then this CA doesn't have the public
+ * key required */
+ if (cert->ca && cert->extAuthKeyIdSet) {
+ WOLFSSL_MSG("CA SKID doesn't match AKID");
+ cert->ca = NULL;
+ }
+ }
+
+ /* OCSP Only: alt lookup using subject and pub key w/o sig check */
+ #ifdef WOLFSSL_NO_TRUSTED_CERTS_VERIFY
+ if (cert->ca == NULL && verify == VERIFY_OCSP) {
+ cert->ca = GetCABySubjectAndPubKey(cert, cm);
+ if (cert->ca) {
+ ret = 0; /* success */
+ goto exit_pcr;
+ }
+ }
+ #endif /* WOLFSSL_NO_TRUSTED_CERTS_VERIFY */
+ #else
+ cert->ca = GetCA(cm, cert->issuerHash);
+ #endif /* !NO_SKID */
+ }
+
+ if (cert->selfSigned) {
+ cert->maxPathLen = WOLFSSL_MAX_PATH_LEN;
+ } else {
+ /* RFC 5280 Section 4.2.1.9:
+ *
+ * load/receive check
+ *
+ * 1) Is CA boolean set?
+ * No - SKIP CHECK
+ * Yes - Check key usage
+ * 2) Is Key usage extension present?
+ * No - goto 3
+ * Yes - check keyCertSign assertion
+ * 2.a) Is keyCertSign asserted?
+ * No - goto 4
+ * Yes - goto 3
+ * 3) Is pathLen set?
+ * No - goto 4
+ * Yes - check pathLen against maxPathLen.
+ * 3.a) Is pathLen less than maxPathLen?
+ * No - goto 4
+ * Yes - set maxPathLen to pathLen and EXIT
+ * 4) Is maxPathLen > 0?
+ * Yes - Reduce by 1
+ * No - ERROR
+ */
+
+ if (cert->ca && cert->pathLengthSet) {
+ cert->maxPathLen = cert->pathLength;
+ if (cert->isCA) {
+ WOLFSSL_MSG("\tCA boolean set");
+ if (cert->extKeyUsageSet) {
+ WOLFSSL_MSG("\tExtension Key Usage Set");
+ if ((cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) != 0) {
+ checkPathLen = 1;
+ } else {
+ decrementMaxPathLen = 1;
+ }
+ } else {
+ checkPathLen = 1;
+ } /* !cert->ca check */
+ } /* cert is not a CA (assuming entity cert) */
+
+ if (checkPathLen && cert->pathLengthSet) {
+ if (cert->pathLength < cert->ca->maxPathLen) {
+ WOLFSSL_MSG("\tmaxPathLen status: set to pathLength");
+ cert->maxPathLen = cert->pathLength;
+ } else {
+ decrementMaxPathLen = 1;
+ }
+ }
+
+ if (decrementMaxPathLen && cert->ca->maxPathLen > 0) {
+ WOLFSSL_MSG("\tmaxPathLen status: reduce by 1");
+ cert->maxPathLen = cert->ca->maxPathLen - 1;
+ if (verify != NO_VERIFY && type != CA_TYPE &&
+ type != TRUSTED_PEER_TYPE) {
+ WOLFSSL_MSG("\tmaxPathLen status: OK");
+ }
+ } else if (decrementMaxPathLen && cert->ca->maxPathLen == 0) {
+ cert->maxPathLen = 0;
+ if (verify != NO_VERIFY && type != CA_TYPE &&
+ type != TRUSTED_PEER_TYPE) {
+ WOLFSSL_MSG("\tNon-entity cert, maxPathLen is 0");
+ WOLFSSL_MSG("\tmaxPathLen status: ERROR");
+ return ASN_PATHLEN_INV_E;
+ }
+ }
+ } else if (cert->ca && cert->isCA) {
+ /* case where cert->pathLength extension is not set */
+ if (cert->ca->maxPathLen > 0) {
+ cert->maxPathLen = cert->ca->maxPathLen - 1;
+ } else {
+ cert->maxPathLen = 0;
+ if (verify != NO_VERIFY && type != CA_TYPE &&
+ type != TRUSTED_PEER_TYPE) {
+ WOLFSSL_MSG("\tNon-entity cert, maxPathLen is 0");
+ WOLFSSL_MSG("\tmaxPathLen status: ERROR");
+ return ASN_PATHLEN_INV_E;
+ }
+ }
+ }
+ #ifdef HAVE_OCSP
+ if (verify != NO_VERIFY && type != CA_TYPE &&
+ type != TRUSTED_PEER_TYPE) {
+ if (cert->ca) {
+ /* Need the CA's public key hash for OCSP */
+ XMEMCPY(cert->issuerKeyHash, cert->ca->subjectKeyHash,
+ KEYID_SIZE);
+ }
+
+ }
+ #endif /* HAVE_OCSP */
+ }
+ }
+#if defined(WOLFSSL_RENESAS_TSIP)
+ /* prepare for TSIP TLS cert verification API use */
+ if (cert->keyOID == RSAk) {
+ /* to call TSIP API, it needs keys position info in bytes */
+ if ((ret = RsaPublicKeyDecodeRawIndex(cert->publicKey, (word32*)&idx,
+ cert->pubKeySize,
+ &cert->sigCtx.pubkey_n_start,
+ &cert->sigCtx.pubkey_n_len,
+ &cert->sigCtx.pubkey_e_start,
+ &cert->sigCtx.pubkey_e_len)) != 0) {
+ WOLFSSL_MSG("Decoding index from cert failed.");
+ return ret;
+ }
+ cert->sigCtx.certBegin = cert->certBegin;
+ }
+ /* check if we can use TSIP for cert verification */
+ /* if the ca is verified as tsip root ca. */
+ /* TSIP can only handle 2048 bits(256 byte) key. */
+ if (cert->ca && tsip_checkCA(cert->ca->cm_idx) != 0 &&
+ cert->sigCtx.pubkey_n_len == 256) {
+
+ /* assign memory to encrypted tsip Rsa key index */
+ if (!cert->tsip_encRsaKeyIdx)
+ cert->tsip_encRsaKeyIdx =
+ (byte*)XMALLOC(TSIP_TLS_ENCPUBKEY_SZ_BY_CERTVRFY,
+ cert->heap, DYNAMIC_TYPE_RSA);
+ if (cert->tsip_encRsaKeyIdx == NULL)
+ return MEMORY_E;
+ } else {
+ if (cert->ca) {
+ /* TSIP isn't usable */
+ if (tsip_checkCA(cert->ca->cm_idx) == 0)
+ WOLFSSL_MSG("TSIP isn't usable because the ca isn't verified "
+ "by TSIP.");
+ else if (cert->sigCtx.pubkey_n_len != 256)
+ WOLFSSL_MSG("TSIP isn't usable because the ca isn't signed by "
+ "RSA 2048.");
+ else
+ WOLFSSL_MSG("TSIP isn't usable");
+ }
+ cert->tsip_encRsaKeyIdx = NULL;
+ }
+
+ tsip_encRsaKeyIdx = cert->tsip_encRsaKeyIdx;
+#else
+ tsip_encRsaKeyIdx = NULL;
+#endif
+
+ if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) {
+ if (cert->ca) {
+ if (verify == VERIFY || verify == VERIFY_OCSP ||
+ verify == VERIFY_SKIP_DATE) {
+ /* try to confirm/verify signature */
+ if ((ret = ConfirmSignature(&cert->sigCtx,
+ cert->source + cert->certBegin,
cert->sigIndex - cert->certBegin,
- ca->publicKey, ca->pubKeySize, ca->keyOID,
- cert->signature, cert->sigLength, cert->signatureOID,
- cert->heap)) {
- WOLFSSL_MSG("Confirm signature failed");
- return ASN_SIG_CONFIRM_E;
+ cert->ca->publicKey, cert->ca->pubKeySize,
+ cert->ca->keyOID, cert->signature,
+ cert->sigLength, cert->signatureOID,
+ tsip_encRsaKeyIdx)) != 0) {
+ if (ret != 0 && ret != WC_PENDING_E) {
+ WOLFSSL_MSG("Confirm signature failed");
+ }
+ return ret;
+ }
}
-#ifndef IGNORE_NAME_CONSTRAINTS
- /* check that this cert's name is permitted by the signer's
- * name constraints */
- if (!ConfirmNameConstraints(ca, cert)) {
- WOLFSSL_MSG("Confirm name constraint failed");
- return ASN_NAME_INVALID_E;
+ #ifndef IGNORE_NAME_CONSTRAINTS
+ if (verify == VERIFY || verify == VERIFY_OCSP ||
+ verify == VERIFY_NAME || verify == VERIFY_SKIP_DATE) {
+ /* check that this cert's name is permitted by the signer's
+ * name constraints */
+ if (!ConfirmNameConstraints(cert->ca, cert)) {
+ WOLFSSL_MSG("Confirm name constraint failed");
+ return ASN_NAME_INVALID_E;
+ }
}
-#endif /* IGNORE_NAME_CONSTRAINTS */
+ #endif /* IGNORE_NAME_CONSTRAINTS */
}
else {
/* no signer */
@@ -4425,15 +9522,22 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
}
}
- if (badDate != 0)
- return badDate;
+#if defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY) && !defined(NO_SKID)
+exit_pcr:
+#endif
- if (criticalExt != 0)
- return criticalExt;
+ if (cert->badDate != 0) {
+ if (verify != VERIFY_SKIP_DATE) {
+ return cert->badDate;
+ }
+ WOLFSSL_MSG("Date error: Verify option is skipping");
+ }
- return 0;
-}
+ if (cert->criticalExt != 0)
+ return cert->criticalExt;
+ return ret;
+}
/* Create and init an new signer */
Signer* MakeSigner(void* heap)
@@ -4441,16 +9545,7 @@ Signer* MakeSigner(void* heap)
Signer* signer = (Signer*) XMALLOC(sizeof(Signer), heap,
DYNAMIC_TYPE_SIGNER);
if (signer) {
- signer->pubKeySize = 0;
- signer->keyOID = 0;
- signer->publicKey = NULL;
- signer->nameLen = 0;
- signer->name = NULL;
- #ifndef IGNORE_NAME_CONSTRAINTS
- signer->permittedNames = NULL;
- signer->excludedNames = NULL;
- #endif /* IGNORE_NAME_CONSTRAINTS */
- signer->next = NULL;
+ XMEMSET(signer, 0, sizeof(Signer));
}
(void)heap;
@@ -4462,13 +9557,16 @@ Signer* MakeSigner(void* heap)
void FreeSigner(Signer* signer, void* heap)
{
XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
- XFREE(signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- #ifndef IGNORE_NAME_CONSTRAINTS
- if (signer->permittedNames)
- FreeNameSubtrees(signer->permittedNames, heap);
- if (signer->excludedNames)
- FreeNameSubtrees(signer->excludedNames, heap);
- #endif
+ XFREE((void*)signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+#ifndef IGNORE_NAME_CONSTRAINTS
+ if (signer->permittedNames)
+ FreeNameSubtrees(signer->permittedNames, heap);
+ if (signer->excludedNames)
+ FreeNameSubtrees(signer->excludedNames, heap);
+#endif
+#ifdef WOLFSSL_SIGNER_DER_CERT
+ FreeDer(&signer->derCert);
+#endif
XFREE(signer, heap, DYNAMIC_TYPE_SIGNER);
(void)heap;
@@ -4491,14 +9589,59 @@ void FreeSignerTable(Signer** table, int rows, void* heap)
}
}
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* Free an individual trusted peer cert */
+void FreeTrustedPeer(TrustedPeerCert* tp, void* heap)
+{
+ if (tp == NULL) {
+ return;
+ }
+
+ if (tp->name) {
+ XFREE(tp->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
+ }
+
+ if (tp->sig) {
+ XFREE(tp->sig, heap, DYNAMIC_TYPE_SIGNATURE);
+ }
+#ifndef IGNORE_NAME_CONSTRAINTS
+ if (tp->permittedNames)
+ FreeNameSubtrees(tp->permittedNames, heap);
+ if (tp->excludedNames)
+ FreeNameSubtrees(tp->excludedNames, heap);
+#endif
+ XFREE(tp, heap, DYNAMIC_TYPE_CERT);
+
+ (void)heap;
+}
+
+/* Free the whole Trusted Peer linked list */
+void FreeTrustedPeerTable(TrustedPeerCert** table, int rows, void* heap)
+{
+ int i;
+
+ for (i = 0; i < rows; i++) {
+ TrustedPeerCert* tp = table[i];
+ while (tp) {
+ TrustedPeerCert* next = tp->next;
+ FreeTrustedPeer(tp, heap);
+ tp = next;
+ }
+ table[i] = NULL;
+ }
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
-WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header)
+int SetMyVersion(word32 version, byte* output, int header)
{
int i = 0;
+ if (output == NULL)
+ return BAD_FUNC_ARG;
+
if (header) {
output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED;
- output[i++] = ASN_BIT_STRING;
+ output[i++] = 3;
}
output[i++] = ASN_INTEGER;
output[i++] = 0x01;
@@ -4507,65 +9650,558 @@ WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header)
return i;
}
+int SetSerialNumber(const byte* sn, word32 snSz, byte* output,
+ word32 outputSz, int maxSnSz)
+{
+ int i;
+ int snSzInt = (int)snSz;
+
+ if (sn == NULL || output == NULL || snSzInt < 0)
+ return BAD_FUNC_ARG;
+
+ /* remove leading zeros */
+ while (snSzInt > 0 && sn[0] == 0) {
+ snSzInt--;
+ sn++;
+ }
+ /* RFC 5280 - 4.1.2.2:
+ * Serial numbers must be a positive value (and not zero) */
+ if (snSzInt == 0)
+ return BAD_FUNC_ARG;
+
+ if (sn[0] & 0x80)
+ maxSnSz--;
+ /* truncate if input is too long */
+ if (snSzInt > maxSnSz)
+ snSzInt = maxSnSz;
+
+ i = SetASNInt(snSzInt, sn[0], NULL);
+ /* truncate if input is too long */
+ if (snSzInt > (int)outputSz - i)
+ snSzInt = (int)outputSz - i;
+ /* sanity check number of bytes to copy */
+ if (snSzInt <= 0) {
+ return BUFFER_E;
+ }
+
+ /* write out ASN.1 Integer */
+ (void)SetASNInt(snSzInt, sn[0], output);
+ XMEMCPY(output + i, sn, snSzInt);
-WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output)
+ /* compute final length */
+ i += snSzInt;
+
+ return i;
+}
+
+#endif /* !NO_CERTS */
+
+int GetSerialNumber(const byte* input, word32* inOutIdx,
+ byte* serial, int* serialSz, word32 maxIdx)
{
int result = 0;
+ int ret;
+
+ WOLFSSL_ENTER("GetSerialNumber");
+
+ if (serial == NULL || input == NULL || serialSz == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* First byte is ASN type */
+ if ((*inOutIdx+1) > maxIdx) {
+ WOLFSSL_MSG("Bad idx first");
+ return BUFFER_E;
+ }
+
+ ret = GetASNInt(input, inOutIdx, serialSz, maxIdx);
+ if (ret != 0)
+ return ret;
+
+ if (*serialSz > EXTERNAL_SERIAL_SIZE) {
+ WOLFSSL_MSG("Serial size bad");
+ return ASN_PARSE_E;
+ }
+
+ /* return serial */
+ XMEMCPY(serial, &input[*inOutIdx], *serialSz);
+ *inOutIdx += *serialSz;
+
+ return result;
+}
- WOLFSSL_ENTER("SetSerialNumber");
+#ifndef NO_CERTS
- if (snSz <= EXTERNAL_SERIAL_SIZE) {
- output[0] = ASN_INTEGER;
- /* The serial number is always positive. When encoding the
- * INTEGER, if the MSB is 1, add a padding zero to keep the
- * number positive. */
- if (sn[0] & 0x80) {
- output[1] = (byte)snSz + 1;
- output[2] = 0;
- XMEMCPY(&output[3], sn, snSz);
- result = snSz + 3;
+int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap)
+{
+ int ret = BAD_FUNC_ARG;
+ if (pDer) {
+ int dynType = 0;
+ DerBuffer* der;
+
+ /* Determine dynamic type */
+ switch (type) {
+ case CA_TYPE: dynType = DYNAMIC_TYPE_CA; break;
+ case CERT_TYPE: dynType = DYNAMIC_TYPE_CERT; break;
+ case CRL_TYPE: dynType = DYNAMIC_TYPE_CRL; break;
+ case DSA_TYPE: dynType = DYNAMIC_TYPE_DSA; break;
+ case ECC_TYPE: dynType = DYNAMIC_TYPE_ECC; break;
+ case RSA_TYPE: dynType = DYNAMIC_TYPE_RSA; break;
+ default: dynType = DYNAMIC_TYPE_KEY; break;
}
- else {
- output[1] = (byte)snSz;
- XMEMCPY(&output[2], sn, snSz);
- result = snSz + 2;
+
+ /* Setup new buffer */
+ *pDer = (DerBuffer*)XMALLOC(sizeof(DerBuffer) + length, heap, dynType);
+ if (*pDer == NULL) {
+ return MEMORY_E;
}
+ XMEMSET(*pDer, 0, sizeof(DerBuffer) + length);
+
+ der = *pDer;
+ der->type = type;
+ der->dynType = dynType; /* Cache this for FreeDer */
+ der->heap = heap;
+ der->buffer = (byte*)der + sizeof(DerBuffer);
+ der->length = length;
+ ret = 0; /* Success */
}
- return result;
+ return ret;
}
+void FreeDer(DerBuffer** pDer)
+{
+ if (pDer && *pDer)
+ {
+ DerBuffer* der = (DerBuffer*)*pDer;
+ /* ForceZero private keys */
+ if (der->type == PRIVATEKEY_TYPE) {
+ ForceZero(der->buffer, der->length);
+ }
+ der->buffer = NULL;
+ der->length = 0;
+ XFREE(der, der->heap, der->dynType);
+ *pDer = NULL;
+ }
+}
-#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)
+int wc_AllocDer(DerBuffer** pDer, word32 length, int type, void* heap)
+{
+ return AllocDer(pDer, length, type, heap);
+}
+void wc_FreeDer(DerBuffer** pDer)
+{
+ FreeDer(pDer);
+}
+
+
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+
+/* Max X509 header length indicates the max length + 2 ('\n', '\0') */
+#define MAX_X509_HEADER_SZ (37 + 2)
+
+wcchar BEGIN_CERT = "-----BEGIN CERTIFICATE-----";
+wcchar END_CERT = "-----END CERTIFICATE-----";
+#ifdef WOLFSSL_CERT_REQ
+ wcchar BEGIN_CERT_REQ = "-----BEGIN CERTIFICATE REQUEST-----";
+ wcchar END_CERT_REQ = "-----END CERTIFICATE REQUEST-----";
+#endif
+#ifndef NO_DH
+ wcchar BEGIN_DH_PARAM = "-----BEGIN DH PARAMETERS-----";
+ wcchar END_DH_PARAM = "-----END DH PARAMETERS-----";
+#endif
+#ifndef NO_DSA
+ wcchar BEGIN_DSA_PARAM = "-----BEGIN DSA PARAMETERS-----";
+ wcchar END_DSA_PARAM = "-----END DSA PARAMETERS-----";
+#endif
+wcchar BEGIN_X509_CRL = "-----BEGIN X509 CRL-----";
+wcchar END_X509_CRL = "-----END X509 CRL-----";
+wcchar BEGIN_RSA_PRIV = "-----BEGIN RSA PRIVATE KEY-----";
+wcchar END_RSA_PRIV = "-----END RSA PRIVATE KEY-----";
+wcchar BEGIN_PRIV_KEY = "-----BEGIN PRIVATE KEY-----";
+wcchar END_PRIV_KEY = "-----END PRIVATE KEY-----";
+wcchar BEGIN_ENC_PRIV_KEY = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
+wcchar END_ENC_PRIV_KEY = "-----END ENCRYPTED PRIVATE KEY-----";
+#ifdef HAVE_ECC
+ wcchar BEGIN_EC_PRIV = "-----BEGIN EC PRIVATE KEY-----";
+ wcchar END_EC_PRIV = "-----END EC PRIVATE KEY-----";
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
+ !defined(NO_DSA)
+ wcchar BEGIN_DSA_PRIV = "-----BEGIN DSA PRIVATE KEY-----";
+ wcchar END_DSA_PRIV = "-----END DSA PRIVATE KEY-----";
+#endif
+#ifdef OPENSSL_EXTRA
+ const char BEGIN_PRIV_KEY_PREFIX[] = "-----BEGIN";
+ const char PRIV_KEY_SUFFIX[] = "PRIVATE KEY-----";
+ const char END_PRIV_KEY_PREFIX[] = "-----END";
+#endif
+wcchar BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----";
+wcchar END_PUB_KEY = "-----END PUBLIC KEY-----";
+#if defined(HAVE_ED25519) || defined(HAVE_ED448)
+ wcchar BEGIN_EDDSA_PRIV = "-----BEGIN EDDSA PRIVATE KEY-----";
+ wcchar END_EDDSA_PRIV = "-----END EDDSA PRIVATE KEY-----";
+#endif
+#ifdef HAVE_CRL
+ const char *const BEGIN_CRL = "-----BEGIN X509 CRL-----";
+ wcchar END_CRL = "-----END X509 CRL-----";
+#endif
+
+
+static WC_INLINE char* SkipEndOfLineChars(char* line, const char* endOfLine)
+{
+ /* eat end of line characters */
+ while (line < endOfLine &&
+ (line[0] == '\r' || line[0] == '\n')) {
+ line++;
+ }
+ return line;
+}
+
+int wc_PemGetHeaderFooter(int type, const char** header, const char** footer)
+{
+ int ret = BAD_FUNC_ARG;
+
+ switch (type) {
+ case CA_TYPE: /* same as below */
+ case TRUSTED_PEER_TYPE:
+ case CERT_TYPE:
+ if (header) *header = BEGIN_CERT;
+ if (footer) *footer = END_CERT;
+ ret = 0;
+ break;
+
+ case CRL_TYPE:
+ if (header) *header = BEGIN_X509_CRL;
+ if (footer) *footer = END_X509_CRL;
+ ret = 0;
+ break;
+ #ifndef NO_DH
+ case DH_PARAM_TYPE:
+ if (header) *header = BEGIN_DH_PARAM;
+ if (footer) *footer = END_DH_PARAM;
+ ret = 0;
+ break;
+ #endif
+ #ifndef NO_DSA
+ case DSA_PARAM_TYPE:
+ if (header) *header = BEGIN_DSA_PARAM;
+ if (footer) *footer = END_DSA_PARAM;
+ ret = 0;
+ break;
+ #endif
+ #ifdef WOLFSSL_CERT_REQ
+ case CERTREQ_TYPE:
+ if (header) *header = BEGIN_CERT_REQ;
+ if (footer) *footer = END_CERT_REQ;
+ ret = 0;
+ break;
+ #endif
+ #ifndef NO_DSA
+ case DSA_TYPE:
+ case DSA_PRIVATEKEY_TYPE:
+ if (header) *header = BEGIN_DSA_PRIV;
+ if (footer) *footer = END_DSA_PRIV;
+ ret = 0;
+ break;
+ #endif
+ #ifdef HAVE_ECC
+ case ECC_TYPE:
+ case ECC_PRIVATEKEY_TYPE:
+ if (header) *header = BEGIN_EC_PRIV;
+ if (footer) *footer = END_EC_PRIV;
+ ret = 0;
+ break;
+ #endif
+ case RSA_TYPE:
+ case PRIVATEKEY_TYPE:
+ if (header) *header = BEGIN_RSA_PRIV;
+ if (footer) *footer = END_RSA_PRIV;
+ ret = 0;
+ break;
+ #ifdef HAVE_ED25519
+ case ED25519_TYPE:
+ #endif
+ #ifdef HAVE_ED448
+ case ED448_TYPE:
+ #endif
+ #if defined(HAVE_ED25519) || defined(HAVE_ED448)
+ case EDDSA_PRIVATEKEY_TYPE:
+ if (header) *header = BEGIN_EDDSA_PRIV;
+ if (footer) *footer = END_EDDSA_PRIV;
+ ret = 0;
+ break;
+ #endif
+ case PUBLICKEY_TYPE:
+ case ECC_PUBLICKEY_TYPE:
+ if (header) *header = BEGIN_PUB_KEY;
+ if (footer) *footer = END_PUB_KEY;
+ ret = 0;
+ break;
+ #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+ case DH_PRIVATEKEY_TYPE:
+ #endif
+ case PKCS8_PRIVATEKEY_TYPE:
+ if (header) *header = BEGIN_PRIV_KEY;
+ if (footer) *footer = END_PRIV_KEY;
+ ret = 0;
+ break;
+ case PKCS8_ENC_PRIVATEKEY_TYPE:
+ if (header) *header = BEGIN_ENC_PRIV_KEY;
+ if (footer) *footer = END_ENC_PRIV_KEY;
+ ret = 0;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+
+static wcchar kProcTypeHeader = "Proc-Type";
+static wcchar kDecInfoHeader = "DEK-Info";
+
+#ifdef WOLFSSL_PEM_TO_DER
+#ifndef NO_DES3
+ static wcchar kEncTypeDes = "DES-CBC";
+ static wcchar kEncTypeDes3 = "DES-EDE3-CBC";
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128)
+ static wcchar kEncTypeAesCbc128 = "AES-128-CBC";
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_192)
+ static wcchar kEncTypeAesCbc192 = "AES-192-CBC";
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256)
+ static wcchar kEncTypeAesCbc256 = "AES-256-CBC";
+#endif
+
+int wc_EncryptedInfoGet(EncryptedInfo* info, const char* cipherInfo)
+{
+ int ret = 0;
+
+ if (info == NULL || cipherInfo == NULL)
+ return BAD_FUNC_ARG;
+
+ /* determine cipher information */
+#ifndef NO_DES3
+ if (XSTRNCMP(cipherInfo, kEncTypeDes, XSTRLEN(kEncTypeDes)) == 0) {
+ info->cipherType = WC_CIPHER_DES;
+ info->keySz = DES_KEY_SIZE;
+ if (info->ivSz == 0) info->ivSz = DES_IV_SIZE;
+ }
+ else if (XSTRNCMP(cipherInfo, kEncTypeDes3, XSTRLEN(kEncTypeDes3)) == 0) {
+ info->cipherType = WC_CIPHER_DES3;
+ info->keySz = DES3_KEY_SIZE;
+ if (info->ivSz == 0) info->ivSz = DES_IV_SIZE;
+ }
+ else
+#endif /* !NO_DES3 */
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128)
+ if (XSTRNCMP(cipherInfo, kEncTypeAesCbc128, XSTRLEN(kEncTypeAesCbc128)) == 0) {
+ info->cipherType = WC_CIPHER_AES_CBC;
+ info->keySz = AES_128_KEY_SIZE;
+ if (info->ivSz == 0) info->ivSz = AES_IV_SIZE;
+ }
+ else
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_192)
+ if (XSTRNCMP(cipherInfo, kEncTypeAesCbc192, XSTRLEN(kEncTypeAesCbc192)) == 0) {
+ info->cipherType = WC_CIPHER_AES_CBC;
+ info->keySz = AES_192_KEY_SIZE;
+ if (info->ivSz == 0) info->ivSz = AES_IV_SIZE;
+ }
+ else
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256)
+ if (XSTRNCMP(cipherInfo, kEncTypeAesCbc256, XSTRLEN(kEncTypeAesCbc256)) == 0) {
+ info->cipherType = WC_CIPHER_AES_CBC;
+ info->keySz = AES_256_KEY_SIZE;
+ if (info->ivSz == 0) info->ivSz = AES_IV_SIZE;
+ }
+ else
+#endif
+ {
+ ret = NOT_COMPILED_IN;
+ }
+ return ret;
+}
+
+int wc_EncryptedInfoParse(EncryptedInfo* info, char** pBuffer, size_t bufSz)
+{
+ int err = 0;
+ char* bufferStart;
+ char* bufferEnd;
+ char* line;
+ word32 lineSz;
+ char* finish;
+ word32 finishSz;
+ char* start = NULL;
+ word32 startSz;
+ char* newline = NULL;
+
+ if (info == NULL || pBuffer == NULL || bufSz == 0)
+ return BAD_FUNC_ARG;
+
+ bufferStart = *pBuffer;
+ bufferEnd = bufferStart + bufSz;
+
+ /* find encrypted info marker */
+ line = XSTRNSTR(bufferStart, kProcTypeHeader,
+ min((word32)bufSz, PEM_LINE_LEN));
+ if (line != NULL) {
+ if (line >= bufferEnd) {
+ return BUFFER_E;
+ }
+
+ lineSz = (word32)(bufferEnd - line);
+
+ /* find DEC-Info marker */
+ start = XSTRNSTR(line, kDecInfoHeader, min(lineSz, PEM_LINE_LEN));
+
+ if (start == NULL)
+ return BUFFER_E;
+
+ /* skip dec-info and ": " */
+ start += XSTRLEN(kDecInfoHeader);
+ if (start >= bufferEnd)
+ return BUFFER_E;
+
+ if (start[0] == ':') {
+ start++;
+ if (start >= bufferEnd)
+ return BUFFER_E;
+ }
+ if (start[0] == ' ')
+ start++;
+
+ startSz = (word32)(bufferEnd - start);
+ finish = XSTRNSTR(start, ",", min(startSz, PEM_LINE_LEN));
+
+ if ((start != NULL) && (finish != NULL) && (start < finish)) {
+ if (finish >= bufferEnd) {
+ return BUFFER_E;
+ }
+
+ finishSz = (word32)(bufferEnd - finish);
+ newline = XSTRNSTR(finish, "\r", min(finishSz, PEM_LINE_LEN));
+
+ /* get cipher name */
+ if (NAME_SZ < (finish - start)) /* buffer size of info->name */
+ return BUFFER_E;
+ if (XMEMCPY(info->name, start, finish - start) == NULL)
+ return BUFFER_E;
+ info->name[finish - start] = '\0'; /* null term */
+
+ /* populate info */
+ err = wc_EncryptedInfoGet(info, info->name);
+ if (err != 0)
+ return err;
+
+ /* get IV */
+ if (finishSz < info->ivSz + 1)
+ return BUFFER_E;
+
+ if (newline == NULL) {
+ newline = XSTRNSTR(finish, "\n", min(finishSz,
+ PEM_LINE_LEN));
+ }
+ if ((newline != NULL) && (newline > finish)) {
+ finish++;
+ info->ivSz = (word32)(newline - finish);
+ if (info->ivSz > IV_SZ)
+ return BUFFER_E;
+ if (XMEMCPY(info->iv, finish, info->ivSz) == NULL)
+ return BUFFER_E;
+ info->set = 1;
+ }
+ else
+ return BUFFER_E;
+ }
+ else
+ return BUFFER_E;
+
+ /* eat end of line characters */
+ newline = SkipEndOfLineChars(newline, bufferEnd);
+
+ /* return new headerEnd */
+
+ *pBuffer = newline;
+ }
+
+ return err;
+}
+#endif /* WOLFSSL_PEM_TO_DER */
+
+#ifdef WOLFSSL_DER_TO_PEM
+static int wc_EncryptedInfoAppend(char* dest, int destSz, char* cipherInfo)
+{
+ if (cipherInfo != NULL) {
+ int cipherInfoStrLen = (int)XSTRLEN((char*)cipherInfo);
+
+ if (cipherInfoStrLen > HEADER_ENCRYPTED_KEY_SIZE - (9+14+10+3))
+ cipherInfoStrLen = HEADER_ENCRYPTED_KEY_SIZE - (9+14+10+3);
+
+ if (destSz - (int)XSTRLEN(dest) >= cipherInfoStrLen + (9+14+8+2+2+1)) {
+ /* strncat's src length needs to include the NULL */
+ XSTRNCAT(dest, kProcTypeHeader, 10);
+ XSTRNCAT(dest, ": 4,ENCRYPTED\n", 15);
+ XSTRNCAT(dest, kDecInfoHeader, 9);
+ XSTRNCAT(dest, ": ", 3);
+ XSTRNCAT(dest, cipherInfo, destSz - (int)XSTRLEN(dest) - 1);
+ XSTRNCAT(dest, "\n\n", 4);
+ }
+ }
+ return 0;
+}
+#endif /* WOLFSSL_DER_TO_PEM */
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
+#ifdef WOLFSSL_DER_TO_PEM
+
+/* Used for compatibility API */
+int wc_DerToPem(const byte* der, word32 derSz,
+ byte* output, word32 outSz, int type)
+{
+ return wc_DerToPemEx(der, derSz, output, outSz, NULL, type);
+}
/* convert der buffer to pem into output, can't do inplace, der and output
need to be different */
-int wc_DerToPem(const byte* der, word32 derSz, byte* output, word32 outSz,
- int type)
+int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz,
+ byte *cipher_info, int type)
{
+ const char* headerStr = NULL;
+ const char* footerStr = NULL;
#ifdef WOLFSSL_SMALL_STACK
char* header = NULL;
char* footer = NULL;
#else
- char header[80];
- char footer[80];
+ char header[MAX_X509_HEADER_SZ + HEADER_ENCRYPTED_KEY_SIZE];
+ char footer[MAX_X509_HEADER_SZ];
#endif
-
- int headerLen = 80;
- int footerLen = 80;
+ int headerLen = MAX_X509_HEADER_SZ + HEADER_ENCRYPTED_KEY_SIZE;
+ int footerLen = MAX_X509_HEADER_SZ;
int i;
int err;
int outLen; /* return length or error */
+ (void)cipher_info;
+
if (der == output) /* no in place conversion */
return BAD_FUNC_ARG;
+ err = wc_PemGetHeaderFooter(type, &headerStr, &footerStr);
+ if (err != 0)
+ return err;
+
#ifdef WOLFSSL_SMALL_STACK
header = (char*)XMALLOC(headerLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (header == NULL)
return MEMORY_E;
-
+
footer = (char*)XMALLOC(footerLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (footer == NULL) {
XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
@@ -4573,39 +10209,44 @@ int wc_DerToPem(const byte* der, word32 derSz, byte* output, word32 outSz,
}
#endif
- if (type == CERT_TYPE) {
- XSTRNCPY(header, "-----BEGIN CERTIFICATE-----\n", headerLen);
- XSTRNCPY(footer, "-----END CERTIFICATE-----\n", footerLen);
- }
- else if (type == PRIVATEKEY_TYPE) {
- XSTRNCPY(header, "-----BEGIN RSA PRIVATE KEY-----\n", headerLen);
- XSTRNCPY(footer, "-----END RSA PRIVATE KEY-----\n", footerLen);
- }
- #ifdef HAVE_ECC
- else if (type == ECC_PRIVATEKEY_TYPE) {
- XSTRNCPY(header, "-----BEGIN EC PRIVATE KEY-----\n", headerLen);
- XSTRNCPY(footer, "-----END EC PRIVATE KEY-----\n", footerLen);
- }
+ /* build header and footer based on type */
+ XSTRNCPY(header, headerStr, headerLen - 1);
+ header[headerLen - 2] = 0;
+ XSTRNCPY(footer, footerStr, footerLen - 1);
+ footer[footerLen - 2] = 0;
+
+ /* add new line to end */
+ XSTRNCAT(header, "\n", 2);
+ XSTRNCAT(footer, "\n", 2);
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+ err = wc_EncryptedInfoAppend(header, headerLen, (char*)cipher_info);
+ if (err != 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- #ifdef WOLFSSL_CERT_REQ
- else if (type == CERTREQ_TYPE)
- {
- XSTRNCPY(header,
- "-----BEGIN CERTIFICATE REQUEST-----\n", headerLen);
- XSTRNCPY(footer, "-----END CERTIFICATE REQUEST-----\n", footerLen);
+ return err;
}
- #endif
- else {
+#endif
+
+ headerLen = (int)XSTRLEN(header);
+ footerLen = (int)XSTRLEN(footer);
+
+ /* if null output and 0 size passed in then return size needed */
+ if (!output && outSz == 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- return BAD_FUNC_ARG;
+ outLen = 0;
+ if ((err = Base64_Encode(der, derSz, NULL, (word32*)&outLen))
+ != LENGTH_ONLY_E) {
+ return err;
+ }
+ return headerLen + footerLen + outLen;
}
- headerLen = (int)XSTRLEN(header);
- footerLen = (int)XSTRLEN(footer);
-
if (!der || !output) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
@@ -4657,12 +10298,846 @@ int wc_DerToPem(const byte* der, word32 derSz, byte* output, word32 outSz,
return outLen + headerLen + footerLen;
}
+#endif /* WOLFSSL_DER_TO_PEM */
+
+#ifdef WOLFSSL_PEM_TO_DER
+
+/* 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,
+ DerBuffer** pDer, void* heap, EncryptedInfo* info, int* keyFormat)
+{
+ 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 sz = (int)longSz;
+ int encrypted_key = 0;
+ DerBuffer* der;
+#if defined(HAVE_PKCS8) || defined(WOLFSSL_ENCRYPTED_KEYS)
+ word32 algId = 0;
+ #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_DES3) && !defined(NO_WOLFSSL_SKIP_TRAILING_PAD)
+ int padVal = 0;
+ #endif
+#endif
+#ifdef OPENSSL_EXTRA
+ char beginBuf[PEM_LINE_LEN + 1]; /* add 1 for null terminator */
+ char endBuf[PEM_LINE_LEN + 1]; /* add 1 for null terminator */
+#endif
+
+ WOLFSSL_ENTER("PemToDer");
+
+ /* get PEM header and footer based on type */
+ ret = wc_PemGetHeaderFooter(type, &header, &footer);
+ if (ret != 0)
+ return ret;
+
+ /* map header if not found for type */
+ for (;;) {
+ headerEnd = XSTRNSTR((char*)buff, header, sz);
+
+ if (headerEnd) {
+ break;
+ } else
+ if (type == PRIVATEKEY_TYPE) {
+ 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
+ #ifdef HAVE_ECC
+ 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
+ #endif
+ #if defined(HAVE_ED25519) || defined(HAVE_ED448)
+ #ifdef HAVE_ECC
+ if (header == BEGIN_DSA_PRIV)
+ #else
+ if (header == BEGIN_ENC_PRIV_KEY)
+ #endif
+ {
+ header = BEGIN_EDDSA_PRIV; footer = END_EDDSA_PRIV;
+ } else
+ #endif
+ {
+ break;
+ }
+ } else
+#ifdef HAVE_CRL
+ if ((type == CRL_TYPE) && (header != BEGIN_CRL)) {
+ header = BEGIN_CRL; footer = END_CRL;
+ } else
+#endif
+ {
+ break;
+ }
+ }
+
+ if (!headerEnd) {
+#ifdef OPENSSL_EXTRA
+ char* beginEnd;
+ int endLen;
+ /* see if there is a -----BEGIN * PRIVATE KEY----- header */
+ headerEnd = XSTRNSTR((char*)buff, PRIV_KEY_SUFFIX, sz);
+ if (headerEnd) {
+ beginEnd = headerEnd + XSTR_SIZEOF(PRIV_KEY_SUFFIX);
+ /* back up to BEGIN_PRIV_KEY_PREFIX */
+ headerEnd -= XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX);
+ while (headerEnd > (char*)buff &&
+ XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX,
+ XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0) {
+ headerEnd--;
+ }
+ if (headerEnd <= (char*)buff ||
+ XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX,
+ XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0 ||
+ beginEnd - headerEnd > PEM_LINE_LEN) {
+ WOLFSSL_MSG("Couldn't find PEM header");
+ return ASN_NO_PEM_HEADER;
+ }
+ /* headerEnd now points to beginning of header */
+ XMEMCPY(beginBuf, headerEnd, beginEnd - headerEnd);
+ beginBuf[beginEnd - headerEnd] = '\0';
+ /* look for matching footer */
+ footer = XSTRNSTR(beginEnd,
+ beginBuf + XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX),
+ (unsigned int)((char*)buff + sz - beginEnd));
+ if (!footer) {
+ WOLFSSL_MSG("Couldn't find PEM footer");
+ return ASN_NO_PEM_HEADER;
+ }
+ footer -= XSTR_SIZEOF(END_PRIV_KEY_PREFIX);
+ endLen = (unsigned int)(beginEnd - headerEnd -
+ (XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX) -
+ XSTR_SIZEOF(END_PRIV_KEY_PREFIX)));
+ XMEMCPY(endBuf, footer, endLen);
+ endBuf[endLen] = '\0';
+
+ header = beginBuf;
+ footer = endBuf;
+ headerEnd = beginEnd;
+ } else {
+ WOLFSSL_MSG("Couldn't find PEM header");
+ return ASN_NO_PEM_HEADER;
+ }
+#else
+ WOLFSSL_MSG("Couldn't find PEM header");
+ return ASN_NO_PEM_HEADER;
+#endif
+ } else {
+ headerEnd += XSTRLEN(header);
+ }
+
+ /* eat end of line characters */
+ headerEnd = SkipEndOfLineChars(headerEnd, bufferEnd);
+
+ if (type == PRIVATEKEY_TYPE) {
+ /* keyFormat is Key_Sum enum */
+ if (keyFormat) {
+ #ifdef HAVE_ECC
+ if (header == BEGIN_EC_PRIV)
+ *keyFormat = ECDSAk;
+ #endif
+ #if !defined(NO_DSA)
+ if (header == BEGIN_DSA_PRIV)
+ *keyFormat = DSAk;
+ #endif
+ }
+ }
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+ if (info) {
+ ret = wc_EncryptedInfoParse(info, &headerEnd, bufferEnd - headerEnd);
+ if (ret < 0)
+ return ret;
+ if (info->set)
+ encrypted_key = 1;
+ }
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
+ /* find footer */
+ footerEnd = XSTRNSTR(headerEnd, footer, (unsigned int)((char*)buff + sz - headerEnd));
+ if (!footerEnd) {
+ if (info)
+ info->consumed = longSz; /* No more certs if no footer */
+ return BUFFER_E;
+ }
+
+ consumedEnd = footerEnd + XSTRLEN(footer);
+
+ if (consumedEnd < bufferEnd) { /* handle no end of line on last line */
+ /* eat end of line characters */
+ consumedEnd = SkipEndOfLineChars(consumedEnd, bufferEnd);
+ /* skip possible null term */
+ if (consumedEnd < bufferEnd && consumedEnd[0] == '\0')
+ consumedEnd++;
+ }
+
+ if (info)
+ info->consumed = (long)(consumedEnd - (char*)buff);
+
+ /* set up der buffer */
+ neededSz = (long)(footerEnd - headerEnd);
+ if (neededSz > sz || neededSz <= 0)
+ return BUFFER_E;
+
+ ret = AllocDer(pDer, (word32)neededSz, type, heap);
+ if (ret < 0) {
+ return ret;
+ }
+ der = *pDer;
+
+ if (Base64_Decode((byte*)headerEnd, (word32)neededSz,
+ der->buffer, &der->length) < 0)
+ return BUFFER_E;
+
+ if ((header == BEGIN_PRIV_KEY
+#ifdef OPENSSL_EXTRA
+ || header == beginBuf
+#endif
+#ifdef HAVE_ECC
+ || header == BEGIN_EC_PRIV
+#endif
+ ) && !encrypted_key)
+ {
+ #ifdef HAVE_PKCS8
+ /* pkcs8 key, convert and adjust length */
+ if ((ret = ToTraditional_ex(der->buffer, der->length, &algId)) > 0) {
+ der->length = ret;
+ if (keyFormat) {
+ *keyFormat = algId;
+ }
+ }
+ else {
+ /* ignore failure here and assume key is not pkcs8 wrapped */
+ }
+ #endif
+
+ return 0;
+ }
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+ if (encrypted_key || header == BEGIN_ENC_PRIV_KEY) {
+ int passwordSz = NAME_SZ;
+ #ifdef WOLFSSL_SMALL_STACK
+ char* password = NULL;
+ #else
+ char password[NAME_SZ];
+ #endif
+
+ if (!info || !info->passwd_cb) {
+ WOLFSSL_MSG("No password callback set");
+ return NO_PASSWORD;
+ }
+
+ #ifdef WOLFSSL_SMALL_STACK
+ password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING);
+ if (password == NULL)
+ return MEMORY_E;
+ #endif
+
+ /* get password */
+ ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ,
+ info->passwd_userdata);
+ if (ret >= 0) {
+ passwordSz = ret;
+
+ /* convert and adjust length */
+ if (header == BEGIN_ENC_PRIV_KEY) {
+ #ifndef NO_PWDBASED
+ ret = ToTraditionalEnc(der->buffer, der->length,
+ password, passwordSz, &algId);
+
+ if (ret >= 0) {
+ der->length = ret;
+ if (keyFormat) {
+ *keyFormat = algId;
+ }
+ ret = 0;
+ }
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif
+ }
+ /* decrypt the key */
+ else {
+ if (passwordSz == 0) {
+ /* The key is encrypted but does not have a password */
+ WOLFSSL_MSG("No password for encrypted key");
+ ret = NO_PASSWORD;
+ }
+ else {
+ ret = wc_BufferKeyDecrypt(info, der->buffer, der->length,
+ (byte*)password, passwordSz, WC_MD5);
+
+#ifndef NO_WOLFSSL_SKIP_TRAILING_PAD
+ #ifndef NO_DES3
+ if (info->cipherType == WC_CIPHER_DES3) {
+ padVal = der->buffer[der->length-1];
+ if (padVal <= DES_BLOCK_SIZE) {
+ der->length -= padVal;
+ }
+ }
+ #endif /* !NO_DES3 */
+#endif /* !NO_WOLFSSL_SKIP_TRAILING_PAD */
+ }
+ }
+#ifdef OPENSSL_EXTRA
+ if (ret) {
+ PEMerr(0, PEM_R_BAD_DECRYPT);
+ }
+#endif
+ ForceZero(password, passwordSz);
+ }
+#ifdef OPENSSL_EXTRA
+ else {
+ PEMerr(0, PEM_R_BAD_PASSWORD_READ);
+ }
+#endif
+
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(password, heap, DYNAMIC_TYPE_STRING);
+ #endif
+ }
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
+ return ret;
+}
+
+int wc_PemToDer(const unsigned char* buff, long longSz, int type,
+ DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey)
+{
+ return PemToDer(buff, longSz, type, pDer, heap, info, eccKey);
+}
+
+
+/* our KeyPemToDer password callback, password in userData */
+static WC_INLINE int OurPasswordCb(char* passwd, int sz, int rw, void* userdata)
+{
+ (void)rw;
+
+ if (userdata == NULL)
+ return 0;
+
+ XSTRNCPY(passwd, (char*)userdata, sz);
+ return min((word32)sz, (word32)XSTRLEN((char*)userdata));
+}
+
+/* Return bytes written to buff or < 0 for error */
+int wc_KeyPemToDer(const unsigned char* pem, int pemSz,
+ unsigned char* buff, int buffSz, const char* pass)
+{
+ int eccKey = 0;
+ int ret;
+ DerBuffer* der = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ EncryptedInfo* info = NULL;
+#else
+ EncryptedInfo info[1];
+#endif
+
+ WOLFSSL_ENTER("wc_KeyPemToDer");
+
+ if (pem == NULL || buff == NULL || buffSz <= 0) {
+ WOLFSSL_MSG("Bad pem der args");
+ return BAD_FUNC_ARG;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
+ DYNAMIC_TYPE_ENCRYPTEDINFO);
+ if (info == NULL)
+ return MEMORY_E;
+#endif
+
+ XMEMSET(info, 0, sizeof(EncryptedInfo));
+ info->passwd_cb = OurPasswordCb;
+ info->passwd_userdata = (void*)pass;
+
+ ret = PemToDer(pem, pemSz, PRIVATEKEY_TYPE, &der, NULL, info, &eccKey);
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+
+ if (ret < 0 || der == NULL) {
+ 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;
+ }
+ }
+
+ FreeDer(&der);
+ return ret;
+}
+
+
+/* Return bytes written to buff or < 0 for error */
+int wc_CertPemToDer(const unsigned char* pem, int pemSz,
+ unsigned char* buff, int buffSz, int type)
+{
+ int eccKey = 0;
+ int ret;
+ DerBuffer* der = NULL;
+
+ WOLFSSL_ENTER("wc_CertPemToDer");
+
+ if (pem == NULL || buff == NULL || buffSz <= 0) {
+ WOLFSSL_MSG("Bad pem der args");
+ return BAD_FUNC_ARG;
+ }
+
+ if (type != CERT_TYPE && type != CA_TYPE && type != CERTREQ_TYPE) {
+ WOLFSSL_MSG("Bad cert type");
+ return BAD_FUNC_ARG;
+ }
+
+
+ ret = PemToDer(pem, pemSz, type, &der, NULL, NULL, &eccKey);
+ if (ret < 0 || der == NULL) {
+ 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;
+ }
+ }
+
+ FreeDer(&der);
+ return ret;
+}
+
+#endif /* WOLFSSL_PEM_TO_DER */
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+
+
+#ifdef WOLFSSL_PEM_TO_DER
+#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
+/* Return bytes written to buff or < 0 for error */
+int wc_PubKeyPemToDer(const unsigned char* pem, int pemSz,
+ unsigned char* buff, int buffSz)
+{
+ int ret;
+ DerBuffer* der = NULL;
+
+ WOLFSSL_ENTER("wc_PubKeyPemToDer");
+
+ if (pem == NULL || buff == NULL || buffSz <= 0) {
+ WOLFSSL_MSG("Bad pem der args");
+ return BAD_FUNC_ARG;
+ }
+
+ ret = PemToDer(pem, pemSz, PUBLICKEY_TYPE, &der, NULL, NULL, NULL);
+ if (ret < 0 || der == NULL) {
+ 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;
+ }
+ }
+
+ FreeDer(&der);
+ return ret;
+}
+#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */
+#endif /* WOLFSSL_PEM_TO_DER */
+
+#ifndef NO_FILESYSTEM
+
+#ifdef WOLFSSL_CERT_GEN
+/* load pem cert from file into der buffer, return der size or error */
+int wc_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz)
+{
+#ifdef WOLFSSL_SMALL_STACK
+ byte staticBuffer[1]; /* force XMALLOC */
+#else
+ byte staticBuffer[FILE_BUFFER_SIZE];
+#endif
+ byte* fileBuf = staticBuffer;
+ int dynamic = 0;
+ int ret = 0;
+ long sz = 0;
+ XFILE file;
+ DerBuffer* converted = NULL;
+
+ WOLFSSL_ENTER("wc_PemCertToDer");
+
+ if (fileName == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ file = XFOPEN(fileName, "rb");
+ if (file == XBADFILE) {
+ ret = BUFFER_E;
+ }
+ }
+
+ if (ret == 0) {
+ if(XFSEEK(file, 0, XSEEK_END) != 0)
+ ret = BUFFER_E;
+ sz = XFTELL(file);
+ XREWIND(file);
+
+ if (sz <= 0) {
+ ret = BUFFER_E;
+ }
+ else if (sz > (long)sizeof(staticBuffer)) {
+ #ifdef WOLFSSL_STATIC_MEMORY
+ WOLFSSL_MSG("File was larger then static buffer");
+ return MEMORY_E;
+ #endif
+ fileBuf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
+ if (fileBuf == NULL)
+ ret = MEMORY_E;
+ else
+ dynamic = 1;
+ }
+
+ if (ret == 0) {
+ if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) {
+ ret = BUFFER_E;
+ }
+ #ifdef WOLFSSL_PEM_TO_DER
+ else {
+ ret = PemToDer(fileBuf, sz, CA_TYPE, &converted, 0, NULL,NULL);
+ }
+ #endif
+
+ if (ret == 0) {
+ if (converted->length < (word32)derSz) {
+ XMEMCPY(derBuf, converted->buffer, converted->length);
+ ret = converted->length;
+ }
+ else
+ ret = BUFFER_E;
+ }
+
+ FreeDer(&converted);
+ }
+
+ XFCLOSE(file);
+ if (dynamic)
+ XFREE(fileBuf, NULL, DYNAMIC_TYPE_FILE);
+ }
+
+ return ret;
+}
+#endif /* WOLFSSL_CERT_GEN */
+
+#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
+/* load pem public key from file into der buffer, return der size or error */
+int wc_PemPubKeyToDer(const char* fileName,
+ unsigned char* derBuf, int derSz)
+{
+#ifdef WOLFSSL_SMALL_STACK
+ byte staticBuffer[1]; /* force XMALLOC */
+#else
+ byte staticBuffer[FILE_BUFFER_SIZE];
+#endif
+ byte* fileBuf = staticBuffer;
+ int dynamic = 0;
+ int ret = 0;
+ long sz = 0;
+ XFILE file;
+ DerBuffer* converted = NULL;
+
+ WOLFSSL_ENTER("wc_PemPubKeyToDer");
+
+ if (fileName == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ file = XFOPEN(fileName, "rb");
+ if (file == XBADFILE) {
+ ret = BUFFER_E;
+ }
+ }
+
+ if (ret == 0) {
+ if(XFSEEK(file, 0, XSEEK_END) != 0)
+ ret = BUFFER_E;
+ sz = XFTELL(file);
+ XREWIND(file);
+
+ if (sz <= 0) {
+ ret = BUFFER_E;
+ }
+ else if (sz > (long)sizeof(staticBuffer)) {
+ #ifdef WOLFSSL_STATIC_MEMORY
+ WOLFSSL_MSG("File was larger then static buffer");
+ return MEMORY_E;
+ #endif
+ fileBuf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
+ if (fileBuf == NULL)
+ ret = MEMORY_E;
+ else
+ dynamic = 1;
+ }
+ if (ret == 0) {
+ if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) {
+ ret = BUFFER_E;
+ }
+ #ifdef WOLFSSL_PEM_TO_DER
+ else {
+ ret = PemToDer(fileBuf, sz, PUBLICKEY_TYPE, &converted,
+ 0, NULL, NULL);
+ }
+ #endif
+
+ if (ret == 0) {
+ if (converted->length < (word32)derSz) {
+ XMEMCPY(derBuf, converted->buffer, converted->length);
+ ret = converted->length;
+ }
+ else
+ ret = BUFFER_E;
+ }
+
+ FreeDer(&converted);
+ }
+
+ XFCLOSE(file);
+ if (dynamic)
+ XFREE(fileBuf, NULL, DYNAMIC_TYPE_FILE);
+ }
+
+ return ret;
+}
+#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */
+
+#endif /* !NO_FILESYSTEM */
+
+
+#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || \
+ ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(HAVE_USER_RSA)))
+/* USER RSA ifdef portions used instead of refactor in consideration for
+ possible fips build */
+/* Write a public RSA key to output */
+static int SetRsaPublicKey(byte* output, RsaKey* key,
+ int outLen, int with_header)
+{
+#ifdef WOLFSSL_SMALL_STACK
+ byte* n = NULL;
+ byte* e = NULL;
+#else
+ byte n[MAX_RSA_INT_SZ];
+ byte e[MAX_RSA_E_SZ];
+#endif
+ byte seq[MAX_SEQ_SZ];
+ byte bitString[1 + MAX_LENGTH_SZ + 1];
+ int nSz;
+ int eSz;
+ int seqSz;
+ int bitStringSz;
+ int idx;
+
+ if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ)
+ return BAD_FUNC_ARG;
+
+ /* n */
+#ifdef WOLFSSL_SMALL_STACK
+ n = (byte*)XMALLOC(MAX_RSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (n == NULL)
+ return MEMORY_E;
+#endif
+
+#ifdef HAVE_USER_RSA
+ nSz = SetASNIntRSA(key->n, n);
+#else
+ nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, n);
+#endif
+ if (nSz < 0) {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return nSz;
+ }
+
+ /* e */
+#ifdef WOLFSSL_SMALL_STACK
+ e = (byte*)XMALLOC(MAX_RSA_E_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (e == NULL) {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return MEMORY_E;
+ }
+#endif
+
+#ifdef HAVE_USER_RSA
+ eSz = SetASNIntRSA(key->e, e);
+#else
+ eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, e);
+#endif
+ if (eSz < 0) {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return eSz;
+ }
+
+ seqSz = SetSequence(nSz + eSz, seq);
+
+ /* check output size */
+ if ( (seqSz + nSz + eSz) > outLen) {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return BUFFER_E;
+ }
+
+ /* headers */
+ if (with_header) {
+ int algoSz;
+#ifdef WOLFSSL_SMALL_STACK
+ byte* algo;
+
+ algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (algo == NULL) {
+ XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
+#else
+ byte algo[MAX_ALGO_SZ];
+#endif
+ algoSz = SetAlgoID(RSAk, algo, oidKeyType, 0);
+ bitStringSz = SetBitString(seqSz + nSz + eSz, 0, bitString);
+
+ idx = SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, output);
+
+ /* check output size */
+ if ( (idx + algoSz + bitStringSz + seqSz + nSz + eSz) > outLen) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+
+ return BUFFER_E;
+ }
+
+ /* algo */
+ XMEMCPY(output + idx, algo, algoSz);
+ idx += algoSz;
+ /* bit string */
+ XMEMCPY(output + idx, bitString, bitStringSz);
+ idx += bitStringSz;
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ }
+ else
+ idx = 0;
+
+ /* seq */
+ XMEMCPY(output + idx, seq, seqSz);
+ idx += seqSz;
+ /* n */
+ XMEMCPY(output + idx, n, nSz);
+ idx += nSz;
+ /* e */
+ XMEMCPY(output + idx, e, eSz);
+ idx += eSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+ return idx;
+}
+
+#endif /* !NO_RSA && (WOLFSSL_CERT_GEN || (WOLFSSL_KEY_GEN &&
+ !HAVE_USER_RSA))) */
+
+#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA))
+int wc_RsaPublicKeyDerSize(RsaKey* key, int with_header)
+{
+ int idx = 0;
+ int nSz, eSz, seqSz, bitStringSz, algoSz;
+
+ if (key == NULL)
+ return BAD_FUNC_ARG;
+
+ /* n */
+#ifdef HAVE_USER_RSA
+ nSz = SetASNIntRSA(key->n, NULL);
+#else
+ nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, NULL);
+#endif
+ if (nSz < 0) {
+ return nSz;
+ }
+
+ /* e */
+#ifdef HAVE_USER_RSA
+ eSz = SetASNIntRSA(key->e, NULL);
+#else
+ eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, NULL);
+#endif
+ if (eSz < 0) {
+ return eSz;
+ }
-#endif /* WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN */
+ seqSz = SetSequence(nSz + eSz, NULL);
+ /* headers */
+ if (with_header) {
+ algoSz = SetAlgoID(RSAk, NULL, oidKeyType, 0);
+ bitStringSz = SetBitString(seqSz + nSz + eSz, 0, NULL);
-#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA)
+ idx += SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, NULL);
+ /* algo */
+ idx += algoSz;
+ /* bit string */
+ idx += bitStringSz;
+ }
+
+ /* seq */
+ idx += seqSz;
+ /* n */
+ idx += nSz;
+ /* e */
+ idx += eSz;
+
+ return idx;
+}
+
+#endif /* !NO_RSA && WOLFSSL_CERT_GEN */
+
+
+#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
static mp_int* GetRsaInt(RsaKey* key, int idx)
{
@@ -4688,13 +11163,13 @@ static mp_int* GetRsaInt(RsaKey* key, int idx)
/* Release Tmp RSA resources */
-static INLINE void FreeTmpRsas(byte** tmps, void* heap)
+static WC_INLINE void FreeTmpRsas(byte** tmps, void* heap)
{
int i;
(void)heap;
- for (i = 0; i < RSA_INTS; i++)
+ for (i = 0; i < RSA_INTS; i++)
XFREE(tmps[i], heap, DYNAMIC_TYPE_RSA);
}
@@ -4705,13 +11180,13 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
{
word32 seqSz, verSz, rawLen, intTotalLen = 0;
word32 sizes[RSA_INTS];
- int i, j, outLen, ret = 0;
+ int i, j, outLen, ret = 0, mpSz;
byte seq[MAX_SEQ_SZ];
byte ver[MAX_VERSION_SZ];
byte* tmps[RSA_INTS];
- if (!key || !output)
+ if (!key)
return BAD_FUNC_ARG;
if (key->type != RSA_PRIVATE)
@@ -4723,7 +11198,8 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
/* write all big ints from key to DER tmps */
for (i = 0; i < RSA_INTS; i++) {
mp_int* keyInt = GetRsaInt(key, i);
- rawLen = mp_unsigned_bin_size(keyInt);
+
+ rawLen = mp_unsigned_bin_size(keyInt) + 1;
tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap,
DYNAMIC_TYPE_RSA);
if (tmps[i] == NULL) {
@@ -4731,24 +11207,12 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
break;
}
- tmps[i][0] = ASN_INTEGER;
- sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1; /* int tag */
-
- if (sizes[i] <= MAX_SEQ_SZ) {
- int err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]);
- if (err == MP_OKAY) {
- sizes[i] += rawLen;
- intTotalLen += sizes[i];
- }
- else {
- ret = err;
- break;
- }
- }
- else {
- ret = ASN_INPUT_E;
+ mpSz = SetASNIntMP(keyInt, MAX_RSA_INT_SZ, tmps[i]);
+ if (mpSz < 0) {
+ ret = mpSz;
break;
}
+ intTotalLen += (sizes[i] = mpSz);
}
if (ret != 0) {
@@ -4761,42 +11225,43 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
seqSz = SetSequence(verSz + intTotalLen, seq);
outLen = seqSz + verSz + intTotalLen;
- if (outLen > (int)inLen)
- return BAD_FUNC_ARG;
+ if (output) {
+ if (outLen > (int)inLen) {
+ FreeTmpRsas(tmps, key->heap);
+ return BAD_FUNC_ARG;
+ }
- /* write to output */
- XMEMCPY(output, seq, seqSz);
- j = seqSz;
- XMEMCPY(output + j, ver, verSz);
- j += verSz;
+ /* write to output */
+ XMEMCPY(output, seq, seqSz);
+ j = seqSz;
+ XMEMCPY(output + j, ver, verSz);
+ j += verSz;
- for (i = 0; i < RSA_INTS; i++) {
- XMEMCPY(output + j, tmps[i], sizes[i]);
- j += sizes[i];
+ for (i = 0; i < RSA_INTS; i++) {
+ XMEMCPY(output + j, tmps[i], sizes[i]);
+ j += sizes[i];
+ }
}
FreeTmpRsas(tmps, key->heap);
return outLen;
}
+#endif
-#endif /* WOLFSSL_KEY_GEN && !NO_RSA */
-
-
-#if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA)
-
-
-#ifndef WOLFSSL_HAVE_MIN
-#define WOLFSSL_HAVE_MIN
+#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+/* Convert Rsa Public key to DER format, write to output (inLen), return bytes
+ written */
+int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen)
+{
+ return SetRsaPublicKey(output, key, inLen, 1);
+}
- static INLINE word32 min(word32 a, word32 b)
- {
- return a > b ? b : a;
- }
+#endif /* (WOLFSSL_KEY_GEN || OPENSSL_EXTRA) && !NO_RSA && !HAVE_USER_RSA */
-#endif /* WOLFSSL_HAVE_MIN */
+#ifdef WOLFSSL_CERT_GEN
-/* Initialize and Set Certficate defaults:
+/* Initialize and Set Certificate defaults:
version = 3 (0x2)
serial = 0
sigType = SHA_WITH_RSA
@@ -4805,57 +11270,57 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
selfSigned = 1 (true) use subject as issuer
subject = blank
*/
-void wc_InitCert(Cert* cert)
+int wc_InitCert(Cert* cert)
{
+#ifdef WOLFSSL_MULTI_ATTRIB
+ int i = 0;
+#endif
+ if (cert == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ XMEMSET(cert, 0, sizeof(Cert));
+
cert->version = 2; /* version 3 is hex 2 */
+#ifndef NO_SHA
cert->sigType = CTC_SHAwRSA;
+#elif !defined(NO_SHA256)
+ cert->sigType = CTC_SHA256wRSA;
+#else
+ cert->sigType = 0;
+#endif
cert->daysValid = 500;
cert->selfSigned = 1;
- cert->isCA = 0;
- cert->bodySz = 0;
-#ifdef WOLFSSL_ALT_NAMES
- cert->altNamesSz = 0;
- cert->beforeDateSz = 0;
- cert->afterDateSz = 0;
-#endif
cert->keyType = RSA_KEY;
- XMEMSET(cert->serial, 0, CTC_SERIAL_SIZE);
- cert->issuer.country[0] = '\0';
cert->issuer.countryEnc = CTC_PRINTABLE;
- cert->issuer.state[0] = '\0';
cert->issuer.stateEnc = CTC_UTF8;
- cert->issuer.locality[0] = '\0';
cert->issuer.localityEnc = CTC_UTF8;
- cert->issuer.sur[0] = '\0';
cert->issuer.surEnc = CTC_UTF8;
- cert->issuer.org[0] = '\0';
cert->issuer.orgEnc = CTC_UTF8;
- cert->issuer.unit[0] = '\0';
cert->issuer.unitEnc = CTC_UTF8;
- cert->issuer.commonName[0] = '\0';
cert->issuer.commonNameEnc = CTC_UTF8;
- cert->issuer.email[0] = '\0';
- cert->subject.country[0] = '\0';
cert->subject.countryEnc = CTC_PRINTABLE;
- cert->subject.state[0] = '\0';
cert->subject.stateEnc = CTC_UTF8;
- cert->subject.locality[0] = '\0';
cert->subject.localityEnc = CTC_UTF8;
- cert->subject.sur[0] = '\0';
cert->subject.surEnc = CTC_UTF8;
- cert->subject.org[0] = '\0';
cert->subject.orgEnc = CTC_UTF8;
- cert->subject.unit[0] = '\0';
cert->subject.unitEnc = CTC_UTF8;
- cert->subject.commonName[0] = '\0';
cert->subject.commonNameEnc = CTC_UTF8;
- cert->subject.email[0] = '\0';
-#ifdef WOLFSSL_CERT_REQ
- cert->challengePw[0] ='\0';
+#ifdef WOLFSSL_MULTI_ATTRIB
+ for (i = 0; i < CTC_MAX_ATTRIB; i++) {
+ cert->issuer.name[i].type = CTC_UTF8;
+ cert->subject.name[i].type = CTC_UTF8;
+ }
+#endif /* WOLFSSL_MULTI_ATTRIB */
+
+#ifdef WOLFSSL_HEAP_TEST
+ cert->heap = (void*)WOLFSSL_HEAP_TEST;
#endif
+
+ return 0;
}
@@ -4863,26 +11328,46 @@ void wc_InitCert(Cert* cert)
typedef struct DerCert {
byte size[MAX_LENGTH_SZ]; /* length encoded */
byte version[MAX_VERSION_SZ]; /* version encoded */
- byte serial[CTC_SERIAL_SIZE + MAX_LENGTH_SZ]; /* serial number encoded */
+ byte serial[(int)CTC_SERIAL_SIZE + (int)MAX_LENGTH_SZ]; /* serial number encoded */
byte sigAlgo[MAX_ALGO_SZ]; /* signature algo encoded */
byte issuer[ASN_NAME_MAX]; /* issuer encoded */
byte subject[ASN_NAME_MAX]; /* subject encoded */
byte validity[MAX_DATE_SIZE*2 + MAX_SEQ_SZ*2]; /* before and after dates */
byte publicKey[MAX_PUBLIC_KEY_SZ]; /* rsa / ntru public key encoded */
byte ca[MAX_CA_SZ]; /* basic constraint CA true size */
- byte extensions[MAX_EXTENSIONS_SZ]; /* all extensions */
+ byte extensions[MAX_EXTENSIONS_SZ]; /* all extensions */
+#ifdef WOLFSSL_CERT_EXT
+ byte skid[MAX_KID_SZ]; /* Subject Key Identifier extension */
+ byte akid[MAX_KID_SZ]; /* Authority Key Identifier extension */
+ byte keyUsage[MAX_KEYUSAGE_SZ]; /* Key Usage extension */
+ byte extKeyUsage[MAX_EXTKEYUSAGE_SZ]; /* Extended Key Usage extension */
+ byte certPolicies[MAX_CERTPOL_NB*MAX_CERTPOL_SZ]; /* Certificate Policies */
+#endif
#ifdef WOLFSSL_CERT_REQ
byte attrib[MAX_ATTRIB_SZ]; /* Cert req attributes encoded */
#endif
+#ifdef WOLFSSL_ALT_NAMES
+ byte altNames[CTC_MAX_ALT_SIZE]; /* Alternative Names encoded */
+#endif
int sizeSz; /* encoded size length */
int versionSz; /* encoded version length */
int serialSz; /* encoded serial length */
- int sigAlgoSz; /* enocded sig alog length */
+ int sigAlgoSz; /* encoded sig algo length */
int issuerSz; /* encoded issuer length */
int subjectSz; /* encoded subject length */
int validitySz; /* encoded validity length */
int publicKeySz; /* encoded public key length */
int caSz; /* encoded CA extension length */
+#ifdef WOLFSSL_CERT_EXT
+ int skidSz; /* encoded SKID extension length */
+ int akidSz; /* encoded SKID extension length */
+ int keyUsageSz; /* encoded KeyUsage extension length */
+ int extKeyUsageSz; /* encoded ExtendedKeyUsage extension length */
+ int certPoliciesSz; /* encoded CertPolicies extension length*/
+#endif
+#ifdef WOLFSSL_ALT_NAMES
+ int altNamesSz; /* encoded AltNames extension length */
+#endif
int extensionsSz; /* encoded extensions total length */
int total; /* total encoded lengths */
#ifdef WOLFSSL_CERT_REQ
@@ -4894,6 +11379,12 @@ typedef struct DerCert {
#ifdef WOLFSSL_CERT_REQ
/* Write a set header to output */
+static word32 SetPrintableString(word32 len, byte* output)
+{
+ output[0] = ASN_PRINTABLE_STRING;
+ return SetLength(len, output + 1) + 1;
+}
+
static word32 SetUTF8String(word32 len, byte* output)
{
output[0] = ASN_UTF8STRING;
@@ -4903,258 +11394,444 @@ static word32 SetUTF8String(word32 len, byte* output)
#endif /* WOLFSSL_CERT_REQ */
-/* Write a serial number to output */
-static int SetSerial(const byte* serial, byte* output)
+#ifndef WOLFSSL_CERT_GEN_CACHE
+/* wc_SetCert_Free is only public when WOLFSSL_CERT_GEN_CACHE is not defined */
+static
+#endif
+void wc_SetCert_Free(Cert* cert)
{
- int length = 0;
+ if (cert != NULL) {
+ cert->der = NULL;
+ if (cert->decodedCert) {
+ FreeDecodedCert((DecodedCert*)cert->decodedCert);
+
+ XFREE(cert->decodedCert, cert->heap, DYNAMIC_TYPE_DCERT);
+ cert->decodedCert = NULL;
+ }
+ }
+}
+
+static int wc_SetCert_LoadDer(Cert* cert, const byte* der, word32 derSz)
+{
+ int ret;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Allocate DecodedCert struct and Zero */
+ cert->decodedCert = (void*)XMALLOC(sizeof(DecodedCert), cert->heap,
+ DYNAMIC_TYPE_DCERT);
- output[length++] = ASN_INTEGER;
- length += SetLength(CTC_SERIAL_SIZE, &output[length]);
- XMEMCPY(&output[length], serial, CTC_SERIAL_SIZE);
+ if (cert->decodedCert == NULL) {
+ ret = MEMORY_E;
+ }
+ else {
+ XMEMSET(cert->decodedCert, 0, sizeof(DecodedCert));
+
+ InitDecodedCert((DecodedCert*)cert->decodedCert, der, derSz,
+ cert->heap);
+ ret = ParseCertRelative((DecodedCert*)cert->decodedCert,
+ CERT_TYPE, 0, NULL);
+ if (ret >= 0) {
+ cert->der = (byte*)der;
+ }
+ else {
+ wc_SetCert_Free(cert);
+ }
+ }
+ }
- return length + CTC_SERIAL_SIZE;
+ return ret;
}
+#endif /* WOLFSSL_CERT_GEN */
-#ifdef HAVE_ECC
+#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
/* Write a public ECC key to output */
-static int SetEccPublicKey(byte* output, ecc_key* key)
+static int SetEccPublicKey(byte* output, ecc_key* key, int with_header)
{
- byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */
+ byte bitString[1 + MAX_LENGTH_SZ + 1];
int algoSz;
int curveSz;
- int lenSz;
+ int bitStringSz;
int idx;
word32 pubSz = ECC_BUFSIZE;
#ifdef WOLFSSL_SMALL_STACK
byte* algo = NULL;
byte* curve = NULL;
- byte* pub = NULL;
+ byte* pub;
#else
byte algo[MAX_ALGO_SZ];
byte curve[MAX_ALGO_SZ];
byte pub[ECC_BUFSIZE];
#endif
+ int ret;
#ifdef WOLFSSL_SMALL_STACK
- pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ pub = (byte*)XMALLOC(ECC_BUFSIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (pub == NULL)
return MEMORY_E;
#endif
- int ret = wc_ecc_export_x963(key, pub, &pubSz);
+#ifdef HAVE_SELFTEST
+ /* older version of ecc.c can not handle dp being NULL */
+ if (key != NULL && key->dp == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ ret = wc_ecc_export_x963(key, pub, &pubSz);
+ }
+#else
+ ret = wc_ecc_export_x963(key, pub, &pubSz);
+#endif
if (ret != 0) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
+ /* headers */
+ if (with_header) {
#ifdef WOLFSSL_SMALL_STACK
- curve = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (curve == NULL) {
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
- }
+ curve = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (curve == NULL) {
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
#endif
-
- /* headers */
- curveSz = SetCurve(key, curve);
- if (curveSz <= 0) {
+ curveSz = SetCurve(key, curve);
+ if (curveSz <= 0) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- return curveSz;
- }
+ return curveSz;
+ }
#ifdef WOLFSSL_SMALL_STACK
- algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (algo == NULL) {
- XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
- }
+ algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (algo == NULL) {
+ XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
#endif
+ algoSz = SetAlgoID(ECDSAk, algo, oidKeyType, curveSz);
+
+ bitStringSz = SetBitString(pubSz, 0, bitString);
+
+ idx = SetSequence(pubSz + curveSz + bitStringSz + algoSz, output);
+ /* algo */
+ if (output)
+ XMEMCPY(output + idx, algo, algoSz);
+ idx += algoSz;
+ /* curve */
+ if (output)
+ XMEMCPY(output + idx, curve, curveSz);
+ idx += curveSz;
+ /* bit string */
+ if (output)
+ XMEMCPY(output + idx, bitString, bitStringSz);
+ idx += bitStringSz;
+ }
+ else
+ idx = 0;
- algoSz = SetAlgoID(ECDSAk, algo, keyType, curveSz);
- lenSz = SetLength(pubSz + 1, len);
- len[lenSz++] = 0; /* trailing 0 */
-
- /* write */
- idx = SetSequence(pubSz + curveSz + lenSz + 1 + algoSz, output);
- /* 1 is for ASN_BIT_STRING */
- /* algo */
- XMEMCPY(output + idx, algo, algoSz);
- idx += algoSz;
- /* curve */
- XMEMCPY(output + idx, curve, curveSz);
- idx += curveSz;
- /* bit string */
- output[idx++] = ASN_BIT_STRING;
- /* length */
- XMEMCPY(output + idx, len, lenSz);
- idx += lenSz;
/* pub */
- XMEMCPY(output + idx, pub, pubSz);
+ if (output)
+ XMEMCPY(output + idx, pub, pubSz);
idx += pubSz;
#ifdef WOLFSSL_SMALL_STACK
- XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (with_header) {
+ XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return idx;
}
-#endif /* HAVE_ECC */
+/* returns the size of buffer used, the public ECC key in DER format is stored
+ in output buffer
+ with_AlgCurve is a flag for when to include a header that has the Algorithm
+ and Curve information */
+int wc_EccPublicKeyToDer(ecc_key* key, byte* output, word32 inLen,
+ int with_AlgCurve)
+{
+ word32 infoSz = 0;
+ word32 keySz = 0;
+ int ret;
+ if (key == NULL) {
+ return BAD_FUNC_ARG;
+ }
-/* Write a public RSA key to output */
-static int SetRsaPublicKey(byte* output, RsaKey* key)
+ if (with_AlgCurve) {
+ /* buffer space for algorithm/curve */
+ infoSz += MAX_SEQ_SZ;
+ infoSz += 2 * MAX_ALGO_SZ;
+
+ /* buffer space for public key sequence */
+ infoSz += MAX_SEQ_SZ;
+ infoSz += TRAILING_ZERO;
+ }
+
+#ifdef HAVE_SELFTEST
+ /* older version of ecc.c can not handle dp being NULL */
+ if (key != NULL && key->dp == NULL) {
+ keySz = 1 + 2 * MAX_ECC_BYTES;
+ ret = LENGTH_ONLY_E;
+ }
+ else {
+ ret = wc_ecc_export_x963(key, NULL, &keySz);
+ }
+#else
+ ret = wc_ecc_export_x963(key, NULL, &keySz);
+#endif
+ if (ret != LENGTH_ONLY_E) {
+ WOLFSSL_MSG("Error in getting ECC public key size");
+ return ret;
+ }
+
+ /* if output null then just return size */
+ if (output == NULL) {
+ return keySz + infoSz;
+ }
+
+ if (inLen < keySz + infoSz) {
+ return BUFFER_E;
+ }
+
+ return SetEccPublicKey(output, key, with_AlgCurve);
+}
+
+int wc_EccPublicKeyDerSize(ecc_key* key, int with_AlgCurve)
+{
+ return wc_EccPublicKeyToDer(key, NULL, 0, with_AlgCurve);
+}
+
+#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */
+
+#if defined(HAVE_ED25519) && (defined(WOLFSSL_CERT_GEN) || \
+ defined(WOLFSSL_KEY_GEN))
+
+/* Write a public ECC key to output */
+static int SetEd25519PublicKey(byte* output, ed25519_key* key, int with_header)
{
+ byte bitString[1 + MAX_LENGTH_SZ + 1];
+ int algoSz;
+ int bitStringSz;
+ int idx;
+ word32 pubSz = ED25519_PUB_KEY_SIZE;
#ifdef WOLFSSL_SMALL_STACK
- byte* n = NULL;
- byte* e = NULL;
byte* algo = NULL;
+ byte* pub;
#else
- byte n[MAX_RSA_INT_SZ];
- byte e[MAX_RSA_E_SZ];
byte algo[MAX_ALGO_SZ];
+ byte pub[ED25519_PUB_KEY_SIZE];
#endif
- byte seq[MAX_SEQ_SZ];
- byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */
- int nSz;
- int eSz;
- int algoSz;
- int seqSz;
- int lenSz;
- int idx;
- int rawLen;
- int leadingBit;
- int err;
- /* n */
#ifdef WOLFSSL_SMALL_STACK
- n = (byte*)XMALLOC(MAX_RSA_INT_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (n == NULL)
+ pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pub == NULL)
return MEMORY_E;
#endif
- leadingBit = mp_leading_bit(&key->n);
- rawLen = mp_unsigned_bin_size(&key->n) + leadingBit;
- n[0] = ASN_INTEGER;
- nSz = SetLength(rawLen, n + 1) + 1; /* int tag */
-
- if ( (nSz + rawLen) < MAX_RSA_INT_SZ) {
- if (leadingBit)
- n[nSz] = 0;
- err = mp_to_unsigned_bin(&key->n, n + nSz + leadingBit);
- if (err == MP_OKAY)
- nSz += rawLen;
- else {
+ idx = wc_ed25519_export_public(key, pub, &pubSz);
+ if (idx != 0) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- return MP_TO_E;
+ return idx;
+ }
+
+ /* headers */
+ if (with_header) {
+#ifdef WOLFSSL_SMALL_STACK
+ algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (algo == NULL) {
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
}
+#endif
+ algoSz = SetAlgoID(ED25519k, algo, oidKeyType, 0);
+
+ bitStringSz = SetBitString(pubSz, 0, bitString);
+
+ idx = SetSequence(pubSz + bitStringSz + algoSz, output);
+ /* algo */
+ XMEMCPY(output + idx, algo, algoSz);
+ idx += algoSz;
+ /* bit string */
+ XMEMCPY(output + idx, bitString, bitStringSz);
+ idx += bitStringSz;
}
- else {
+ else
+ idx = 0;
+
+ /* pub */
+ XMEMCPY(output + idx, pub, pubSz);
+ idx += pubSz;
+
#ifdef WOLFSSL_SMALL_STACK
- XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (with_header) {
+ XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
+
+ return idx;
+}
+
+int wc_Ed25519PublicKeyToDer(ed25519_key* key, byte* output, word32 inLen,
+ int withAlg)
+{
+ word32 infoSz = 0;
+ word32 keySz = 0;
+ int ret;
+
+ if (output == NULL || key == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (withAlg) {
+ /* buffer space for algorithm */
+ infoSz += MAX_SEQ_SZ;
+ infoSz += MAX_ALGO_SZ;
+
+ /* buffer space for public key sequence */
+ infoSz += MAX_SEQ_SZ;
+ infoSz += TRAILING_ZERO;
+ }
+
+ if ((ret = wc_ed25519_export_public(key, output, &keySz)) != BUFFER_E) {
+ WOLFSSL_MSG("Error in getting ECC public key size");
+ return ret;
+ }
+
+ if (inLen < keySz + infoSz) {
return BUFFER_E;
}
- /* e */
-#ifdef WOLFSSL_SMALL_STACK
- e = (byte*)XMALLOC(MAX_RSA_E_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (e == NULL) {
+ return SetEd25519PublicKey(output, key, withAlg);
+}
+#endif /* HAVE_ED25519 && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */
+#if defined(HAVE_ED448) && (defined(WOLFSSL_CERT_GEN) || \
+ defined(WOLFSSL_KEY_GEN))
+
+/* Write a public ECC key to output */
+static int SetEd448PublicKey(byte* output, ed448_key* key, int with_header)
+{
+ byte bitString[1 + MAX_LENGTH_SZ + 1];
+ int algoSz;
+ int bitStringSz;
+ int idx;
+ word32 pubSz = ED448_PUB_KEY_SIZE;
#ifdef WOLFSSL_SMALL_STACK
- XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ byte* algo = NULL;
+ byte* pub = NULL;
+#else
+ byte algo[MAX_ALGO_SZ];
+ byte pub[ED448_PUB_KEY_SIZE];
#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+ pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pub == NULL)
return MEMORY_E;
- }
#endif
- leadingBit = mp_leading_bit(&key->e);
- rawLen = mp_unsigned_bin_size(&key->e) + leadingBit;
- e[0] = ASN_INTEGER;
- eSz = SetLength(rawLen, e + 1) + 1; /* int tag */
-
- if ( (eSz + rawLen) < MAX_RSA_E_SZ) {
- if (leadingBit)
- e[eSz] = 0;
- err = mp_to_unsigned_bin(&key->e, e + eSz + leadingBit);
- if (err == MP_OKAY)
- eSz += rawLen;
- else {
+ idx = wc_ed448_export_public(key, pub, &pubSz);
+ if (idx != 0) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- return MP_TO_E;
- }
+ return idx;
}
- else {
+
+ /* headers */
+ if (with_header) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (algo == NULL) {
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
#endif
- return BUFFER_E;
+ algoSz = SetAlgoID(ED448k, algo, oidKeyType, 0);
+
+ bitStringSz = SetBitString(pubSz, 0, bitString);
+
+ idx = SetSequence(pubSz + bitStringSz + algoSz, output);
+ /* algo */
+ XMEMCPY(output + idx, algo, algoSz);
+ idx += algoSz;
+ /* bit string */
+ XMEMCPY(output + idx, bitString, bitStringSz);
+ idx += bitStringSz;
}
+ else
+ idx = 0;
+
+ /* pub */
+ XMEMCPY(output + idx, pub, pubSz);
+ idx += pubSz;
#ifdef WOLFSSL_SMALL_STACK
- algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (algo == NULL) {
- XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
+ if (with_header) {
+ XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
+ XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- /* headers */
- algoSz = SetAlgoID(RSAk, algo, keyType, 0);
- seqSz = SetSequence(nSz + eSz, seq);
- lenSz = SetLength(seqSz + nSz + eSz + 1, len);
- len[lenSz++] = 0; /* trailing 0 */
+ return idx;
+}
- /* write */
- idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output);
- /* 1 is for ASN_BIT_STRING */
- /* algo */
- XMEMCPY(output + idx, algo, algoSz);
- idx += algoSz;
- /* bit string */
- output[idx++] = ASN_BIT_STRING;
- /* length */
- XMEMCPY(output + idx, len, lenSz);
- idx += lenSz;
- /* seq */
- XMEMCPY(output + idx, seq, seqSz);
- idx += seqSz;
- /* n */
- XMEMCPY(output + idx, n, nSz);
- idx += nSz;
- /* e */
- XMEMCPY(output + idx, e, eSz);
- idx += eSz;
+int wc_Ed448PublicKeyToDer(ed448_key* key, byte* output, word32 inLen,
+ int withAlg)
+{
+ word32 infoSz = 0;
+ word32 keySz = 0;
+ int ret;
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ if (output == NULL || key == NULL) {
+ return BAD_FUNC_ARG;
+ }
- return idx;
+ if (withAlg) {
+ /* buffer space for algorithm */
+ infoSz += MAX_SEQ_SZ;
+ infoSz += MAX_ALGO_SZ;
+
+ /* buffer space for public key sequence */
+ infoSz += MAX_SEQ_SZ;
+ infoSz += TRAILING_ZERO;
+ }
+
+ if ((ret = wc_ed448_export_public(key, output, &keySz)) != BUFFER_E) {
+ WOLFSSL_MSG("Error in getting ECC public key size");
+ return ret;
+ }
+
+ if (inLen < keySz + infoSz) {
+ return BUFFER_E;
+ }
+
+ return SetEd448PublicKey(output, key, withAlg);
}
+#endif /* HAVE_ED448 && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */
+
+#ifdef WOLFSSL_CERT_GEN
-static INLINE byte itob(int number)
+static WC_INLINE byte itob(int number)
{
return (byte)number + 0x30;
}
@@ -5184,7 +11861,7 @@ static void SetTime(struct tm* date, byte* output)
output[i++] = itob(date->tm_sec / 10);
output[i++] = itob(date->tm_sec % 10);
-
+
output[i] = 'Z'; /* Zulu profile */
}
@@ -5200,28 +11877,19 @@ static int CopyValidity(byte* output, Cert* cert)
/* headers and output */
seqSz = SetSequence(cert->beforeDateSz + cert->afterDateSz, output);
- XMEMCPY(output + seqSz, cert->beforeDate, cert->beforeDateSz);
- XMEMCPY(output + seqSz + cert->beforeDateSz, cert->afterDate,
- cert->afterDateSz);
+ if (output) {
+ XMEMCPY(output + seqSz, cert->beforeDate, cert->beforeDateSz);
+ XMEMCPY(output + seqSz + cert->beforeDateSz, cert->afterDate,
+ cert->afterDateSz);
+ }
return seqSz + cert->beforeDateSz + cert->afterDateSz;
}
#endif
-/* for systems where mktime() doesn't normalize fully */
-static void RebuildTime(time_t* in, struct tm* out)
-{
- #ifdef FREESCALE_MQX
- out = localtime_r(in, out);
- #else
- (void)in;
- (void)out;
- #endif
-}
-
-
-/* Set Date validity from now until now + daysValid */
+/* Set Date validity from now until now + daysValid
+ * return size in bytes written to output, 0 on error */
static int SetValidity(byte* output, int daysValid)
{
byte before[MAX_DATE_SIZE];
@@ -5231,55 +11899,60 @@ static int SetValidity(byte* output, int daysValid)
int afterSz;
int seqSz;
- time_t ticks;
- time_t normalTime;
- struct tm* now;
- struct tm* tmpTime = NULL;
- struct tm local;
+ time_t now;
+ time_t then;
+ struct tm* tmpTime;
+ struct tm* expandedTime;
+ struct tm localTime;
-#if defined(FREESCALE_MQX) || defined(TIME_OVERRIDES)
+#if defined(NEED_TMP_TIME)
/* for use with gmtime_r */
struct tm tmpTimeStorage;
tmpTime = &tmpTimeStorage;
#else
- (void)tmpTime;
+ tmpTime = NULL;
#endif
+ (void)tmpTime;
- ticks = XTIME(0);
- now = XGMTIME(&ticks, tmpTime);
+ now = XTIME(0);
/* before now */
- local = *now;
before[0] = ASN_GENERALIZED_TIME;
- beforeSz = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1; /* gen tag */
-
- /* subtract 1 day for more compliance */
- local.tm_mday -= 1;
- normalTime = mktime(&local);
- RebuildTime(&normalTime, &local);
+ beforeSz = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1; /* gen tag */
+
+ /* subtract 1 day of seconds for more compliance */
+ then = now - 86400;
+ expandedTime = XGMTIME(&then, tmpTime);
+ if (expandedTime == NULL) {
+ WOLFSSL_MSG("XGMTIME failed");
+ return 0; /* error */
+ }
+ localTime = *expandedTime;
/* adjust */
- local.tm_year += 1900;
- local.tm_mon += 1;
+ localTime.tm_year += 1900;
+ localTime.tm_mon += 1;
- SetTime(&local, before + beforeSz);
+ SetTime(&localTime, before + beforeSz);
beforeSz += ASN_GEN_TIME_SZ;
- /* after now + daysValid */
- local = *now;
after[0] = ASN_GENERALIZED_TIME;
afterSz = SetLength(ASN_GEN_TIME_SZ, after + 1) + 1; /* gen tag */
- /* add daysValid */
- local.tm_mday += daysValid;
- normalTime = mktime(&local);
- RebuildTime(&normalTime, &local);
+ /* add daysValid of seconds */
+ then = now + (daysValid * (time_t)86400);
+ expandedTime = XGMTIME(&then, tmpTime);
+ if (expandedTime == NULL) {
+ WOLFSSL_MSG("XGMTIME failed");
+ return 0; /* error */
+ }
+ localTime = *expandedTime;
/* adjust */
- local.tm_year += 1900;
- local.tm_mon += 1;
+ localTime.tm_year += 1900;
+ localTime.tm_mon += 1;
- SetTime(&local, after + afterSz);
+ SetTime(&localTime, after + afterSz);
afterSz += ASN_GEN_TIME_SZ;
/* headers and output */
@@ -5327,6 +12000,16 @@ static const char* GetOneName(CertName* name, int idx)
return name->commonName;
case 7:
+ return name->serialDev;
+
+#ifdef WOLFSSL_CERT_EXT
+ case 8:
+ return name->busCat;
+
+ case 9:
+#else
+ case 8:
+#endif
return name->email;
default:
@@ -5360,6 +12043,20 @@ static char GetNameType(CertName* name, int idx)
case 6:
return name->commonNameEnc;
+ case 7:
+ return name->serialDevEnc;
+
+#ifdef WOLFSSL_CERT_EXT
+ case 8:
+ return name->busCatEnc;
+
+ case 9:
+#else
+ case 8:
+#endif
+ /* FALL THROUGH */
+ /* The last index, email name, does not have encoding type.
+ The empty case here is to keep track of it for future reference. */
default:
return 0;
}
@@ -5392,54 +12089,589 @@ static byte GetNameId(int idx)
return ASN_COMMON_NAME;
case 7:
- /* email uses different id type */
- return 0;
+ return ASN_SERIAL_NUMBER;
+
+#ifdef WOLFSSL_CERT_EXT
+ case 8:
+ return ASN_BUS_CAT;
+
+ case 9:
+#else
+ case 8:
+#endif
+ return ASN_EMAIL_NAME;
default:
return 0;
}
}
+/*
+ Extensions ::= SEQUENCE OF Extension
+
+ Extension ::= SEQUENCE {
+ extnId OBJECT IDENTIFIER,
+ critical BOOLEAN DEFAULT FALSE,
+ extnValue OCTET STRING }
+ */
/* encode all extensions, return total bytes written */
-static int SetExtensions(byte* output, const byte* ext, int extSz, int header)
+static int SetExtensions(byte* out, word32 outSz, int *IdxInOut,
+ const byte* ext, int extSz)
+{
+ if (out == NULL || IdxInOut == NULL || ext == NULL)
+ return BAD_FUNC_ARG;
+
+ if (outSz < (word32)(*IdxInOut+extSz))
+ return BUFFER_E;
+
+ XMEMCPY(&out[*IdxInOut], ext, extSz); /* extensions */
+ *IdxInOut += extSz;
+
+ return *IdxInOut;
+}
+
+/* encode extensions header, return total bytes written */
+static int SetExtensionsHeader(byte* out, word32 outSz, int extSz)
{
byte sequence[MAX_SEQ_SZ];
byte len[MAX_LENGTH_SZ];
+ int seqSz, lenSz, idx = 0;
- int sz = 0;
- int seqSz = SetSequence(extSz, sequence);
+ if (out == NULL)
+ return BAD_FUNC_ARG;
- if (header) {
- int lenSz = SetLength(seqSz + extSz, len);
- output[0] = ASN_EXTENSIONS; /* extensions id */
- sz++;
- XMEMCPY(&output[sz], len, lenSz); /* length */
- sz += lenSz;
- }
- XMEMCPY(&output[sz], sequence, seqSz); /* sequence */
- sz += seqSz;
- XMEMCPY(&output[sz], ext, extSz); /* extensions */
- sz += extSz;
+ if (outSz < 3)
+ return BUFFER_E;
- return sz;
+ seqSz = SetSequence(extSz, sequence);
+
+ /* encode extensions length provided */
+ lenSz = SetLength(extSz+seqSz, len);
+
+ if (outSz < (word32)(lenSz+seqSz+1))
+ return BUFFER_E;
+
+ out[idx++] = ASN_EXTENSIONS; /* extensions id */
+ XMEMCPY(&out[idx], len, lenSz); /* length */
+ idx += lenSz;
+
+ XMEMCPY(&out[idx], sequence, seqSz); /* sequence */
+ idx += seqSz;
+
+ return idx;
}
/* encode CA basic constraint true, return total bytes written */
-static int SetCa(byte* output)
+static int SetCa(byte* out, word32 outSz)
{
- static const byte ca[] = { 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
+ const byte ca[] = { 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
0x05, 0x30, 0x03, 0x01, 0x01, 0xff };
-
- XMEMCPY(output, ca, sizeof(ca));
+
+ if (out == NULL)
+ return BAD_FUNC_ARG;
+
+ if (outSz < sizeof(ca))
+ return BUFFER_E;
+
+ XMEMCPY(out, ca, sizeof(ca));
return (int)sizeof(ca);
}
+#ifdef WOLFSSL_CERT_EXT
+/* encode OID and associated value, return total bytes written */
+static int SetOidValue(byte* out, word32 outSz, const byte *oid, word32 oidSz,
+ byte *in, word32 inSz)
+{
+ int idx = 0;
+
+ if (out == NULL || oid == NULL || in == NULL)
+ return BAD_FUNC_ARG;
+
+ if (outSz < 3)
+ return BUFFER_E;
+
+ /* sequence, + 1 => byte to put value size */
+ idx = SetSequence(inSz + oidSz + 1, out);
+
+ if ((idx + inSz + oidSz + 1) > outSz)
+ return BUFFER_E;
+
+ XMEMCPY(out+idx, oid, oidSz);
+ idx += oidSz;
+ out[idx++] = (byte)inSz;
+ XMEMCPY(out+idx, in, inSz);
+
+ return (idx+inSz);
+}
+
+/* encode Subject Key Identifier, return total bytes written
+ * RFC5280 : non-critical */
+static int SetSKID(byte* output, word32 outSz, const byte *input, word32 length)
+{
+ byte skid_len[1 + MAX_LENGTH_SZ];
+ byte skid_enc_len[MAX_LENGTH_SZ];
+ int idx = 0, skid_lenSz, skid_enc_lenSz;
+ const byte skid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04 };
+
+ if (output == NULL || input == NULL)
+ return BAD_FUNC_ARG;
+
+ /* Octet String header */
+ skid_lenSz = SetOctetString(length, skid_len);
+
+ /* length of encoded value */
+ skid_enc_lenSz = SetLength(length + skid_lenSz, skid_enc_len);
+
+ if (outSz < 3)
+ return BUFFER_E;
+
+ idx = SetSequence(length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz,
+ output);
+
+ if ((length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz) > outSz)
+ return BUFFER_E;
+
+ /* put oid */
+ XMEMCPY(output+idx, skid_oid, sizeof(skid_oid));
+ idx += sizeof(skid_oid);
+
+ /* put encoded len */
+ XMEMCPY(output+idx, skid_enc_len, skid_enc_lenSz);
+ idx += skid_enc_lenSz;
+
+ /* put octet header */
+ XMEMCPY(output+idx, skid_len, skid_lenSz);
+ idx += skid_lenSz;
+
+ /* put value */
+ XMEMCPY(output+idx, input, length);
+ idx += length;
+
+ return idx;
+}
+
+/* encode Authority Key Identifier, return total bytes written
+ * RFC5280 : non-critical */
+static int SetAKID(byte* output, word32 outSz,
+ byte *input, word32 length, void* heap)
+{
+ byte *enc_val;
+ int ret, enc_valSz;
+ const byte akid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04 };
+ const byte akid_cs[] = { 0x80 };
+
+ (void)heap;
+
+ if (output == NULL || input == NULL)
+ return BAD_FUNC_ARG;
+
+ enc_valSz = length + 3 + sizeof(akid_cs);
+ enc_val = (byte *)XMALLOC(enc_valSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (enc_val == NULL)
+ return MEMORY_E;
+
+ /* sequence for ContentSpec & value */
+ ret = SetOidValue(enc_val, enc_valSz, akid_cs, sizeof(akid_cs),
+ input, length);
+ if (ret > 0) {
+ enc_valSz = ret;
+
+ ret = SetOidValue(output, outSz, akid_oid, sizeof(akid_oid),
+ enc_val, enc_valSz);
+ }
+
+ XFREE(enc_val, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+}
+
+/* encode Key Usage, return total bytes written
+ * RFC5280 : critical */
+static int SetKeyUsage(byte* output, word32 outSz, word16 input)
+{
+ byte ku[5];
+ int idx;
+ const byte keyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0f,
+ 0x01, 0x01, 0xff, 0x04};
+ if (output == NULL)
+ return BAD_FUNC_ARG;
+
+ idx = SetBitString16Bit(input, ku);
+ return SetOidValue(output, outSz, keyusage_oid, sizeof(keyusage_oid),
+ ku, idx);
+}
+
+static int SetOjectIdValue(byte* output, word32 outSz, int* idx,
+ const byte* oid, word32 oidSz)
+{
+ /* verify room */
+ if (*idx + 2 + oidSz >= outSz)
+ return ASN_PARSE_E;
+
+ *idx += SetObjectId(oidSz, &output[*idx]);
+ XMEMCPY(&output[*idx], oid, oidSz);
+ *idx += oidSz;
+
+ return 0;
+}
+
+/* encode Extended Key Usage (RFC 5280 4.2.1.12), return total bytes written */
+static int SetExtKeyUsage(Cert* cert, byte* output, word32 outSz, byte input)
+{
+ int idx = 0, oidListSz = 0, totalSz, ret = 0;
+ const byte extkeyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x25 };
+
+ if (output == NULL)
+ return BAD_FUNC_ARG;
+
+ /* Skip to OID List */
+ totalSz = 2 + sizeof(extkeyusage_oid) + 4;
+ idx = totalSz;
+
+ /* Build OID List */
+ /* If any set, then just use it */
+ if (input & EXTKEYUSE_ANY) {
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ extExtKeyUsageAnyOid, sizeof(extExtKeyUsageAnyOid));
+ }
+ else {
+ if (input & EXTKEYUSE_SERVER_AUTH)
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ extExtKeyUsageServerAuthOid, sizeof(extExtKeyUsageServerAuthOid));
+ if (input & EXTKEYUSE_CLIENT_AUTH)
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ extExtKeyUsageClientAuthOid, sizeof(extExtKeyUsageClientAuthOid));
+ if (input & EXTKEYUSE_CODESIGN)
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ extExtKeyUsageCodeSigningOid, sizeof(extExtKeyUsageCodeSigningOid));
+ if (input & EXTKEYUSE_EMAILPROT)
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ extExtKeyUsageEmailProtectOid, sizeof(extExtKeyUsageEmailProtectOid));
+ if (input & EXTKEYUSE_TIMESTAMP)
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ extExtKeyUsageTimestampOid, sizeof(extExtKeyUsageTimestampOid));
+ if (input & EXTKEYUSE_OCSP_SIGN)
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ extExtKeyUsageOcspSignOid, sizeof(extExtKeyUsageOcspSignOid));
+ #ifdef WOLFSSL_EKU_OID
+ /* iterate through OID values */
+ if (input & EXTKEYUSE_USER) {
+ int i, sz;
+ for (i = 0; i < CTC_MAX_EKU_NB; i++) {
+ sz = cert->extKeyUsageOIDSz[i];
+ if (sz > 0) {
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ cert->extKeyUsageOID[i], sz);
+ }
+ }
+ }
+ #endif /* WOLFSSL_EKU_OID */
+ }
+ if (ret != 0)
+ return ASN_PARSE_E;
+
+ /* Calculate Sizes */
+ oidListSz = idx - totalSz;
+ totalSz = idx - 2; /* exclude first seq/len (2) */
+
+ /* 1. Seq + Total Len (2) */
+ idx = SetSequence(totalSz, output);
+
+ /* 2. Object ID (2) */
+ XMEMCPY(&output[idx], extkeyusage_oid, sizeof(extkeyusage_oid));
+ idx += sizeof(extkeyusage_oid);
+
+ /* 3. Octet String (2) */
+ idx += SetOctetString(totalSz - idx, &output[idx]);
+
+ /* 4. Seq + OidListLen (2) */
+ idx += SetSequence(oidListSz, &output[idx]);
+
+ /* 5. Oid List (already set in-place above) */
+ idx += oidListSz;
+
+ (void)cert;
+ return idx;
+}
+
+/* encode Certificate Policies, return total bytes written
+ * each input value must be ITU-T X.690 formatted : a.b.c...
+ * input must be an array of values with a NULL terminated for the latest
+ * RFC5280 : non-critical */
+static int SetCertificatePolicies(byte *output,
+ word32 outputSz,
+ char input[MAX_CERTPOL_NB][MAX_CERTPOL_SZ],
+ word16 nb_certpol,
+ void* heap)
+{
+ byte oid[MAX_OID_SZ],
+ der_oid[MAX_CERTPOL_NB][MAX_OID_SZ],
+ out[MAX_CERTPOL_SZ];
+ word32 oidSz;
+ word32 outSz, i = 0, der_oidSz[MAX_CERTPOL_NB];
+ int ret;
+
+ const byte certpol_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04 };
+ const byte oid_oid[] = { 0x06 };
+
+ if (output == NULL || input == NULL || nb_certpol > MAX_CERTPOL_NB)
+ return BAD_FUNC_ARG;
+
+ for (i = 0; i < nb_certpol; i++) {
+ oidSz = sizeof(oid);
+ XMEMSET(oid, 0, oidSz);
+
+ ret = EncodePolicyOID(oid, &oidSz, input[i], heap);
+ if (ret != 0)
+ return ret;
+
+ /* compute sequence value for the oid */
+ ret = SetOidValue(der_oid[i], MAX_OID_SZ, oid_oid,
+ sizeof(oid_oid), oid, oidSz);
+ if (ret <= 0)
+ return ret;
+ else
+ der_oidSz[i] = (word32)ret;
+ }
+
+ /* concatenate oid, keep two byte for sequence/size of the created value */
+ for (i = 0, outSz = 2; i < nb_certpol; i++) {
+ XMEMCPY(out+outSz, der_oid[i], der_oidSz[i]);
+ outSz += der_oidSz[i];
+ }
+
+ /* add sequence */
+ ret = SetSequence(outSz-2, out);
+ if (ret <= 0)
+ return ret;
+
+ /* add Policy OID to compute final value */
+ return SetOidValue(output, outputSz, certpol_oid, sizeof(certpol_oid),
+ out, outSz);
+}
+#endif /* WOLFSSL_CERT_EXT */
+
+
+#ifdef WOLFSSL_ALT_NAMES
+
+/* encode Alternative Names, return total bytes written */
+static int SetAltNames(byte *output, word32 outSz,
+ const byte *input, word32 length)
+{
+ byte san_len[1 + MAX_LENGTH_SZ];
+ int idx = 0, san_lenSz;
+ const byte san_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x11 };
+
+ if (output == NULL || input == NULL)
+ return BAD_FUNC_ARG;
+
+ if (outSz < length)
+ return BUFFER_E;
+
+ /* Octet String header */
+ san_lenSz = SetOctetString(length, san_len);
+
+ if (outSz < MAX_SEQ_SZ)
+ return BUFFER_E;
+
+ idx = SetSequence(length + sizeof(san_oid) + san_lenSz, output);
+
+ if ((length + sizeof(san_oid) + san_lenSz) > outSz)
+ return BUFFER_E;
+
+ /* put oid */
+ XMEMCPY(output+idx, san_oid, sizeof(san_oid));
+ idx += sizeof(san_oid);
+
+ /* put octet header */
+ XMEMCPY(output+idx, san_len, san_lenSz);
+ idx += san_lenSz;
+
+ /* put value */
+ XMEMCPY(output+idx, input, length);
+ idx += length;
+
+ return idx;
+}
+
+
+#ifdef WOLFSSL_CERT_GEN
+
+int FlattenAltNames(byte* output, word32 outputSz, const DNS_entry* names)
+{
+ word32 idx;
+ const DNS_entry* curName;
+ word32 namesSz = 0;
+
+ if (output == NULL)
+ return BAD_FUNC_ARG;
+
+ if (names == NULL)
+ return 0;
+
+ curName = names;
+ do {
+ namesSz += curName->len + 2 +
+ ((curName->len < ASN_LONG_LENGTH) ? 0
+ : BytePrecision(curName->len));
+ curName = curName->next;
+ } while (curName != NULL);
+
+ if (outputSz < MAX_SEQ_SZ + namesSz)
+ return BUFFER_E;
+
+ idx = SetSequence(namesSz, output);
+
+ curName = names;
+ do {
+ output[idx++] = ASN_CONTEXT_SPECIFIC | curName->type;
+ idx += SetLength(curName->len, output + idx);
+ XMEMCPY(output + idx, curName->name, curName->len);
+ idx += curName->len;
+ curName = curName->next;
+ } while (curName != NULL);
+
+ return idx;
+}
+
+#endif /* WOLFSSL_CERT_GEN */
+
+#endif /* WOLFSSL_ALT_NAMES */
+
+/* Encodes one attribute of the name (issuer/subject)
+ *
+ * name structure to hold result of encoding
+ * nameStr value to be encoded
+ * nameType type of encoding i.e CTC_UTF8
+ * type id of attribute i.e ASN_COMMON_NAME
+ *
+ * returns length on success
+ */
+static int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType,
+ byte type)
+{
+ word32 idx = 0;
+
+ if (nameStr) {
+ /* bottom up */
+ byte firstLen[1 + MAX_LENGTH_SZ];
+ byte secondLen[MAX_LENGTH_SZ];
+ byte sequence[MAX_SEQ_SZ];
+ byte set[MAX_SET_SZ];
+
+ int strLen = (int)XSTRLEN(nameStr);
+ int thisLen = strLen;
+ int firstSz, secondSz, seqSz, setSz;
+
+ if (strLen == 0) { /* no user data for this item */
+ name->used = 0;
+ return 0;
+ }
+
+ /* Restrict country code size */
+ if (ASN_COUNTRY_NAME == type && strLen != CTC_COUNTRY_SIZE) {
+ return ASN_COUNTRY_SIZE_E;
+ }
+
+ secondSz = SetLength(strLen, secondLen);
+ thisLen += secondSz;
+ switch (type) {
+ case ASN_EMAIL_NAME: /* email */
+ thisLen += EMAIL_JOINT_LEN;
+ firstSz = EMAIL_JOINT_LEN;
+ break;
+
+ case ASN_DOMAIN_COMPONENT:
+ thisLen += PILOT_JOINT_LEN;
+ firstSz = PILOT_JOINT_LEN;
+ break;
+
+ default:
+ thisLen++; /* str type */
+ thisLen += JOINT_LEN;
+ firstSz = JOINT_LEN + 1;
+ }
+ thisLen++; /* id type */
+ firstSz = SetObjectId(firstSz, firstLen);
+ thisLen += firstSz;
+
+ seqSz = SetSequence(thisLen, sequence);
+ thisLen += seqSz;
+ setSz = SetSet(thisLen, set);
+ thisLen += setSz;
+
+ if (thisLen > (int)sizeof(name->encoded)) {
+ return BUFFER_E;
+ }
+
+ /* store it */
+ idx = 0;
+ /* set */
+ XMEMCPY(name->encoded, set, setSz);
+ idx += setSz;
+ /* seq */
+ XMEMCPY(name->encoded + idx, sequence, seqSz);
+ idx += seqSz;
+ /* asn object id */
+ XMEMCPY(name->encoded + idx, firstLen, firstSz);
+ idx += firstSz;
+ switch (type) {
+ case ASN_EMAIL_NAME:
+ {
+ const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x09, 0x01, 0x16 };
+ /* email joint id */
+ XMEMCPY(name->encoded + idx, EMAIL_OID, sizeof(EMAIL_OID));
+ idx += (int)sizeof(EMAIL_OID);
+ }
+ break;
+
+ case ASN_DOMAIN_COMPONENT:
+ {
+ const byte PILOT_OID[] = { 0x09, 0x92, 0x26, 0x89,
+ 0x93, 0xF2, 0x2C, 0x64, 0x01
+ };
+
+ XMEMCPY(name->encoded + idx, PILOT_OID,
+ sizeof(PILOT_OID));
+ idx += (int)sizeof(PILOT_OID);
+ /* id type */
+ name->encoded[idx++] = type;
+ /* str type */
+ name->encoded[idx++] = nameType;
+ }
+ break;
+
+ default:
+ name->encoded[idx++] = 0x55;
+ name->encoded[idx++] = 0x04;
+ /* id type */
+ name->encoded[idx++] = type;
+ /* str type */
+ name->encoded[idx++] = nameType;
+ }
+ /* second length */
+ XMEMCPY(name->encoded + idx, secondLen, secondSz);
+ idx += secondSz;
+ /* str value */
+ XMEMCPY(name->encoded + idx, nameStr, strLen);
+ idx += strLen;
+
+ name->type = type;
+ name->totalLen = idx;
+ name->used = 1;
+ }
+ else
+ name->used = 0;
+
+ return idx;
+}
+
/* encode CertName into output, return total bytes written */
-static int SetName(byte* output, CertName* name)
+int SetName(byte* output, word32 outputSz, CertName* name)
{
int totalBytes = 0, i, idx;
#ifdef WOLFSSL_SMALL_STACK
@@ -5447,6 +12679,16 @@ static int SetName(byte* output, CertName* name)
#else
EncodedName names[NAME_ENTRIES];
#endif
+#ifdef WOLFSSL_MULTI_ATTRIB
+ EncodedName addNames[CTC_MAX_ATTRIB];
+ int j, type;
+#endif
+
+ if (output == NULL || name == NULL)
+ return BAD_FUNC_ARG;
+
+ if (outputSz < 3)
+ return BUFFER_E;
#ifdef WOLFSSL_SMALL_STACK
names = (EncodedName*)XMALLOC(sizeof(EncodedName) * NAME_ENTRIES, NULL,
@@ -5456,96 +12698,38 @@ static int SetName(byte* output, CertName* name)
#endif
for (i = 0; i < NAME_ENTRIES; i++) {
+ int ret;
const char* nameStr = GetOneName(name, i);
- if (nameStr) {
- /* bottom up */
- byte firstLen[MAX_LENGTH_SZ];
- byte secondLen[MAX_LENGTH_SZ];
- byte sequence[MAX_SEQ_SZ];
- byte set[MAX_SET_SZ];
-
- int email = i == (NAME_ENTRIES - 1) ? 1 : 0;
- int strLen = (int)XSTRLEN(nameStr);
- int thisLen = strLen;
- int firstSz, secondSz, seqSz, setSz;
-
- if (strLen == 0) { /* no user data for this item */
- names[i].used = 0;
- continue;
- }
-
- secondSz = SetLength(strLen, secondLen);
- thisLen += secondSz;
- if (email) {
- thisLen += EMAIL_JOINT_LEN;
- thisLen ++; /* id type */
- firstSz = SetLength(EMAIL_JOINT_LEN, firstLen);
- }
- else {
- thisLen++; /* str type */
- thisLen++; /* id type */
- thisLen += JOINT_LEN;
- firstSz = SetLength(JOINT_LEN + 1, firstLen);
- }
- thisLen += firstSz;
- thisLen++; /* object id */
-
- seqSz = SetSequence(thisLen, sequence);
- thisLen += seqSz;
- setSz = SetSet(thisLen, set);
- thisLen += setSz;
- if (thisLen > (int)sizeof(names[i].encoded)) {
-#ifdef WOLFSSL_SMALL_STACK
+ ret = wc_EncodeName(&names[i], nameStr, GetNameType(name, i),
+ GetNameId(i));
+ if (ret < 0) {
+ #ifdef WOLFSSL_SMALL_STACK
XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ #endif
+ return BUFFER_E;
+ }
+ totalBytes += ret;
+ }
+#ifdef WOLFSSL_MULTI_ATTRIB
+ for (i = 0; i < CTC_MAX_ATTRIB; i++) {
+ if (name->name[i].sz > 0) {
+ int ret;
+ ret = wc_EncodeName(&addNames[i], name->name[i].value,
+ name->name[i].type, name->name[i].id);
+ if (ret < 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
return BUFFER_E;
}
-
- /* store it */
- idx = 0;
- /* set */
- XMEMCPY(names[i].encoded, set, setSz);
- idx += setSz;
- /* seq */
- XMEMCPY(names[i].encoded + idx, sequence, seqSz);
- idx += seqSz;
- /* asn object id */
- names[i].encoded[idx++] = ASN_OBJECT_ID;
- /* first length */
- XMEMCPY(names[i].encoded + idx, firstLen, firstSz);
- idx += firstSz;
- if (email) {
- const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x09, 0x01, 0x16 };
- /* email joint id */
- XMEMCPY(names[i].encoded + idx, EMAIL_OID, sizeof(EMAIL_OID));
- idx += (int)sizeof(EMAIL_OID);
- }
- else {
- /* joint id */
- byte bType = GetNameId(i);
- names[i].encoded[idx++] = 0x55;
- names[i].encoded[idx++] = 0x04;
- /* id type */
- names[i].encoded[idx++] = bType;
- /* str type */
- names[i].encoded[idx++] = GetNameType(name, i);
- }
- /* second length */
- XMEMCPY(names[i].encoded + idx, secondLen, secondSz);
- idx += secondSz;
- /* str value */
- XMEMCPY(names[i].encoded + idx, nameStr, strLen);
- idx += strLen;
-
- totalBytes += idx;
- names[i].totalLen = idx;
- names[i].used = 1;
+ totalBytes += ret;
+ }
+ else {
+ addNames[i].used = 0;
}
- else
- names[i].used = 0;
}
+#endif /* WOLFSSL_MULTI_ATTRIB */
/* header */
idx = SetSequence(totalBytes, output);
@@ -5558,7 +12742,54 @@ static int SetName(byte* output, CertName* name)
}
for (i = 0; i < NAME_ENTRIES; i++) {
+ #ifdef WOLFSSL_MULTI_ATTRIB
+ type = GetNameId(i);
+
+ /* list all DC values before OUs */
+ if (type == ASN_ORGUNIT_NAME) {
+ type = ASN_DOMAIN_COMPONENT;
+ for (j = 0; j < CTC_MAX_ATTRIB; j++) {
+ if (name->name[j].sz > 0 && type == name->name[j].id) {
+ if (outputSz < (word32)(idx+addNames[j].totalLen)) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return BUFFER_E;
+ }
+
+ XMEMCPY(output + idx, addNames[j].encoded,
+ addNames[j].totalLen);
+ idx += addNames[j].totalLen;
+ }
+ }
+ type = ASN_ORGUNIT_NAME;
+ }
+
+ /* write all similar types to the buffer */
+ for (j = 0; j < CTC_MAX_ATTRIB; j++) {
+ if (name->name[j].sz > 0 && type == name->name[j].id) {
+ if (outputSz < (word32)(idx+addNames[j].totalLen)) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return BUFFER_E;
+ }
+
+ XMEMCPY(output + idx, addNames[j].encoded,
+ addNames[j].totalLen);
+ idx += addNames[j].totalLen;
+ }
+ }
+ #endif /* WOLFSSL_MULTI_ATTRIB */
+
if (names[i].used) {
+ if (outputSz < (word32)(idx+names[i].totalLen)) {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return BUFFER_E;
+ }
+
XMEMCPY(output + idx, names[i].encoded, names[i].totalLen);
idx += names[i].totalLen;
}
@@ -5573,13 +12804,19 @@ static int SetName(byte* output, CertName* name)
/* encode info from cert into DER encoded format */
static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
- RNG* rng, const byte* ntruKey, word16 ntruSz)
+ WC_RNG* rng, const byte* ntruKey, word16 ntruSz,
+ ed25519_key* ed25519Key, ed448_key* ed448Key)
{
int ret;
- (void)eccKey;
- (void)ntruKey;
- (void)ntruSz;
+ if (cert == NULL || der == NULL || rng == NULL)
+ return BAD_FUNC_ARG;
+
+ /* make sure at least one key type is provided */
+ if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL &&
+ ed448Key == NULL && ntruKey == NULL) {
+ return PUBLIC_KEY_E;
+ }
/* init */
XMEMSET(der, 0, sizeof(DerCert));
@@ -5587,65 +12824,95 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
/* version */
der->versionSz = SetMyVersion(cert->version, der->version, TRUE);
- /* serial number */
- ret = wc_RNG_GenerateBlock(rng, cert->serial, CTC_SERIAL_SIZE);
- if (ret != 0)
- return ret;
-
- cert->serial[0] = 0x01; /* ensure positive */
- der->serialSz = SetSerial(cert->serial, der->serial);
+ /* serial number (must be positive) */
+ if (cert->serialSz == 0) {
+ /* generate random serial */
+ cert->serialSz = CTC_GEN_SERIAL_SZ;
+ ret = wc_RNG_GenerateBlock(rng, cert->serial, cert->serialSz);
+ if (ret != 0)
+ return ret;
+ /* Clear the top bit to avoid a negative value */
+ cert->serial[0] &= 0x7f;
+ }
+ der->serialSz = SetSerialNumber(cert->serial, cert->serialSz, der->serial,
+ sizeof(der->serial), CTC_SERIAL_SIZE);
+ if (der->serialSz < 0)
+ return der->serialSz;
/* signature algo */
- der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, sigType, 0);
- if (der->sigAlgoSz == 0)
+ der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, oidSigType, 0);
+ if (der->sigAlgoSz <= 0)
return ALGO_ID_E;
/* public key */
+#ifndef NO_RSA
if (cert->keyType == RSA_KEY) {
if (rsaKey == NULL)
return PUBLIC_KEY_E;
- der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey);
- if (der->publicKeySz <= 0)
- return PUBLIC_KEY_E;
+ der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey,
+ sizeof(der->publicKey), 1);
}
+#endif
#ifdef HAVE_ECC
if (cert->keyType == ECC_KEY) {
if (eccKey == NULL)
return PUBLIC_KEY_E;
- der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey);
- if (der->publicKeySz <= 0)
+ der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1);
+ }
+#endif
+
+#ifdef HAVE_ED25519
+ if (cert->keyType == ED25519_KEY) {
+ if (ed25519Key == NULL)
return PUBLIC_KEY_E;
+ der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1);
}
-#endif /* HAVE_ECC */
+#endif
+
+#ifdef HAVE_ED448
+ if (cert->keyType == ED448_KEY) {
+ if (ed448Key == NULL)
+ return PUBLIC_KEY_E;
+ der->publicKeySz = SetEd448PublicKey(der->publicKey, ed448Key, 1);
+ }
+#endif
#ifdef HAVE_NTRU
if (cert->keyType == NTRU_KEY) {
word32 rc;
word16 encodedSz;
- rc = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruSz,
+ if (ntruKey == NULL)
+ return PUBLIC_KEY_E;
+
+ rc = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(ntruSz,
ntruKey, &encodedSz, NULL);
if (rc != NTRU_OK)
return PUBLIC_KEY_E;
if (encodedSz > MAX_PUBLIC_KEY_SZ)
return PUBLIC_KEY_E;
- rc = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruSz,
+ rc = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(ntruSz,
ntruKey, &encodedSz, der->publicKey);
if (rc != NTRU_OK)
return PUBLIC_KEY_E;
der->publicKeySz = encodedSz;
}
+#else
+ (void)ntruSz;
#endif /* HAVE_NTRU */
+ if (der->publicKeySz <= 0)
+ return PUBLIC_KEY_E;
+
der->validitySz = 0;
#ifdef WOLFSSL_ALT_NAMES
/* date validity copy ? */
if (cert->beforeDateSz && cert->afterDateSz) {
der->validitySz = CopyValidity(der->validity, cert);
- if (der->validitySz == 0)
+ if (der->validitySz <= 0)
return DATE_E;
}
#endif
@@ -5653,49 +12920,247 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
/* date validity */
if (der->validitySz == 0) {
der->validitySz = SetValidity(der->validity, cert->daysValid);
- if (der->validitySz == 0)
+ if (der->validitySz <= 0)
return DATE_E;
}
/* subject name */
- der->subjectSz = SetName(der->subject, &cert->subject);
- if (der->subjectSz == 0)
+#ifdef WOLFSSL_CERT_EXT
+ if (XSTRLEN((const char*)cert->sbjRaw) > 0) {
+ /* Use the raw subject */
+ int idx;
+
+ der->subjectSz = min(sizeof(der->subject),
+ (word32)XSTRLEN((const char*)cert->sbjRaw));
+ /* header */
+ idx = SetSequence(der->subjectSz, der->subject);
+ if (der->subjectSz + idx > (int)sizeof(der->subject)) {
+ return SUBJECT_E;
+ }
+
+ XMEMCPY((char*)der->subject + idx, (const char*)cert->sbjRaw,
+ der->subjectSz);
+ der->subjectSz += idx;
+ }
+ else
+#endif
+ {
+ /* Use the name structure */
+ der->subjectSz = SetName(der->subject, sizeof(der->subject),
+ &cert->subject);
+ }
+ if (der->subjectSz <= 0)
return SUBJECT_E;
/* issuer name */
- der->issuerSz = SetName(der->issuer, cert->selfSigned ?
- &cert->subject : &cert->issuer);
- if (der->issuerSz == 0)
+#ifdef WOLFSSL_CERT_EXT
+ if (XSTRLEN((const char*)cert->issRaw) > 0) {
+ /* Use the raw issuer */
+ int idx;
+
+ der->issuerSz = min(sizeof(der->issuer),
+ (word32)XSTRLEN((const char*)cert->issRaw));
+ /* header */
+ idx = SetSequence(der->issuerSz, der->issuer);
+ if (der->issuerSz + idx > (int)sizeof(der->issuer)) {
+ return ISSUER_E;
+ }
+
+ XMEMCPY((char*)der->issuer + idx, (const char*)cert->issRaw,
+ der->issuerSz);
+ der->issuerSz += idx;
+ }
+ else
+#endif
+ {
+ /* Use the name structure */
+ der->issuerSz = SetName(der->issuer, sizeof(der->issuer),
+ cert->selfSigned ? &cert->subject : &cert->issuer);
+ }
+ if (der->issuerSz <= 0)
return ISSUER_E;
+ /* set the extensions */
+ der->extensionsSz = 0;
+
/* CA */
if (cert->isCA) {
- der->caSz = SetCa(der->ca);
- if (der->caSz == 0)
+ der->caSz = SetCa(der->ca, sizeof(der->ca));
+ if (der->caSz <= 0)
return CA_TRUE_E;
+
+ der->extensionsSz += der->caSz;
}
else
der->caSz = 0;
- /* extensions, just CA now */
- if (cert->isCA) {
- der->extensionsSz = SetExtensions(der->extensions,
- der->ca, der->caSz, TRUE);
- if (der->extensionsSz == 0)
- return EXTENSIONS_E;
+#ifdef WOLFSSL_ALT_NAMES
+ /* Alternative Name */
+ if (cert->altNamesSz) {
+ der->altNamesSz = SetAltNames(der->altNames, sizeof(der->altNames),
+ cert->altNames, cert->altNamesSz);
+ if (der->altNamesSz <= 0)
+ return ALT_NAME_E;
+
+ der->extensionsSz += der->altNamesSz;
}
else
- der->extensionsSz = 0;
+ der->altNamesSz = 0;
+#endif
-#ifdef WOLFSSL_ALT_NAMES
- if (der->extensionsSz == 0 && cert->altNamesSz) {
- der->extensionsSz = SetExtensions(der->extensions, cert->altNames,
- cert->altNamesSz, TRUE);
- if (der->extensionsSz == 0)
- return EXTENSIONS_E;
+#ifdef WOLFSSL_CERT_EXT
+ /* SKID */
+ if (cert->skidSz) {
+ /* check the provided SKID size */
+ if (cert->skidSz > (int)min(CTC_MAX_SKID_SIZE, sizeof(der->skid)))
+ return SKID_E;
+
+ /* Note: different skid buffers sizes for der (MAX_KID_SZ) and
+ cert (CTC_MAX_SKID_SIZE). */
+ der->skidSz = SetSKID(der->skid, sizeof(der->skid),
+ cert->skid, cert->skidSz);
+ if (der->skidSz <= 0)
+ return SKID_E;
+
+ der->extensionsSz += der->skidSz;
+ }
+ else
+ der->skidSz = 0;
+
+ /* AKID */
+ if (cert->akidSz) {
+ /* check the provided AKID size */
+ if (cert->akidSz > (int)min(CTC_MAX_AKID_SIZE, sizeof(der->akid)))
+ return AKID_E;
+
+ der->akidSz = SetAKID(der->akid, sizeof(der->akid),
+ cert->akid, cert->akidSz, cert->heap);
+ if (der->akidSz <= 0)
+ return AKID_E;
+
+ der->extensionsSz += der->akidSz;
+ }
+ else
+ der->akidSz = 0;
+
+ /* Key Usage */
+ if (cert->keyUsage != 0){
+ der->keyUsageSz = SetKeyUsage(der->keyUsage, sizeof(der->keyUsage),
+ cert->keyUsage);
+ if (der->keyUsageSz <= 0)
+ return KEYUSAGE_E;
+
+ der->extensionsSz += der->keyUsageSz;
+ }
+ else
+ der->keyUsageSz = 0;
+
+ /* Extended Key Usage */
+ if (cert->extKeyUsage != 0){
+ der->extKeyUsageSz = SetExtKeyUsage(cert, der->extKeyUsage,
+ sizeof(der->extKeyUsage), cert->extKeyUsage);
+ if (der->extKeyUsageSz <= 0)
+ return EXTKEYUSAGE_E;
+
+ der->extensionsSz += der->extKeyUsageSz;
+ }
+ else
+ der->extKeyUsageSz = 0;
+
+ /* Certificate Policies */
+ if (cert->certPoliciesNb != 0) {
+ der->certPoliciesSz = SetCertificatePolicies(der->certPolicies,
+ sizeof(der->certPolicies),
+ cert->certPolicies,
+ cert->certPoliciesNb,
+ cert->heap);
+ if (der->certPoliciesSz <= 0)
+ return CERTPOLICIES_E;
+
+ der->extensionsSz += der->certPoliciesSz;
}
+ else
+ der->certPoliciesSz = 0;
+#endif /* WOLFSSL_CERT_EXT */
+
+ /* put extensions */
+ if (der->extensionsSz > 0) {
+
+ /* put the start of extensions sequence (ID, Size) */
+ der->extensionsSz = SetExtensionsHeader(der->extensions,
+ sizeof(der->extensions),
+ der->extensionsSz);
+ if (der->extensionsSz <= 0)
+ return EXTENSIONS_E;
+
+ /* put CA */
+ if (der->caSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->ca, der->caSz);
+ if (ret == 0)
+ return EXTENSIONS_E;
+ }
+
+#ifdef WOLFSSL_ALT_NAMES
+ /* put Alternative Names */
+ if (der->altNamesSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->altNames, der->altNamesSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
#endif
+#ifdef WOLFSSL_CERT_EXT
+ /* put SKID */
+ if (der->skidSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->skid, der->skidSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ /* put AKID */
+ if (der->akidSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->akid, der->akidSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ /* put KeyUsage */
+ if (der->keyUsageSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->keyUsage, der->keyUsageSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ /* put ExtendedKeyUsage */
+ if (der->extKeyUsageSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->extKeyUsage, der->extKeyUsageSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ /* put Certificate Policies */
+ if (der->certPoliciesSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->certPolicies, der->certPoliciesSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+#endif /* WOLFSSL_CERT_EXT */
+ }
+
der->total = der->versionSz + der->serialSz + der->sigAlgoSz +
der->publicKeySz + der->validitySz + der->subjectSz + der->issuerSz +
der->extensionsSz;
@@ -5705,37 +13170,37 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
/* write DER encoded cert to buffer, size already checked */
-static int WriteCertBody(DerCert* der, byte* buffer)
+static int WriteCertBody(DerCert* der, byte* buf)
{
int idx;
/* signed part header */
- idx = SetSequence(der->total, buffer);
+ idx = SetSequence(der->total, buf);
/* version */
- XMEMCPY(buffer + idx, der->version, der->versionSz);
+ XMEMCPY(buf + idx, der->version, der->versionSz);
idx += der->versionSz;
/* serial */
- XMEMCPY(buffer + idx, der->serial, der->serialSz);
+ XMEMCPY(buf + idx, der->serial, der->serialSz);
idx += der->serialSz;
/* sig algo */
- XMEMCPY(buffer + idx, der->sigAlgo, der->sigAlgoSz);
+ XMEMCPY(buf + idx, der->sigAlgo, der->sigAlgoSz);
idx += der->sigAlgoSz;
/* issuer */
- XMEMCPY(buffer + idx, der->issuer, der->issuerSz);
+ XMEMCPY(buf + idx, der->issuer, der->issuerSz);
idx += der->issuerSz;
/* validity */
- XMEMCPY(buffer + idx, der->validity, der->validitySz);
+ XMEMCPY(buf + idx, der->validity, der->validitySz);
idx += der->validitySz;
/* subject */
- XMEMCPY(buffer + idx, der->subject, der->subjectSz);
+ XMEMCPY(buf + idx, der->subject, der->subjectSz);
idx += der->subjectSz;
/* public key */
- XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz);
+ XMEMCPY(buf + idx, der->publicKey, der->publicKeySz);
idx += der->publicKeySz;
if (der->extensionsSz) {
/* extensions */
- XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz,
- sizeof(der->extensions)));
+ XMEMCPY(buf + idx, der->extensions, min(der->extensionsSz,
+ (int)sizeof(der->extensions)));
idx += der->extensionsSz;
}
@@ -5744,97 +13209,126 @@ static int WriteCertBody(DerCert* der, byte* buffer)
/* Make RSA signature from buffer (sz), write to sig (sigSz) */
-static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz,
- RsaKey* rsaKey, ecc_key* eccKey, RNG* rng,
- int sigAlgoType)
+static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, int sz,
+ byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey,
+ ed25519_key* ed25519Key, ed448_key* ed448Key, WC_RNG* rng, int sigAlgoType,
+ void* heap)
{
- int encSigSz, digestSz, typeH = 0, ret = 0;
- byte digest[SHA256_DIGEST_SIZE]; /* max size */
-#ifdef WOLFSSL_SMALL_STACK
- byte* encSig;
-#else
- byte encSig[MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ];
-#endif
+ int digestSz = 0, typeH = 0, ret = 0;
- (void)digest;
(void)digestSz;
- (void)encSig;
- (void)encSigSz;
(void)typeH;
-
- (void)buffer;
+ (void)buf;
(void)sz;
(void)sig;
(void)sigSz;
(void)rsaKey;
(void)eccKey;
+ (void)ed25519Key;
+ (void)ed448Key;
(void)rng;
+ (void)heap;
- switch (sigAlgoType) {
- #ifndef NO_MD5
- case CTC_MD5wRSA:
- if ((ret = wc_Md5Hash(buffer, sz, digest)) == 0) {
- typeH = MD5h;
- digestSz = MD5_DIGEST_SIZE;
+ switch (certSignCtx->state) {
+ case CERTSIGN_STATE_BEGIN:
+ case CERTSIGN_STATE_DIGEST:
+
+ certSignCtx->state = CERTSIGN_STATE_DIGEST;
+ certSignCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (certSignCtx->digest == NULL) {
+ ret = MEMORY_E; goto exit_ms;
}
- break;
- #endif
- #ifndef NO_SHA
- case CTC_SHAwRSA:
- case CTC_SHAwECDSA:
- if ((ret = wc_ShaHash(buffer, sz, digest)) == 0) {
- typeH = SHAh;
- digestSz = SHA_DIGEST_SIZE;
+
+ ret = HashForSignature(buf, sz, sigAlgoType, certSignCtx->digest,
+ &typeH, &digestSz, 0);
+ /* set next state, since WC_PENDING_E rentry for these are not "call again" */
+ certSignCtx->state = CERTSIGN_STATE_ENCODE;
+ if (ret != 0) {
+ goto exit_ms;
}
- break;
- #endif
- #ifndef NO_SHA256
- case CTC_SHA256wRSA:
- case CTC_SHA256wECDSA:
- if ((ret = wc_Sha256Hash(buffer, sz, digest)) == 0) {
- typeH = SHA256h;
- digestSz = SHA256_DIGEST_SIZE;
+ FALL_THROUGH;
+
+ case CERTSIGN_STATE_ENCODE:
+ #ifndef NO_RSA
+ if (rsaKey) {
+ certSignCtx->encSig = (byte*)XMALLOC(MAX_DER_DIGEST_SZ, heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (certSignCtx->encSig == NULL) {
+ ret = MEMORY_E; goto exit_ms;
+ }
+
+ /* signature */
+ certSignCtx->encSigSz = wc_EncodeSignature(certSignCtx->encSig,
+ certSignCtx->digest, digestSz, typeH);
}
+ #endif /* !NO_RSA */
+ FALL_THROUGH;
+
+ case CERTSIGN_STATE_DO:
+ certSignCtx->state = CERTSIGN_STATE_DO;
+ ret = ALGO_ID_E; /* default to error */
+
+ #ifndef NO_RSA
+ if (rsaKey) {
+ /* signature */
+ ret = wc_RsaSSL_Sign(certSignCtx->encSig, certSignCtx->encSigSz,
+ sig, sigSz, rsaKey, rng);
+ }
+ #endif /* !NO_RSA */
+
+ #ifdef HAVE_ECC
+ if (!rsaKey && eccKey) {
+ word32 outSz = sigSz;
+
+ ret = wc_ecc_sign_hash(certSignCtx->digest, digestSz,
+ sig, &outSz, rng, eccKey);
+ if (ret == 0)
+ ret = outSz;
+ }
+ #endif /* HAVE_ECC */
+
+ #ifdef HAVE_ED25519
+ if (!rsaKey && !eccKey && ed25519Key) {
+ word32 outSz = sigSz;
+
+ ret = wc_ed25519_sign_msg(buf, sz, sig, &outSz, ed25519Key);
+ if (ret == 0)
+ ret = outSz;
+ }
+ #endif /* HAVE_ECC */
+
+ #ifdef HAVE_ED448
+ if (!rsaKey && !eccKey && !ed25519Key && ed448Key) {
+ word32 outSz = sigSz;
+
+ ret = wc_ed448_sign_msg(buf, sz, sig, &outSz, ed448Key, NULL, 0);
+ if (ret == 0)
+ ret = outSz;
+ }
+ #endif /* HAVE_ECC */
break;
- #endif
- default:
- WOLFSSL_MSG("MakeSignautre called with unsupported type");
- ret = ALGO_ID_E;
}
-
- if (ret != 0)
+
+exit_ms:
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
return ret;
-
-#ifdef WOLFSSL_SMALL_STACK
- encSig = (byte*)XMALLOC(MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ,
- NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (encSig == NULL)
- return MEMORY_E;
+ }
#endif
-
- ret = ALGO_ID_E;
-
+
#ifndef NO_RSA
if (rsaKey) {
- /* signature */
- encSigSz = wc_EncodeSignature(encSig, digest, digestSz, typeH);
- ret = wc_RsaSSL_Sign(encSig, encSigSz, sig, sigSz, rsaKey, rng);
+ XFREE(certSignCtx->encSig, heap, DYNAMIC_TYPE_TMP_BUFFER);
}
-#endif
-
-#ifdef HAVE_ECC
- if (!rsaKey && eccKey) {
- word32 outSz = sigSz;
- ret = wc_ecc_sign_hash(digest, digestSz, sig, &outSz, rng, eccKey);
+#endif /* !NO_RSA */
- if (ret == 0)
- ret = outSz;
- }
-#endif
+ XFREE(certSignCtx->digest, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ certSignCtx->digest = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(encSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ /* reset state */
+ certSignCtx->state = CERTSIGN_STATE_BEGIN;
return ret;
}
@@ -5842,27 +13336,27 @@ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz,
/* add signature to end of buffer, size of buffer assumed checked, return
new length */
-static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz,
+static int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz,
int sigAlgoType)
{
byte seq[MAX_SEQ_SZ];
int idx = bodySz, seqSz;
/* algo */
- idx += SetAlgoID(sigAlgoType, buffer + idx, sigType, 0);
+ idx += SetAlgoID(sigAlgoType, buf ? buf + idx : NULL, oidSigType, 0);
/* bit string */
- buffer[idx++] = ASN_BIT_STRING;
- /* length */
- idx += SetLength(sigSz + 1, buffer + idx);
- buffer[idx++] = 0; /* trailing 0 */
+ idx += SetBitString(sigSz, 0, buf ? buf + idx : NULL);
/* signature */
- XMEMCPY(buffer + idx, sig, sigSz);
+ if (buf)
+ XMEMCPY(buf + idx, sig, sigSz);
idx += sigSz;
/* make room for overall header */
seqSz = SetSequence(idx, seq);
- XMEMMOVE(buffer + seqSz, buffer, idx);
- XMEMCPY(buffer, seq, seqSz);
+ if (buf) {
+ XMEMMOVE(buf + seqSz, buf, idx);
+ XMEMCPY(buf, seq, seqSz);
+ }
return idx + seqSz;
}
@@ -5870,8 +13364,9 @@ static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz,
/* Make an x509 Certificate v3 any key type from cert input, write to buffer */
static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
- RsaKey* rsaKey, ecc_key* eccKey, RNG* rng,
- const byte* ntruKey, word16 ntruSz)
+ RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng,
+ const byte* ntruKey, word16 ntruSz,
+ ed25519_key* ed25519Key, ed448_key* ed448Key)
{
int ret;
#ifdef WOLFSSL_SMALL_STACK
@@ -5880,16 +13375,21 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
DerCert der[1];
#endif
- cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY : NTRU_KEY);
+ if (derBuffer == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY :
+ (ed25519Key ? ED25519_KEY : (ed448Key ? ED448_KEY : NTRU_KEY)));
#ifdef WOLFSSL_SMALL_STACK
- der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ der = (DerCert*)XMALLOC(sizeof(DerCert), cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (der == NULL)
return MEMORY_E;
#endif
- ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz);
-
+ ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz,
+ ed25519Key, ed448Key);
if (ret == 0) {
if (der->total + MAX_SEQ_SZ * 2 > (int)derSz)
ret = BUFFER_E;
@@ -5898,7 +13398,7 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
}
#ifdef WOLFSSL_SMALL_STACK
- XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
@@ -5906,19 +13406,41 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */
+int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType,
+ void* key, WC_RNG* rng)
+{
+ RsaKey* rsaKey = NULL;
+ ecc_key* eccKey = NULL;
+ ed25519_key* ed25519Key = NULL;
+ ed448_key* ed448Key = NULL;
+
+ if (keyType == RSA_TYPE)
+ rsaKey = (RsaKey*)key;
+ else if (keyType == ECC_TYPE)
+ eccKey = (ecc_key*)key;
+ else if (keyType == ED25519_TYPE)
+ ed25519Key = (ed25519_key*)key;
+ else if (keyType == ED448_TYPE)
+ ed448Key = (ed448_key*)key;
+
+ return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0,
+ ed25519Key, ed448Key);
+}
+/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */
int wc_MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey,
- ecc_key* eccKey, RNG* rng)
+ ecc_key* eccKey, WC_RNG* rng)
{
- return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0);
+ return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0,
+ NULL, NULL);
}
#ifdef HAVE_NTRU
int wc_MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz,
- const byte* ntruKey, word16 keySz, RNG* rng)
+ const byte* ntruKey, word16 keySz, WC_RNG* rng)
{
- return MakeAnyCert(cert, derBuffer, derSz, NULL, NULL, rng, ntruKey, keySz);
+ return MakeAnyCert(cert, derBuffer, derSz, NULL, NULL, rng, ntruKey, keySz, NULL);
}
#endif /* HAVE_NTRU */
@@ -5926,12 +13448,13 @@ int wc_MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz,
#ifdef WOLFSSL_CERT_REQ
-static int SetReqAttrib(byte* output, char* pw, int extSz)
+static int SetReqAttrib(byte* output, char* pw, int pwPrintableString,
+ int extSz)
{
- static const byte cpOid[] =
+ const byte cpOid[] =
{ ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
0x09, 0x07 };
- static const byte erOid[] =
+ const byte erOid[] =
{ ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
0x09, 0x0e };
@@ -5955,7 +13478,11 @@ static int SetReqAttrib(byte* output, char* pw, int extSz)
if (pw && pw[0]) {
pwSz = (int)XSTRLEN(pw);
- cpStrSz = SetUTF8String(pwSz, cpStr);
+ if (pwPrintableString) {
+ cpStrSz = SetPrintableString(pwSz, cpStr);
+ } else {
+ cpStrSz = SetUTF8String(pwSz, cpStr);
+ }
cpSetSz = SetSet(cpStrSz + pwSz, cpSet);
cpSeqSz = SetSequence(sizeof(cpOid) + cpSetSz + cpStrSz + pwSz, cpSeq);
cpSz = cpSeqSz + sizeof(cpOid) + cpSetSz + cpStrSz + pwSz;
@@ -5998,10 +13525,21 @@ static int SetReqAttrib(byte* output, char* pw, int extSz)
/* encode info from cert into DER encoded format */
-static int EncodeCertReq(Cert* cert, DerCert* der,
- RsaKey* rsaKey, ecc_key* eccKey)
+static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey,
+ ecc_key* eccKey, ed25519_key* ed25519Key,
+ ed448_key* ed448Key)
{
(void)eccKey;
+ (void)ed25519Key;
+ (void)ed448Key;
+
+ if (cert == NULL || der == NULL)
+ return BAD_FUNC_ARG;
+
+ if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL &&
+ ed448Key == NULL) {
+ return PUBLIC_KEY_E;
+ }
/* init */
XMEMSET(der, 0, sizeof(DerCert));
@@ -6010,51 +13548,163 @@ static int EncodeCertReq(Cert* cert, DerCert* der,
der->versionSz = SetMyVersion(cert->version, der->version, FALSE);
/* subject name */
- der->subjectSz = SetName(der->subject, &cert->subject);
- if (der->subjectSz == 0)
+ der->subjectSz = SetName(der->subject, sizeof(der->subject), &cert->subject);
+ if (der->subjectSz <= 0)
return SUBJECT_E;
/* public key */
+#ifndef NO_RSA
if (cert->keyType == RSA_KEY) {
if (rsaKey == NULL)
return PUBLIC_KEY_E;
- der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey);
- if (der->publicKeySz <= 0)
- return PUBLIC_KEY_E;
+ der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey,
+ sizeof(der->publicKey), 1);
}
+#endif
#ifdef HAVE_ECC
if (cert->keyType == ECC_KEY) {
- if (eccKey == NULL)
+ der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1);
+ }
+#endif
+
+#ifdef HAVE_ED25519
+ if (cert->keyType == ED25519_KEY) {
+ if (ed25519Key == NULL)
return PUBLIC_KEY_E;
- der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey);
- if (der->publicKeySz <= 0)
+ der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1);
+ }
+#endif
+
+#ifdef HAVE_ED448
+ if (cert->keyType == ED448_KEY) {
+ if (ed448Key == NULL)
return PUBLIC_KEY_E;
+ der->publicKeySz = SetEd448PublicKey(der->publicKey, ed448Key, 1);
}
-#endif /* HAVE_ECC */
+#endif
+ if (der->publicKeySz <= 0)
+ return PUBLIC_KEY_E;
+
+ /* set the extensions */
+ der->extensionsSz = 0;
/* CA */
if (cert->isCA) {
- der->caSz = SetCa(der->ca);
- if (der->caSz == 0)
+ der->caSz = SetCa(der->ca, sizeof(der->ca));
+ if (der->caSz <= 0)
return CA_TRUE_E;
+
+ der->extensionsSz += der->caSz;
}
else
der->caSz = 0;
- /* extensions, just CA now */
- if (cert->isCA) {
- der->extensionsSz = SetExtensions(der->extensions,
- der->ca, der->caSz, FALSE);
- if (der->extensionsSz == 0)
- return EXTENSIONS_E;
+#ifdef WOLFSSL_CERT_EXT
+ /* SKID */
+ if (cert->skidSz) {
+ /* check the provided SKID size */
+ if (cert->skidSz > (int)min(CTC_MAX_SKID_SIZE, sizeof(der->skid)))
+ return SKID_E;
+
+ der->skidSz = SetSKID(der->skid, sizeof(der->skid),
+ cert->skid, cert->skidSz);
+ if (der->skidSz <= 0)
+ return SKID_E;
+
+ der->extensionsSz += der->skidSz;
+ }
+ else
+ der->skidSz = 0;
+
+ /* Key Usage */
+ if (cert->keyUsage != 0){
+ der->keyUsageSz = SetKeyUsage(der->keyUsage, sizeof(der->keyUsage),
+ cert->keyUsage);
+ if (der->keyUsageSz <= 0)
+ return KEYUSAGE_E;
+
+ der->extensionsSz += der->keyUsageSz;
}
else
- der->extensionsSz = 0;
+ der->keyUsageSz = 0;
- der->attribSz = SetReqAttrib(der->attrib,
- cert->challengePw, der->extensionsSz);
- if (der->attribSz == 0)
+ /* Extended Key Usage */
+ if (cert->extKeyUsage != 0){
+ der->extKeyUsageSz = SetExtKeyUsage(cert, der->extKeyUsage,
+ sizeof(der->extKeyUsage), cert->extKeyUsage);
+ if (der->extKeyUsageSz <= 0)
+ return EXTKEYUSAGE_E;
+
+ der->extensionsSz += der->extKeyUsageSz;
+ }
+ else
+ der->extKeyUsageSz = 0;
+
+#endif /* WOLFSSL_CERT_EXT */
+
+ /* put extensions */
+ if (der->extensionsSz > 0) {
+ int ret;
+
+ /* put the start of sequence (ID, Size) */
+ der->extensionsSz = SetSequence(der->extensionsSz, der->extensions);
+ if (der->extensionsSz <= 0)
+ return EXTENSIONS_E;
+
+ /* put CA */
+ if (der->caSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->ca, der->caSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+#ifdef WOLFSSL_CERT_EXT
+ /* put SKID */
+ if (der->skidSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->skid, der->skidSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ /* put AKID */
+ if (der->akidSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->akid, der->akidSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ /* put KeyUsage */
+ if (der->keyUsageSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->keyUsage, der->keyUsageSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ /* put ExtendedKeyUsage */
+ if (der->extKeyUsageSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->extKeyUsage, der->extKeyUsageSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+#endif /* WOLFSSL_CERT_EXT */
+ }
+
+ der->attribSz = SetReqAttrib(der->attrib, cert->challengePw,
+ cert->challengePwPrintableString,
+ der->extensionsSz);
+ if (der->attribSz <= 0)
return REQ_ATTRIBUTE_E;
der->total = der->versionSz + der->subjectSz + der->publicKeySz +
@@ -6065,28 +13715,33 @@ static int EncodeCertReq(Cert* cert, DerCert* der,
/* write DER encoded cert req to buffer, size already checked */
-static int WriteCertReqBody(DerCert* der, byte* buffer)
+static int WriteCertReqBody(DerCert* der, byte* buf)
{
int idx;
/* signed part header */
- idx = SetSequence(der->total, buffer);
+ idx = SetSequence(der->total, buf);
/* version */
- XMEMCPY(buffer + idx, der->version, der->versionSz);
+ if (buf)
+ XMEMCPY(buf + idx, der->version, der->versionSz);
idx += der->versionSz;
/* subject */
- XMEMCPY(buffer + idx, der->subject, der->subjectSz);
+ if (buf)
+ XMEMCPY(buf + idx, der->subject, der->subjectSz);
idx += der->subjectSz;
/* public key */
- XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz);
+ if (buf)
+ XMEMCPY(buf + idx, der->publicKey, der->publicKeySz);
idx += der->publicKeySz;
/* attributes */
- XMEMCPY(buffer + idx, der->attrib, der->attribSz);
+ if (buf)
+ XMEMCPY(buf + idx, der->attrib, der->attribSz);
idx += der->attribSz;
/* extensions */
if (der->extensionsSz) {
- XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz,
- sizeof(der->extensions)));
+ if (buf)
+ XMEMCPY(buf + idx, der->extensions, min(der->extensionsSz,
+ (int)sizeof(der->extensions)));
idx += der->extensionsSz;
}
@@ -6094,8 +13749,9 @@ static int WriteCertReqBody(DerCert* der, byte* buffer)
}
-int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
- RsaKey* rsaKey, ecc_key* eccKey)
+static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
+ RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key,
+ ed448_key* ed448Key)
{
int ret;
#ifdef WOLFSSL_SMALL_STACK
@@ -6104,15 +13760,17 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
DerCert der[1];
#endif
- cert->keyType = eccKey ? ECC_KEY : RSA_KEY;
+ cert->keyType = eccKey ? ECC_KEY : (ed25519Key ? ED25519_KEY :
+ (ed448Key ? ED448_KEY: RSA_KEY));
#ifdef WOLFSSL_SMALL_STACK
- der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ der = (DerCert*)XMALLOC(sizeof(DerCert), cert->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
if (der == NULL)
return MEMORY_E;
#endif
- ret = EncodeCertReq(cert, der, rsaKey, eccKey);
+ ret = EncodeCertReq(cert, der, rsaKey, eccKey, ed25519Key, ed448Key);
if (ret == 0) {
if (der->total + MAX_SEQ_SZ * 2 > (int)derSz)
@@ -6122,100 +13780,669 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
}
#ifdef WOLFSSL_SMALL_STACK
- XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
+int wc_MakeCertReq_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType,
+ void* key)
+{
+ RsaKey* rsaKey = NULL;
+ ecc_key* eccKey = NULL;
+ ed25519_key* ed25519Key = NULL;
+ ed448_key* ed448Key = NULL;
+
+ if (keyType == RSA_TYPE)
+ rsaKey = (RsaKey*)key;
+ else if (keyType == ECC_TYPE)
+ eccKey = (ecc_key*)key;
+ else if (keyType == ED25519_TYPE)
+ ed25519Key = (ed25519_key*)key;
+ else if (keyType == ED448_TYPE)
+ ed448Key = (ed448_key*)key;
+
+ return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, ed25519Key,
+ ed448Key);
+}
+
+int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
+ RsaKey* rsaKey, ecc_key* eccKey)
+{
+ return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, NULL, NULL);
+}
#endif /* WOLFSSL_CERT_REQ */
-int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz,
- RsaKey* rsaKey, ecc_key* eccKey, RNG* rng)
+static int SignCert(int requestSz, int sType, byte* buf, word32 buffSz,
+ RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key,
+ ed448_key* ed448Key, WC_RNG* rng)
{
- int sigSz;
-#ifdef WOLFSSL_SMALL_STACK
- byte* sig;
+ int sigSz = 0;
+ void* heap = NULL;
+ CertSignCtx* certSignCtx;
+#ifndef WOLFSSL_ASYNC_CRYPT
+ CertSignCtx certSignCtx_lcl;
+
+ certSignCtx = &certSignCtx_lcl;
+ XMEMSET(certSignCtx, 0, sizeof(CertSignCtx));
#else
- byte sig[MAX_ENCODED_SIG_SZ];
+ certSignCtx = NULL;
#endif
if (requestSz < 0)
return requestSz;
-#ifdef WOLFSSL_SMALL_STACK
- sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (sig == NULL)
- return MEMORY_E;
+ /* locate ctx */
+ if (rsaKey) {
+ #ifndef NO_RSA
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ certSignCtx = &rsaKey->certSignCtx;
+ #endif
+ heap = rsaKey->heap;
+ #else
+ return NOT_COMPILED_IN;
+ #endif /* NO_RSA */
+ }
+ else if (eccKey) {
+ #ifdef HAVE_ECC
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ certSignCtx = &eccKey->certSignCtx;
+ #endif
+ heap = eccKey->heap;
+ #else
+ return NOT_COMPILED_IN;
+ #endif /* HAVE_ECC */
+ }
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (certSignCtx == NULL) {
+ return BAD_FUNC_ARG;
+ }
#endif
- sigSz = MakeSignature(buffer, requestSz, sig, MAX_ENCODED_SIG_SZ, rsaKey,
- eccKey, rng, sType);
+ if (certSignCtx->sig == NULL) {
+ certSignCtx->sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (certSignCtx->sig == NULL)
+ return MEMORY_E;
+ }
+
+ sigSz = MakeSignature(certSignCtx, buf, requestSz, certSignCtx->sig,
+ MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, ed448Key, rng, sType,
+ heap);
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (sigSz == WC_PENDING_E) {
+ /* Not free'ing certSignCtx->sig here because it could still be in use
+ * with async operations. */
+ return sigSz;
+ }
+#endif
if (sigSz >= 0) {
if (requestSz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz)
sigSz = BUFFER_E;
else
- sigSz = AddSignature(buffer, requestSz, sig, sigSz, sType);
+ sigSz = AddSignature(buf, requestSz, certSignCtx->sig, sigSz,
+ sType);
}
-
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+
+ XFREE(certSignCtx->sig, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ certSignCtx->sig = NULL;
return sigSz;
}
+int wc_SignCert_ex(int requestSz, int sType, byte* buf, word32 buffSz,
+ int keyType, void* key, WC_RNG* rng)
+{
+ RsaKey* rsaKey = NULL;
+ ecc_key* eccKey = NULL;
+ ed25519_key* ed25519Key = NULL;
+ ed448_key* ed448Key = NULL;
+
+ if (keyType == RSA_TYPE)
+ rsaKey = (RsaKey*)key;
+ else if (keyType == ECC_TYPE)
+ eccKey = (ecc_key*)key;
+ else if (keyType == ED25519_TYPE)
+ ed25519Key = (ed25519_key*)key;
+ else if (keyType == ED448_TYPE)
+ ed448Key = (ed448_key*)key;
+
+ return SignCert(requestSz, sType, buf, buffSz, rsaKey, eccKey, ed25519Key,
+ ed448Key, rng);
+}
+
+int wc_SignCert(int requestSz, int sType, byte* buf, word32 buffSz,
+ RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng)
+{
+ return SignCert(requestSz, sType, buf, buffSz, rsaKey, eccKey, NULL, NULL,
+ rng);
+}
-int wc_MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, RNG* rng)
+int wc_MakeSelfCert(Cert* cert, byte* buf, word32 buffSz,
+ RsaKey* key, WC_RNG* rng)
{
- int ret = wc_MakeCert(cert, buffer, buffSz, key, NULL, rng);
+ int ret;
+ ret = wc_MakeCert(cert, buf, buffSz, key, NULL, rng);
if (ret < 0)
return ret;
- return wc_SignCert(cert->bodySz, cert->sigType, buffer, buffSz, key, NULL,rng);
+ return wc_SignCert(cert->bodySz, cert->sigType,
+ buf, buffSz, key, NULL, rng);
}
-#ifdef WOLFSSL_ALT_NAMES
+#ifdef WOLFSSL_CERT_EXT
-/* Set Alt Names from der cert, return 0 on success */
-static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz)
+/* Get raw subject from cert, which may contain OIDs not parsed by Decode.
+ The raw subject pointer will only be valid while "cert" is valid. */
+int wc_GetSubjectRaw(byte **subjectRaw, Cert *cert)
{
- int ret;
-#ifdef WOLFSSL_SMALL_STACK
- DecodedCert* decoded;
+ int rc = BAD_FUNC_ARG;
+ if ((subjectRaw != NULL) && (cert != NULL)) {
+ *subjectRaw = cert->sbjRaw;
+ rc = 0;
+ }
+ return rc;
+}
+
+/* Set KID from public key */
+static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey,
+ byte *ntruKey, word16 ntruKeySz,
+ ed25519_key* ed25519Key, ed448_key* ed448Key,
+ int kid_type)
+{
+ byte *buf;
+ int bufferSz, ret;
+
+ if (cert == NULL ||
+ (rsakey == NULL && eckey == NULL && ntruKey == NULL &&
+ ed25519Key == NULL && ed448Key == NULL) ||
+ (kid_type != SKID_TYPE && kid_type != AKID_TYPE))
+ return BAD_FUNC_ARG;
+
+ buf = (byte *)XMALLOC(MAX_PUBLIC_KEY_SZ, cert->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (buf == NULL)
+ return MEMORY_E;
+
+ /* Public Key */
+ bufferSz = -1;
+#ifndef NO_RSA
+ /* RSA public key */
+ if (rsakey != NULL)
+ bufferSz = SetRsaPublicKey(buf, rsakey, MAX_PUBLIC_KEY_SZ, 0);
+#endif
+#ifdef HAVE_ECC
+ /* ECC public key */
+ if (eckey != NULL)
+ bufferSz = SetEccPublicKey(buf, eckey, 0);
+#endif
+#ifdef HAVE_NTRU
+ /* NTRU public key */
+ if (ntruKey != NULL) {
+ bufferSz = MAX_PUBLIC_KEY_SZ;
+ ret = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(
+ ntruKeySz, ntruKey, (word16 *)(&bufferSz), buf);
+ if (ret != NTRU_OK)
+ bufferSz = -1;
+ }
#else
- DecodedCert decoded[1];
+ (void)ntruKeySz;
+#endif
+#ifdef HAVE_ED25519
+ /* ED25519 public key */
+ if (ed25519Key != NULL)
+ bufferSz = SetEd25519PublicKey(buf, ed25519Key, 0);
+#endif
+#ifdef HAVE_ED448
+ /* ED448 public key */
+ if (ed448Key != NULL)
+ bufferSz = SetEd448PublicKey(buffer, ed448Key, 0);
#endif
- if (derSz < 0)
+ if (bufferSz <= 0) {
+ XFREE(buf, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return PUBLIC_KEY_E;
+ }
+
+ /* Compute SKID by hashing public key */
+ if (kid_type == SKID_TYPE) {
+ ret = CalcHashId(buf, bufferSz, cert->skid);
+ cert->skidSz = KEYID_SIZE;
+ }
+ else if (kid_type == AKID_TYPE) {
+ ret = CalcHashId(buf, bufferSz, cert->akid);
+ cert->akidSz = KEYID_SIZE;
+ }
+ else
+ ret = BAD_FUNC_ARG;
+
+ XFREE(buf, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+}
+
+int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key)
+{
+ RsaKey* rsaKey = NULL;
+ ecc_key* eccKey = NULL;
+ ed25519_key* ed25519Key = NULL;
+ ed448_key* ed448Key = NULL;
+
+ if (keyType == RSA_TYPE)
+ rsaKey = (RsaKey*)key;
+ else if (keyType == ECC_TYPE)
+ eccKey = (ecc_key*)key;
+ else if (keyType == ED25519_TYPE)
+ ed25519Key = (ed25519_key*)key;
+ else if (keyType == ED448_TYPE)
+ ed448Key = (ed448_key*)key;
+
+ return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key,
+ ed448Key, SKID_TYPE);
+}
+
+/* Set SKID from RSA or ECC public key */
+int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey)
+{
+ return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, NULL,
+ SKID_TYPE);
+}
+
+#ifdef HAVE_NTRU
+/* Set SKID from NTRU public key */
+int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert,
+ byte *ntruKey, word16 ntruKeySz)
+{
+ return SetKeyIdFromPublicKey(cert, NULL,NULL,ntruKey, ntruKeySz, NULL, NULL,
+ SKID_TYPE);
+}
+#endif
+
+int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key)
+{
+ RsaKey* rsaKey = NULL;
+ ecc_key* eccKey = NULL;
+ ed25519_key* ed25519Key = NULL;
+ ed448_key* ed448Key = NULL;
+
+ if (keyType == RSA_TYPE)
+ rsaKey = (RsaKey*)key;
+ else if (keyType == ECC_TYPE)
+ eccKey = (ecc_key*)key;
+ else if (keyType == ED25519_TYPE)
+ ed25519Key = (ed25519_key*)key;
+ else if (keyType == ED448_TYPE)
+ ed448Key = (ed448_key*)key;
+
+ return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key,
+ ed448Key, AKID_TYPE);
+}
+
+/* Set SKID from RSA or ECC public key */
+int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey)
+{
+ return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, NULL,
+ AKID_TYPE);
+}
+
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_ASN_CRYPT)
+
+/* Set SKID from public key file in PEM */
+int wc_SetSubjectKeyId(Cert *cert, const char* file)
+{
+ int ret, derSz;
+ byte* der;
+ word32 idx;
+ RsaKey *rsakey = NULL;
+ ecc_key *eckey = NULL;
+
+ if (cert == NULL || file == NULL)
+ return BAD_FUNC_ARG;
+
+ der = (byte*)XMALLOC(MAX_PUBLIC_KEY_SZ, cert->heap, DYNAMIC_TYPE_CERT);
+ if (der == NULL) {
+ WOLFSSL_MSG("wc_SetSubjectKeyId memory Problem");
+ return MEMORY_E;
+ }
+ derSz = MAX_PUBLIC_KEY_SZ;
+
+ XMEMSET(der, 0, derSz);
+ derSz = wc_PemPubKeyToDer(file, der, derSz);
+ if (derSz <= 0) {
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
return derSz;
+ }
-#ifdef WOLFSSL_SMALL_STACK
- decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (decoded == NULL)
+ /* Load PubKey in internal structure */
+#ifndef NO_RSA
+ rsakey = (RsaKey*) XMALLOC(sizeof(RsaKey), cert->heap, DYNAMIC_TYPE_RSA);
+ if (rsakey == NULL) {
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+ return MEMORY_E;
+ }
+
+ if (wc_InitRsaKey(rsakey, cert->heap) != 0) {
+ WOLFSSL_MSG("wc_InitRsaKey failure");
+ XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
return MEMORY_E;
+ }
+
+ idx = 0;
+ ret = wc_RsaPublicKeyDecode(der, &idx, rsakey, derSz);
+ if (ret != 0)
#endif
-
- InitDecodedCert(decoded, (byte*)der, derSz, 0);
- ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0);
+ {
+#ifndef NO_RSA
+ WOLFSSL_MSG("wc_RsaPublicKeyDecode failed");
+ wc_FreeRsaKey(rsakey);
+ XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA);
+ rsakey = NULL;
+#endif
+#ifdef HAVE_ECC
+ /* Check to load ecc public key */
+ eckey = (ecc_key*) XMALLOC(sizeof(ecc_key), cert->heap,
+ DYNAMIC_TYPE_ECC);
+ if (eckey == NULL) {
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+ return MEMORY_E;
+ }
- if (ret < 0) {
- WOLFSSL_MSG("ParseCertRelative error");
+ if (wc_ecc_init(eckey) != 0) {
+ WOLFSSL_MSG("wc_ecc_init failure");
+ wc_ecc_free(eckey);
+ XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+ return MEMORY_E;
+ }
+
+ idx = 0;
+ ret = wc_EccPublicKeyDecode(der, &idx, eckey, derSz);
+ if (ret != 0) {
+ WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+ wc_ecc_free(eckey);
+ XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC);
+ return PUBLIC_KEY_E;
+ }
+#else
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+ return PUBLIC_KEY_E;
+#endif /* HAVE_ECC */
+ }
+
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+
+ ret = wc_SetSubjectKeyIdFromPublicKey(cert, rsakey, eckey);
+
+#ifndef NO_RSA
+ wc_FreeRsaKey(rsakey);
+ XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA);
+#endif
+#ifdef HAVE_ECC
+ wc_ecc_free(eckey);
+ XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC);
+#endif
+ return ret;
+}
+
+#endif /* !NO_FILESYSTEM && !NO_ASN_CRYPT */
+
+static int SetAuthKeyIdFromDcert(Cert* cert, DecodedCert* decoded)
+{
+ int ret = 0;
+
+ /* Subject Key Id not found !! */
+ if (decoded->extSubjKeyIdSet == 0) {
+ ret = ASN_NO_SKID;
+ }
+
+ /* SKID invalid size */
+ else if (sizeof(cert->akid) < sizeof(decoded->extSubjKeyId)) {
+ ret = MEMORY_E;
+ }
+
+ else {
+ /* Put the SKID of CA to AKID of certificate */
+ XMEMCPY(cert->akid, decoded->extSubjKeyId, KEYID_SIZE);
+ cert->akidSz = KEYID_SIZE;
+ }
+
+ return ret;
+}
+
+/* Set AKID from certificate contains in buffer (DER encoded) */
+int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz)
+{
+ int ret = 0;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Check if decodedCert is cached */
+ if (cert->der != der) {
+ /* Allocate cache for the decoded cert */
+ ret = wc_SetCert_LoadDer(cert, der, derSz);
+ }
+
+ if (ret >= 0) {
+ ret = SetAuthKeyIdFromDcert(cert, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+ wc_SetCert_Free(cert);
+#endif
+ }
+ }
+
+ return ret;
+}
+
+
+#ifndef NO_FILESYSTEM
+
+/* Set AKID from certificate file in PEM */
+int wc_SetAuthKeyId(Cert *cert, const char* file)
+{
+ int ret;
+ int derSz;
+ byte* der;
+
+ if (cert == NULL || file == NULL)
+ return BAD_FUNC_ARG;
+
+ der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
+ if (der == NULL) {
+ WOLFSSL_MSG("wc_SetAuthKeyId OOF Problem");
+ return MEMORY_E;
+ }
+
+ derSz = wc_PemCertToDer(file, der, EIGHTK_BUF);
+ if (derSz <= 0)
+ {
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+ return derSz;
}
- else if (decoded->extensions) {
- byte b;
+
+ ret = wc_SetAuthKeyIdFromCert(cert, der, derSz);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+
+ return ret;
+}
+
+#endif /* !NO_FILESYSTEM */
+
+/* Set KeyUsage from human readable string */
+int wc_SetKeyUsage(Cert *cert, const char *value)
+{
+ int ret = 0;
+ char *token, *str, *ptr;
+ word32 len;
+
+ if (cert == NULL || value == NULL)
+ return BAD_FUNC_ARG;
+
+ cert->keyUsage = 0;
+
+ /* duplicate string (including terminator) */
+ len = (word32)XSTRLEN(value);
+ str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (str == NULL)
+ return MEMORY_E;
+ XMEMCPY(str, value, len+1);
+
+ /* parse value, and set corresponding Key Usage value */
+ if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
+ XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return KEYUSAGE_E;
+ }
+ while (token != NULL)
+ {
+ len = (word32)XSTRLEN(token);
+
+ if (!XSTRNCASECMP(token, "digitalSignature", len))
+ cert->keyUsage |= KEYUSE_DIGITAL_SIG;
+ else if (!XSTRNCASECMP(token, "nonRepudiation", len) ||
+ !XSTRNCASECMP(token, "contentCommitment", len))
+ cert->keyUsage |= KEYUSE_CONTENT_COMMIT;
+ else if (!XSTRNCASECMP(token, "keyEncipherment", len))
+ cert->keyUsage |= KEYUSE_KEY_ENCIPHER;
+ else if (!XSTRNCASECMP(token, "dataEncipherment", len))
+ cert->keyUsage |= KEYUSE_DATA_ENCIPHER;
+ else if (!XSTRNCASECMP(token, "keyAgreement", len))
+ cert->keyUsage |= KEYUSE_KEY_AGREE;
+ else if (!XSTRNCASECMP(token, "keyCertSign", len))
+ cert->keyUsage |= KEYUSE_KEY_CERT_SIGN;
+ else if (!XSTRNCASECMP(token, "cRLSign", len))
+ cert->keyUsage |= KEYUSE_CRL_SIGN;
+ else if (!XSTRNCASECMP(token, "encipherOnly", len))
+ cert->keyUsage |= KEYUSE_ENCIPHER_ONLY;
+ else if (!XSTRNCASECMP(token, "decipherOnly", len))
+ cert->keyUsage |= KEYUSE_DECIPHER_ONLY;
+ else {
+ ret = KEYUSAGE_E;
+ break;
+ }
+
+ token = XSTRTOK(NULL, ",", &ptr);
+ }
+
+ XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+}
+
+/* Set ExtendedKeyUsage from human readable string */
+int wc_SetExtKeyUsage(Cert *cert, const char *value)
+{
+ int ret = 0;
+ char *token, *str, *ptr;
+ word32 len;
+
+ if (cert == NULL || value == NULL)
+ return BAD_FUNC_ARG;
+
+ cert->extKeyUsage = 0;
+
+ /* duplicate string (including terminator) */
+ len = (word32)XSTRLEN(value);
+ str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (str == NULL)
+ return MEMORY_E;
+ XMEMCPY(str, value, len+1);
+
+ /* parse value, and set corresponding Key Usage value */
+ if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
+ XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return EXTKEYUSAGE_E;
+ }
+
+ while (token != NULL)
+ {
+ len = (word32)XSTRLEN(token);
+
+ if (!XSTRNCASECMP(token, "any", len))
+ cert->extKeyUsage |= EXTKEYUSE_ANY;
+ else if (!XSTRNCASECMP(token, "serverAuth", len))
+ cert->extKeyUsage |= EXTKEYUSE_SERVER_AUTH;
+ else if (!XSTRNCASECMP(token, "clientAuth", len))
+ cert->extKeyUsage |= EXTKEYUSE_CLIENT_AUTH;
+ else if (!XSTRNCASECMP(token, "codeSigning", len))
+ cert->extKeyUsage |= EXTKEYUSE_CODESIGN;
+ else if (!XSTRNCASECMP(token, "emailProtection", len))
+ cert->extKeyUsage |= EXTKEYUSE_EMAILPROT;
+ else if (!XSTRNCASECMP(token, "timeStamping", len))
+ cert->extKeyUsage |= EXTKEYUSE_TIMESTAMP;
+ else if (!XSTRNCASECMP(token, "OCSPSigning", len))
+ cert->extKeyUsage |= EXTKEYUSE_OCSP_SIGN;
+ else {
+ ret = EXTKEYUSAGE_E;
+ break;
+ }
+
+ token = XSTRTOK(NULL, ",", &ptr);
+ }
+
+ XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+}
+
+#ifdef WOLFSSL_EKU_OID
+/*
+ * cert structure to set EKU oid in
+ * oid the oid in byte representation
+ * sz size of oid buffer
+ * idx index of array to place oid
+ *
+ * returns 0 on success
+ */
+int wc_SetExtKeyUsageOID(Cert *cert, const char *in, word32 sz, byte idx,
+ void* heap)
+{
+ byte oid[MAX_OID_SZ];
+ word32 oidSz = MAX_OID_SZ;
+
+ if (idx >= CTC_MAX_EKU_NB || sz >= CTC_MAX_EKU_OID_SZ) {
+ WOLFSSL_MSG("Either idx or sz was too large");
+ return BAD_FUNC_ARG;
+ }
+
+ if (EncodePolicyOID(oid, &oidSz, in, heap) != 0) {
+ return BUFFER_E;
+ }
+
+ XMEMCPY(cert->extKeyUsageOID[idx], oid, oidSz);
+ cert->extKeyUsageOIDSz[idx] = oidSz;
+ cert->extKeyUsage |= EXTKEYUSE_USER;
+
+ return 0;
+}
+#endif /* WOLFSSL_EKU_OID */
+#endif /* WOLFSSL_CERT_EXT */
+
+
+#ifdef WOLFSSL_ALT_NAMES
+
+static int SetAltNamesFromDcert(Cert* cert, DecodedCert* decoded)
+{
+ int ret = 0;
+ byte tag;
+
+ if (decoded->extensions) {
int length;
word32 maxExtensionsIdx;
decoded->srcIdx = decoded->extensionsIdx;
- b = decoded->source[decoded->srcIdx++];
-
- if (b != ASN_EXTENSIONS) {
+ if (GetASNTag(decoded->source, &decoded->srcIdx, &tag, decoded->maxIdx)
+ != 0) {
+ return ASN_PARSE_E;
+ }
+
+ if (tag != ASN_EXTENSIONS) {
ret = ASN_PARSE_E;
}
else if (GetLength(decoded->source, &decoded->srcIdx, &length,
@@ -6244,7 +14471,7 @@ static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz)
decoded->srcIdx = startIdx;
if (GetAlgoId(decoded->source, &decoded->srcIdx, &oid,
- decoded->maxIdx) < 0) {
+ oidCertExtType, decoded->maxIdx) < 0) {
ret = ASN_PARSE_E;
break;
}
@@ -6267,17 +14494,13 @@ static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz)
}
}
- FreeDecodedCert(decoded);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
- return ret < 0 ? ret : 0;
+ return ret;
}
+#ifndef NO_FILESYSTEM
-/* Set Dates from der cert, return 0 on success */
-static int SetDatesFromCert(Cert* cert, const byte* der, int derSz)
+/* Set Alt Names from der cert, return 0 on success */
+static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz)
{
int ret;
#ifdef WOLFSSL_SMALL_STACK
@@ -6286,28 +14509,45 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz)
DecodedCert decoded[1];
#endif
- WOLFSSL_ENTER("SetDatesFromCert");
if (derSz < 0)
return derSz;
-
+
#ifdef WOLFSSL_SMALL_STACK
- decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+ decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cert->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (decoded == NULL)
return MEMORY_E;
#endif
- InitDecodedCert(decoded, (byte*)der, derSz, 0);
+ InitDecodedCert(decoded, der, derSz, NULL);
ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0);
if (ret < 0) {
WOLFSSL_MSG("ParseCertRelative error");
}
- else if (decoded->beforeDate == NULL || decoded->afterDate == NULL) {
+ else {
+ ret = SetAltNamesFromDcert(cert, decoded);
+ }
+
+ FreeDecodedCert(decoded);
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+ return ret < 0 ? ret : 0;
+}
+
+#endif
+
+static int SetDatesFromDcert(Cert* cert, DecodedCert* decoded)
+{
+ int ret = 0;
+
+ if (decoded->beforeDate == NULL || decoded->afterDate == NULL) {
WOLFSSL_MSG("Couldn't extract dates");
ret = -1;
}
- else if (decoded->beforeDateLen > MAX_DATE_SIZE ||
+ else if (decoded->beforeDateLen > MAX_DATE_SIZE ||
decoded->afterDateLen > MAX_DATE_SIZE) {
WOLFSSL_MSG("Bad date size");
ret = -1;
@@ -6320,23 +14560,108 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz)
cert->afterDateSz = decoded->afterDateLen;
}
- FreeDecodedCert(decoded);
-
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
- return ret < 0 ? ret : 0;
+ return ret;
}
+#endif /* WOLFSSL_ALT_NAMES */
-#endif /* WOLFSSL_ALT_NAMES && !NO_RSA */
+static void SetNameFromDcert(CertName* cn, DecodedCert* decoded)
+{
+ int sz;
+
+ if (decoded->subjectCN) {
+ sz = (decoded->subjectCNLen < CTC_NAME_SIZE) ? decoded->subjectCNLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->commonName, decoded->subjectCN, sz);
+ cn->commonName[sz] = '\0';
+ cn->commonNameEnc = decoded->subjectCNEnc;
+ }
+ if (decoded->subjectC) {
+ sz = (decoded->subjectCLen < CTC_NAME_SIZE) ? decoded->subjectCLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->country, decoded->subjectC, sz);
+ cn->country[sz] = '\0';
+ cn->countryEnc = decoded->subjectCEnc;
+ }
+ if (decoded->subjectST) {
+ sz = (decoded->subjectSTLen < CTC_NAME_SIZE) ? decoded->subjectSTLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->state, decoded->subjectST, sz);
+ cn->state[sz] = '\0';
+ cn->stateEnc = decoded->subjectSTEnc;
+ }
+ if (decoded->subjectL) {
+ sz = (decoded->subjectLLen < CTC_NAME_SIZE) ? decoded->subjectLLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->locality, decoded->subjectL, sz);
+ cn->locality[sz] = '\0';
+ cn->localityEnc = decoded->subjectLEnc;
+ }
+ if (decoded->subjectO) {
+ sz = (decoded->subjectOLen < CTC_NAME_SIZE) ? decoded->subjectOLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->org, decoded->subjectO, sz);
+ cn->org[sz] = '\0';
+ cn->orgEnc = decoded->subjectOEnc;
+ }
+ if (decoded->subjectOU) {
+ sz = (decoded->subjectOULen < CTC_NAME_SIZE) ? decoded->subjectOULen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->unit, decoded->subjectOU, sz);
+ cn->unit[sz] = '\0';
+ cn->unitEnc = decoded->subjectOUEnc;
+ }
+ if (decoded->subjectSN) {
+ sz = (decoded->subjectSNLen < CTC_NAME_SIZE) ? decoded->subjectSNLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->sur, decoded->subjectSN, sz);
+ cn->sur[sz] = '\0';
+ cn->surEnc = decoded->subjectSNEnc;
+ }
+ if (decoded->subjectSND) {
+ sz = (decoded->subjectSNDLen < CTC_NAME_SIZE) ? decoded->subjectSNDLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->serialDev, decoded->subjectSND, sz);
+ cn->serialDev[sz] = '\0';
+ cn->serialDevEnc = decoded->subjectSNDEnc;
+ }
+#ifdef WOLFSSL_CERT_EXT
+ if (decoded->subjectBC) {
+ sz = (decoded->subjectBCLen < CTC_NAME_SIZE) ? decoded->subjectBCLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->busCat, decoded->subjectBC, sz);
+ cn->busCat[sz] = '\0';
+ cn->busCatEnc = decoded->subjectBCEnc;
+ }
+ if (decoded->subjectJC) {
+ sz = (decoded->subjectJCLen < CTC_NAME_SIZE) ? decoded->subjectJCLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->joiC, decoded->subjectJC, sz);
+ cn->joiC[sz] = '\0';
+ cn->joiCEnc = decoded->subjectJCEnc;
+ }
+ if (decoded->subjectJS) {
+ sz = (decoded->subjectJSLen < CTC_NAME_SIZE) ? decoded->subjectJSLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->joiSt, decoded->subjectJS, sz);
+ cn->joiSt[sz] = '\0';
+ cn->joiStEnc = decoded->subjectJSEnc;
+ }
+#endif
+ if (decoded->subjectEmail) {
+ sz = (decoded->subjectEmailLen < CTC_NAME_SIZE)
+ ? decoded->subjectEmailLen : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->email, decoded->subjectEmail, sz);
+ cn->email[sz] = '\0';
+ }
+}
+#ifndef NO_FILESYSTEM
/* Set cn name from der buffer, return 0 on success */
static int SetNameFromCert(CertName* cn, const byte* der, int derSz)
{
- int ret, sz;
+ int ret;
#ifdef WOLFSSL_SMALL_STACK
DecodedCert* decoded;
#else
@@ -6353,68 +14678,14 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz)
return MEMORY_E;
#endif
- InitDecodedCert(decoded, (byte*)der, derSz, 0);
+ InitDecodedCert(decoded, der, derSz, NULL);
ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0);
if (ret < 0) {
WOLFSSL_MSG("ParseCertRelative error");
}
else {
- if (decoded->subjectCN) {
- sz = (decoded->subjectCNLen < CTC_NAME_SIZE) ? decoded->subjectCNLen
- : CTC_NAME_SIZE - 1;
- strncpy(cn->commonName, decoded->subjectCN, CTC_NAME_SIZE);
- cn->commonName[sz] = 0;
- cn->commonNameEnc = decoded->subjectCNEnc;
- }
- if (decoded->subjectC) {
- sz = (decoded->subjectCLen < CTC_NAME_SIZE) ? decoded->subjectCLen
- : CTC_NAME_SIZE - 1;
- strncpy(cn->country, decoded->subjectC, CTC_NAME_SIZE);
- cn->country[sz] = 0;
- cn->countryEnc = decoded->subjectCEnc;
- }
- if (decoded->subjectST) {
- sz = (decoded->subjectSTLen < CTC_NAME_SIZE) ? decoded->subjectSTLen
- : CTC_NAME_SIZE - 1;
- strncpy(cn->state, decoded->subjectST, CTC_NAME_SIZE);
- cn->state[sz] = 0;
- cn->stateEnc = decoded->subjectSTEnc;
- }
- if (decoded->subjectL) {
- sz = (decoded->subjectLLen < CTC_NAME_SIZE) ? decoded->subjectLLen
- : CTC_NAME_SIZE - 1;
- strncpy(cn->locality, decoded->subjectL, CTC_NAME_SIZE);
- cn->locality[sz] = 0;
- cn->localityEnc = decoded->subjectLEnc;
- }
- if (decoded->subjectO) {
- sz = (decoded->subjectOLen < CTC_NAME_SIZE) ? decoded->subjectOLen
- : CTC_NAME_SIZE - 1;
- strncpy(cn->org, decoded->subjectO, CTC_NAME_SIZE);
- cn->org[sz] = 0;
- cn->orgEnc = decoded->subjectOEnc;
- }
- if (decoded->subjectOU) {
- sz = (decoded->subjectOULen < CTC_NAME_SIZE) ? decoded->subjectOULen
- : CTC_NAME_SIZE - 1;
- strncpy(cn->unit, decoded->subjectOU, CTC_NAME_SIZE);
- cn->unit[sz] = 0;
- cn->unitEnc = decoded->subjectOUEnc;
- }
- if (decoded->subjectSN) {
- sz = (decoded->subjectSNLen < CTC_NAME_SIZE) ? decoded->subjectSNLen
- : CTC_NAME_SIZE - 1;
- strncpy(cn->sur, decoded->subjectSN, CTC_NAME_SIZE);
- cn->sur[sz] = 0;
- cn->surEnc = decoded->subjectSNEnc;
- }
- if (decoded->subjectEmail) {
- sz = (decoded->subjectEmailLen < CTC_NAME_SIZE)
- ? decoded->subjectEmailLen : CTC_NAME_SIZE - 1;
- strncpy(cn->email, decoded->subjectEmail, CTC_NAME_SIZE);
- cn->email[sz] = 0;
- }
+ SetNameFromDcert(cn, decoded);
}
FreeDecodedCert(decoded);
@@ -6426,24 +14697,26 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz)
return ret < 0 ? ret : 0;
}
-
-#ifndef NO_FILESYSTEM
-
/* Set cert issuer from issuerFile in PEM */
int wc_SetIssuer(Cert* cert, const char* issuerFile)
{
int ret;
int derSz;
- byte* der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT);
+ byte* der;
+ if (cert == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
if (der == NULL) {
WOLFSSL_MSG("wc_SetIssuer OOF Problem");
return MEMORY_E;
}
- derSz = wolfSSL_PemCertToDer(issuerFile, der, EIGHTK_BUF);
+ derSz = wc_PemCertToDer(issuerFile, der, EIGHTK_BUF);
cert->selfSigned = 0;
ret = SetNameFromCert(&cert->issuer, der, derSz);
- XFREE(der, NULL, DYNAMIC_TYPE_CERT);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
return ret;
}
@@ -6454,77 +14727,367 @@ int wc_SetSubject(Cert* cert, const char* subjectFile)
{
int ret;
int derSz;
- byte* der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT);
+ byte* der;
+
+ if (cert == NULL) {
+ return BAD_FUNC_ARG;
+ }
+ der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
if (der == NULL) {
WOLFSSL_MSG("wc_SetSubject OOF Problem");
return MEMORY_E;
}
- derSz = wolfSSL_PemCertToDer(subjectFile, der, EIGHTK_BUF);
+
+ derSz = wc_PemCertToDer(subjectFile, der, EIGHTK_BUF);
ret = SetNameFromCert(&cert->subject, der, derSz);
- XFREE(der, NULL, DYNAMIC_TYPE_CERT);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
return ret;
}
-
#ifdef WOLFSSL_ALT_NAMES
-/* Set atl names from file in PEM */
+/* Set alt names from file in PEM */
int wc_SetAltNames(Cert* cert, const char* file)
{
int ret;
int derSz;
- byte* der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT);
+ byte* der;
+
+ if (cert == NULL) {
+ return BAD_FUNC_ARG;
+ }
+ der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
if (der == NULL) {
WOLFSSL_MSG("wc_SetAltNames OOF Problem");
return MEMORY_E;
}
- derSz = wolfSSL_PemCertToDer(file, der, EIGHTK_BUF);
+ derSz = wc_PemCertToDer(file, der, EIGHTK_BUF);
ret = SetAltNamesFromCert(cert, der, derSz);
- XFREE(der, NULL, DYNAMIC_TYPE_CERT);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
return ret;
}
#endif /* WOLFSSL_ALT_NAMES */
-#endif /* NO_FILESYSTEM */
+#endif /* !NO_FILESYSTEM */
/* Set cert issuer from DER buffer */
int wc_SetIssuerBuffer(Cert* cert, const byte* der, int derSz)
{
- cert->selfSigned = 0;
- return SetNameFromCert(&cert->issuer, der, derSz);
-}
+ int ret = 0;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ cert->selfSigned = 0;
+
+ /* Check if decodedCert is cached */
+ if (cert->der != der) {
+ /* Allocate cache for the decoded cert */
+ ret = wc_SetCert_LoadDer(cert, der, derSz);
+ }
+ if (ret >= 0) {
+ SetNameFromDcert(&cert->issuer, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+ wc_SetCert_Free(cert);
+#endif
+ }
+ }
+
+ return ret;
+}
/* Set cert subject from DER buffer */
int wc_SetSubjectBuffer(Cert* cert, const byte* der, int derSz)
{
- return SetNameFromCert(&cert->subject, der, derSz);
+ int ret = 0;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Check if decodedCert is cached */
+ if (cert->der != der) {
+ /* Allocate cache for the decoded cert */
+ ret = wc_SetCert_LoadDer(cert, der, derSz);
+ }
+
+ if (ret >= 0) {
+ SetNameFromDcert(&cert->subject, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+ wc_SetCert_Free(cert);
+#endif
+ }
+ }
+
+ return ret;
+}
+#ifdef WOLFSSL_CERT_EXT
+/* Set cert raw subject from DER buffer */
+int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz)
+{
+ int ret = 0;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Check if decodedCert is cached */
+ if (cert->der != der) {
+ /* Allocate cache for the decoded cert */
+ ret = wc_SetCert_LoadDer(cert, der, derSz);
+ }
+
+ if (ret >= 0) {
+ if ((((DecodedCert*)cert->decodedCert)->subjectRaw) &&
+ (((DecodedCert*)cert->decodedCert)->subjectRawLen <=
+ (int)sizeof(CertName))) {
+ XMEMCPY(cert->sbjRaw,
+ ((DecodedCert*)cert->decodedCert)->subjectRaw,
+ ((DecodedCert*)cert->decodedCert)->subjectRawLen);
+ }
+#ifndef WOLFSSL_CERT_GEN_CACHE
+ wc_SetCert_Free(cert);
+#endif
+ }
+ }
+
+ return ret;
}
+/* Set cert raw issuer from DER buffer */
+int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz)
+{
+ int ret = 0;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Check if decodedCert is cached */
+ if (cert->der != der) {
+ /* Allocate cache for the decoded cert */
+ ret = wc_SetCert_LoadDer(cert, der, derSz);
+ }
+
+ if (ret >= 0) {
+ if ((((DecodedCert*)cert->decodedCert)->issuerRaw) &&
+ (((DecodedCert*)cert->decodedCert)->issuerRawLen <=
+ (int)sizeof(CertName))) {
+ XMEMCPY(cert->issRaw,
+ ((DecodedCert*)cert->decodedCert)->issuerRaw,
+ ((DecodedCert*)cert->decodedCert)->issuerRawLen);
+ }
+#ifndef WOLFSSL_CERT_GEN_CACHE
+ wc_SetCert_Free(cert);
+#endif
+ }
+ }
+ return ret;
+}
+#endif
#ifdef WOLFSSL_ALT_NAMES
/* Set cert alt names from DER buffer */
int wc_SetAltNamesBuffer(Cert* cert, const byte* der, int derSz)
{
- return SetAltNamesFromCert(cert, der, derSz);
+ int ret = 0;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Check if decodedCert is cached */
+ if (cert->der != der) {
+ /* Allocate cache for the decoded cert */
+ ret = wc_SetCert_LoadDer(cert, der, derSz);
+ }
+
+ if (ret >= 0) {
+ ret = SetAltNamesFromDcert(cert, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+ wc_SetCert_Free(cert);
+#endif
+ }
+ }
+
+ return(ret);
}
/* Set cert dates from DER buffer */
int wc_SetDatesBuffer(Cert* cert, const byte* der, int derSz)
{
- return SetDatesFromCert(cert, der, derSz);
+ int ret = 0;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Check if decodedCert is cached */
+ if (cert->der != der) {
+ /* Allocate cache for the decoded cert */
+ ret = wc_SetCert_LoadDer(cert, der, derSz);
+ }
+
+ if (ret >= 0) {
+ ret = SetDatesFromDcert(cert, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+ wc_SetCert_Free(cert);
+#endif
+ }
+ }
+
+ return(ret);
}
#endif /* WOLFSSL_ALT_NAMES */
#endif /* WOLFSSL_CERT_GEN */
+#if (defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT)) \
+ || defined(OPENSSL_EXTRA)
+/* Encode OID string representation to ITU-T X.690 format */
+int EncodePolicyOID(byte *out, word32 *outSz, const char *in, void* heap)
+{
+ word32 val, idx = 0, nb_val;
+ char *token, *str, *ptr;
+ word32 len;
+
+ (void)heap;
+
+ if (out == NULL || outSz == NULL || *outSz < 2 || in == NULL)
+ return BAD_FUNC_ARG;
+
+ /* duplicate string (including terminator) */
+ len = (word32)XSTRLEN(in);
+ str = (char *)XMALLOC(len+1, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (str == NULL)
+ return MEMORY_E;
+ XMEMCPY(str, in, len+1);
+
+ nb_val = 0;
+
+ /* parse value, and set corresponding Policy OID value */
+ token = XSTRTOK(str, ".", &ptr);
+ while (token != NULL)
+ {
+ val = (word32)XATOI(token);
+
+ if (nb_val == 0) {
+ if (val > 2) {
+ XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ASN_OBJECT_ID_E;
+ }
+
+ out[idx] = (byte)(40 * val);
+ }
+ else if (nb_val == 1) {
+ if (val > 127) {
+ XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ASN_OBJECT_ID_E;
+ }
+
+ if (idx > *outSz) {
+ XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return BUFFER_E;
+ }
+
+ out[idx++] += (byte)val;
+ }
+ else {
+ word32 tb = 0, x;
+ int i = 0;
+ byte oid[MAX_OID_SZ];
+
+ while (val >= 128) {
+ x = val % 128;
+ val /= 128;
+ oid[i++] = (byte) (((tb++) ? 0x80 : 0) | x);
+ }
+
+ if ((idx+(word32)i) > *outSz) {
+ XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return BUFFER_E;
+ }
+
+ oid[i] = (byte) (((tb++) ? 0x80 : 0) | val);
+
+ /* push value in the right order */
+ while (i >= 0)
+ out[idx++] = oid[i--];
+ }
+
+ token = XSTRTOK(NULL, ".", &ptr);
+ nb_val++;
+ }
+
+ *outSz = idx;
+
+ XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return 0;
+}
+#endif /* WOLFSSL_CERT_EXT || OPENSSL_EXTRA */
+
+#endif /* !NO_CERTS */
+
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+/* Helper function for wolfSSL_i2d_DHparams */
+int StoreDHparams(byte* out, word32* outLen, mp_int* p, mp_int* g)
+{
+ word32 idx = 0;
+ int pSz;
+ int gSz;
+ unsigned int tmp;
+ word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */
+
+ /* If the leading bit on the INTEGER is a 1, add a leading zero */
+ int pLeadingZero = mp_leading_bit(p);
+ int gLeadingZero = mp_leading_bit(g);
+ int pLen = mp_unsigned_bin_size(p);
+ int gLen = mp_unsigned_bin_size(g);
+
+ WOLFSSL_ENTER("StoreDHparams");
+ if (out == NULL) {
+ WOLFSSL_MSG("Null buffer error");
+ return BUFFER_E;
+ }
+
+ tmp = pLeadingZero + gLeadingZero + pLen + gLen;
+ if (*outLen < (tmp + headerSz)) {
+ return BUFFER_E;
+ }
+
+ /* Set sequence */
+ idx = SetSequence(tmp + headerSz + 2, out);
+
+ /* Encode p */
+ pSz = SetASNIntMP(p, -1, &out[idx]);
+ if (pSz < 0) {
+ WOLFSSL_MSG("SetASNIntMP failed");
+ return pSz;
+ }
+ idx += pSz;
+
+ /* Encode g */
+ gSz = SetASNIntMP(g, -1, &out[idx]);
+ if (gSz < 0) {
+ WOLFSSL_MSG("SetASNIntMP failed");
+ return gSz;
+ }
+ idx += gSz;
+
+ *outLen = idx;
+
+ return 0;
+}
+#endif /* !NO_DH && WOLFSSL_QT || OPENSSL_ALL */
#ifdef HAVE_ECC
@@ -6532,8 +15095,8 @@ int wc_SetDatesBuffer(Cert* cert, const byte* der, int derSz)
int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s)
{
word32 idx = 0;
- word32 rSz; /* encoding size */
- word32 sSz;
+ int rSz; /* encoding size */
+ int sSz;
word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */
/* If the leading bit on the INTEGER is a 1, add a leading zero */
@@ -6541,33 +15104,24 @@ int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s)
int sLeadingZero = mp_leading_bit(s);
int rLen = mp_unsigned_bin_size(r); /* big int size */
int sLen = mp_unsigned_bin_size(s);
- int err;
if (*outLen < (rLen + rLeadingZero + sLen + sLeadingZero +
headerSz + 2)) /* SEQ_TAG + LEN(ENUM) */
- return BAD_FUNC_ARG;
+ return BUFFER_E;
- idx = SetSequence(rLen+rLeadingZero+sLen+sLeadingZero+headerSz, out);
+ idx = SetSequence(rLen + rLeadingZero + sLen+sLeadingZero + headerSz, out);
/* store r */
- out[idx++] = ASN_INTEGER;
- rSz = SetLength(rLen + rLeadingZero, &out[idx]);
+ rSz = SetASNIntMP(r, -1, &out[idx]);
+ if (rSz < 0)
+ return rSz;
idx += rSz;
- if (rLeadingZero)
- out[idx++] = 0;
- err = mp_to_unsigned_bin(r, &out[idx]);
- if (err != MP_OKAY) return err;
- idx += rLen;
/* store s */
- out[idx++] = ASN_INTEGER;
- sSz = SetLength(sLen + sLeadingZero, &out[idx]);
+ sSz = SetASNIntMP(s, -1, &out[idx]);
+ if (sSz < 0)
+ return sSz;
idx += sSz;
- if (sLeadingZero)
- out[idx++] = 0;
- err = mp_to_unsigned_bin(s, &out[idx]);
- if (err != MP_OKAY) return err;
- idx += sLen;
*outLen = idx;
@@ -6575,23 +15129,35 @@ int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s)
}
-/* Der Decode ECC-DSA Signautre, r & s stored as big ints */
+/* Der Decode ECC-DSA Signature, r & s stored as big ints */
int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s)
{
word32 idx = 0;
int len = 0;
- if (GetSequence(sig, &idx, &len, sigLen) < 0)
+ if (GetSequence(sig, &idx, &len, sigLen) < 0) {
return ASN_ECC_KEY_E;
+ }
- if ((word32)len > (sigLen - idx))
+#ifndef NO_STRICT_ECDSA_LEN
+ /* enable strict length checking for signature */
+ if (sigLen != idx + (word32)len) {
+ return ASN_ECC_KEY_E;
+ }
+#else
+ /* allow extra signature bytes at end */
+ if ((word32)len > (sigLen - idx)) {
return ASN_ECC_KEY_E;
+ }
+#endif
- if (GetInt(r, sig, &idx, sigLen) < 0)
+ if (GetInt(r, sig, &idx, sigLen) < 0) {
return ASN_ECC_KEY_E;
+ }
- if (GetInt(s, sig, &idx, sigLen) < 0)
+ if (GetInt(s, sig, &idx, sigLen) < 0) {
return ASN_ECC_KEY_E;
+ }
return 0;
}
@@ -6600,18 +15166,20 @@ int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s)
int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
word32 inSz)
{
- word32 oid = 0;
+ word32 oidSum;
int version, length;
- int privSz, pubSz;
+ int privSz, pubSz = 0;
byte b;
int ret = 0;
+ int curve_id = ECC_CURVE_DEF;
#ifdef WOLFSSL_SMALL_STACK
byte* priv;
byte* pub;
#else
- byte priv[ECC_MAXSIZE];
- byte pub[ECC_MAXSIZE * 2 + 1]; /* public key has two parts plus header */
+ byte priv[ECC_MAXSIZE+1];
+ byte pub[2*(ECC_MAXSIZE+1)]; /* public key has two parts plus header */
#endif
+ byte* pubData = NULL;
if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
return BAD_FUNC_ARG;
@@ -6619,14 +15187,17 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
- if (GetMyVersion(input, inOutIdx, &version) < 0)
+ if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (*inOutIdx >= inSz)
return ASN_PARSE_E;
b = input[*inOutIdx];
*inOutIdx += 1;
/* priv type */
- if (b != 4 && b != 6 && b != 7)
+ if (b != 4 && b != 6 && b != 7)
return ASN_PARSE_E;
if (GetLength(input, inOutIdx, &length, inSz) < 0)
@@ -6636,13 +15207,13 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
return BUFFER_E;
#ifdef WOLFSSL_SMALL_STACK
- priv = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ priv = (byte*)XMALLOC(ECC_MAXSIZE+1, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (priv == NULL)
return MEMORY_E;
-
- pub = (byte*)XMALLOC(ECC_MAXSIZE * 2 + 1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ pub = (byte*)XMALLOC(2*(ECC_MAXSIZE+1), key->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (pub == NULL) {
- XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(priv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif
@@ -6652,36 +15223,30 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
XMEMCPY(priv, &input[*inOutIdx], privSz);
*inOutIdx += length;
- /* prefix 0, may have */
- b = input[*inOutIdx];
- if (b == ECC_PREFIX_0) {
- *inOutIdx += 1;
-
- if (GetLength(input, inOutIdx, &length, inSz) < 0)
- ret = ASN_PARSE_E;
- else {
- /* object id */
- b = input[*inOutIdx];
+ if ((*inOutIdx + 1) < inSz) {
+ /* prefix 0, may have */
+ b = input[*inOutIdx];
+ if (b == ECC_PREFIX_0) {
*inOutIdx += 1;
- if (b != ASN_OBJECT_ID) {
- ret = ASN_OBJECT_ID_E;
- }
- else if (GetLength(input, inOutIdx, &length, inSz) < 0) {
+ if (GetLength(input, inOutIdx, &length, inSz) <= 0)
ret = ASN_PARSE_E;
- }
else {
- while(length--) {
- oid += input[*inOutIdx];
- *inOutIdx += 1;
+ ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType,
+ inSz);
+ if (ret == 0) {
+ if ((ret = CheckCurve(oidSum)) < 0)
+ ret = ECC_CURVE_OID_E;
+ else {
+ curve_id = ret;
+ ret = 0;
+ }
}
- if (CheckCurve(oid) < 0)
- ret = ECC_CURVE_OID_E;
}
}
}
- if (ret == 0) {
+ if (ret == 0 && (*inOutIdx + 1) < inSz) {
/* prefix 1 */
b = input[*inOutIdx];
*inOutIdx += 1;
@@ -6689,142 +15254,879 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
if (b != ECC_PREFIX_1) {
ret = ASN_ECC_KEY_E;
}
- else if (GetLength(input, inOutIdx, &length, inSz) < 0) {
+ else if (GetLength(input, inOutIdx, &length, inSz) <= 0) {
ret = ASN_PARSE_E;
}
else {
/* key header */
- b = input[*inOutIdx];
- *inOutIdx += 1;
-
- if (b != ASN_BIT_STRING) {
- ret = ASN_BITSTR_E;
- }
- else if (GetLength(input, inOutIdx, &length, inSz) < 0) {
- ret = ASN_PARSE_E;
- }
- else {
- b = input[*inOutIdx];
- *inOutIdx += 1;
-
- if (b != 0x00) {
- ret = ASN_EXPECT_0_E;
- }
- else {
- /* pub key */
- pubSz = length - 1; /* null prefix */
- if (pubSz < (ECC_MAXSIZE*2 + 1)) {
- XMEMCPY(pub, &input[*inOutIdx], pubSz);
- *inOutIdx += length;
- ret = wc_ecc_import_private_key(priv, privSz, pub, pubSz,
- key);
- } else
- ret = BUFFER_E;
+ ret = CheckBitString(input, inOutIdx, &length, inSz, 0, NULL);
+ if (ret == 0) {
+ /* pub key */
+ pubSz = length;
+ if (pubSz < 2*(ECC_MAXSIZE+1)) {
+ XMEMCPY(pub, &input[*inOutIdx], pubSz);
+ *inOutIdx += length;
+ pubData = pub;
}
+ else
+ ret = BUFFER_E;
}
}
}
+ if (ret == 0) {
+ ret = wc_ecc_import_private_key_ex(priv, privSz, pubData, pubSz, key,
+ curve_id);
+ }
+
#ifdef WOLFSSL_SMALL_STACK
- XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(priv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
-#ifdef WOLFSSL_KEY_GEN
+#ifdef WOLFSSL_CUSTOM_CURVES
+static void ByteToHex(byte n, char* str)
+{
+ const char hexChar[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
-/* Write a Private ecc key to DER format, length on success else < 0 */
-int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen)
+ str[0] = hexChar[n >> 4];
+ str[1] = hexChar[n & 0xf];
+}
+
+/* returns 0 on success */
+static int ASNToHexString(const byte* input, word32* inOutIdx, char** out,
+ word32 inSz, void* heap, int heapType)
+{
+ int len;
+ int i;
+ char* str;
+ word32 localIdx;
+ byte tag;
+
+ if (*inOutIdx >= inSz) {
+ return BUFFER_E;
+ }
+
+ localIdx = *inOutIdx;
+ if (GetASNTag(input, &localIdx, &tag, inSz) == 0 && tag == ASN_INTEGER) {
+ if (GetASNInt(input, inOutIdx, &len, inSz) < 0)
+ return ASN_PARSE_E;
+ }
+ else {
+ if (GetOctetString(input, inOutIdx, &len, inSz) < 0)
+ return ASN_PARSE_E;
+ }
+
+ str = (char*)XMALLOC(len * 2 + 1, heap, heapType);
+ for (i=0; i<len; i++)
+ ByteToHex(input[*inOutIdx + i], str + i*2);
+ str[len*2] = '\0';
+
+ *inOutIdx += len;
+ *out = str;
+
+ (void)heap;
+ (void)heapType;
+
+ return 0;
+}
+#endif /* WOLFSSL_CUSTOM_CURVES */
+
+#ifdef WOLFSSL_CUSTOM_CURVES
+static int EccKeyParamCopy(char** dst, char* src)
+{
+ int ret = 0;
+#ifdef WOLFSSL_ECC_CURVE_STATIC
+ word32 length;
+#endif
+
+ if (dst == NULL || src == NULL)
+ return BAD_FUNC_ARG;
+
+#ifndef WOLFSSL_ECC_CURVE_STATIC
+ *dst = src;
+#else
+ length = (int)XSTRLEN(src) + 1;
+ if (length > MAX_ECC_STRING) {
+ WOLFSSL_MSG("ECC Param too large for buffer");
+ ret = BUFFER_E;
+ }
+ else {
+ XSTRNCPY(*dst, src, length);
+ }
+ XFREE(src, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+#endif
+
+ return ret;
+}
+#endif /* WOLFSSL_CUSTOM_CURVES */
+
+int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
+ ecc_key* key, word32 inSz)
+{
+ int length;
+ int ret;
+ int curve_id = ECC_CURVE_DEF;
+ word32 oidSum, localIdx;
+ byte tag;
+
+ if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+ return BAD_FUNC_ARG;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ ret = SkipObjectId(input, inOutIdx, inSz);
+ if (ret != 0)
+ return ret;
+
+ if (*inOutIdx >= inSz) {
+ return BUFFER_E;
+ }
+
+ localIdx = *inOutIdx;
+ if (GetASNTag(input, &localIdx, &tag, inSz) == 0 &&
+ tag == (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
+#ifdef WOLFSSL_CUSTOM_CURVES
+ ecc_set_type* curve;
+ int len;
+ char* point = NULL;
+
+ ret = 0;
+
+ curve = (ecc_set_type*)XMALLOC(sizeof(*curve), key->heap,
+ DYNAMIC_TYPE_ECC_BUFFER);
+ if (curve == NULL)
+ ret = MEMORY_E;
+
+ if (ret == 0) {
+ static const char customName[] = "Custom";
+ XMEMSET(curve, 0, sizeof(*curve));
+ #ifndef WOLFSSL_ECC_CURVE_STATIC
+ curve->name = customName;
+ #else
+ XMEMCPY((void*)curve->name, customName, sizeof(customName));
+ #endif
+ curve->id = ECC_CURVE_CUSTOM;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+
+ if (ret == 0) {
+ GetInteger7Bit(input, inOutIdx, inSz);
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ char* p = NULL;
+ SkipObjectId(input, inOutIdx, inSz);
+ ret = ASNToHexString(input, inOutIdx, &p, inSz,
+ key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+ if (ret == 0)
+ ret = EccKeyParamCopy((char**)&curve->prime, p);
+ }
+ if (ret == 0) {
+ curve->size = (int)XSTRLEN(curve->prime) / 2;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ char* af = NULL;
+ ret = ASNToHexString(input, inOutIdx, &af, inSz,
+ key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+ if (ret == 0)
+ ret = EccKeyParamCopy((char**)&curve->Af, af);
+ }
+ if (ret == 0) {
+ char* bf = NULL;
+ ret = ASNToHexString(input, inOutIdx, &bf, inSz,
+ key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+ if (ret == 0)
+ ret = EccKeyParamCopy((char**)&curve->Bf, bf);
+ }
+ if (ret == 0) {
+ localIdx = *inOutIdx;
+ if (*inOutIdx < inSz && GetASNTag(input, &localIdx, &tag, inSz)
+ == 0 && tag == ASN_BIT_STRING) {
+ len = 0;
+ ret = GetASNHeader(input, ASN_BIT_STRING, inOutIdx, &len, inSz);
+ *inOutIdx += len;
+ }
+ }
+ if (ret == 0) {
+ ret = ASNToHexString(input, inOutIdx, (char**)&point, inSz,
+ key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+
+ /* sanity check that point buffer is not smaller than the expected
+ * size to hold ( 0 4 || Gx || Gy )
+ * where Gx and Gy are each the size of curve->size * 2 */
+ if (ret == 0 && (int)XSTRLEN(point) < (curve->size * 4) + 2) {
+ XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+ ret = BUFFER_E;
+ }
+ }
+ if (ret == 0) {
+ #ifndef WOLFSSL_ECC_CURVE_STATIC
+ curve->Gx = (const char*)XMALLOC(curve->size * 2 + 2, key->heap,
+ DYNAMIC_TYPE_ECC_BUFFER);
+ curve->Gy = (const char*)XMALLOC(curve->size * 2 + 2, key->heap,
+ DYNAMIC_TYPE_ECC_BUFFER);
+ if (curve->Gx == NULL || curve->Gy == NULL) {
+ XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+ ret = MEMORY_E;
+ }
+ #else
+ if (curve->size * 2 + 2 > MAX_ECC_STRING) {
+ WOLFSSL_MSG("curve size is too large to fit in buffer");
+ ret = BUFFER_E;
+ }
+ #endif
+ }
+ if (ret == 0) {
+ char* o = NULL;
+
+ XMEMCPY((char*)curve->Gx, point + 2, curve->size * 2);
+ XMEMCPY((char*)curve->Gy, point + curve->size * 2 + 2,
+ curve->size * 2);
+ ((char*)curve->Gx)[curve->size * 2] = '\0';
+ ((char*)curve->Gy)[curve->size * 2] = '\0';
+ XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+ ret = ASNToHexString(input, inOutIdx, &o, inSz,
+ key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+ if (ret == 0)
+ ret = EccKeyParamCopy((char**)&curve->order, o);
+ }
+ if (ret == 0) {
+ curve->cofactor = GetInteger7Bit(input, inOutIdx, inSz);
+
+ #ifndef WOLFSSL_ECC_CURVE_STATIC
+ curve->oid = NULL;
+ #else
+ XMEMSET((void*)curve->oid, 0, sizeof(curve->oid));
+ #endif
+ curve->oidSz = 0;
+ curve->oidSum = 0;
+
+ if (wc_ecc_set_custom_curve(key, curve) < 0) {
+ ret = ASN_PARSE_E;
+ }
+ #ifdef WOLFSSL_CUSTOM_CURVES
+ key->deallocSet = 1;
+ #endif
+ curve = NULL;
+ }
+ if (curve != NULL)
+ wc_ecc_free_curve(curve, key->heap);
+
+ if (ret < 0)
+ return ret;
+#else
+ return ASN_PARSE_E;
+#endif /* WOLFSSL_CUSTOM_CURVES */
+ }
+ else {
+ /* ecc params information */
+ ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType, inSz);
+ if (ret != 0)
+ return ret;
+
+ /* get curve id */
+ curve_id = wc_ecc_get_oid(oidSum, NULL, 0);
+ if (curve_id < 0)
+ return ECC_CURVE_OID_E;
+ }
+
+ /* key header */
+ ret = CheckBitString(input, inOutIdx, &length, inSz, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ /* This is the raw point data compressed or uncompressed. */
+ if (wc_ecc_import_x963_ex(input + *inOutIdx, length, key,
+ curve_id) != 0) {
+ return ASN_ECC_KEY_E;
+ }
+
+ *inOutIdx += length;
+
+ return 0;
+}
+
+#if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT)
+/* build DER formatted ECC key, include optional public key if requested,
+ * return length on success, negative on error */
+static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen,
+ int pubIn)
{
- byte curve[MAX_ALGO_SZ];
+ byte curve[MAX_ALGO_SZ+2];
byte ver[MAX_VERSION_SZ];
byte seq[MAX_SEQ_SZ];
- int ret;
- int curveSz;
- int verSz;
+ byte *prv = NULL, *pub = NULL;
+ int ret, totalSz, curveSz, verSz;
int privHdrSz = ASN_ECC_HEADER_SZ;
int pubHdrSz = ASN_ECC_CONTEXT_SZ + ASN_ECC_HEADER_SZ;
- int curveHdrSz = ASN_ECC_CONTEXT_SZ;
- word32 seqSz;
- word32 idx = 0;
- word32 pubSz = ECC_BUFSIZE;
- word32 privSz;
- word32 totalSz;
+
+ word32 idx = 0, prvidx = 0, pubidx = 0, curveidx = 0;
+ word32 seqSz, privSz, pubSz = ECC_BUFSIZE;
if (key == NULL || output == NULL || inLen == 0)
return BAD_FUNC_ARG;
- ret = wc_ecc_export_x963(key, NULL, &pubSz);
- if (ret != LENGTH_ONLY_E) {
- return ret;
- }
- curveSz = SetCurve(key, curve);
- if (curveSz < 0) {
+ /* curve */
+ curve[curveidx++] = ECC_PREFIX_0;
+ curveidx++ /* to put the size after computation */;
+ curveSz = SetCurve(key, curve+curveidx);
+ if (curveSz < 0)
return curveSz;
- }
+ /* set computed size */
+ curve[1] = (byte)curveSz;
+ curveidx += curveSz;
+ /* private */
privSz = key->dp->size;
+ prv = (byte*)XMALLOC(privSz + privHdrSz + MAX_SEQ_SZ,
+ key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (prv == NULL) {
+ return MEMORY_E;
+ }
+ prvidx += SetOctetString8Bit(key->dp->size, &prv[prvidx]);
+ ret = wc_ecc_export_private_only(key, prv + prvidx, &privSz);
+ if (ret < 0) {
+ XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+ prvidx += privSz;
- verSz = SetMyVersion(1, ver, FALSE);
- if (verSz < 0) {
- return verSz;
+ /* pubIn */
+ if (pubIn) {
+ ret = wc_ecc_export_x963(key, NULL, &pubSz);
+ if (ret != LENGTH_ONLY_E) {
+ XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+
+ pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ,
+ key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pub == NULL) {
+ XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
+
+ pub[pubidx++] = ECC_PREFIX_1;
+ if (pubSz > 128) /* leading zero + extra size byte */
+ pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 2, pub+pubidx);
+ else /* leading zero */
+ pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 1, pub+pubidx);
+
+ /* SetBitString adds leading zero */
+ pubidx += SetBitString(pubSz, 0, pub + pubidx);
+ ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz);
+ if (ret != 0) {
+ XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+ pubidx += pubSz;
}
- totalSz = verSz + privSz + privHdrSz + curveSz + curveHdrSz +
- pubSz + pubHdrSz + 1; /* plus null byte b4 public */
- seqSz = SetSequence(totalSz, seq);
- totalSz += seqSz;
+ /* make headers */
+ verSz = SetMyVersion(1, ver, FALSE);
+ seqSz = SetSequence(verSz + prvidx + pubidx + curveidx, seq);
- if (totalSz > inLen) {
- return BUFFER_E;
+ totalSz = prvidx + pubidx + curveidx + verSz + seqSz;
+ if (totalSz > (int)inLen) {
+ XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pubIn) {
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ return BAD_FUNC_ARG;
}
- /* write it out */
+ /* write out */
/* seq */
XMEMCPY(output + idx, seq, seqSz);
- idx += seqSz;
+ idx = seqSz;
- /* ver */
+ /* ver */
XMEMCPY(output + idx, ver, verSz);
idx += verSz;
/* private */
- output[idx++] = ASN_OCTET_STRING;
- output[idx++] = (byte)privSz;
- ret = wc_ecc_export_private_only(key, output + idx, &privSz);
+ XMEMCPY(output + idx, prv, prvidx);
+ idx += prvidx;
+ XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ /* curve */
+ XMEMCPY(output + idx, curve, curveidx);
+ idx += curveidx;
+
+ /* pubIn */
+ if (pubIn) {
+ XMEMCPY(output + idx, pub, pubidx);
+ /* idx += pubidx; not used after write, if more data remove comment */
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+
+ return totalSz;
+}
+
+/* Write a Private ecc key, including public to DER format,
+ * length on success else < 0 */
+int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen)
+{
+ return wc_BuildEccKeyDer(key, output, inLen, 1);
+}
+
+
+/* Write only private ecc key to DER format,
+ * length on success else < 0 */
+int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen)
+{
+ return wc_BuildEccKeyDer(key, output, inLen, 0);
+}
+
+#ifdef HAVE_PKCS8
+/* Write only private ecc key to unencrypted PKCS#8 format.
+ *
+ * If output is NULL, places required PKCS#8 buffer size in outLen and
+ * returns LENGTH_ONLY_E.
+ *
+ * return length on success else < 0 */
+int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen)
+{
+ int ret, tmpDerSz;
+ int algoID = 0;
+ word32 oidSz = 0;
+ word32 pkcs8Sz = 0;
+ const byte* curveOID = NULL;
+ byte* tmpDer = NULL;
+
+ if (key == NULL || outLen == NULL)
+ return BAD_FUNC_ARG;
+
+ /* set algoID, get curve OID */
+ algoID = ECDSAk;
+ ret = wc_ecc_get_oid(key->dp->oidSum, &curveOID, &oidSz);
+ if (ret < 0)
+ return ret;
+
+ /* temp buffer for plain DER key */
+ tmpDer = (byte*)XMALLOC(ECC_BUFSIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (tmpDer == NULL)
+ return MEMORY_E;
+
+ XMEMSET(tmpDer, 0, ECC_BUFSIZE);
+
+ tmpDerSz = wc_BuildEccKeyDer(key, tmpDer, ECC_BUFSIZE, 0);
+ if (tmpDerSz < 0) {
+ XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return tmpDerSz;
+ }
+
+ /* get pkcs8 expected output size */
+ ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, tmpDer, tmpDerSz, algoID,
+ curveOID, oidSz);
+ if (ret != LENGTH_ONLY_E) {
+ XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+
+ if (output == NULL) {
+ XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ *outLen = pkcs8Sz;
+ return LENGTH_ONLY_E;
+
+ } else if (*outLen < pkcs8Sz) {
+ XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ WOLFSSL_MSG("Input buffer too small for ECC PKCS#8 key");
+ return BUFFER_E;
+ }
+
+ ret = wc_CreatePKCS8Key(output, &pkcs8Sz, tmpDer, tmpDerSz,
+ algoID, curveOID, oidSz);
if (ret < 0) {
+ XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
- idx += privSz;
- /* curve */
- output[idx++] = ECC_PREFIX_0;
- output[idx++] = (byte)curveSz;
- XMEMCPY(output + idx, curve, curveSz);
- idx += curveSz;
-
- /* public */
- output[idx++] = ECC_PREFIX_1;
- output[idx++] = (byte)pubSz + ASN_ECC_CONTEXT_SZ + 1; /* plus null byte */
- output[idx++] = ASN_BIT_STRING;
- output[idx++] = (byte)pubSz + 1; /* plus null byte */
- output[idx++] = (byte)0; /* null byte */
- ret = wc_ecc_export_x963(key, output + idx, &pubSz);
- if (ret != 0) {
+ XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ *outLen = ret;
+ return ret;
+}
+#endif /* HAVE_PKCS8 */
+#endif /* HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */
+#endif /* HAVE_ECC */
+
+
+#ifdef HAVE_ED25519
+
+int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
+ ed25519_key* key, word32 inSz)
+{
+ word32 oid;
+ int ret, version, length, endKeyIdx, privSz, pubSz;
+ const byte* priv;
+ const byte* pub;
+
+ if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+ return BAD_FUNC_ARG;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) >= 0) {
+ endKeyIdx = *inOutIdx + length;
+
+ if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
+ return ASN_PARSE_E;
+ if (version != 0) {
+ WOLFSSL_MSG("Unrecognized version of ED25519 private key");
+ return ASN_PARSE_E;
+ }
+
+ if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0)
+ return ASN_PARSE_E;
+ if (oid != ED25519k)
+ return ASN_PARSE_E;
+
+ if (GetOctetString(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
+ return ASN_PARSE_E;
+
+ priv = input + *inOutIdx;
+ *inOutIdx += privSz;
+ }
+ else {
+ if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (privSz != 32)
+ return ASN_PARSE_E;
+
+ priv = input + *inOutIdx;
+ *inOutIdx += privSz;
+ endKeyIdx = *inOutIdx;
+ }
+
+ if (endKeyIdx == (int)*inOutIdx) {
+ ret = wc_ed25519_import_private_only(priv, privSz, key);
+ }
+ else {
+ if (GetASNHeader(input, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1,
+ inOutIdx, &length, inSz) < 0) {
+ return ASN_PARSE_E;
+ }
+ if (GetOctetString(input, inOutIdx, &pubSz, inSz) < 0)
+ return ASN_PARSE_E;
+ pub = input + *inOutIdx;
+ *inOutIdx += pubSz;
+
+ ret = wc_ed25519_import_private_key(priv, privSz, pub, pubSz, key);
+ }
+ if (ret == 0 && endKeyIdx != (int)*inOutIdx)
+ return ASN_PARSE_E;
+
+ return ret;
+}
+
+
+int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx,
+ ed25519_key* key, word32 inSz)
+{
+ int length;
+ int ret;
+
+ if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+ return BAD_FUNC_ARG;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ ret = SkipObjectId(input, inOutIdx, inSz);
+ if (ret != 0)
+ return ret;
+
+ /* key header */
+ ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
+ if (ret != 0)
return ret;
+
+ /* This is the raw point data compressed or uncompressed. */
+ if (wc_ed25519_import_public(input + *inOutIdx, inSz - *inOutIdx, key) != 0)
+ return ASN_ECC_KEY_E;
+
+ return 0;
+}
+
+
+#ifdef WOLFSSL_KEY_GEN
+
+/* build DER formatted ED25519 key,
+ * return length on success, negative on error */
+static int wc_BuildEd25519KeyDer(ed25519_key* key, byte* output, word32 inLen,
+ int pubOut)
+{
+ byte algoArray[MAX_ALGO_SZ];
+ byte ver[MAX_VERSION_SZ];
+ byte seq[MAX_SEQ_SZ];
+ int ret;
+ word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0;
+
+ if (key == NULL || output == NULL || inLen == 0)
+ return BAD_FUNC_ARG;
+
+ if (pubOut)
+ pubSz = 2 + 2 + ED25519_PUB_KEY_SIZE;
+ privSz = 2 + 2 + ED25519_KEY_SIZE;
+ algoSz = SetAlgoID(ED25519k, algoArray, oidKeyType, 0);
+ verSz = SetMyVersion(0, ver, FALSE);
+ seqSz = SetSequence(verSz + algoSz + privSz + pubSz, seq);
+
+ if (seqSz + verSz + algoSz + privSz + pubSz > inLen)
+ return BAD_FUNC_ARG;
+
+ /* write out */
+ /* seq */
+ XMEMCPY(output + idx, seq, seqSz);
+ idx = seqSz;
+ /* ver */
+ XMEMCPY(output + idx, ver, verSz);
+ idx += verSz;
+ /* algo */
+ XMEMCPY(output + idx, algoArray, algoSz);
+ idx += algoSz;
+ /* privKey */
+ idx += SetOctetString(2 + ED25519_KEY_SIZE, output + idx);
+ idx += SetOctetString(ED25519_KEY_SIZE, output + idx);
+ ret = wc_ed25519_export_private_only(key, output + idx, &privSz);
+ if (ret != 0)
+ return ret;
+ idx += privSz;
+ /* pubKey */
+ if (pubOut) {
+ idx += SetExplicit(1, 2 + ED25519_PUB_KEY_SIZE, output + idx);
+ idx += SetOctetString(ED25519_KEY_SIZE, output + idx);
+ ret = wc_ed25519_export_public(key, output + idx, &pubSz);
+ if (ret != 0)
+ return ret;
+ idx += pubSz;
}
- /* idx += pubSz if do more later */
- return totalSz;
+ return idx;
+}
+
+/* Write a Private ecc key, including public to DER format,
+ * length on success else < 0 */
+int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, word32 inLen)
+{
+ return wc_BuildEd25519KeyDer(key, output, inLen, 1);
+}
+
+
+
+/* Write only private ecc key to DER format,
+ * length on success else < 0 */
+int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, word32 inLen)
+{
+ return wc_BuildEd25519KeyDer(key, output, inLen, 0);
}
#endif /* WOLFSSL_KEY_GEN */
-#endif /* HAVE_ECC */
+#endif /* HAVE_ED25519 */
+#ifdef HAVE_ED448
+
+int wc_Ed448PrivateKeyDecode(const byte* input, word32* inOutIdx,
+ ed448_key* key, word32 inSz)
+{
+ word32 oid;
+ int ret, version, length, endKeyIdx, privSz, pubSz;
+ const byte* priv;
+ const byte* pub;
+
+ if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+ return BAD_FUNC_ARG;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) >= 0) {
+ endKeyIdx = *inOutIdx + length;
+
+ if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
+ return ASN_PARSE_E;
+ if (version != 0) {
+ WOLFSSL_MSG("Unrecognized version of ED448 private key");
+ return ASN_PARSE_E;
+ }
+
+ if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0)
+ return ASN_PARSE_E;
+ if (oid != ED448k)
+ return ASN_PARSE_E;
+
+ if (GetOctetString(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
+ return ASN_PARSE_E;
+
+ priv = input + *inOutIdx;
+ *inOutIdx += privSz;
+ }
+ else {
+ if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (privSz != 57)
+ return ASN_PARSE_E;
+
+ priv = input + *inOutIdx;
+ *inOutIdx += privSz;
+ endKeyIdx = *inOutIdx;
+ }
+
+ if (endKeyIdx == (int)*inOutIdx) {
+ ret = wc_ed448_import_private_only(priv, privSz, key);
+ }
+ else {
+ if (GetASNHeader(input, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1,
+ inOutIdx, &length, inSz) < 0) {
+ return ASN_PARSE_E;
+ }
+ if (GetOctetString(input, inOutIdx, &pubSz, inSz) < 0)
+ return ASN_PARSE_E;
+ pub = input + *inOutIdx;
+ *inOutIdx += pubSz;
+
+ ret = wc_ed448_import_private_key(priv, privSz, pub, pubSz, key);
+ }
+ if (ret == 0 && endKeyIdx != (int)*inOutIdx)
+ return ASN_PARSE_E;
+
+ return ret;
+}
+
+
+int wc_Ed448PublicKeyDecode(const byte* input, word32* inOutIdx,
+ ed448_key* key, word32 inSz)
+{
+ int length;
+ int ret;
+
+ if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+ return BAD_FUNC_ARG;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ ret = SkipObjectId(input, inOutIdx, inSz);
+ if (ret != 0)
+ return ret;
+
+ /* key header */
+ ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ /* This is the raw point data compressed or uncompressed. */
+ if (wc_ed448_import_public(input + *inOutIdx, inSz - *inOutIdx, key) != 0)
+ return ASN_ECC_KEY_E;
+
+ return 0;
+}
+
+
+#ifdef WOLFSSL_KEY_GEN
+
+/* build DER formatted ED448 key,
+ * return length on success, negative on error */
+static int wc_BuildEd448KeyDer(ed448_key* key, byte* output, word32 inLen,
+ int pubOut)
+{
+ byte algoArray[MAX_ALGO_SZ];
+ byte ver[MAX_VERSION_SZ];
+ byte seq[MAX_SEQ_SZ];
+ int ret;
+ word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0;
+
+ if (key == NULL || output == NULL || inLen == 0)
+ return BAD_FUNC_ARG;
+
+ if (pubOut) {
+ pubSz = 2 + 2 + ED448_PUB_KEY_SIZE;
+ }
+ privSz = 2 + 2 + ED448_KEY_SIZE;
+ algoSz = SetAlgoID(ED448k, algoArray, oidKeyType, 0);
+ verSz = SetMyVersion(0, ver, FALSE);
+ seqSz = SetSequence(verSz + algoSz + privSz + pubSz, seq);
+
+ if (seqSz + verSz + algoSz + privSz + pubSz > inLen)
+ return BAD_FUNC_ARG;
+
+ /* write out */
+ /* seq */
+ XMEMCPY(output + idx, seq, seqSz);
+ idx = seqSz;
+ /* ver */
+ XMEMCPY(output + idx, ver, verSz);
+ idx += verSz;
+ /* algo */
+ XMEMCPY(output + idx, algoArray, algoSz);
+ idx += algoSz;
+ /* privKey */
+ idx += SetOctetString(2 + ED448_KEY_SIZE, output + idx);
+ idx += SetOctetString(ED448_KEY_SIZE, output + idx);
+ ret = wc_ed448_export_private_only(key, output + idx, &privSz);
+ if (ret != 0)
+ return ret;
+ idx += privSz;
+ /* pubKey */
+ if (pubOut) {
+ idx += SetExplicit(1, 2 + ED448_PUB_KEY_SIZE, output + idx);
+ idx += SetOctetString(ED448_KEY_SIZE, output + idx);
+ ret = wc_ed448_export_public(key, output + idx, &pubSz);
+ if (ret != 0)
+ return ret;
+ idx += pubSz;
+ }
+
+ return idx;
+}
+
+/* Write a Private ecc key, including public to DER format,
+ * length on success else < 0 */
+int wc_Ed448KeyToDer(ed448_key* key, byte* output, word32 inLen)
+{
+ return wc_BuildEd448KeyDer(key, output, inLen, 1);
+}
+
+
+
+/* Write only private ecc key to DER format,
+ * length on success else < 0 */
+int wc_Ed448PrivateKeyToDer(ed448_key* key, byte* output, word32 inLen)
+{
+ return wc_BuildEd448KeyDer(key, output, inLen, 0);
+}
+
+#endif /* WOLFSSL_KEY_GEN */
+
+#endif /* HAVE_ED448 */
#if defined(HAVE_OCSP) || defined(HAVE_CRL)
@@ -6832,46 +16134,47 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen)
static int GetBasicDate(const byte* source, word32* idx, byte* date,
byte* format, int maxIdx)
{
- int length;
+ int ret, length;
+ const byte *datePtr = NULL;
WOLFSSL_ENTER("GetBasicDate");
- *format = source[*idx];
- *idx += 1;
- if (*format != ASN_UTC_TIME && *format != ASN_GENERALIZED_TIME)
- return ASN_TIME_E;
-
- if (GetLength(source, idx, &length, maxIdx) < 0)
- return ASN_PARSE_E;
-
- if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE)
- return ASN_DATE_SZ_E;
+ ret = GetDateInfo(source, idx, &datePtr, format, &length, maxIdx);
+ if (ret < 0)
+ return ret;
- XMEMCPY(date, &source[*idx], length);
- *idx += length;
+ XMEMCPY(date, datePtr, length);
return 0;
}
-#endif
+#endif /* HAVE_OCSP || HAVE_CRL */
#ifdef HAVE_OCSP
-static int GetEnumerated(const byte* input, word32* inOutIdx, int *value)
+static int GetEnumerated(const byte* input, word32* inOutIdx, int *value,
+ int sz)
{
word32 idx = *inOutIdx;
word32 len;
+ byte tag;
WOLFSSL_ENTER("GetEnumerated");
*value = 0;
- if (input[idx++] != ASN_ENUMERATED)
+ if (GetASNTag(input, &idx, &tag, sz) < 0)
+ return ASN_PARSE_E;
+
+ if (tag != ASN_ENUMERATED)
return ASN_PARSE_E;
+ if ((int)idx >= sz)
+ return BUFFER_E;
+
len = input[idx++];
- if (len > 4)
+ if (len > 4 || (int)(len + idx) > sz)
return ASN_PARSE_E;
while (len--) {
@@ -6887,9 +16190,11 @@ static int GetEnumerated(const byte* input, word32* inOutIdx, int *value)
static int DecodeSingleResponse(byte* source,
word32* ioIndex, OcspResponse* resp, word32 size)
{
- word32 idx = *ioIndex, prevIndex, oid;
+ word32 idx = *ioIndex, prevIndex, oid, localIdx;
int length, wrapperSz;
CertStatus* cs = resp->status;
+ int ret;
+ byte tag;
WOLFSSL_ENTER("DecodeSingleResponse");
@@ -6910,45 +16215,27 @@ static int DecodeSingleResponse(byte* source,
if (GetSequence(source, &idx, &length, size) < 0)
return ASN_PARSE_E;
/* Skip the hash algorithm */
- if (GetAlgoId(source, &idx, &oid, size) < 0)
+ if (GetAlgoId(source, &idx, &oid, oidIgnoreType, size) < 0)
return ASN_PARSE_E;
/* Save reference to the hash of CN */
- if (source[idx++] != ASN_OCTET_STRING)
- return ASN_PARSE_E;
- if (GetLength(source, &idx, &length, size) < 0)
- return ASN_PARSE_E;
+ ret = GetOctetString(source, &idx, &length, size);
+ if (ret < 0)
+ return ret;
resp->issuerHash = source + idx;
idx += length;
/* Save reference to the hash of the issuer public key */
- if (source[idx++] != ASN_OCTET_STRING)
- return ASN_PARSE_E;
- if (GetLength(source, &idx, &length, size) < 0)
- return ASN_PARSE_E;
+ ret = GetOctetString(source, &idx, &length, size);
+ if (ret < 0)
+ return ret;
resp->issuerKeyHash = source + idx;
idx += length;
- /* Read the serial number, it is handled as a string, not as a
- * proper number. Just XMEMCPY the data over, rather than load it
- * as an mp_int. */
- if (source[idx++] != ASN_INTEGER)
- return ASN_PARSE_E;
- if (GetLength(source, &idx, &length, size) < 0)
+ /* Get serial number */
+ if (GetSerialNumber(source, &idx, cs->serial, &cs->serialSz, size) < 0)
return ASN_PARSE_E;
- if (length <= EXTERNAL_SERIAL_SIZE)
- {
- if (source[idx] == 0)
- {
- idx++;
- length--;
- }
- XMEMCPY(cs->serial, source + idx, length);
- cs->serialSz = length;
- }
- else
- {
- return ASN_GETINT_E;
- }
- idx += length;
+
+ if ( idx >= size )
+ return BUFFER_E;
/* CertStatus */
switch (source[idx++])
@@ -6971,27 +16258,66 @@ static int DecodeSingleResponse(byte* source,
return ASN_PARSE_E;
}
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+ cs->thisDateAsn = source + idx;
+ localIdx = 0;
+ if (GetDateInfo(cs->thisDateAsn, &localIdx, NULL,
+ (byte*)&cs->thisDateParsed.type,
+ &cs->thisDateParsed.length, size) < 0)
+ return ASN_PARSE_E;
+ XMEMCPY(cs->thisDateParsed.data,
+ cs->thisDateAsn + localIdx - cs->thisDateParsed.length,
+ cs->thisDateParsed.length);
+#endif
if (GetBasicDate(source, &idx, cs->thisDate,
&cs->thisDateFormat, size) < 0)
return ASN_PARSE_E;
+
+#ifndef NO_ASN_TIME
+#ifndef WOLFSSL_NO_OCSP_DATE_CHECK
if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE))
return ASN_BEFORE_DATE_E;
-
+#endif
+#endif
+
/* The following items are optional. Only check for them if there is more
* unprocessed data in the singleResponse wrapper. */
-
+
+ localIdx = idx;
if (((int)(idx - prevIndex) < wrapperSz) &&
- (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)))
+ GetASNTag(source, &localIdx, &tag, size) == 0 &&
+ tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
{
idx++;
if (GetLength(source, &idx, &length, size) < 0)
return ASN_PARSE_E;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+ cs->nextDateAsn = source + idx;
+ localIdx = 0;
+ if (GetDateInfo(cs->nextDateAsn, &localIdx, NULL,
+ (byte*)&cs->nextDateParsed.type,
+ &cs->nextDateParsed.length, size) < 0)
+ return ASN_PARSE_E;
+ XMEMCPY(cs->nextDateParsed.data,
+ cs->nextDateAsn + localIdx - cs->nextDateParsed.length,
+ cs->nextDateParsed.length);
+#endif
if (GetBasicDate(source, &idx, cs->nextDate,
&cs->nextDateFormat, size) < 0)
return ASN_PARSE_E;
+
+#ifndef NO_ASN_TIME
+#ifndef WOLFSSL_NO_OCSP_DATE_CHECK
+ if (!XVALIDATE_DATE(cs->nextDate, cs->nextDateFormat, AFTER))
+ return ASN_AFTER_DATE_E;
+#endif
+#endif
}
+
+ localIdx = idx;
if (((int)(idx - prevIndex) < wrapperSz) &&
- (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)))
+ GetASNTag(source, &localIdx, &tag, size) == 0 &&
+ tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
{
idx++;
if (GetLength(source, &idx, &length, size) < 0)
@@ -7011,48 +16337,66 @@ static int DecodeOcspRespExtensions(byte* source,
int length;
int ext_bound; /* boundary index for the sequence of extensions */
word32 oid;
+ int ret;
+ byte tag;
WOLFSSL_ENTER("DecodeOcspRespExtensions");
- if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
+ if ((idx + 1) > sz)
+ return BUFFER_E;
+
+ if (GetASNTag(source, &idx, &tag, sz) < 0)
+ return ASN_PARSE_E;
+
+ if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
return ASN_PARSE_E;
- if (GetLength(source, &idx, &length, sz) < 0) return ASN_PARSE_E;
+ if (GetLength(source, &idx, &length, sz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetSequence(source, &idx, &length, sz) < 0)
+ return ASN_PARSE_E;
- if (GetSequence(source, &idx, &length, sz) < 0) return ASN_PARSE_E;
-
ext_bound = idx + length;
while (idx < (word32)ext_bound) {
+ word32 localIdx;
+
if (GetSequence(source, &idx, &length, sz) < 0) {
WOLFSSL_MSG("\tfail: should be a SEQUENCE");
return ASN_PARSE_E;
}
oid = 0;
- if (GetObjectId(source, &idx, &oid, sz) < 0) {
+ if (GetObjectId(source, &idx, &oid, oidOcspType, sz) < 0) {
WOLFSSL_MSG("\tfail: OBJECT ID");
return ASN_PARSE_E;
}
/* check for critical flag */
- if (source[idx] == ASN_BOOLEAN) {
- WOLFSSL_MSG("\tfound optional critical flag, moving past");
- idx += (ASN_BOOL_SIZE + 1);
+ if ((idx + 1) > (word32)sz) {
+ WOLFSSL_MSG("\tfail: malformed buffer");
+ return BUFFER_E;
}
- /* process the extension based on the OID */
- if (source[idx++] != ASN_OCTET_STRING) {
- WOLFSSL_MSG("\tfail: should be an OCTET STRING");
- return ASN_PARSE_E;
+ localIdx = idx;
+ if (GetASNTag(source, &localIdx, &tag, sz) == 0 && tag == ASN_BOOLEAN) {
+ WOLFSSL_MSG("\tfound optional critical flag, moving past");
+ ret = GetBoolean(source, &idx, sz);
+ if (ret < 0)
+ return ret;
}
- if (GetLength(source, &idx, &length, sz) < 0) {
- WOLFSSL_MSG("\tfail: extension data length");
- return ASN_PARSE_E;
- }
+ ret = GetOctetString(source, &idx, &length, sz);
+ if (ret < 0)
+ return ret;
if (oid == OCSP_NONCE_OID) {
+ /* get data inside extra OCTET_STRING */
+ ret = GetOctetString(source, &idx, &length, sz);
+ if (ret < 0)
+ return ret;
+
resp->nonce = source + idx;
resp->nonceSz = length;
}
@@ -7068,10 +16412,11 @@ static int DecodeOcspRespExtensions(byte* source,
static int DecodeResponseData(byte* source,
word32* ioIndex, OcspResponse* resp, word32 size)
{
- word32 idx = *ioIndex, prev_idx;
+ word32 idx = *ioIndex, prev_idx, localIdx;
int length;
int version;
- word32 responderId = 0;
+ int ret;
+ byte tag;
WOLFSSL_ENTER("DecodeResponseData");
@@ -7085,49 +16430,64 @@ static int DecodeResponseData(byte* source,
* item isn't an EXPLICIT[0], then set version to zero and move
* onto the next item.
*/
- if (source[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
- {
+ localIdx = idx;
+ if (GetASNTag(source, &localIdx, &tag, size) == 0 &&
+ tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
+ {
idx += 2; /* Eat the value and length */
- if (GetMyVersion(source, &idx, &version) < 0)
+ if (GetMyVersion(source, &idx, &version, size) < 0)
return ASN_PARSE_E;
} else
version = 0;
- responderId = source[idx++];
- if ((responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) ||
- (responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)))
+ localIdx = idx;
+ if (GetASNTag(source, &localIdx, &tag, size) == 0 &&
+ ( tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1) ||
+ tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2) ))
{
+ idx++; /* advance past ASN tag */
if (GetLength(source, &idx, &length, size) < 0)
return ASN_PARSE_E;
idx += length;
}
else
return ASN_PARSE_E;
-
+
/* save pointer to the producedAt time */
if (GetBasicDate(source, &idx, resp->producedDate,
&resp->producedDateFormat, size) < 0)
return ASN_PARSE_E;
- if (DecodeSingleResponse(source, &idx, resp, size) < 0)
- return ASN_PARSE_E;
+ if ((ret = DecodeSingleResponse(source, &idx, resp, size)) < 0)
+ return ret; /* ASN_PARSE_E, ASN_BEFORE_DATE_E, ASN_AFTER_DATE_E */
- if (DecodeOcspRespExtensions(source, &idx, resp, size) < 0)
- return ASN_PARSE_E;
+ /*
+ * Check the length of the ResponseData against the current index to
+ * see if there are extensions, they are optional.
+ */
+ if (idx - prev_idx < resp->responseSz)
+ if (DecodeOcspRespExtensions(source, &idx, resp, size) < 0)
+ return ASN_PARSE_E;
*ioIndex = idx;
return 0;
}
+#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
+
static int DecodeCerts(byte* source,
word32* ioIndex, OcspResponse* resp, word32 size)
{
word32 idx = *ioIndex;
+ byte tag;
WOLFSSL_ENTER("DecodeCerts");
- if (source[idx++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
+ if (GetASNTag(source, &idx, &tag, size) < 0)
+ return ASN_PARSE_E;
+
+ if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
{
int length;
@@ -7146,14 +16506,20 @@ static int DecodeCerts(byte* source,
return 0;
}
-static int DecodeBasicOcspResponse(byte* source,
- word32* ioIndex, OcspResponse* resp, word32 size)
+#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */
+
+
+static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
+ OcspResponse* resp, word32 size, void* cm, void* heap, int noVerify)
{
- int length;
+ int length;
word32 idx = *ioIndex;
word32 end_index;
+ int ret;
+ int sigLength;
WOLFSSL_ENTER("DecodeBasicOcspResponse");
+ (void)heap;
if (GetSequence(source, &idx, &length, size) < 0)
return ASN_PARSE_E;
@@ -7162,51 +16528,102 @@ static int DecodeBasicOcspResponse(byte* source,
return ASN_INPUT_E;
end_index = idx + length;
- if (DecodeResponseData(source, &idx, resp, size) < 0)
- return ASN_PARSE_E;
-
+ if ((ret = DecodeResponseData(source, &idx, resp, size)) < 0)
+ return ret; /* ASN_PARSE_E, ASN_BEFORE_DATE_E, ASN_AFTER_DATE_E */
+
/* Get the signature algorithm */
- if (GetAlgoId(source, &idx, &resp->sigOID, size) < 0)
+ if (GetAlgoId(source, &idx, &resp->sigOID, oidSigType, size) < 0)
return ASN_PARSE_E;
- /* Obtain pointer to the start of the signature, and save the size */
- if (source[idx++] == ASN_BIT_STRING)
- {
- int sigLength = 0;
- if (GetLength(source, &idx, &sigLength, size) < 0)
- return ASN_PARSE_E;
- resp->sigSz = sigLength;
- resp->sig = source + idx;
- idx += sigLength;
- }
+ ret = CheckBitString(source, &idx, &sigLength, size, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ resp->sigSz = sigLength;
+ resp->sig = source + idx;
+ idx += sigLength;
/*
* Check the length of the BasicOcspResponse against the current index to
* see if there are certificates, they are optional.
*/
+#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
if (idx < end_index)
{
DecodedCert cert;
- int ret;
if (DecodeCerts(source, &idx, resp, size) < 0)
return ASN_PARSE_E;
- InitDecodedCert(&cert, resp->cert, resp->certSz, 0);
- ret = ParseCertRelative(&cert, CA_TYPE, NO_VERIFY, 0);
- if (ret < 0)
+ InitDecodedCert(&cert, resp->cert, resp->certSz, heap);
+
+ /* Don't verify if we don't have access to Cert Manager. */
+ ret = ParseCertRelative(&cert, CERT_TYPE,
+ noVerify ? NO_VERIFY : VERIFY_OCSP, cm);
+ if (ret < 0) {
+ WOLFSSL_MSG("\tOCSP Responder certificate parsing failed");
+ FreeDecodedCert(&cert);
return ret;
+ }
+
+#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
+ if ((cert.extExtKeyUsage & EXTKEYUSE_OCSP_SIGN) == 0) {
+ if (XMEMCMP(cert.subjectHash,
+ resp->issuerHash, KEYID_SIZE) == 0) {
+ WOLFSSL_MSG("\tOCSP Response signed by issuer");
+ }
+ else {
+ WOLFSSL_MSG("\tOCSP Responder key usage check failed");
+ #ifdef OPENSSL_EXTRA
+ resp->verifyError = OCSP_BAD_ISSUER;
+ #else
+ FreeDecodedCert(&cert);
+ return BAD_OCSP_RESPONDER;
+ #endif
+ }
+ }
+#endif
+
+ /* ConfirmSignature is blocking here */
+ ret = ConfirmSignature(&cert.sigCtx,
+ resp->response, resp->responseSz,
+ cert.publicKey, cert.pubKeySize, cert.keyOID,
+ resp->sig, resp->sigSz, resp->sigOID, NULL);
- ret = ConfirmSignature(resp->response, resp->responseSz,
- cert.publicKey, cert.pubKeySize, cert.keyOID,
- resp->sig, resp->sigSz, resp->sigOID, NULL);
FreeDecodedCert(&cert);
- if (ret == 0)
- {
+ if (ret != 0) {
+ WOLFSSL_MSG("\tOCSP Confirm signature failed");
+ return ASN_OCSP_CONFIRM_E;
+ }
+ }
+ else
+#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */
+ {
+ Signer* ca;
+ int sigValid = -1;
+
+ #ifndef NO_SKID
+ ca = GetCA(cm, resp->issuerKeyHash);
+ #else
+ ca = GetCA(cm, resp->issuerHash);
+ #endif
+
+ if (ca) {
+ SignatureCtx sigCtx;
+ InitSignatureCtx(&sigCtx, heap, INVALID_DEVID);
+
+ /* ConfirmSignature is blocking here */
+ sigValid = ConfirmSignature(&sigCtx, resp->response,
+ resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID,
+ resp->sig, resp->sigSz, resp->sigOID, NULL);
+ }
+ if (ca == NULL || sigValid != 0) {
WOLFSSL_MSG("\tOCSP Confirm signature failed");
return ASN_OCSP_CONFIRM_E;
}
+
+ (void)noVerify;
}
*ioIndex = idx;
@@ -7219,39 +16636,34 @@ void InitOcspResponse(OcspResponse* resp, CertStatus* status,
{
WOLFSSL_ENTER("InitOcspResponse");
+ XMEMSET(status, 0, sizeof(CertStatus));
+ XMEMSET(resp, 0, sizeof(OcspResponse));
+
resp->responseStatus = -1;
- resp->response = NULL;
- resp->responseSz = 0;
- resp->producedDateFormat = 0;
- resp->issuerHash = NULL;
- resp->issuerKeyHash = NULL;
- resp->sig = NULL;
- resp->sigSz = 0;
- resp->sigOID = 0;
- resp->status = status;
- resp->nonce = NULL;
- resp->nonceSz = 0;
- resp->source = source;
- resp->maxIdx = inSz;
+ resp->status = status;
+ resp->source = source;
+ resp->maxIdx = inSz;
}
-int OcspResponseDecode(OcspResponse* resp)
+int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify)
{
+ int ret;
int length = 0;
word32 idx = 0;
byte* source = resp->source;
word32 size = resp->maxIdx;
word32 oid;
+ byte tag;
WOLFSSL_ENTER("OcspResponseDecode");
/* peel the outer SEQUENCE wrapper */
if (GetSequence(source, &idx, &length, size) < 0)
return ASN_PARSE_E;
-
+
/* First get the responseStatus, an ENUMERATED */
- if (GetEnumerated(source, &idx, &resp->responseStatus) < 0)
+ if (GetEnumerated(source, &idx, &resp->responseStatus, size) < 0)
return ASN_PARSE_E;
if (resp->responseStatus != OCSP_SUCCESSFUL)
@@ -7260,7 +16672,9 @@ int OcspResponseDecode(OcspResponse* resp)
/* Next is an EXPLICIT record called ResponseBytes, OPTIONAL */
if (idx >= size)
return ASN_INPUT_E;
- if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
+ if (GetASNTag(source, &idx, &tag, size) < 0)
+ return ASN_PARSE_E;
+ if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
return ASN_PARSE_E;
if (GetLength(source, &idx, &length, size) < 0)
return ASN_PARSE_E;
@@ -7270,77 +16684,72 @@ int OcspResponseDecode(OcspResponse* resp)
return ASN_PARSE_E;
/* Check ObjectID for the resposeBytes */
- if (GetObjectId(source, &idx, &oid, size) < 0)
+ if (GetObjectId(source, &idx, &oid, oidOcspType, size) < 0)
return ASN_PARSE_E;
if (oid != OCSP_BASIC_OID)
return ASN_PARSE_E;
- if (source[idx++] != ASN_OCTET_STRING)
- return ASN_PARSE_E;
+ ret = GetOctetString(source, &idx, &length, size);
+ if (ret < 0)
+ return ret;
- if (GetLength(source, &idx, &length, size) < 0)
- return ASN_PARSE_E;
+ ret = DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap, noVerify);
+ if (ret < 0)
+ return ret;
- if (DecodeBasicOcspResponse(source, &idx, resp, size) < 0)
- return ASN_PARSE_E;
-
return 0;
}
-static word32 SetOcspReqExtensions(word32 extSz, byte* output,
- const byte* nonce, word32 nonceSz)
+word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size)
{
- static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
0x30, 0x01, 0x02 };
byte seqArray[5][MAX_SEQ_SZ];
- word32 seqSz[5], totalSz;
+ word32 seqSz[5], totalSz = (word32)sizeof(NonceObjId);
WOLFSSL_ENTER("SetOcspReqExtensions");
- if (nonce == NULL || nonceSz == 0) return 0;
-
- seqArray[0][0] = ASN_OCTET_STRING;
- seqSz[0] = 1 + SetLength(nonceSz, &seqArray[0][1]);
+ if (!req || !output || !req->nonceSz)
+ return 0;
+
+ totalSz += req->nonceSz;
+ totalSz += seqSz[0] = SetOctetString(req->nonceSz, seqArray[0]);
+ totalSz += seqSz[1] = SetOctetString(req->nonceSz + seqSz[0], seqArray[1]);
+ totalSz += seqSz[2] = SetObjectId(sizeof(NonceObjId), seqArray[2]);
+ totalSz += seqSz[3] = SetSequence(totalSz, seqArray[3]);
+ totalSz += seqSz[4] = SetSequence(totalSz, seqArray[4]);
- seqArray[1][0] = ASN_OBJECT_ID;
- seqSz[1] = 1 + SetLength(sizeof(NonceObjId), &seqArray[1][1]);
+ if (totalSz > size)
+ return 0;
- totalSz = seqSz[0] + seqSz[1] + nonceSz + (word32)sizeof(NonceObjId);
+ totalSz = 0;
- seqSz[2] = SetSequence(totalSz, seqArray[2]);
- totalSz += seqSz[2];
+ XMEMCPY(output + totalSz, seqArray[4], seqSz[4]);
+ totalSz += seqSz[4];
- seqSz[3] = SetSequence(totalSz, seqArray[3]);
+ XMEMCPY(output + totalSz, seqArray[3], seqSz[3]);
totalSz += seqSz[3];
- seqArray[4][0] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2);
- seqSz[4] = 1 + SetLength(totalSz, &seqArray[4][1]);
- totalSz += seqSz[4];
+ XMEMCPY(output + totalSz, seqArray[2], seqSz[2]);
+ totalSz += seqSz[2];
- if (totalSz < extSz)
- {
- totalSz = 0;
- XMEMCPY(output + totalSz, seqArray[4], seqSz[4]);
- totalSz += seqSz[4];
- XMEMCPY(output + totalSz, seqArray[3], seqSz[3]);
- totalSz += seqSz[3];
- XMEMCPY(output + totalSz, seqArray[2], seqSz[2]);
- totalSz += seqSz[2];
- XMEMCPY(output + totalSz, seqArray[1], seqSz[1]);
- totalSz += seqSz[1];
- XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId));
- totalSz += (word32)sizeof(NonceObjId);
- XMEMCPY(output + totalSz, seqArray[0], seqSz[0]);
- totalSz += seqSz[0];
- XMEMCPY(output + totalSz, nonce, nonceSz);
- totalSz += nonceSz;
- }
+ XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId));
+ totalSz += (word32)sizeof(NonceObjId);
+
+ XMEMCPY(output + totalSz, seqArray[1], seqSz[1]);
+ totalSz += seqSz[1];
+
+ XMEMCPY(output + totalSz, seqArray[0], seqSz[0]);
+ totalSz += seqSz[0];
+
+ XMEMCPY(output + totalSz, req->nonce, req->nonceSz);
+ totalSz += req->nonceSz;
return totalSz;
}
-int EncodeOcspRequest(OcspRequest* req)
+int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size)
{
byte seqArray[5][MAX_SEQ_SZ];
/* The ASN.1 of the OCSP Request is an onion of sequences */
@@ -7349,66 +16758,65 @@ int EncodeOcspRequest(OcspRequest* req)
byte issuerKeyArray[MAX_ENCODED_DIG_SZ];
byte snArray[MAX_SN_SZ];
byte extArray[MAX_OCSP_EXT_SZ];
- byte* output = req->dest;
- word32 seqSz[5], algoSz, issuerSz, issuerKeySz, snSz, extSz, totalSz;
- int i;
+ word32 seqSz[5], algoSz, issuerSz, issuerKeySz, extSz, totalSz;
+ int i, snSz;
WOLFSSL_ENTER("EncodeOcspRequest");
#ifdef NO_SHA
- algoSz = SetAlgoID(SHA256h, algoArray, hashType, 0);
+ algoSz = SetAlgoID(SHA256h, algoArray, oidHashType, 0);
#else
- algoSz = SetAlgoID(SHAh, algoArray, hashType, 0);
+ algoSz = SetAlgoID(SHAh, algoArray, oidHashType, 0);
#endif
- req->issuerHash = req->cert->issuerHash;
- issuerSz = SetDigest(req->cert->issuerHash, KEYID_SIZE, issuerArray);
-
- req->issuerKeyHash = req->cert->issuerKeyHash;
- issuerKeySz = SetDigest(req->cert->issuerKeyHash,
- KEYID_SIZE, issuerKeyArray);
-
- req->serial = req->cert->serial;
- req->serialSz = req->cert->serialSz;
- snSz = SetSerialNumber(req->cert->serial, req->cert->serialSz, snArray);
-
- extSz = 0;
- if (req->useNonce) {
- RNG rng;
- if (wc_InitRng(&rng) != 0) {
- WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce.");
- } else {
- if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0)
- WOLFSSL_MSG("\tCannot run RNG. Skipping the OSCP Nonce.");
- else {
- req->nonceSz = MAX_OCSP_NONCE_SZ;
- extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray,
- req->nonce, req->nonceSz);
- }
- wc_FreeRng(&rng);
- }
+ issuerSz = SetDigest(req->issuerHash, KEYID_SIZE, issuerArray);
+ issuerKeySz = SetDigest(req->issuerKeyHash, KEYID_SIZE, issuerKeyArray);
+ snSz = SetSerialNumber(req->serial, req->serialSz, snArray,
+ MAX_SN_SZ, MAX_SN_SZ);
+ extSz = 0;
+
+ if (snSz < 0)
+ return snSz;
+
+ if (req->nonceSz) {
+ /* TLS Extensions use this function too - put extensions after
+ * ASN.1: Context Specific [2].
+ */
+ extSz = EncodeOcspRequestExtensions(req, extArray + 2,
+ OCSP_NONCE_EXT_SZ);
+ extSz += SetExplicit(2, extSz, extArray);
}
totalSz = algoSz + issuerSz + issuerKeySz + snSz;
-
for (i = 4; i >= 0; i--) {
seqSz[i] = SetSequence(totalSz, seqArray[i]);
totalSz += seqSz[i];
if (i == 2) totalSz += extSz;
}
+
+ if (output == NULL)
+ return totalSz;
+ if (totalSz > size)
+ return BUFFER_E;
+
totalSz = 0;
for (i = 0; i < 5; i++) {
XMEMCPY(output + totalSz, seqArray[i], seqSz[i]);
totalSz += seqSz[i];
}
+
XMEMCPY(output + totalSz, algoArray, algoSz);
totalSz += algoSz;
+
XMEMCPY(output + totalSz, issuerArray, issuerSz);
totalSz += issuerSz;
+
XMEMCPY(output + totalSz, issuerKeyArray, issuerKeySz);
totalSz += issuerKeySz;
+
XMEMCPY(output + totalSz, snArray, snSz);
totalSz += snSz;
+
if (extSz != 0) {
XMEMCPY(output + totalSz, extArray, extSz);
totalSz += extSz;
@@ -7418,19 +16826,91 @@ int EncodeOcspRequest(OcspRequest* req)
}
-void InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce,
- byte* dest, word32 destSz)
+int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce,
+ void* heap)
{
+ int ret;
+
WOLFSSL_ENTER("InitOcspRequest");
- req->cert = cert;
- req->useNonce = useNonce;
- req->nonceSz = 0;
- req->issuerHash = NULL;
- req->issuerKeyHash = NULL;
- req->serial = NULL;
- req->dest = dest;
- req->destSz = destSz;
+ if (req == NULL)
+ return BAD_FUNC_ARG;
+
+ ForceZero(req, sizeof(OcspRequest));
+ req->heap = heap;
+
+ if (cert) {
+ XMEMCPY(req->issuerHash, cert->issuerHash, KEYID_SIZE);
+ XMEMCPY(req->issuerKeyHash, cert->issuerKeyHash, KEYID_SIZE);
+
+ req->serial = (byte*)XMALLOC(cert->serialSz, req->heap,
+ DYNAMIC_TYPE_OCSP_REQUEST);
+ if (req->serial == NULL)
+ return MEMORY_E;
+
+ XMEMCPY(req->serial, cert->serial, cert->serialSz);
+ req->serialSz = cert->serialSz;
+
+ if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) {
+ req->url = (byte*)XMALLOC(cert->extAuthInfoSz + 1, req->heap,
+ DYNAMIC_TYPE_OCSP_REQUEST);
+ if (req->url == NULL) {
+ XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP);
+ return MEMORY_E;
+ }
+
+ XMEMCPY(req->url, cert->extAuthInfo, cert->extAuthInfoSz);
+ req->urlSz = cert->extAuthInfoSz;
+ req->url[req->urlSz] = 0;
+ }
+ }
+
+ if (useNonce) {
+ WC_RNG rng;
+
+ #ifndef HAVE_FIPS
+ ret = wc_InitRng_ex(&rng, req->heap, INVALID_DEVID);
+ #else
+ ret = wc_InitRng(&rng);
+ #endif
+ if (ret != 0) {
+ WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce.");
+ } else {
+ if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0)
+ WOLFSSL_MSG("\tCannot run RNG. Skipping the OSCP Nonce.");
+ else
+ req->nonceSz = MAX_OCSP_NONCE_SZ;
+
+ wc_FreeRng(&rng);
+ }
+ }
+
+ return 0;
+}
+
+void FreeOcspRequest(OcspRequest* req)
+{
+ WOLFSSL_ENTER("FreeOcspRequest");
+
+ if (req) {
+ if (req->serial)
+ XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ req->serial = NULL;
+
+#ifdef OPENSSL_EXTRA
+ if (req->serialInt) {
+ if (req->serialInt->isDynamic) {
+ XFREE(req->serialInt->data, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+ XFREE(req->serialInt, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+ req->serialInt = NULL;
+#endif
+
+ if (req->url)
+ XFREE(req->url, req->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ req->url = NULL;
+ }
}
@@ -7454,14 +16934,18 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
/* Nonces are not critical. The responder may not necessarily add
* the nonce to the response. */
- if (req->useNonce && resp->nonceSz != 0) {
+ if (req->nonceSz
+#ifndef WOLFSSL_FORCE_OCSP_NONCE_CHECK
+ && resp->nonceSz != 0
+#endif
+ ) {
cmp = req->nonceSz - resp->nonceSz;
if (cmp != 0)
{
WOLFSSL_MSG("\tnonceSz mismatch");
return cmp;
}
-
+
cmp = XMEMCMP(req->nonce, resp->nonce, req->nonceSz);
if (cmp != 0)
{
@@ -7501,20 +16985,22 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
return 0;
}
-#endif
+#endif /* HAVE_OCSP */
-/* store SHA hash of NAME */
-WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
+/* store WC_SHA hash of NAME */
+int GetNameHash(const byte* source, word32* idx, byte* hash,
int maxIdx)
{
int length; /* length of all distinguished names */
int ret;
word32 dummy;
+ byte tag;
WOLFSSL_ENTER("GetNameHash");
- if (source[*idx] == ASN_OBJECT_ID) {
+ dummy = *idx;
+ if (GetASNTag(source, &dummy, &tag, maxIdx) == 0 && tag == ASN_OBJECT_ID) {
WOLFSSL_MSG("Trying optional prefix...");
if (GetLength(source, idx, &length, maxIdx) < 0)
@@ -7531,11 +17017,7 @@ WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
if (GetSequence(source, idx, &length, maxIdx) < 0)
return ASN_PARSE_E;
-#ifdef NO_SHA
- ret = wc_Sha256Hash(source + dummy, length + *idx - dummy, hash);
-#else
- ret = wc_ShaHash(source + dummy, length + *idx - dummy, hash);
-#endif
+ ret = CalcHashId(source + dummy, length + *idx - dummy, hash);
*idx += length;
@@ -7546,16 +17028,15 @@ WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
#ifdef HAVE_CRL
/* initialize decoded CRL */
-void InitDecodedCRL(DecodedCRL* dcrl)
+void InitDecodedCRL(DecodedCRL* dcrl, void* heap)
{
WOLFSSL_MSG("InitDecodedCRL");
- dcrl->certBegin = 0;
- dcrl->sigIndex = 0;
- dcrl->sigLength = 0;
- dcrl->signatureOID = 0;
- dcrl->certs = NULL;
- dcrl->totalCerts = 0;
+ XMEMSET(dcrl, 0, sizeof(DecodedCRL));
+ dcrl->heap = heap;
+ #ifdef WOLFSSL_HEAP_TEST
+ dcrl->heap = (void*)WOLFSSL_HEAP_TEST;
+ #endif
}
@@ -7568,7 +17049,7 @@ void FreeDecodedCRL(DecodedCRL* dcrl)
while(tmp) {
RevokedCert* next = tmp->next;
- XFREE(tmp, NULL, DYNAMIC_TYPE_REVOKED);
+ XFREE(tmp, dcrl->heap, DYNAMIC_TYPE_REVOKED);
tmp = next;
}
}
@@ -7578,7 +17059,7 @@ void FreeDecodedCRL(DecodedCRL* dcrl)
static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
int maxIdx)
{
- int len;
+ int ret, len;
word32 end;
byte b;
RevokedCert* rc;
@@ -7590,56 +17071,33 @@ static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
end = *idx + len;
- /* get serial number */
- b = buff[*idx];
- *idx += 1;
-
- if (b != ASN_INTEGER) {
- WOLFSSL_MSG("Expecting Integer");
- return ASN_PARSE_E;
- }
-
- if (GetLength(buff, idx, &len, maxIdx) < 0)
- return ASN_PARSE_E;
-
- if (len > EXTERNAL_SERIAL_SIZE) {
- WOLFSSL_MSG("Serial Size too big");
- return ASN_PARSE_E;
- }
-
- rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), NULL, DYNAMIC_TYPE_CRL);
+ rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), dcrl->heap,
+ DYNAMIC_TYPE_REVOKED);
if (rc == NULL) {
WOLFSSL_MSG("Alloc Revoked Cert failed");
return MEMORY_E;
}
- XMEMCPY(rc->serialNumber, &buff[*idx], len);
- rc->serialSz = len;
+ if (GetSerialNumber(buff, idx, rc->serialNumber, &rc->serialSz,
+ maxIdx) < 0) {
+ XFREE(rc, dcrl->heap, DYNAMIC_TYPE_REVOKED);
+ return ASN_PARSE_E;
+ }
/* add to list */
rc->next = dcrl->certs;
dcrl->certs = rc;
dcrl->totalCerts++;
- *idx += len;
-
/* get date */
- b = buff[*idx];
- *idx += 1;
-
- if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME) {
+ ret = GetDateInfo(buff, idx, NULL, &b, NULL, maxIdx);
+ if (ret < 0) {
WOLFSSL_MSG("Expecting Date");
- return ASN_PARSE_E;
+ return ret;
}
- if (GetLength(buff, idx, &len, maxIdx) < 0)
- return ASN_PARSE_E;
-
- /* skip for now */
- *idx += len;
-
- if (*idx != end) /* skip extensions */
- *idx = end;
+ /* skip extensions */
+ *idx = end;
return 0;
}
@@ -7650,29 +17108,244 @@ static int GetCRL_Signature(const byte* source, word32* idx, DecodedCRL* dcrl,
int maxIdx)
{
int length;
- byte b;
+ int ret;
WOLFSSL_ENTER("GetCRL_Signature");
- b = source[*idx];
- *idx += 1;
- if (b != ASN_BIT_STRING)
- return ASN_BITSTR_E;
+ ret = CheckBitString(source, idx, &length, maxIdx, 1, NULL);
+ if (ret != 0)
+ return ret;
+ dcrl->sigLength = length;
- if (GetLength(source, idx, &length, maxIdx) < 0)
+ dcrl->signature = (byte*)&source[*idx];
+ *idx += dcrl->sigLength;
+
+ return 0;
+}
+
+int VerifyCRL_Signature(SignatureCtx* sigCtx, const byte* toBeSigned,
+ word32 tbsSz, const byte* signature, word32 sigSz,
+ word32 signatureOID, Signer *ca, void* heap)
+{
+ /* try to confirm/verify signature */
+#ifndef IGNORE_KEY_EXTENSIONS
+ if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) {
+ WOLFSSL_MSG("CA cannot sign CRLs");
+ return ASN_CRL_NO_SIGNER_E;
+ }
+#endif /* IGNORE_KEY_EXTENSIONS */
+
+ InitSignatureCtx(sigCtx, heap, INVALID_DEVID);
+ if (ConfirmSignature(sigCtx, toBeSigned, tbsSz, ca->publicKey,
+ ca->pubKeySize, ca->keyOID, signature, sigSz,
+ signatureOID, NULL) != 0) {
+ WOLFSSL_MSG("CRL Confirm signature failed");
+ return ASN_CRL_CONFIRM_E;
+ }
+
+ return 0;
+}
+
+
+static int ParseCRL_CertList(DecodedCRL* dcrl, const byte* buf,
+ word32* inOutIdx, int sz)
+{
+ word32 oid, dateIdx, idx, checkIdx;
+ int version, doNextDate = 1;
+ byte tag;
+
+ if (dcrl == NULL || inOutIdx == NULL || buf == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* may have version */
+ idx = *inOutIdx;
+
+ checkIdx = idx;
+ if (GetASNTag(buf, &checkIdx, &tag, sz) == 0 && tag == ASN_INTEGER) {
+ if (GetMyVersion(buf, &idx, &version, sz) < 0)
+ return ASN_PARSE_E;
+ }
+
+ if (GetAlgoId(buf, &idx, &oid, oidIgnoreType, sz) < 0)
return ASN_PARSE_E;
- dcrl->sigLength = length;
+ if (GetNameHash(buf, &idx, dcrl->issuerHash, sz) < 0)
+ return ASN_PARSE_E;
- b = source[*idx];
- *idx += 1;
- if (b != 0x00)
- return ASN_EXPECT_0_E;
+ if (GetBasicDate(buf, &idx, dcrl->lastDate, &dcrl->lastDateFormat, sz) < 0)
+ return ASN_PARSE_E;
- dcrl->sigLength--;
- dcrl->signature = (byte*)&source[*idx];
+ dateIdx = idx;
- *idx += dcrl->sigLength;
+ if (GetBasicDate(buf, &idx, dcrl->nextDate, &dcrl->nextDateFormat, sz) < 0)
+ {
+#ifndef WOLFSSL_NO_CRL_NEXT_DATE
+ (void)dateIdx;
+ return ASN_PARSE_E;
+#else
+ dcrl->nextDateFormat = ASN_OTHER_TYPE; /* skip flag */
+ doNextDate = 0;
+ idx = dateIdx;
+#endif
+ }
+
+ if (doNextDate) {
+#ifndef NO_ASN_TIME
+ if (!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, AFTER)) {
+ WOLFSSL_MSG("CRL after date is no longer valid");
+ return ASN_AFTER_DATE_E;
+ }
+#endif
+ }
+
+ checkIdx = idx;
+ if (idx != dcrl->sigIndex &&
+ GetASNTag(buf, &checkIdx, &tag, sz) == 0 && tag != CRL_EXTENSIONS) {
+
+ int len;
+
+ if (GetSequence(buf, &idx, &len, sz) < 0)
+ return ASN_PARSE_E;
+ len += idx;
+
+ while (idx < (word32)len) {
+ if (GetRevoked(buf, &idx, dcrl, len) < 0)
+ return ASN_PARSE_E;
+ }
+ }
+
+ *inOutIdx = idx;
+
+ return 0;
+}
+
+
+#ifndef NO_SKID
+static int ParseCRL_AuthKeyIdExt(const byte* input, int sz, DecodedCRL* dcrl)
+{
+ word32 idx = 0;
+ int length = 0, ret = 0;
+ byte tag;
+
+ WOLFSSL_ENTER("ParseCRL_AuthKeyIdExt");
+
+ if (GetSequence(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: should be a SEQUENCE\n");
+ return ASN_PARSE_E;
+ }
+
+ if (GetASNTag(input, &idx, &tag, sz) < 0) {
+ return ASN_PARSE_E;
+ }
+
+ if (tag != (ASN_CONTEXT_SPECIFIC | 0)) {
+ WOLFSSL_MSG("\tinfo: OPTIONAL item 0, not available\n");
+ return 0;
+ }
+
+ if (GetLength(input, &idx, &length, sz) <= 0) {
+ WOLFSSL_MSG("\tfail: extension data length");
+ return ASN_PARSE_E;
+ }
+
+ dcrl->extAuthKeyIdSet = 1;
+ if (length == KEYID_SIZE) {
+ XMEMCPY(dcrl->extAuthKeyId, input + idx, length);
+ }
+ else {
+ ret = CalcHashId(input + idx, length, dcrl->extAuthKeyId);
+ }
+
+ return ret;
+}
+#endif
+
+
+static int ParseCRL_Extensions(DecodedCRL* dcrl, const byte* buf,
+ word32* inOutIdx, word32 sz)
+{
+ int length;
+ word32 idx;
+ word32 ext_bound; /* boundary index for the sequence of extensions */
+ word32 oid;
+ byte tag;
+
+ WOLFSSL_ENTER("ParseCRL_Extensions");
+ (void)dcrl;
+
+ if (inOutIdx == NULL)
+ return BAD_FUNC_ARG;
+
+ idx = *inOutIdx;
+
+ /* CRL Extensions are optional */
+ if ((idx + 1) > sz)
+ return 0;
+
+ /* CRL Extensions are optional */
+ if (GetASNTag(buf, &idx, &tag, sz) < 0)
+ return 0;
+
+ /* CRL Extensions are optional */
+ if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
+ return 0;
+
+ if (GetLength(buf, &idx, &length, sz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetSequence(buf, &idx, &length, sz) < 0)
+ return ASN_PARSE_E;
+
+ ext_bound = idx + length;
+
+ while (idx < (word32)ext_bound) {
+ word32 localIdx;
+ int ret;
+
+ if (GetSequence(buf, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: should be a SEQUENCE");
+ return ASN_PARSE_E;
+ }
+
+ oid = 0;
+ if (GetObjectId(buf, &idx, &oid, oidCrlExtType, sz) < 0) {
+ WOLFSSL_MSG("\tfail: OBJECT ID");
+ return ASN_PARSE_E;
+ }
+
+ /* check for critical flag */
+ if ((idx + 1) > (word32)sz) {
+ WOLFSSL_MSG("\tfail: malformed buffer");
+ return BUFFER_E;
+ }
+
+ localIdx = idx;
+ if (GetASNTag(buf, &localIdx, &tag, sz) == 0 && tag == ASN_BOOLEAN) {
+ WOLFSSL_MSG("\tfound optional critical flag, moving past");
+ ret = GetBoolean(buf, &idx, sz);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = GetOctetString(buf, &idx, &length, sz);
+ if (ret < 0)
+ return ret;
+
+ if (oid == AUTH_KEY_OID) {
+ #ifndef NO_SKID
+ ret = ParseCRL_AuthKeyIdExt(buf + idx, length, dcrl);
+ if (ret < 0) {
+ WOLFSSL_MSG("\tcouldn't parse AuthKeyId extension");
+ return ret;
+ }
+ #endif
+ }
+
+ idx += length;
+ }
+
+ *inOutIdx = idx;
return 0;
}
@@ -7681,15 +17354,16 @@ static int GetCRL_Signature(const byte* source, word32* idx, DecodedCRL* dcrl,
/* prase crl buffer into decoded state, 0 on success */
int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm)
{
- int version, len;
- word32 oid, idx = 0;
- Signer* ca = NULL;
+ int len;
+ word32 idx = 0;
+ Signer* ca = NULL;
+ SignatureCtx sigCtx;
WOLFSSL_MSG("ParseCRL");
/* raw crl hash */
/* hash here if needed for optimized comparisons
- * Sha sha;
+ * wc_Sha sha;
* wc_InitSha(&sha);
* wc_ShaUpdate(&sha, buff, sz);
* wc_ShaFinal(&sha, dcrl->crlHash); */
@@ -7698,98 +17372,154 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm)
return ASN_PARSE_E;
dcrl->certBegin = idx;
+ /* Normalize sz for the length inside the outer sequence. */
+ sz = len + idx;
if (GetSequence(buff, &idx, &len, sz) < 0)
return ASN_PARSE_E;
dcrl->sigIndex = len + idx;
- /* may have version */
- if (buff[idx] == ASN_INTEGER) {
- if (GetMyVersion(buff, &idx, &version) < 0)
- return ASN_PARSE_E;
- }
-
- if (GetAlgoId(buff, &idx, &oid, sz) < 0)
+ if (ParseCRL_CertList(dcrl, buff, &idx, idx + len) < 0)
return ASN_PARSE_E;
- if (GetNameHash(buff, &idx, dcrl->issuerHash, sz) < 0)
+ if (ParseCRL_Extensions(dcrl, buff, &idx, idx + len) < 0)
return ASN_PARSE_E;
- if (GetBasicDate(buff, &idx, dcrl->lastDate, &dcrl->lastDateFormat, sz) < 0)
+ idx = dcrl->sigIndex;
+
+ if (GetAlgoId(buff, &idx, &dcrl->signatureOID, oidSigType, sz) < 0)
return ASN_PARSE_E;
- if (GetBasicDate(buff, &idx, dcrl->nextDate, &dcrl->nextDateFormat, sz) < 0)
+ if (GetCRL_Signature(buff, &idx, dcrl, sz) < 0)
return ASN_PARSE_E;
- if (!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, AFTER)) {
- WOLFSSL_MSG("CRL after date is no longer valid");
- return ASN_AFTER_DATE_E;
+ /* openssl doesn't add skid by default for CRLs cause firefox chokes
+ if experiencing issues uncomment NO_SKID define in CRL section of
+ wolfssl/wolfcrypt/settings.h */
+#ifndef NO_SKID
+ if (dcrl->extAuthKeyIdSet) {
+ ca = GetCA(cm, dcrl->extAuthKeyId); /* more unique than issuerHash */
+ }
+ if (ca != NULL && XMEMCMP(dcrl->issuerHash, ca->subjectNameHash,
+ KEYID_SIZE) != 0) {
+ ca = NULL;
+ }
+ if (ca == NULL) {
+ ca = GetCAByName(cm, dcrl->issuerHash); /* last resort */
+ /* If AKID is available then this CA doesn't have the public
+ * key required */
+ if (ca && dcrl->extAuthKeyIdSet) {
+ WOLFSSL_MSG("CA SKID doesn't match AKID");
+ ca = NULL;
+ }
}
+#else
+ ca = GetCA(cm, dcrl->issuerHash);
+#endif /* !NO_SKID */
+ WOLFSSL_MSG("About to verify CRL signature");
- if (idx != dcrl->sigIndex && buff[idx] != CRL_EXTENSIONS) {
- if (GetSequence(buff, &idx, &len, sz) < 0)
- return ASN_PARSE_E;
+ if (ca == NULL) {
+ WOLFSSL_MSG("Did NOT find CRL issuer CA");
+ return ASN_CRL_NO_SIGNER_E;
+ }
- len += idx;
+ WOLFSSL_MSG("Found CRL issuer CA");
+ return VerifyCRL_Signature(&sigCtx, buff + dcrl->certBegin,
+ dcrl->sigIndex - dcrl->certBegin, dcrl->signature, dcrl->sigLength,
+ dcrl->signatureOID, ca, dcrl->heap);
+}
- while (idx < (word32)len) {
- if (GetRevoked(buff, &idx, dcrl, sz) < 0)
- return ASN_PARSE_E;
+#endif /* HAVE_CRL */
+
+
+
+#ifdef WOLFSSL_CERT_PIV
+
+int wc_ParseCertPIV(wc_CertPIV* piv, const byte* buf, word32 totalSz)
+{
+ int length = 0;
+ word32 idx = 0;
+
+ WOLFSSL_ENTER("wc_ParseCertPIV");
+
+ if (piv == NULL || buf == NULL || totalSz == 0)
+ return BAD_FUNC_ARG;
+
+ XMEMSET(piv, 0, sizeof(wc_CertPIV));
+
+ /* Detect Identiv PIV (with 0x0A, 0x0B and 0x0C sections) */
+ /* Certificate (0A 82 05FA) */
+ if (GetASNHeader(buf, ASN_PIV_CERT, &idx, &length, totalSz) >= 0) {
+ /* Identiv Type PIV card */
+ piv->isIdentiv = 1;
+
+ piv->cert = &buf[idx];
+ piv->certSz = length;
+ idx += length;
+
+ /* Nonce (0B 14) */
+ if (GetASNHeader(buf, ASN_PIV_NONCE, &idx, &length, totalSz) >= 0) {
+ piv->nonce = &buf[idx];
+ piv->nonceSz = length;
+ idx += length;
}
- }
- if (idx != dcrl->sigIndex)
- idx = dcrl->sigIndex; /* skip extensions */
+ /* Signed Nonce (0C 82 0100) */
+ if (GetASNHeader(buf, ASN_PIV_SIGNED_NONCE, &idx, &length, totalSz) >= 0) {
+ piv->signedNonce = &buf[idx];
+ piv->signedNonceSz = length;
+ }
- if (GetAlgoId(buff, &idx, &dcrl->signatureOID, sz) < 0)
- return ASN_PARSE_E;
+ idx = 0;
+ buf = piv->cert;
+ totalSz = piv->certSz;
+ }
- if (GetCRL_Signature(buff, &idx, dcrl, sz) < 0)
+ /* Certificate Buffer Total Size (53 82 05F6) */
+ if (GetASNHeader(buf, ASN_APPLICATION | ASN_PRINTABLE_STRING, &idx,
+ &length, totalSz) < 0) {
return ASN_PARSE_E;
+ }
+ /* PIV Certificate (70 82 05ED) */
+ if (GetASNHeader(buf, ASN_PIV_TAG_CERT, &idx, &length,
+ totalSz) < 0) {
+ return ASN_PARSE_E;
+ }
- /* openssl doesn't add skid by default for CRLs cause firefox chokes
- we're not assuming it's available yet */
- #if !defined(NO_SKID) && defined(CRL_SKID_READY)
- if (dcrl->extAuthKeyIdSet)
- ca = GetCA(cm, dcrl->extAuthKeyId);
- if (ca == NULL)
- ca = GetCAByName(cm, dcrl->issuerHash);
- #else /* NO_SKID */
- ca = GetCA(cm, dcrl->issuerHash);
- #endif /* NO_SKID */
- WOLFSSL_MSG("About to verify CRL signature");
+ /* Capture certificate buffer pointer and length */
+ piv->cert = &buf[idx];
+ piv->certSz = length;
+ idx += length;
- if (ca) {
- WOLFSSL_MSG("Found CRL issuer CA");
- /* try to confirm/verify signature */
- #ifndef IGNORE_KEY_EXTENSIONS
- if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) {
- WOLFSSL_MSG("CA cannot sign CRLs");
- return ASN_CRL_NO_SIGNER_E;
- }
- #endif /* IGNORE_KEY_EXTENSIONS */
- if (!ConfirmSignature(buff + dcrl->certBegin,
- dcrl->sigIndex - dcrl->certBegin,
- ca->publicKey, ca->pubKeySize, ca->keyOID,
- dcrl->signature, dcrl->sigLength, dcrl->signatureOID, NULL)) {
- WOLFSSL_MSG("CRL Confirm signature failed");
- return ASN_CRL_CONFIRM_E;
+ /* PIV Certificate Info (71 01 00) */
+ if (GetASNHeader(buf, ASN_PIV_TAG_CERT_INFO, &idx, &length,
+ totalSz) >= 0) {
+ if (length >= 1) {
+ piv->compression = (buf[idx] & ASN_PIV_CERT_INFO_COMPRESSED);
+ piv->isX509 = (buf[idx] & ASN_PIV_CERT_INFO_ISX509);
}
+ idx += length;
}
- else {
- WOLFSSL_MSG("Did NOT find CRL issuer CA");
- return ASN_CRL_NO_SIGNER_E;
+
+ /* PIV Error Detection (FE 00) */
+ if (GetASNHeader(buf, ASN_PIV_TAG_ERR_DET, &idx, &length,
+ totalSz) >= 0) {
+ piv->certErrDet = &buf[idx];
+ piv->certErrDetSz = length;
+ idx += length;
}
return 0;
}
-#endif /* HAVE_CRL */
-#endif
+#endif /* WOLFSSL_CERT_PIV */
-#ifdef WOLFSSL_SEP
+#undef ERROR_OUT
+#endif /* !NO_ASN */
-#endif /* WOLFSSL_SEP */
+#ifdef WOLFSSL_SEP
+
+#endif /* WOLFSSL_SEP */